From 39334070a7881fec2fbcab2ec902175ff0701c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SvenjaRei=C3=9Faus?= Date: Tue, 26 Feb 2019 12:15:17 -0500 Subject: [PATCH 1/5] WIP: DCustom Default Faction Permissions - No reliable --- classes/artifacts/Factions_jar/Factions.jar | Bin 0 -> 2425359 bytes .../java/com/massivecraft/factions/Conf.java | 17 ++ .../com/massivecraft/factions/Faction.java | 1 + .../massivecraft/factions/cmd/CmdCreate.java | 5 + .../zcore/fperms/DefaultPermissions.java | 147 ++++++++++++++++++ .../zcore/fperms/PermissableAction.java | 10 ++ .../factions/zcore/persist/MemoryFaction.java | 27 ++++ .../massivecraft/factions/zcore/util/TL.java | 2 + 8 files changed, 209 insertions(+) create mode 100644 classes/artifacts/Factions_jar/Factions.jar create mode 100644 src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java diff --git a/classes/artifacts/Factions_jar/Factions.jar b/classes/artifacts/Factions_jar/Factions.jar new file mode 100644 index 0000000000000000000000000000000000000000..18bc737e19ec9ea024ce43272f00ffb48b5ac3ca GIT binary patch literal 2425359 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%0Dx+aFD~9*-#e>>gYdC`!Ls(=vny`o8o|m^z&tS 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�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

Wrfh>Li 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 z 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[p&V) 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

|Vz57h+E}6jB8uTRn4o6E-K8!-Ur&*6D7 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

ryLxIQo1 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 aM*_ta6upe8Hr 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

bJbyw^Y~h=K2Y-@l@IMrVi4f zf5C41nOfyfYUQiVZ@ae(#`~@Iw$5FUfu?%0+S1CxMzk=DGUE^XS&ESzT5$&(cNqn5 zT|{Ka4|R#-1N6ofErF zgTLV-IT3Cjg@CS?wjv+6+UE2Bi6|L>WPBV)YZz!rOAEKAOkGZvg

Sm8ZkzY4uqw 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

    (wn&lX6$2Te#TvNw8mX_?7CV{5Qkb% zSi9O!A<fnvif2&yis~@+Dm}XXDn685BWgTW5JopO(Bj(C(qe06 zg_0jIz0mH;?Kofginu@hDm0qFNkb5Tx-!q~ujGVyt|ogF9Blykgd0s=&ImXnE+-4E zYdx<6F2u1=2$!)ZD&{QRKupK_^4fiCRsZ>G10FZVa91shlvVLT7M)z)RJ?hljZ?Kv zz`8|Oo@1QUmR=(luC8aOsLV?rP{2MnePTc1>5?PMss|o({8cX!F=UH+TQX zIFkj%CiB!t=9(&xMS9Z8OQxQe(ir_0(#%R;<#@xx(*bEEj&$nSUM{q;mR^z9j_}Gz`D22aWHi=YXQf_kEq4nJ&wsuik1DgFg=({Wm@bd zA0S^7nZ#@><2WLXw>2V+SbLmMVD|2&h9EYhryQNxwUaYydrA;Udd9Vm>jmp_UKrMI z2fO5js@4%@6X&9pkkeUB4{kpwFY&JK>NON{Qg_t%%v>#AuDI)u!XNc8$50fR-DWkh z6Rr5=80_9#+&-By#(dd;$3-+HPTli;to^MGA%+^KEXu#R*Y3EZd#u+uP;c z2@8kdcGp``1EwKt^P;kQEhE%m8c@*+x?cV_Ul z4=(0y#b2_DBKOy5%PTwGuKnqC^YV(u%}<{6xS3f!S zb+iRkazGYL_hwYKNlWSi0Yj00-@e?0T51=9lkzI!tF~l7N!Eehd#@P~v+?M2><3Xk z0dW-Sr~c8t#Jk7eAFnSZ^TPqD-4j~)$NkQ)@YYAG7Je4J?8=#%m(}F zb{s)l5ql58a5fZE3}x)Hzh@9dSUN_kqr$u5as;5<{8}S24>=jI7fHM(cGm;{q|pwR zgEypzn3JzH`~;Z7)e`?)#WJ6j#&YI<9{8`S^&N@qUi&Ls?+M|bsuu14yjL}HHTzG^ zTGh01{a1q4+zyY+?aa=A=>#M=jHuv@i7*J8p=T8@t0XGhH$DxvfU8X1ev~RlhsH-K}-yk>^F8877wYQ~DtH z_NU)3{_~&B{k;mF*CiSHkd6c&SVO8isG^Ye2#3Nu<;Ty+h)2ytxgk8HT`KGzlZU&g zyCgY2A{|H(tUL9`pa=zUheEvHg|P|NfRf*oc8U)lU`Oy1Y+i-GE#Fnz5~R!)+J+0i z68DwH`nwud;Q4E@N0>dNA-~*ph#IUmN(`eB&7_R=m6s?;RK!!b*)H9s#?Ny1)tSV^ z8{w~CyoSejyg%n~=cn)c%COH*oM~

    WsVK#7}_pGa$PsTm6BZcKWF+Ug&&GZ&Sa@ zdO)fo$JM>Qx38*5hqR#V#b@U5!#d}*pD{HS@o+4xBk-nZskMuyn{5LdS zX9nt2lYjnVx(q<>`SF`9gOQufE|fPB6~`O`5Xc8UCm1hid)n_xCDEoOUpzlIxr*ee z4`14hU6C-*Ki}rjtkDescizarPxPkCn}O$S6ZPUrnst@YQ*b9-o@GM?Lq}WFG%5Qj z+fFu1(?gM8yxfS|yf@lV_R!#uW}Q>4RC(~ z{oBj1mm)(>#^R1wehs{u*H8%EgGh})v3qwk*vqDV_huHu^)xl#mfns_tRklsS9&jZ z>&CytwCN9o`ilP&en!jbv`3u53dAfK_@rvPhthrIW3mJ8{Pn!16<1~(AeC-cniR@e z{RqUX+Nd5%Kd6s5iQ18PWs*j2<2r?TV|r}JvxwF7fLPbokV_rQ6J;L-#9?Z{!zn8W z1&_@UexC)HEILl+ja@%+Sc9X_0`%*d!$*H%@oy(}XHIMK0i>RvNIJ<&tkd%xT6zu- zAOS@>-xDCr(evD?j@e|~&BuBqjQyCklNBre>GNe}nAQkDqw1+DF^YJyzBM`L(hZ^QF5U z|ltuKW6j`og3tngsd)fRn>sGhe4JXJ zU6Gl5-Na3;&M|*eZ)cZA(!Y8&3XPv87Hm7V~n}7?6&7!%9V+YPNdmr$#oobaOfDwX}<(72>FP zAwo2@`|qg5fGK;3K_Q56iO*`*h*?ImA__(U^Kc1de$Zv`T$a$nEj%1?prIywLZ3r8 zl!SzFHIG&JcDD;WCP7Fe^_hp8MQ3jfjSG?6>=(#d5h{90Q0Owj3bIUH)f&=_upBeh zTd4{&Rh#x`Gw%{qgKuZcJ-2+_mVBwV1D4Z6^}pNL`nnKs?72{^rO^mneTY?a0kF8f}AgZ`}Nj z!WJb!LiZg`$4|)iMXYg{18x2H*)g{Pp9ck(t3Y|;+><3q*>EzGrN<_z5_BEmu&V)G z-G~}9=qpBH%ER~6w=*NOr0B?cC=IkXrdf@+Sy52gb84MPR@L9;2ROv|YJIRHQNfwV zG~?>ph&E6nU{c05g`^ZlC z0&Tuf7t(ybP-}&4#%6C?9!5;OmCTWSzREauS&Qdf6YKfd^B|0S@CL3cv(%@gPpK6{ zOza$@^X3zIf#U$AV@?UV{AAGL-i-u5`u;YSBd_n;nq*pHDaz1sXrfIWP<*n_TCh7G3?@O*Yo5EU-sW4(Gh|fDTV-7;H7zv%90SjR`hzU&% z&=eP8umz#_&+tUh_?yJy~`Cs8lRRKJqB9HjP%yhA^}=cJ_})LvU471MIJD`v$@ z!Z>W#*YU=C?F_#^OCFpm>MHRZRrizpTIV?mlI$R<6N`=SAfURoR3aIp;iRY&#r$sT zI<|VzdA#uhfIl8&xy!j${B*3Dz#e-nNr*#(*kWnoR49Ro0X=A`;)EPcPmMUVIBF7- zKBP0cLcOX{AlQu!Y@S0j(JQmIhP%eCjyIBOrk^%E9t^aM&F2VykQ2X!q_2L=$?l(D zS*7Tu)NrRSa*e^gkid~x;ALHO`A$pM)6`ShADxEO5%=QAbMo1vc7V9n#gkQbYu?%& z!O-S&2l{I`f^%fbP2eLA8fd^f0pcZ@dT4|)NMcNd7?tLkivE*nF}{e2-BCUTcbxlU z%zEieoYi6F6jFEPnt6nRy|V{s6r?F?&b6~$W=#Fon$h?OYGVB3?dY7KiSvNDbRayX z61j9_djXE9_Rt%F!?HtZEpdXf6PH)-IQh&QW*5l7CPXKTTr2pFdx&C>6Yw(URs|ng zJpDeta8K-ee@8>kt9|P7#6nMG|8Ewk6Hd=r*}o{BU#ivrcLV|5|JeSD+d3Gz{-^(q zOWwCf75YBb9~4$LtxOFI0BE+TX|5DM8OX(P5HCX9f!P_~hMR54>$y+aoZC+4bA-89?FrUli+Gp6GOE56#1MP@|hGN!aYKW$x)?HPSFESPkDSKZ1 zUWfff;iRsuQe1XY8K(O}ie!d=lXfZi z0n8rW-PPuKEbH#JV#Crbg!tqx4#CG!O|**G@qfsD87CY|X>YrTSaP{E=T5Hl3Awl^ zz;Ux)E)!~Ae1__y!%;?`Cn%|_k|8%wT5Yr^P6(Fb-#60Ccg4kC0lpI;C4gd`Y4@ll z3r#)^ErEKNYP5dwi}Jhj1I~U?j_=E040iRvZw0xbT4dykMr1^Q@Bw}6TK5Qf@-}rL z0kw+qj>%Y&I7U)gRz-)Umw5^-2L6yr~nuq`5{Wr>n9 z3H9$E6qQFN)mas%M6p!V(xnxZQw1M|)QNk%N^}d>NjMBBYIonO%~H!Nk0`3JwCZ(x z-*NwSn#hPK8#4?qC%93eajIAQU?^+Dpn zwGJQ>!O445UzC%q>?XKWtWPRZI#r6S?Y^jZ94soVi9XaEdT*Ltn$?Rqrb1G+OrZ8c2rTi?S*ZITb3w?aM`w zywWU?G^=zgvhdL9&M8$+HMg_-!aDC`KkUfY!usJXX@LQ1cz=whE0iS_C1JDBz0}=z{0~7-l0~Q141CR%B*+yIW z^>g7do!Tbe>$Xg~wd*ly;l8*}z+78Jz8=qR;qFYZDCsiIm~3VF7 z&o}{6lky}t!tutTe`&kBvf7LuJMVmCrDpkcDY6M~7N2o34(+d_dF<9OP^!zSSIoB=)aLBL?{Ak(?a-Oam%+ zN-C1%aI02QPEv+hi4(G^K_T9rj$-*OA)_dsDBkfZxjM<|cR}C37N2TMeZvadFDG}J z`-v8{Rrtj>(!Is_(mZ0l(tgEx(tnEw#a8uzVyB?5#lP)46ugjj>U%Kv%6PvaQ5t~V zs_#MHD(xZNs_}y$Q5(P-6#HWLD7-m)_TLM=2Hv9s%ceAjGN=q74eET^d==ktUSUsd z4r$WrL+X|JAq)V%e7tsoInLL$#Os7yIzvPf?yHhjo4^C@2#sd3PvxcPK=0sQluU-1m|1=kGl& zGp^!L<_NQl;!t%5?@Pres_iqms)XZcq*WPdn&}f0ggLndH3iw4s>w#FIn@Q)y1CgJ z$yu2ywMgnC6NDhjscG4|Lt_&I69Xe4V6n7<57?T5v{34VlOqFAUmXkd zH_5RA{*bRvEY~x(!q#+8+5pcQX*g;?@tAi7J7~1sV#II1 z-zP7Z8vDMFlbBu)Dt8{{9A5!Uai>Hsb8q{%=e8ff{q{Z32DE;-BG5@`S3_Z6_&YAN z5z}u}rDmBzywt zTzxco$X3=Lb)4wfsyD+q&x1fch6?NR{yNd%ud;3DUC3Swd+M9IO8ri>SGaWVKkVqL z+8!Dq(uh$YSY^(qW$@fjYFJ~=poE5Jp(-NTaoC)^sQP(QDl}a|$#~_-x_DaJ3wG+I zlq6-v(nVLR54)6TlMNki zXZn&Kca6Q?AbaHdTMNb-lsR3l42pJ`)Q3oKm$@B_%!8c!Kug@z1@v=5xe;&r8`^{c zrDYl>8qCehcM2HX^a@w<=EODVTiD6IBg$VC0Ue^YQ;F`Wq;%JxAHBA2*!yPZ&5*s~ zzFNYTi&o`!4~FTqR(>mv@Ho46+37W>PC7B*hi|@`END~=J%h1!n(S=RvT5W56Do;a z#h)9Rw+oDPSWQjtx&oGwlx(RqzaoKZgZjGaKt^{ePf=g)MwKBG+f+$m58dr-CtVxo zv1n7#6batZB;79J&OU~@tXK{7p72{K%iajt=C3&3rIe)+SM6rrLD;?o8d!o+g2q2V z!Sp|kc&J~A{71TQoG4|UYLz`i-Cf(N$yO?@99}t@&C%bn>S;FO^ibVTG9#G9mz*bi zd74T}SU-iACtst23yv&c;}6bh!65qw7|`EgH8yKKG%|uYfHv3;)R}0a4;?+R7aLV9 zxiPZ$sFe(9ODWpbJOt;t+O?G7EuOj0St>t~g9z4a_m$Xh%59W$otf-Zo^TvwtaZF9q_s3mNu;?q z<$JbEjH@tl)d)HYmD-cvWpPzA%&13ZlQ2em4d>l0i26}hmutGvx~k1!n)q&YIgVY$ zN~DJ4u+&|xU+yfFQ5L~#L-r5sAa4)!U~;D1dL)nOV73Jg7E%~@Q(EneocSYTFnmI- zhnDcu(1d2;P!=)!YOy{exs#*|)uI>eOjax<*rKJF7@T`$``^B#WcGw>qT7N_eC z*-?8?JV4P99_fWKj#Yngu(jB9?Y^bF$ zy~JxC_%iE?s?%PXqR2f+Bc+ZDM9!d-sV>Ri-i&zK!f;^fGExao63iM&byeZTGhhw# z+TGDJpyw_^&Y?m9l^Hql$-R(%Qk~2qjMW8H>;U$FUNEr%&-`H zMeI6Cv9cPmoI(Zi$eMNQv>}l;+iOG50T!Gk*;btTOsX5+TiM0ixH1rFZnH}%<6Y1u zevKlvZ^~LIqN-OEg2DEkco#d+u0Z;t1>AsJLvP1MmjOe>})%}&e(szsyR4F zpU(=GA!+3f)3`#j>m1)GrauvycxNN{dIiw}@>v5pNT`9yo)|#PLHT%$AgsF-Ev)JOpZk0^vYf-x>?{ z>1z+$5kXgqQLnwK$GLy2B>*CY$@*X-oCLywAn_0F%bY`!h1gKqKu#`>6WZ~J1q4qX z6c`xjj{0!d2zY*MK4yN|z)*d>Qe*BLp7{m<@lSR;eGim+*kzqEuiE~wg~c}94ML(d ze{ftfUD3=OIaGTi7mYyIpxGeY%7?o&#Q>DF5xXQtpK}IcC;+_Da7VvgWbl~z-INlT zUxp$@M-Ns{Psm&2d zy{R~3PZ*Zqa~nbQesc9`%(qv0V1%;>^+|i=(kqGS8pANdqxc#4Vi39dDbyS56y7xI z5wV&}Gmw&K>RWmj7+ayb-;YAb{m$^}>EDI;gUlq*y6w^jIZkI(-$^pb|z zK?~?+xt4NiX1$hjZ_f-oU%~nmp)fn&jNkN$XUn(^&d#R!Ql~X0UZpSfPRn3?TQlkp zXP35*PHo<}t?Jg_ppf2P#jWg7qd9zDG5XZ9w|RYe_KDzb?E6%p`ezQiU+uFx$3^`6 z)i{{-N!j7ifEzhZ1j0 zNThx{B5d!Wj{Zx-{bv=fA90Gl+UFLbY$>2dAOzEp2M@#$b~-nEYRJ-@16l6k50 zT2j5V?#uY40$0ikVcWUIyEt`fR;k;yZ;B{Z8wuQUxiV_l6(*6&palG!M>w8iu_LE4FvI(Z14Ge}fW zayqO876d>P1RDAUfi8+Af|{xZC|mM3$f3JS**WAw&{Umf_6B~%#q@7sG#HTDjmavQ z*6|RicET>!>#NvnjChf(8Y^VRMUoGXu~}D=#2a|Aas^~3Bthwf6F>Iz1VviPh_NEc z)@1ErqHWtm(aV8Pqmz8H^8+<7qi9;3^UT;@IwnQwg0?1fuS~1&4nMn+BbIQtje~wG za;AQpG)H`MXi;h>$C1fYeU$VYYMM^{j26^Jlu)6J-Hp3+;)wxE5_D;B;vW$G=}9B1 zk19zT-1sepA;bnAgS&G`AI#ET#Me&`({eplku)`P)YVXG{zIh;PgqSHH{?jLNV1^~ zP{xm?gHwsg^k7qr5Cpszq$M@+SxVAG3xOrgD~Q6y>eR@MQ*m9`Ca z83~Sh3ToJJ>hH*}PQeWZL@BZoOHjms_#HS{a~W^ZR}f4^+=coGk()bf3u}BiKD!2& z427VE%OE~$&xU1W6}eJvcoK$kaBXWs#!mnunu&I%c`o< z4T%l8!q9}cg5qp|+O?eo z;daPwLU90D5*C=1h!TWr>MQW%D>L0CuBRZ+g|R!$8jP0^Zx(-8d1EJEIZ7=1mWCy2%j72CGnuwvV`Z6_!D|Gw7#tFzl_=Vq;oHE+jU zV~*MT)7AOKgZ(^yXz)9D8$S=9J2ydEuql}vPfaUf_!lfnafc=ui=nugVRRW_`gp-h z^RCxsx0!2I5^`+G{Oec@<`X1>e;Tgm4$Z*NjmAgAN~?&c*u z_&w>coW^_Y$(=fOES~Wm{*?#E+>_(?4wq2w2>Tk-#Xj$T>LvUkq?20#4eN}^4eMOj z1}YhtN2iL8amwV(DYL1A7}6%BV^LZ$zwjGgVTquLVczuTR(|!uf^$fl?uLFT_JS6;^MGleI>aNE9P8A3Q4 z12q)AY;JCApPZSbOA5~N265vLSe|xZiLG{rotS<-(exD_TeyX>@k_Qd2N5++!DQRZ zpQql5TqWp7eXCYfPv4n8I( zcEO*=*eGlaPUj~5r*dLSBcs_!z>{4JsaAvR^72^f%O<5pTCFnBmY*Kufn3kAR84J2VC}xnsIh_`pO^fDv5IIIhU5N$ zK$KdV96sYMkqC1kF$bsLGDFg&aIUcUL^CpN*(e&KMhz4BmavJjYG@N)jcal!=8_HC zB_4Sxc1{jtYUHvhtEOdcJlGXtT}3i3@Scc)u?cp8G1P)zL6Eypz5rYX>Su4(aAwBg z{oKb4vQSt`NhQ&o@u{AYlyH3nnY}<{;L? z{@oMu*9a7(x^9XJl7^mq3Beee(v=Pu%Dkni%z?%hg@+G!#qh7Kx5PATXW!_D+eE#D zqL3xwoAP8eck>x3DRt)+0wifl90mXWN;AYYw!rpj$yFKiD#(7TKyvcJSyui)DW)+4 z>WnxCN^1|lk$TNv^XUTCG5UX1Qq-7mGl3&gl?!060D1vai)-j@M z1g<~LO{fPZ{E*CHe^mT3HUGwhq#=w6V3pqvGFs|jRf&cPs$8x}ZJc^JX|~yMH=VMC zGvTIBgn1jqr5NzL4<>>Smal@bE;x%9;!!cH9n^6lR>ebTg>(Gflq8c;6SK{naI4j< zj|{MG4_)CQ3rkCT{GkGVvIyR5(=&i1FLl}m_znTz`Bh~TZcA17VZ4=AImyymk(byF zA+SNZ;Oy|L19nD&2qB^${WrS{GK-|EDm(Vmpgc57?}YYY*EVHfJ*ta>TyEY^vwFAP z{%{FMsmC|nHBzzwX+gGn{iCpqQ##rcpM-XlRG|T$#QLvHHwMNM(p9uN`Q_VrPv+yl z_arF_5$b&|^5KpRAl)z%Cd6atKT#q9o)l9FC{&NrRwP*lF75D!TKxYn$4 zUsl_SRK;@?ntpKMr_MX7Iy!nB5jRkAfq;_0pQHX*wF)E5fH$mO^)kxQx#hPSf?ZfX z(lXzot|H?jvcJNvVTvp`qgP(o7gyk>xoG+?1%(C#%0nMjre zU|~A0^A^LJBNw22*fYhdMFA_tG<_Wu*!B3?Y;n+-@T-KCzwK@F5iG!u_z@%^bFeH^CawC|sjM?n+b9NyCUqr1<_#UQ(V& z>keM+zAI`G>4dsXA&KyM`+HPI1R^n zY*1cLAm+uIE{bXRB#p7s0TgH~yXZ9ffS}Z)ZLPE9rEkCL|H-VA@79*u(O+Iowfk7) z=xDVShB%=BMPR3GmOv?)6K=wi@L*ZQh!~!ZrltL>&Qa0Y)XtfjWyIIN5>opHvVZ9B z5*U3Fjqa4w@U)F+k_NBx<8~M=F%aiYKd69FvWM303Jsx+uM>4m{p)&@kY+0f-yDW4 zynRByy(db*G$vjy-t>N_SF_6~6-9DV6lCxSkn-&wT(8%|5)G&8Y=~#mU~)liG)L5#VXy3Cs1y%|mH>F0QtJQk^thDV(Js}1~7 zV>hSYOZ;R0MgK9Q!>@D-g+~Va6*(npd@>ts&RHF^wlgW$2d5>ShUS;CkEJMu^0HTKT#oMap)I+9Hs%IMTjg(5#}&SOz~nfPE^J27_|9F zT=D zj!K~85r#7o!@OdjhARMXs>$L5j{AcIE|)pzMDlha*>!pvo1#YhEZ4xjz>Y}W^Jwkd zwX{smrabbajcoyz>f?vn@zl+M)3kqvMJN5xj9}jfUXB@ew3`}$@4=m`l)`u41?%7m zrS&SoTP5)!=iHLxb8yEF>J#qCy?OQ+j_Q$nwd{}i_sQA1ByX16yu2doR;JCTQ-?yY zab)5m>*y7yor@Yeb7^GWX{CNjaeGzH$W2Wf4z!|6btizPb>=$r{2E-icV2+Rl z#&Lk<@2CaVYM(je%MRXLS-hztGp?MK1zXcJj%ATlL?2MDfQk$H=t@XaKz$a`2^Lqf zWk$#YOYX_DyhvSO2bL>hGoLGSuIL_-c4$P~9~p>54q%mAt>e%bYRE_4_V|e>^T3mg z<;KHWpOfzXvuei#WtX7pfTC&-Blv}UzSm4Kh`xkkONRW$2IWX6X&b#PTCez_I8smK zgK!SZrA`h{-*b6_b06$dPz}EE1vYa7jW6iU-q%5qT7Fl%@-&y%|E~75 zc&;@S9Kd%VP_D`o2Ob}qe66Vcg98@nn9M{LF50_s{ap($it`YJfhus5Rx+fJBtAQs z6Eqd=9pT^Gk1Y|9Cxxy_;U|T($-c*FK`wNcS%lkTFM?vmP{{Wwn&`>v7v7+gUVAY) zxtLX1xxF}E7TF`jEQW^UULsJ&rqI`d_6(?=sxWaP5(!W%KNL7G@Z{)*7#VQcDq8yU zT#JLJ5<@xPyP&Lq=WAq+$+F_!F`7md8O-5=Tr@V%f;>JjbKGx@j4Cb(U09Pl*;yT$ z)zFGUGdRtnIdfAPTx+9iX8(_psTILc+hRgKa;`orZ#i^62Y`KQ)?R-D{F;oe*Wh@6 z8lD;KkcO}wuqkp?Xo%LS6KB=o?VJ4%eh7K*I(?t!Fql|T_iG5vvd&B<4ilF}nFG&A zF|#QPZc9{n7NmO&9B3MNG=IS|WZE8hNF`N+@~Xpau{ruqHDtu%TcoDjl7;q+fEVK? z)Q??1wc4lhA+qDbr9{Ca-8cRayvS87ok+l4W?B@dvA;z6gY-$k243dI+oxqJOK(ju z5)o~j;Xq78CqZ{W`wQ18DF`8ngm2?$Q_vaf#W}}{nzl0#EkdkA%R&R3mc0t(81>hm z?Pa+kr)jD1?3ULJqJ25d=pQcDpZ2&;UO$&J<9vxca8VE}f^|P|RV;R2HZGjv_{q7I zgt10;LmlRhE^~8hxm1!?leX3ct=N=rT%c@Wxr*RDADr0R%Ic*Hbyf9M-)b9%#4%W_z}r zp@Vbo9Lnef+PV_Vh_;6_11iEPMEyGc(=McNSE`Nv)xYOioj`2z+D|k+Qmcg{0KBc6 zVgKBa-L{}E+2_`rpq1iWKzq4?_!|=-CwQR#p6)~&LvtrSd;xgdsEvO??g?6E*t){- z4lB&Lx1?gPT|8hCuJ(tH6@60hj$%)i-bs0*b$AB!=IrJLJj9}lbx!p?)Ntjd%8Kqg zG-bP$1wCeXTAsE+;Y&WXi3DMg+FFyw5Ps-MK5Pz}Fv0y?0mCd#6P$syB?e~NJNu;! zqQ=d`+AeCtxgBaaI;1Be{^X@5qF4yprb09bxLxzgD)%QRzUHD(ui6hpG|qyk9YcsA z{3#Ev6OPk{i56QDAXmC&64D@KOl!J*270isLWT8sRr4jVK&*bsV-jWuA3f`S8p|SY z7S!Ln!D2iOl?9LMjDqEOQM-|(cX^7G^*-HAHX}JPg!9-3eX#~~dEet`2pmN$(BwWQ zdAl{ms*#>rqG5UY;uVVIUV0N5PpLls{{CTS3d+38bE=&@oj)}c@-W6X(~ z>x~NaNlcf*PZ;eDi#~cb%)Ke#b4`{NZsdUJ5Jr81i<82BLg(=IjY4)@UDj!(Df;;Yi}-q~l$&`=cA; znpOnXH+D>2T@M{*hiJBsXOpmwD8>!zTSDxsO@g`kY~1xn>yrkRoUpNSOs)%mkRyP`CJLn#$Dl}<5=@g>*cxp2{Y&Dngluk~AVC{JQJ}bhR;jwl zj6XF{Qcn%nNe2yg7_Ca5ZbcnyeSxFHP4!%Hve96+Nl^G5nGNM9a~W2xttXi}Ug=oQn4)Og8y;s=nXd(qHCE zCoEGNzbg52qXAMzqKwL=$>>vB{TyV8{B*cv60%k6UN*q!v_Jj7kVz zBl81T-JpIh+&?bse_l@hFkkX9P;4Jk+UV42Ok-P^Pby=3D|&Tuohz13x~`~RwO*p4 zS$)z7xMFEp$7n2kl^{aOCo#>kUcl$ZNtQq(IO-66Gk2Wf0 zAJzoClg6q>=3zC2`r7oo`d@(8g57hJPUTw^?mhU=uLAvhkii_#0zD|Wvc7u0 zT8IrrW>mY*zSZ>uv4Zw<26KN@q$nIb5mej8ig%(%1-Bkj@p^6Pcu-Zvw7 z3=w_VN~NzCvH&eCeq8G+rSs_NN~L!sv4D7iSXWNw z0!a>kkSuO=1DuWbtb9j zRXe0MhAS56U;aE0;g|4j?=6^l1-vH6&pUAD!tQ!h#bGzq;mnV=N>U%0+CbGTpxtm) zW%sRW+RkWl^0yR@U7Xi=^eMG(mQC6p>tmzNaH-+nZ)3F0r%{?dT)sIPTXQ^94x(> z8u0b@a7Ht-65S&25V{sQqwSm~4>K}Zy&4=@w|1>}w6aoeZ6>W=T#mB5Lhm4LUHJxF z$ATvz1FGYHs7W6LoK~Q{YJ`;=a-bGemkO%d!@=%}YD;r={66ukJgwD4r9UK-G$D}7uNrtAPe#T&$PZ@R!iV$z-;4En(Ihv2Wr>xmm zElsoy3Rb_XE3|62pghI}k77So;mejMXxZbSIzU#uJK&%bGf|y_-M81423rqX9XUG( zhoq`4;5kxob3$Su&p!>)Nx+HdmLQRyEVS18!$`vNB zam5F7P7v9ptL_bi`Q*NMmZ}^*v|HTkV*Pfst&Qs@Uyu|{nuFCnN}M3C?PL)@il$sG z@sfAfk5;K3n|~_2B74An;Zh{`Y>WR@m9so$u_Je!*KVFD#U0PN?=nP$e5b;u*j@6n zqQD*R06!c8F+S(?Sr)u5dH2*4H0e87vNq)&I$Ximg?DD)!=(I*I%R^!^OPZ3V<5P~ z)=ZVieC=Ai@&?@Jm59o^k0&?;o*<*>E?a!eEp5rnc8g0Z1(m)fHrNv z55X{kA3xAV|C_Rb=)Wi%q%E8r|5skA4ymtvfcxbwo1Q`zt2Cs1qk#s;&9HeH8Miyun{C{m1bYRxE#~D1k9Zr!lm{4 zY&|8g*d#{qZob8QJ$?Cny?w>xbUab`LHG0Et8JUYUd>yx!vgEYrEyZv%2}> zF7AQodMU^~K6AXp;avPJ(AwV&?L1DVZW$f2!LofK^vn2ohTuCL8UlpkyYBAY-ax|U zB#pH!8sPIC^l5u(%Go8xemJ~hj@&gk+;ajS-C^~vcW~Cv2Y$Zr9S`W-eu&~<4)WeM zf9OVyKBc0EdT~T~c5>|Yr2ul!#aVH_8Q1v9J7c#usQ6tGHSRagu<*~<1YLwD-DNwi z@Q9L#J;K>W@+XS4N93 z*cHYnBa6B*K0cr(cA;d(+y*N%H&$q?6f+7l6kcmj?v7skGYBaM87y) zXMs=(q_x9$du47)2KQvZi&Ad1h$307)x&^VMr+yYmh!{31m*_OzjF6zu0)9i&8Pck zx0QbxiV7p>OqK(8SQr0kG8+^{kyz*mE7h6Fp;OE<&mPicpexx}jpz}fL&yO=WjCcB zk^c%r1Euv{Fnii`ARSw`&*^T_Q`L1$b>mB%=D=zbvMK*+{OOxYeNiEM1BU1^v@^;` zJ>8J$@g#o7nLH%3*kq}^C_&1I!!-8o&PBoxb|wst29XlOcF*5Xzo)w-SpZHXs3>1} ziSWB;>@nNiRNcJJzDZ#*w9DmtPq%fj^h-0*uw0*h;?D1gzDVXZ=`3vNWil?tLZ|w* zXV1)^`8$lbz5`nrFI;#-$XuT>8#F*&3#aHn=igdNJDh;d5*LIsvV2&@hZhHzsiy`-qrXy(0Dk(xV%+4h}u zs$S+4I_7RFKb*QP$(A!&jTck?76+!I>gvox;=@)$cTZx`s{ z&C?ByaOo->=mRn2*(>qa$EQ_f{|4yj+cx=S{C+?~4TY93V5-Ndv#eybHu4_4NexjT zB%r6af|VI%;LGp2X=g7zD%xX^S?N#R@8`U)TLgTjusxEUrJXRX6a>IJ7lyEHv% z77AE9S82DC%D8TKV168L&X>VD2kBy9CH&VeO)Nl)tE_Is+XPHjTcc-(it$>JoOb}P zr0CTwya2N~#s^P7b(M#XAGg?|p*_O5qxir*eA!bI_#DT|GmdF@ww1)ju0^S=7W=Rw z6LFP#+O-~(odEmUDA?@&9py*qsi}!a`%a+KZH@b1`0ZdDqE*|G%=r=juc^?6sZB;rj zN5<1HCa}_8so$ORJM`@i*Te7bftQc6mD^YHf zOR&BW;~}3f+sAr(wF)htdx%*ybf%B84_CpdKyAXSpp-36OGmA&Y2#lLx1k^0_mBur zU*pE%@1r!*=UMv0B2U!@RvNn+cR&Ny;2~m0ank2U9rCr@OM!%YbyXza3Vn3v1%W>eRYK0cU>+K(w)f zRDXEt_3-X0$%+HuvJ4Ei*A;1q3Pt?~yrOnHl7%6n4JAbr)Itk&F446YZq}OvNij21 z!)7qqh(@j00S{35^y%44DGEc-r3c5qVJOpfC5S|IPZBl{bVEF2B>J>H!RliqSlN|~ zn9UOoNa?RAb7NY$N7s3juq$afUX>kGuASuH0?pytK$6TAryU`1z3kRPLsuj7=~c1i zKskD2i8|2VKsA`M83G?8k&QX8q{*@jeT()E|x?vTh^UTGRbbjhYHEDN@hb-X&_|4@*}ok%Rw8 z!Q^xY2DDK6sqxd14wCqf)pD0`at-sp1;=!Fgw8`4i@1rWsI6Pr~Z?Z5(f%d&}w0P?T5)LEB3wSynJw+$~DW@wypODq0aBG(Lx7rhYgA~#{9Xn4=h z{zO?@!D5VwM|vYXopF?(s%}j%!gU?TnmC=mYgBJ(ht94&+9F}1ZLYILBBe;|^y%Eu zF0eM;kTCfcwlcCo_?I`&E%|~quD?yoeOfFXO-?`bA2~(;RnOu*+dr|biyYeOq91&% z{mtpx`}&Wu=Ti_b9_`zjT>4+F$yEQP%apY<6ftlzAo55iAYGhA|cusb-6+Gz?EFG)zyb#;NeCG>rIV!%Wyz$!XwFc+wb? zDUX$Hpuqim97vCqrw!Y>gUsx<5+u_~(~>OvEZZwL;DxES<%4JT9M^;jS16BRI;nUc z^o!83VxVP_0voCM`pas6O9ks%<6TjLC|$GGrpE`jt)^+6F120q1QL34 zgX&(=gIBP3<)5bVCNF(eDX|1?*h1@*7K=>-h|oQM2nlcc)JZlW4+vUNx)M&UWln zH0y_tr%kQLQrVA*%lmd&*KbJSL#=20+=xPn~P=rYwd# zb%t>)!C11cP~-5=p$6I?Gz}&iX&Q}WlW_?NZEbX&BGZaJ&Lk$Cd1Z9c)}fG2W62@^Pk@tqW4hoX8Xs#bfQ-c=xu`Y#3neu(Xeund;$ zNk3A~L$J2%HyBD!sQg!}kxT6}5ugEq0^lx@2=EM&(;(~3dIBDwS36Zig0G;&9KE11 zCl2mTZsd(ATZZ7Y9)UIvd_Dr;{JY%mL031-ZEj-Z2#~HFpvnN`tH{1We)#pF`@!e` zBa9a)5ybcZwsp6DW4Hd_9eWc0rLh06V^6`_!2SO^_DC2N>|9M8RP5}mRlgIC3>>Zg zr|gSV*OZV25qJ}$X{^<319E@;hQZ3OMeGPH1w~-dCMhjSh8JcE37)8KLZ|WVqk7@eLM-^q<2tUsuSO7|jU zlUr}?C!6sUKPZNz_9GSdU;Glba*4JB^zFLL48K%cphGGh)uexm>>0EZtxs#(&2L(I zC(^U&&lvWSZx^blhlIR$JJ>F6CH2YJ$iMN zKWk*fOdMb)A}6tbam9#^kF9H&O`F*y#MN<#lJ@V%FObt+krz3z?2qS9eEcg~mQp%Z zUH@k~?I5>(IM7Hb>b#VXlYpsgtL(Drz%%M5_go<-IADXj*IH13OYYp5t2zYPcycUI z6Vc9fX&@y2JCUl`NoKDr26MdJEq9Nw9>$v4&Q_%Cbxlk>QN?m$3{D34NIA#tclNcdL`a@K-vZPCBxF|)sXRLp($mVt2_tnQ7)B+xy=h#Q*oW`jP$Xdno+aHNY{(db| zoRR2{`ENLNfX#VMe7swlmeALbe;t%&Mk;DdLbfY(VpE_;AKfJh?n-g#EF$Iq+G>Ou zqeO!=H697kF!F=(X86HxI);+8#RRqw9kWb6ANo{399}~(Gt01q~ZvP($e`NVS7X5dTHviWm z<@o>k2wg3234SS0+W!qmYNB9t;(V<1k68`hu8QAMYby z&nQ^Vq{>KJ3uKa@jH)yjT8 z!Px*~ls{CO2GChi5kw7J<_UYZds@eZ{zFZ$1I!W!zjndI=@Y z)Tnr_4#j_W8%Qxm^Zjg4m_l3^~O{ zhZzH0vnkgl@IUv8mumKDhV4=u#z?=&*xr>j95-mX%TV%A6-rvow-SgBsL>+{ZYu*O@g5f1rB;Cf# z=(Ok}(}PCU2<9k!wHKE^$6jb)5}_laLwVV!qywWv0*hk$@GbVPdpSvl-%r=2m1rU0 z4Y)@ViVWRu!)<{E1}T=W6=%m7e^P;iz2zvQXi#QGZCV(O4H)j|^yCycX%LF%<2qScjIn>}md^@opc0s_!k zJAzVBJMwo_JBoLlaptZ={%N#{o9QJYKl=S+KJ-hcN(!v?POPn8#f~h6b3|03M}f85 zvB`Uk330v24tbj4c1>~eFr+fWM=8qN0m+=dCe$UkUv~?46xRVm%~ui!Lw`#MY8Fkw zK=&O57_&zM?8sq#(qO3V8WZ}2HfiW&S6rxU7*xoNv>ZqFH0_e6%&ix|-gDE8W)i-V zx=W>P@`BoDQ`zq1bT@&KfT!JF!}jInYk+{vt!`b}*EhI)EkT zQP{;%v8&yEzo@Y#j`z!1 z*4E_K2ygZBV!p*|Ou%$x%g-oiQgN@*XQPE4?I2tKZo=O=#w;~cI9lS_D)5=rNnnr4 z8Iol-r@2V>3W}S*eak2}pU6X>VboM@GWtD+cC7pFR?^-Bj#`Y;=O;Be_ap%TZUPZr z)bbY|-`)83q2CcwGq@$4fv8^#t*CW`8wl&qD;Qf!LmiF9AtrikcQfJ$hF0&qp4qTi zSg+ZC*hF};c7s?KlSp(B<^LhWyO|O*kJ6E?q`8!pfz6^J$82K?AO)4P$|;|A<~7W8hgeU7dM za;~B2QeL*+i<{;Jq}_Zm)%Uv++sa~}%ueXAsO~t%@biX_B^zfEY*0P`ie z>1TaLg5ODUpn=;$lbJEIRtY(U%1YI_!Ci42p``o)Q{OAh0_M=~i`LssRJ%vLf3+b) zRR!c+3Nkm<(c}IR)j7^zSeDsH&Bg2TjJxr$4_e&isOo`iOZmVsK7Ydi<`igz<{bZg z7do>~Tk@Urh`ADsDbLv*f0`q}&8P5e_m7zodvuT6-20F`%&A>eXQAOPi)}v#eUijq z1T4LWfnE-HuTyMogI5lG0A?6j2#Dl?cB8mUQ{8rm&(Kv+iyz@b_)6CT*HGAQsFh~% z0pO_C3bpZ+VUimRiL&qQ0c6iq6cf}Q)nO;K3Ls(3s-dYc(m`USOW9-U6e|_B23J&B zAQ>xll4w?eGM|1eh&-XcM;*=4hent~xH~%w?r@Gz&u=0$gvJh;`?>BK219#pD{lxj zvsw9IMl^`k`j-1!>7pbWC;reL1i^1b^zP(6p+Y>Z)9}&bwNgKl(mj&s;A%(ngr#6*KUGW5AqJ2Dg=;zAHN$Ju}qFJYpO3CCs6@wo##mOvwlm@B3Y0JE2W+X@}K3r)up zvd1N7p1NijJg!JRZ4_J?FTt{DG#J8yQMFTxY6F*6mx?;aP*G4}cQ<)hJ$acOoyCjQ zh&G!}yz^%rX6S8Pp?8?gwNGu`Y`~D(>ri5PX%)L6Ult2WVx|@_x?}1? zjsu^bhoKQMm(G$ocNq)wM#GGSugzy2?l*BLy(axR>jqekxRjCBU@30&js;HLlkWD! z)wHxU1#8n~NWYXcMf5}n;8P$IRLKT%i$Y7tULDBT6MJUaKL2mA*pWm9LK#HuCJDt<3I8`Vo$U;~k ze$M(HZmuE|2~JFsEPu~0n|yv2lku4c=O}_%y(i7pHNI|e_)-;zF#^xYOZBT7K!Uf< zONDmg7T`H|RU*Cs3p>U-?{VwYR1{LwZ*LL^6RklS4O{4Tr>ZoU{8yVU;ba18MLV-4 z-77*?^Fd0nlg@X6GtxkFNV>7b_HtAILx_WU6MZY~(79V8Gd zK%T$zA3J?!O&FH3TCfV3dm?>(Vzv{v*?;PQgr~`W%FpF7HJEN#Qy9-&*$1*L0H`VR zKM5(=TwMm+8PCc7RkwL|k?A(|9&&0`^{;SUR@+3@(*RR7Y45hh`HC1t{_$j^ZBMsN z0dg*<4*l)7Xa5*{tY<_Y>uvJqGJjqSrfcSR?Y>}lO!bY_y%j?L=U{)mT~Uzk-Wuok z!GCr)+_>HB*WmAp!UJKbaG-r4E1(JWC<%u;<*(kuF!0Z9E*Ew0PG9oBKcl)ao~b{J z_pW|_`lmR(C+3=Hw2=4isN}t+gs|3dhL$c_+3(M4Yd$ORl zgs_gsCrsE$ZgU0X#W^9MIWBT#t#pngUC}+tba_NMd(E?bUkotLVQPUpTQ}gd&5u%@ zlaX2-28^VW-$RhUJb$KTHMRDk&<20IGjQTQr-{U%)?()8bCfo*;VxzWR2fqi+*-i1 z5M!*RhQW*F_f&w+ILN;RrS=!}>wKr3rO}b={k3*WkSJHQiHZ*SfB|qMgat1PFUicO z{O&5NvPsBb{K`d@2!ePe6GgCLsXAq$DFcj3br^BHbkM*Jw)GP7!K38y2WwI>V(}<< z<^WSyvJAbu2B_5w;$1okY+Tv<61u!b@4+}hi0Q(VH`JVRmbLjf@s*6R*vzovB_g!B zWUzR$)xQYcYk9 zy2_l9oxbv$b1I*<^LWpVGB;W>{*D9@=8$61!@pp?d`k;?~4uJL*y_ZQOl}(*6XnzA9UBI6$Rrd6@sPI&5YF?EQJ%K>2vPCV0#8Yz_wyXx1x{P^V{=CRhxzH!&$Du zrij3Nv}%9&{-f*&53{r+P34-GQlM3+pbm>wuG*C8B5GQd{5D#8K+jOBQ71kpl`hZ` z9p#Jh|6-HtqflAZz2*zZPy9oah+AnHy*Qa6ps$@nWC$i+yU#F!<%=G>#{<4a0F2K}AqWRtHTg0WE>0n=ONy1bEpR8IfgC zfHyFUySZ9$9aS*sFAY}rD|neK$-$b4%_@9=%dpOWkBn%3{JD|AwS`G(O`q}ViQy;| zqXL=7JHXxxNqx_~Lp9GyjY^kI>I_g4(IvL>k+dP3^jm^HR9E>KU*!a2U!|J(nW-5) zA)3BS<@g2(HM|^zWeu5!tFVAPvGdc2?xx^C)yO~p=SqCI{MEz64?enl;93XZ9O+VkC z>y)n9uJWaDY>!Y`oJ!Bt7z(S>7}72CR6!|1r4;464HF^crE_N}!6F`rQxe{BliS&S z4?@1@rL8mxdI-Hk+Ki=kgg`$a=ZUCrfIvSa_hMCcYpcEU?+Drwt1N*=-+wv)ktsRp zjd>5M8Q^w+uyTjEd*@=+onoS{8tp-Xt=zwI;fc9~{rd&-pRS8?b-o(+n_z~6_TT1* zr2nPs`W{F)+F6_Y?;Jw)Ozk^gW+PD~#Q3*A#UITx*h<2mB~Zzl9R>oCzpcXu46W7- zID%)46IhvRPo?iAU;A{e)lW6Of8du_yvc+Z$Uqp^rQ;tZ+g&wuucftoeSX0EQNE{& z{eq^tG~w7Y<9^Uom@hQzu@{b?|YAjwu=-uy1TeRlqMGaxeZBuhrj_!oxbg9)9 z@0JD3->%OF1X!N{fks%Ub1N*PT~^!~4N$KUtV4IQLwc;#YeIrGxYo3EQz@023kbz$ zb~;s1!fx3BueD0Ikp6k9fNK(YRPA$fU@JnE1+T(^-eK_{#AKZo_v&p;ar3!ks_20t zG>o!F*&TW@C2_|+oiJHcD{Pia`jwbJo7L6OPjx`uo$$kf5eH!P`Zp?!uu8+!WWmWs z5~UtiL9u*}Cz4c;D&)59IcqfItTNKe*jFudn= zV@#%8ayz_WX7DHCxQVT~yJ<03*PZL{xkjK@%JVx3qb^Olh*fPQkak}`N>nS)YX6}r z6s!&Emu~X}TX2q_wo-okGkQlw2Z;Zj|Ld^P|8wEI&e= zcd`3tv|q{QDbM{@tLhxnH5AKnemchm8j7{+n>kLW=?sNzJ`j1_PvSn}?Lc)$YA~Qm z)RoE^hJA~?jF6|};vYtw)snRs8Vos}2&3WcLz2ya+!Gp~O5K9)18FS|=a6y@#{=%# z5VZWlOdJba1a-+@&?8%U?^x@kh_}$Nn^iZ9iWUovuvc;oH1tXZ`@mk`eP7Ei|D*tQ zMA5rhX2#ZtSU|X=9Mt{@$F2XekU1}+J~?r?Jb)(7KH@g!0J>%-(HF$I>YvS(RpHaT zsU-MoG7-xJbZD6!%QXH!d(N;-ZOIQM`ZcPKeUH*^{x5J3tYM1frC4c3{#RikFnsV! z>GY8}va|)wykHC#Ou-r#5Z1@wTUv-bQB7&|ruUp_XxMww>GVFz$+Mzk8E{os-4)_Vhn{Ql5Oi1=R77cMX;?(We_jv~5ZT-rE~c8#GdaG-S1(<69YoG7O(7_|SxT`E)}wZo)Bad&o)ORd6Q= zKBe3gBYcV9v##MOyF{MJcT9Szkv<}??RqPe-r;vxdwu^O*1j^fk{I1G(Bb5U8M-?i zW@ct)W@cvQ+;BR~%*@OT9cJbZGjp<;H}jsft9_&0)z*)aRV9D2rLyaM_VGD|U(G;3 z(UXTp`H7-WE+RG`Q<7+q@GZ9F7xFK8S%KJfG!#W~srX$d6h^TUg$!|nBs^2m!Hg0% zA_@R{=!27K{Kj!)Ps4l(OBJ)SRsQsRVPYD)>Ci}Ons%*|e{@b$AuL>4s^y>MB>jUl zMPbS%CbgBWjhb``;We@}Y3_>{EbN((v$M&#&5r1Nifbi?td-=Zra?Lc&&)4L>RR0& zvnqIt#`M6_VoJlnw!{TUxbc$G-58alB`U#PaR!6KsJfoKc{%$E@g*wGZVM^f*)iiU zH?K;$tcn~e()hXa#Y}VS$c;r7JT;%a-ubC_ienlyH3vHY@|<)jL5jSd#LyzJ$&qv8 z`05zxN7edj>I{2tBv3?mF4ZDBy#Jd8%51=E3X}AP1*I96=0$JQd!=RoWz&H3Yxk0L z6<#Ae`ugDR`!A$1G|I)8uHG29TqzchLip-!d^c02api%X-O!Sh;?QRUe?p9KVfk7$ zWYKV9dHV#yq;O-{&A>+rw(po^dHhrn;UdCRn3Ufzy1nILX-rraoxdvkxBuar9j!JU*U6^SH_914u zkg_#HezM*;i`!Wkk8;6zUqZZDVrbeWX{z*!ZD=j&JR~aPi~d}zCat14X^F9fjz44d zOLYfpxRo4885|&`ui2Jbe;ckwe5^4f%sBkQuc}+V;!sUDd8)yWTwW-z^v5NORWMUO z$y!>#JXhT?Turf2Zzaaw0>N>fd$h5CH6_XLr$x#y2tk|u5i{e8g3!GU57@Rdoyt<> zKW#;!sAb-Ehhh#f=Q}}y!j1(B2k1M4&374-p7QZ<1)->gqETblG_`kiy@jcQTsw_6 zbHHH-<+#e0w!A@=U%*0Dap4T2$|8@*yA4dSS+IN5v`Wpuq^eP1<{8HmnQLFTel)JJ z;WQc6gN!g!dn+k>tFfh4swqcR>c#9L0U?&L5rTfO<;nGL-qpJ@m;>8UCa&%EP=$%sf3QC~4Zyy%=*x<1{Xl0L9l>pr!(Ocl z1vF=cs|#nMOx)SzS#46tDB0dY*gD2LI%nxVZkKqXPkF_s%jE1-3W)bRDBe3C8>(Lf zJ1A^|*KeKaFSkAV*sC|~Wll`w#F-@CH@isw@fl?$9gWgijNuxAGHGMQd>o92VvfBK zBWBEe)j`f~VxNw&u-PPWsr~I*w@{S0;%naTZxdzvKv1h$##XyzEs^tO2JUd9tZ|ZU z=?n_iOG18OUPKyeX4i0RO0-~i;~2pk`{QmKx-%?Vh+_tKs?APh!9IsI zR@|iS+6i|!rRnEN`}cbGEa^KygF}^-X=9908*i$36N%#J8OG#vnncmsTo}CX8riXt zsHqEInK5v6vdc*{FS&X0K*&pRp`fXlGu1vZJ$^-|RLN*#Wzv7~;zBA(R<(n9ZevZc zl0GTS^z{J)?|d83LOh@l_F?1_7hUkO%3|Nq)qqwL%G)xvhxmYW@W&Mc472Tsa0nC1 zF38xY<@r&2oavg(twP<0b|ABAl=w~aG)~cu{F6c%Tnp%Wt46wYBYwC6UC%w;=*23) zsz-siv!S&@gMmN49=N&@TBO1i&JHN~Gk?xc6%-=JD^3YD?P}Lkqd8!J^r;g-mYnNw zyF-;(}?GU0_G% z+!l!KnFFj%EiRpe&rt_u;`BRsLMjbmW1FAD$KZ4H4xR7E$J;qRfS7&*(LmyZ12>CB zjBQ))jrBj{X&49*Mue);`4ahO{3Y|{`q;YN3f;wq|RKn&g z@CcpYKn;7gp?r>xT?8tfOPj*44U7z*Z-Yn3;&MU?=nBSPK!WWW#!#4hqCqZh(uGb`=o95IGz9 z=AuF?H4{OltE7m$cWQ@Was$B;QQfnm7Q!yJgJd`KepEO?zedly6gbBpQ!3WZ&0EVNb6TQC=gm z9<(=T%_e^~q;U-`gCU!z&J}@iO(=t0y*D2daG%?1hQORd?F6RGzMOhQ-psqfsg zab^rPU8PR<4ZrMUF(Z$UsBlgICBj> z5w}3L+gV$0eEx^Jwegu>!24IO%Z~c*@Fdf}$#qrr9qb&56rCK*ZA`^YZEPKk1@#^O zmHH+sNZQWvA$_pWvR*v!n@hT(!6w8(4HQBIp$!n{A(1Bt%EeIFF9#{_?k*3yY{TNU z__5jT@!o+z2MmDrCVmf2*=UhZ6A>Gkbu%?RSi4M5-SX}F1gY^qC7D%|>F-gGA8%!v zG#ng&sGxA1;gfm4g@lDK{c&gAJV>Xyfjkwo58Z6MaHk!X$7;O9Z(Et^PDRTLO;Gn;jh3; zwpv3T;49$=V-;ECn(?%fy8K!_PJ*|TPd}({wU1)3)LF9qBdxigo@OLpXm6*rOGiIy z4=V{tg|nehI`T_*}kU9b&MyO;brDE6126=QoWe zubca8O(^nR@1Wa%A5ItfRY(V((Wn@i^fiD&2W5zIJg#|pY6y88{G~w79CaRxa2z+G zU&*^G8^2T?|mHl_YM{V@}K-r^`a}dA*gZknm$>qyHkAw+N!Hv zL9VTs+2(N^9syD3&XrL={n^Smi#ktc;5%*_b%G zu+9+NhdfPm=Rnoo<2{4EkpWy?z=hLsevhuCa!###9=6gl%4WYmf9nCm*<%Z{0we!B zL?5>Djb?|NTAQF>3x(tchn(ok)r6>OyG%!CuHTuPDtZqxX-JN#CZp$7O?(^N%WV4> zI4ibDVA8oMETjsyn=tutB}d<5;gnsjMXR+UEUno@b0Im5vOhK6RtI@SrVS~hF43#8 z=1MPY|KOS3{W^)D*MhYea8Frt^xmeOrn5co0x7PlEy<20*!0x-d!(fYd@&&=ap6qb z(M(f!e+}E+h?IT|@pZJjwy>d!Vp<7AK?4cLyC5oa^Qn5B)u}Lp1Kp$C-M1MU@-cgF zP39$|X$M@qLwo-{XDNFr%VP`)$Uk`B_fVr@d5r12IPUAp;k}0B2XTfuSm4(Wp731Z z=h-fH;i9FjJA*y(9&4?)L5Gu{!gtiTxw@p(A2jQFV`hb z()F7gE4ASDB%N7zPMQxv@wI&e363wpNj#Wez=^m-n2r zol|N>lQ)lG71F{1aE?5uaB#Bt678~hEp#DWMxceV|9%VJjM_LHL09#+^dL1?->Mtu zr32u7U~7ffyix$4s+`u(kU>yG>N%Thnp3BksJ~+u=M8=~G715n zqQRaC+|LYPcyl7Z+avM@JGl!L$UdG=M^n$lz~r}wx|&5RDqZd}iJSM4AivAZK4M(q z{bN{*l@A?Re-XfNzbw7~`(aJ?e>ANBxtNit{XPHntdu}pn;I=?B$Mg4f{)1BFdG5()a-vtFKXy7;b|n79+KpBu&&mhT%CMBP;rr{>^^(3Vftl9 z?&{`-3;D|uY}7z55v()mbgb~;pbcL2-1&D>13Ft%vq?zR%O)cUx}pDB?r~lG-z8)g z@90*x-^1Tv@BKvBVYR!9oPuVn{>bT->^p-yHo0GB!5cdhKhTl<{0@!hyPvH~!)^Ch zpCii}*JLY+1ib;nz+_j9_Iv!{z9+RNxWUGXLYs7AgK;A{%r5k@B7lyGCVi_b) zPmMpk3>F)34^qZJ?Z;eJQcsww*IT8D5dZ9^)iVa*=7B z$qo)3p&4Pl*A?=jObFci4*Q7!9sLe`ZTG4T?hZe}&D~p&19{9xPs9Ah$C7c10P+Dx z$+G!@e5h!_1M6+R@5DF1{af^+(Oq^MH2i@`1q;L;Bw&A)Lun5lujL_)U;TGUQtfUM zN7L^Y55-LPW)7F&bF!?J(l8kRxz`^PBll9YB@3Yj8X0>RxK?}dYqN&BQ?wJ*^~kH0 zD##M+YktqR(?964JWo$p6Upy0%S_3+m1!yyRV2U$KLhm|SNQvOsStaZ)a;2~UX&ie zGoC50Vx+Fv!xZnb4m4x8@H0Gb^MC)m2_6>v>pF8y2JrfA81BypVajH*JJ{)#4TIE8 zF4mjgy-KjX#bpwoftf|9?jAlV@qtO?60;iI6!B~E2+)QBH#Kwn?PcnS=B$V8?c+u^ z&67YtSK)TKK7?z)z_&Ul_Y!%|gbo;CKWjd|O~y{?ph(BIS-4b`=ZxY=2R6ElLn40| zjh-_8wGtKAY`!2RcY07t8x0I~5STeRQjfi)c3}tl^)#7SBD^r#OP9S$7_KS) z%Bk2h)i-MhL@$spB-!|jB1nO}u7fj~(bUA0soUrC2}bXGyChkD)o%n;NET_XzC{Lt zy)ge`NF2y4`t^*fnphG-ljXZNv%jze<@}aJTCqd|Wqu)Huc>cP@W#y0aYF=xmNa#@ zs&7a)rJF6ZP`2eRE*iN?w>pSig9 z?Q`x^YYVdb^zg+EY(p}j#l0Kt^rJ93E3k^=WHgiYvxLmgBAWdt>*#5%9wTMh(AQ#p zu!#N7x=}5V?%}zbufUpujny!c^fc7?C-~+90ei7bM;&^de=Xv@y{n9 z)w^xx;YD;y1heEao!g%gd3)!bhNKkLvk&vTiuVXqcg0Q$4A<@c|H(dQ} zaKNY){6Emw32lQ5SdN9;C?_A-Q|cX~102J4li}40>!tW=s#~NTsNt&g&|UqcW)mX2 z+W(HhATnesux-h;@Evp7&}q%2rUhvC7$jpCCI*@&2(ORDoVLii!XREDS*oL*YbK%i z{zuXxbkYa{@`VTy|1Bc?cN=v7I=S<&MR0X@y*c3rU&i$)#Z6{Ubr_Y|Y z2kA_~erL44e;F^mH^)0#H^;pWM|GPnK>T2;cp$cSQP=u59np`Q68Nto_@fExEYa$0EI^S9Jn9la%Xv_P(ImgQo5J(A7kNe!ah)1o5-? zfIM7gR}`#h$65(VP32UWxsT+`T7ak}Hc@0 z^N5z;w-S;!7bNMr0JrG6Ng!+Y+^A)Jn-aEnST(NZ&o(KB0K|UTHq2~>&_yQI^Ciqo zwc0A4bgrF%0e5)r}JPtuQ7$r-7 zAju=fzl9p9ihYoc{*HZXF;bQI_%1&P_MUJ;CUu zWRuDbBH44U5v$k-vi$e>H`Y;`gf~nQ@;| z^Rz^t6f4>aAS4j+XEx+)3IZ`_ac2bNH)N@_D<0(V5)z{qiFtl;HltSLu;hW_4y>ar zVl$a>+(hlNun}?G#A{^1P{rL>aqE(G(h7GZsd+(ce038Fcf_rse|_StWAl7Lg$6<5 z5ECi{!~GMu#Of*);0aIk;-Dm(q{9Wt*oEp|3$Y|d_2aBb<9CSAB%1`okrSw5BS~Vg z$X8_g~kbHiOl~0#h}R-r8B-W1 zb|)CUCH52!he*)+B7Z7S5uTXE{f<3jCXXh5W{bm=d}u@K{`E*mv?TceL_;8Ajl)Yk zlSWBG>v5<}V3LmOBo>bRyC<$gva+TyAZ|m_DqQDUAQrPOaRU?ADJc*a#6qrMGeeUU zU(<&~iBKEvUrrboPDck$O+91e&NaJ;VJ%oYuG(Z*YumJ?igCxt#-cf0K#~%1VmMsMLFWh7K$``&Q}wO#GbP4ccU3DcalKLf zqN+A>nFQuSJ{KDN0!rc{+G0?EqZc-9U#^^Xk}Urgp)ZCi4{1hH8^n7qj;^(^#>Gx~ z={1C4uAQkma~Gepwn!Q5w?iX|i?4M#mn2n}(lRd@AWijM$Z6T3%K-rL;MsC6PF?5p zQQ7z=tv;X&;^U;@C`^^o`+Js;zoNpajp zwsDI6q3iOjOqSBy#F=$D^Nrxu5}OM!Utuvg4-0Bo9nLA37%Te#z={o&3THOAyqDS;_ zA&7^@hXHrrz>OQbR{g3uBv%_$8! zvLHiAO~TR#qD59_QRY|egWb=S;m=0M#ep9!wwRwwgq~DUMHVR5*7RpColCM50FpS# z;rV7-O$^DX+-r$SoIO=P^|~U?$zbD|p+91pipm9v2V(huY#SOyR2rr;&YB+s?C_h) z-0>{Js`K14N)U%u72v}k7KW0*ybbC!ast^mn(%BL)nk60u0JB3DKCwNGvGQ)08tWE-0dvo$;&L@e{95g%hV zM)0~O+18Orv3HFi89$*A9Wa8Bt;88-D#`)p`3;}CRQ84;%7uak)w{^80aY^?(#J30 zuVucnMI;33!TQ`GrY+GoX(*#jWD{H5j4CL?(z5z;bBr#0fO?LQ!oq~e1}2jxu!X|L z5^<(q!*rgPRHSc|xOtVOYI(s;VL&0S*aB2{((3;E3L%uoaI3X9wK0c^)ZQ8^-3ErQ z-KL<=pa(Te#xgQdinsy5WM@t0X77izh>F}Nj#q5&6vLCQof^Zv!Fb{v&aR9S=HR?D zY8~#}>?W6W_acxp!%UV%$aJuTQ#u4&nmF~0@u9Vshjs9BkQ^TH5;ZIJkjS=R^odcN zdglG$Kl&l#`+asx^vp2+J?eu;KbwI~k9G`~@s^(CHQ*f_%Egv3ybm1`Me&V4!zP?@ zAQi|qhGrV!C}m&8HihPkc4)|SaR%eO!Z4UUkS%TR--3kbo!R&rH#$P0VMy|t`X0a> z(T%lBsHjCn(`#%IE;(pi)S{IUFt&)M8pfpw?Se}+a+NjU!5ChR+`XNT#wxNX@hJjT^p^?9Ou2oeU3?-c4}zW z6%E@NHEz2lIl4b;*1(*`G>C8HL8^{llk98~-ac|*WB;3cF~SoYew@7>ywt27_NJ(2 z5EAF(6~1-`Eq%a5(JB|#<1l5fw$R9b&^1Q5yR%wf(W>yl3iWWOZU%GQsoS*D1QN;w z-T#y^TvO9aik;e^^Lkx2uzdrKa{#<(ncQW@$eWHEvyH}gzKL0%Ratmf(ymq%cg&fp z#%1dX;W~z#0OPk@{&(gO4!N2U_v|dt2gA66 zi`;ZNV&>T9k)lWy1W)Gq*9(6R4=k7zxyg47=pALfb*OPgi@yAgNi#Bl5y4ydbz${$ zcwXF;VQ_309dDc}g2L1!Wmow+ja;Xg{ROgcv*73|$*uB~$`uxVC~0qXab_6JHo_JD zx{CaRVv}+3br&4+s~=Zl3}NT0qExFmkx~?*v}T5iUSvFdlV!i>tNXAAyO>vk;SGIs z3TnBdK~D%#ZZr)g_v9Piu{upKDZ3gw8`0liaLsAt(||=-mBX@Pj^yTAEt&er$)$uf z2TBctXxS*H}z>Xu7Fq8inSPL^X~p&JrcRMP&v?@0n+o zIGy_ISmG;*dqYK0D`SZ~ZV|B8`Pu@+EG>z$#2R*Jobsy(Q7n6XUNBR?wC*NqpBO53 zO;C(9DP=lUXrILK?aG2UzebJk zM+ac3{t_rdlS?(}9J;1>ihn_o7sP~xMeFImkjASR=2it|7m9^6(gU>_CK_A33JIHH z8uj!T<}wWhVcDU}1;rVQZ&GO!Wm9X@OyTKZYlL>$>v+lPF{XSewI2W4;`TO4}TWcxj0F}<5 z=HHc8)ld+HG{(eUk<2%&ONAuo~@{ za2{oPqi+94|x`%Tq@a0_I*y+1>WMc?(1AvLA!AU9xJ2i7J2SZ;WqM)R0~FJ zu%W)n?h0EnqOMfy(rrr#HmfbO_J+fgblSo50ZZab_|AL7MZRLGLY@Ab?QQyh7B&|8 zjcm&}l6HGRH|oT0lhTs!uOCW|PsGEUoyXOLqdmp00T@5Kis#!c$lg->^LB31s&uM0 zNnR;E5xI{%3G#vnHd|=J!Dgs&4My zM|8P4v7l95I?v3Kx?&1Z_|y9Kk=wKoC^zRw4)JA6JTDXQZ2sC&sftQiHJ|XVhqgO4 zUMN{fR7`|;KF?xs6i-OZs#h&#Wy(ffXl8gb4$Z+*^Lj&^CQ8bFe`eU*D3(09dc*3Zh^+I$>=TyT7 z>{>ZJ^}^2LKFam8n$4bHc$L#2bLujif_xa%3p|!@FCLuH)3>xWl~!+VZgshN2v5O6CKlEO%}$%`HCVKO+ zVsaoQ&f7P%(z4Gm>Lo)k8tyXyM=L0ksfoLc0Es9I#=JtIJ$S1=^RO#6y!W}H^4gI4UF zE7M`7?Y6Bo3kAxwJ0hl>N2=>EaYT$sy?&l0M4fib#SX&>X1T z0}dW!%Nf$Vox#_3mW`L(W>K=Af>TKY(3a%G+IkBtr00 zeNu*frhi{83*Nb;_^_(}-c`yIQS7`*dbXehTc|&7+;E4PG?ThtPDgfhkLd)ne|L75 zDq8v&$7O)clpVfH*?cyL%vTc0H!{+3yS<;Iet7k%(p~?_VB4Oe&3jw~CCI&La6Oq$ zEe&{=So40wTz$LyRbEo4ZF*%pB}^s7{dYF^2iubDR3hAHaF?fNdLgAcQ=-i8$=33- zdu`VPHoMweP`!_F!k0x*KeyOGOis73z+?`$)WBp;x8Oikj+WJ4W`NHA_5wg>Z@Uqo zbGUsEsB*r7gtB$IB7w4Xxx#>2Vs|SKY-V?B4|HX7D-LvJcWVxOWNX>%^~7($U*F#L z2G}^+#RsP2ukY%G1Zv{1A8fw^Y+UU^0uk9-=6baOJV)Dt0G_k$UjUwyZ9@Rh#WpH{ z=XhHYz;nLM2;e#0b_DQTZo>h(j-n+0oA+DFGfz-kmH*|?^#YJLx6<5b6o3T0o{Tz z;FgGdNBz7-KjeR{US5iR&+SQEJhxA@^6$vp)~G%isWaW$?k=rd?oP1H-~sINCfcz> z(;-DjiU5}3pNR``dvkcjeIba2tD?4P$p5TC2NQSRvIe-@7QOZUxb}rutVe;>M_02W zyaUGP@Mge6^yWW%mPk+fM#;zXL5tT^rX^(ObT3BkpUeO>KUiOC`Z^h z3HQ#RAAS{SQQXIVmG+w^`E78c*LZh+ypQ|L*wp*Y4K~{Z+Q6|2K9*5W=eIcx6D6l4 zEOAyhpF+0OG`Ma)l|BnUKl*!Os+I55!~u@NmJk%Iz@{w7F1m4G#hI4;W_%Iu@Pz~P z16@(?DE@4H>pZLuWGMFIDc7%)xCr7QPT%&Eo_1x1->3}Q^h~ldA<%rZJS9sLsH)Iu zhyJ7m^4r0D+ffMZF}4GhNk5f$g{zS7R0()zfR-`rHmH`jUH?;iT=r?RkM|1kXwZ@c zcL6qen{iyi{9KaTg$;Y7dL_`+OU&rz4;r8k%G;X@=^CLkxC?dk%>DQHVn0}}M|yK2 z6}#CC5>;q7B+Qh~l;g8=lRd24}RCvPvf0B2Mc>x>(mk?i%9_ zefVYu>+`@1^D0xIWOEzom2OUTFZaCB#XBe@C-qq{_1VNLTlpJAaqvfM`u6t1GQz23 z(A+>TzMYr~YDhskn-H@-D!ewrhKRfY)*#TiyQ|mb`-Y~y%_by-9qFB4dk)$KP}~l2 zJjgQ_?@TH}vNwWy@pda4Te};U%uOjkT%DSQG0lmS+7A53Jee4CEnfKsU0fy0eb4^SW=p%fyY%7bot=XIpd5@2dSwB-e&3|<46+; zlqMhy=rXlF#mnkugFZ7V^@+-or5fjnMn^DK0l(-etOD6v%mNf|YrertEeN|mH5;M^ z4Y~3mB!LJsc>;96xkq!LlNY}h-RxcQ?=sVx5iBr0`V2Vdt^Het-P83q!B3Z0+BTod zHWkL(a-86(&isUrGb-%MB=@;UGUtTZotq39SEA=uFih(bIaYj{MVqvd)DgT(e8pE` zVgV(^kZ&cUKpG=KC?=HWDw6y(t-Mh)C@NxyWRi3y>^UPvC_LG}(rH>vI5PccHp|zM zbBcG{3KWbL9JdVI4HHUyfs>1MFeoXG2x=NO%7f#5??)2ho7g@uB-3S*nnc z5F#feL@UnvO)F#u?*;ZbD zrXeqv*MDl8xYHEZ>o4MTgeW{uS@H|6U-x(Y1HWBD9f?}Jv2ut}(OY_sER5X){zmlm zZUikj?((2Rp(!$WM>a>9RS;6j{Y&jEMKN{-N?GMUb2nVRH9JmB=n|g5*{sw{_Ay{R zQPCLY(7f8yn$6MI14vXWo@&dfmO5U z5JUOU%DO|Q)V8tB-KM{#8Nz1iFgJ1(A9q{E*dcjg!?D?7jho}pqp)k~WT&=KW2v6M z^s=66O5`i&tz@OV$0#o@7A$YPS1H^yap!uZymztg6fFH-(~*^_QCaCqejlhpJ0&Rb zUen|wRQkQq!;@gn!uq{Mfmi?jnk%)^N1`;l32?=gKRyL4-M(U#&~Q^j{`?JM|}{E2HNXjV7Hz31wSci~45$MkKk zisk9=gcn20oI_iQ_pqi9rP5Cu{J+mqUrjuecn@YCx&3W*pDgh%d#X33x^hyT_=0O$ zbEqrvZma#!Eb;#R6lu!!D|WZ)$)|=O7cbepk@b7N!lx0!{aeL+x7mGl!2?4L&>j0% zfW0tXE=)4>`q&LxY&DD^>MX@W9hk6Ari+S4MKedN=sFanjZWcBc)Qb#wY zokkH4bz12oyiVqsVVr$qC?iyFW_hE;Ss^}eUTp>6%I|tn4|U+oxs34h1N@6vQ(+!! zeStBPjADvVnugrP1*NrVI2EOW74|wT13Sxd69{wbc9tE<=*6wbX_PbTVwM5PQ4)@Y zX}FcG^ozMVEG!dIb2`yW>)$N%lJV1aoVvo&(v74Qx*AOIQY*s97mfDCEQcccndleN z@;b~WTI^a#iqu2MF*O+PWtRrvEz8QfnH8Ur(^AawFN}GF6U_6pP|+8eXm8i7FbD{l z=`~Rk7oBL~%mkL~3rG&s7(1v^q?OF`RyhJps6=j3+X`Y9m(&Eq2+;`^GRRcU{v$&GI&HJk=H?5RD^A5^3!q(BNtojGD*Mnmfh6N zq1yvVCg%s#RhWV7v)PsRhibX!Bha`q09vONI}5j;BL0khaJSZMq#a1M+lL{T61X(b zv<-63^k646qI~-}-{29J2)9@4sKE$++X~QGtA+T@?8pRNuvCa1>Gwl^i-b={_E@b! z?=|cPe5*!iN1|in3YcC44kN!TU!j3P0uPa1RB$3q$);_ZIdttIhb>E;F7Ti#}A(KF)p;aroKDKlOK`h&Plpq)u+$g(} ziJ@Oo4J$%H;wJAtVjg0 zv-G>`?X+81|gYeqW|ygPqekLg>6A*~FbX@YW;1 z1F=7XD;7l7d3o*iIQm_D1$xDU2ffwHw}=4fbA0^4f(tMi?$uiagls>1K(`|U>niCY zJ3;!d@wCT%f{{BAH{&GriK_kN-^|GN#jz%)0_op8u*O*X**>T?ZFzw(Z=~=HIw@ol zdU031MztVCq2KUGCWA{2sPSl;`k1a!q%d`R;8h9mc5p&_O;L1I1?3Jn2&PO-`GYN~ zpS0KXlTH!1G`-;x-MN3psDgy^=WeFipg9rK%e&%ifJ{Tp&hUp1cX|W9XPZ zgf4IW(LXuYvI(BKRzE;MHu(R^eEZTMg$4luYHP@Rk=_35`uSD*?^InJj7`lQos1o5 z|3RGl-&ZI9KdEk~?{5926!UMw(Es0ru{L%xvo&)3k8o%p(9qBzlCA3hQ>R4!U&5IS z+A<_qS(Y?FpSp39d$%VaM8lUHLF zGN>hTiPAH|m338H6pM&Pi_Z?U7vdWxl2*W~1d$kb4+Kmj#V5*c=ezjo4pB-o+uVH$w!qS+(|}!Bcl*eN z^Y9m|H9ovW5--C~JCb!X3EC3r)gqghuH$b>6|ZfkD%7yIcg!md=JL%GIR`3UCYc7| zj!A|PhY%`oo`07s({{`FEEX$Mz@RXwhP5n~jpy2F#+)@qXFYG9$?O{p+x~Gb-LdD& z)yGn0<_aH1)0(@2RAIs!_zAJZ%oS+L9Jvbw(gPLY_ux7Dzro^U8KxMqMIACr?UaF8 zoCJTaf%$*w*36}<-0$B=&q1Sgkkf6jUK@yU&Egm=S`BB&gnwx&v^Ijh9#M=B+g?09 zVCJ4L;BO9Yv>_L;H5P-TOn(}_yTx@CbA1EG6vVDd@v3KW!vA&f0yWDb{-gt-66B@| z1w4R-NRYDrl;|du$5|7qV`>VXCxN_(q4dxHDII>rU1DayyGc5WXcws>)6i#+CkvW8 z$UxY@=KpO)){rP}&fI8=?--NFcKC1L&Th!h+{INSWZ14``70wa$O3XVJ-EPTj$K}h z2-)H5d@`ZyOS!U)Go<0qF#o@hxcQoL3b+j!R^_*bWKTgB?+Jjr`k03w;__x%he+XM z$k(HE3MEF-_bL*um@@w2Q2chuzGOVzV(wuMs3vyTOL z;NsuF=_%X1)wi9H}4652I3p*GqX%T-{3{m0~tOmlnc2=fhqT z`oaHRsp4Al7(`9+`eXJHO-|bmUVLl3V15yKTGAM}$$3Hi2m7}I9c7{YizpcIb@t@H zXa92kzf2d>g31d2Bz6_5thvmIpl#Ge8B3%kJk7q;1L~~%LI7AJhu66s74BS zC}d%GWP?WpL>P=2a1>_lARSTuU>5YG;9J(95({qsy;jtsg$=*O*pva2a5oWC%IEu+piPLOb zrxC9LS)MeRCOOX1VOpDFj|H^30%eC9%Mw7v?*aA z4?~HD2{)a>k$Ko!v_7)&PS=D}a#4jk{R!~&X*eTaajW?ZBOmFUN(Du{z5-oHtxRl$ zImOXGl@jy~V2%Pu;KRLIKQjMz-b-W?JiUWpBBlG_rw6|@j2arReSgYgO0z{(XW)Ev z;Z>kz*idlW_;m^dNurk`5HQDksjG8jMt^*kE*tD;ZG}MYj{l=NR&2yfVi_5$5+GLc>M7+*w5hUe)sTxg5g$Y?yfsgS^w!kQ4SWZ|pA7 zeGy|Y!PTSjDx080Dp9!H@boQi2fWjOV;5h0P;$@K^;XHeM8yI(fwnIaJNtwcrZ_X>ah(#_dUUU`9g_T0xUS%zUAGTQ}wSr4d$Fzy_?+~^*% zI|;vYFFWt?QrU*@An`6?q8Z(E?Z&55WajDj93vsyPn|023e9-%DcT|WOkTsQ@&%QnW+0RVOjt0y#)43~o=J z#@S1(gz3TQZ97a(-yS>LpVDx$^l~q7?O6hoZ=sRC>Bpg`?a0p>M;iTjJbCYwUD_`> z414&6;qE(LDr{4-Nje5gwqo}{xwbYT&|9*29eO&QT`j z?9EVc?2{14S;j-Bi4%VG0$11$mNQHQf!4TIbSp8&{p<$=29%lsfq0sknD+bv2sCw_ z?#RhR^Lqy5Sp$kFStc=4Vs02yVQyL8-AKa`XRpLXA9bN)ggVIAWqvnZ*I~cB%jlQV zrPA2@k$)iK0!{9VmDd)nKntaMw-T0BXPL&wJN$sL1?H!~A|feG$KXFVA3mUiP)>rb z0GQCG1{v7U`}8>+{^*zqHJbS83RDY1>9{}0jHN}S%95sAS#$^EM?u}md<@}58k174 zB8p7mf9#x?ttpd|X01i*6Dl~ef9A%`WMDh49?;(*d5KFnMi)7fZy-%C&%Wr+gctA> znLv9ml24T#Dic@YkQ?{aI{gxcEi9ljz#&%^&#M-nsB?~ASIuagFA$Vu=FTa08a`l0 zRD_vKQxPfrqudA|#6hjXXk#7>3VLlcS;zE?eaZqQuS362KHf3kB56r%z|x2zfA#E5 zYk*v$AC+!ofhR?Ts<)X~;SQ0-^m$7$~DCxt%0^ZX8)@ zrPQjT9o)G)`ZWh=)Q#hVKS|%LmhV!_rc0HbM2T?_PDxNG>o+T>L=`kKU0r`0`YaH% zL84Qa?$pt;=twD-T%SbI|gamcFCe$>ay)F+qPX#*|u%lwr$($vTb$QwyXNo`_1eVF=t|b5qtLe z@!10;&;!kHZ)Y7mVnG(`MkZi{Fdd*?H2MF@Bvy0P?52{&jS z#x0Y*jDC;D!-t0^lQB2&>-i}&qsV8Yt{H0H-nc0E+xVzh2Eu(P?2z;eWSDTZxcV?z zW3P}Iu!lcb&KEFpcv8F2nDF|-y*t)znsbu6<1bLUkuM?e>BuAJ3I*6^M-E9_cH^{^<=XWs0WJAHuJd?efZx;tmK~>+QNE%F8veIOa)x_)Gi?J* zF)E_afOFsy`E93K+m5JAv8vfN0u)zW2pjo)b4Bti@73#c7ta#=6kEI@Rp<*%;3xa- zuODz8PpOE7e0dAa=pz{uwbTWRpAoTt_{Yl6<1+5atCQ|mX9fPcCu#4`Io%dU-h%EO zR7Vjn1@$6eo9A|UgjqR5JR_TA!TqK8FmH_&BmRiCK>TcC@*~ob?(EJYtnasa`q>cv zvIb)?+Q=3hT{q@8>4vmX*09T<+!qBEtG~TO02Oa8v8l`)8zHFc4WyfJ zE!7{GL+63Zqsw# z5ko=q+yIR8;>-?1ErznSQaAvbJVNJjyy4Zz3UiXD50Nuc9_ovnbyw|IJtcnIxKvfF zCKS>L)_onVylx|VreIwPQgs2L3V3|w7(^QJL1GZM$mn-;XBJ%1pMyd+_Y*4?8F|qF zdz=ACx)`Q|gkbH7eKp~DyUU*zGR@76ziJ9y+U+OU{UmoFfmeVjR^IZOD;0e(VqZef zO0-sn6Dq%>y}hfrpz2M^XO85ch~o6JW0j9{Ewy*FAe)ndO3OHDD|T@!=D(;~AVv)> zjfLODU*NPsoOfzO$8+h@maD#v4J8E$JXzch@hpFuKG}q;6-!D|{DD)) zfnpL+2u^PmBWJf0Bj`v zDY#)W%o3@TV~ov*fpwBlY;K4)?DcOF;HA?X823J$;=YhCF|eyYRS7yAqK71@SF>7! zt78n|_}AaDt3W4W)HaUvUMH9dCdDeXmNkp8+V9!CvW^Qd}603U>URT;}p`Akc@A1RQic>i>qV^97v9zeH6iS$SEuV0> zW~+qAp~E)u89&7ei<&gw*d(@Wld~w5`SW~p>zXu8`Fw^(!K9u%c{uL{!cyMQgof6$ z#b4nO-PX`^-+TAe?7BspMe|2>Hja4R6CPtU5lzP7RNR+fE-y`>2rFiAWnmQ0bp~2r z3TXO^HHUN&oKM{#h&V-WJ7NT2PBBD92NGh8yYlmk_Ng28Zku9ItIpI0L~w1PEOBPc z+#>Z~|0?Fnyz`$o-#Oa^W7RNBKH(UMgkaeAz{Q8krV*u=(adahdY4lTdgoZ;-b!D& zDIR#X{akUYJ8TCkg`<490^rgW{I(2jjrA>?J{5Er|i*>eY{CW>mw{>Y6}_Y_7v#XizB=@csq*l zmqe|vgi$6&e<$qpm^k}~aJq_%^6)FWYxb=9Xr^VR4=?N72o#Fl}O1%X;vR1~INH zg-Gu(w{k#MQpLh>e{X)HWq^#U9}=Q?ekMWA%r3*4BUJUwuKX*cR&MC;9P1lkR(=$D2vfXhab%07Z5p$y|nC^7SXQkVqVU0o0ww?eGgZCcO><~}mgH*%MrSU{3t znqZo|s|q{D*t#dwLAWglO9f@N_#D;|$vv4ciB7PAjsthnW_iDlFfLE|5q{Lo5&yG8 zJ`H7-JBUcB<1 z`OxC(DvRiaeKdKios}}f8_jku9s=_zc$v;d=A&rJmOC*XF{g18c6-7>)u@1AF66nf5IP#xKq}g&Q`FKQ<3Zn0| zW!rIzxzJvI>O!U@r%$OSZZzb?|5c2|&oH+rSHZ|GB`nrZSEO41_>`4PuR6MNGTL>E&SXrQXQx@ zD_0@5w*35zQ+}go^x8cpcG}27~2|;6GV$I-2MuBd7=* z;0)yXD`W(F5_x26(SSrY!!X79vyxdSxVb@?B8ss1#;~B$*Nh3f4X=W|oHBNWw&bH{ zd;k0+9_bmMSVJm4Q|9D0zqh>JKgucY*kUO3ejD0pQJK|;+C_3Xf>AqItdn{58LKFv zI)|X{vlH6&RU_hpjSc%+Pq;Z3g*FxjQMPj^7X1syb!l$^;{s7QUO!F+3jNX6lr%96 z$CZXyF-RmbOeYDM#BhNoT~UXS$8;7^ODzXPsR4E@3Z~Y1LjQq5Zs|#LYLe~=dO_89 zo$ZDV9@NVksAcSaAlEg-pdyck`P4M3ve>mU>$adHL+zwJ<6}hl9KcZP?9bSOzKte* zq=R1EqDe*qKQlI8+7jLD>>IaLKTR#zHzk; zn3_yM?BdHe%&Lg$oW2YSX40?Wb&FD?{?-(m*f#7D^7O5EnVUv?_(K;~DLBU_s$2Bs zuNb*@aY?TNacsx_P@KoOLb$s<{#~D4wW8i? z4qRkCUJYu{Y0e4|hbp3&Dkcfm%KIjahm0+%PiUTO7d3%|x4;4Da_&HV&=5NOzeG?# z86Y6>_-T-QQTDPPO)RaV0B$$8Yv~-nuP3vZ?niR@K7sXs=_*eK3Lzi%8JDW}WL6vbeo7OAgn@oUP%dW%fG~f(7 z!DKwPgj=YmkXC3rTFnT1W;{T(?!F?%xR+#}zGd#;yoiTM^Bk{(9yYb%E~NK2!5ot+ z*HO6*lc@f56~Mu4GyQSc2aJC}L|BfuoVGH0^8ftoGgQ`neScFBoK zeI}km1BFgiGN)aBy`ZXU zaY=mVilSE4GjoNvv?N}FVp)mPMw#T{bt-d!WNzX-deH+3h4)hVe7KxBshk3c|AC8; zl(+VXl28d2J=pIW8o75Y`R!%_K$GyLt?=jSPZ2tAKP>nftu7Z!4{Qm(74394H{+82 z7iap#{a}*by_o7^?Nai7#Cj6d1fhj_muu6`>Wz-*i%+BT)fAf{_4VpP&!&y9q)*sS zYp&-r4S5`J;E(=m$&TmEYp>(Y`?jO)zux;aKc4q=?TzeuV9mL4OZ9nU1h|n$8ryo0 zaw2zML4Vr$S8Ipu2D9_}%QnQyGNj8kHqX@UHd?)C0q2gOuWoQ-_h5{q-WWeU8Nkrh zAFHn3C}ZkI7Q)jprPWTnh~j*@aroQrC4=?^+fKa50HfFc+V8aYg5Qqa1(!aDH~tVG zj>Y_~x;mXZ`cfX1JND8Z6tiGaeSxPkwI&Z}v?!qx;4sPP@Gh$2jJcX6OTAHLo2r+E z+!zM@nNp6ryGU~G$=Yw^pv_4Ab)I3Yk?ao1r5PT+w3+r?1Um;3V%|1@)L+h1N+KMi zw$Kqovma8PTc%v%^p5CUAH%%@$; z#^NiTE^lwJNO2HZVVzXqrB|%85N7&)%wS+qfod~^GdMuBK+sCmS?$BEb5vYiy3X2?&7MvA_K+R&O~wknll5%rhn6h#7_cd0 z@q8BP1?ngxZ9Es58|ce;M0J`CcMf+`b|wE9&t(ydUSgE4o+^9yr8Z3BW)xE$(ROSNn?oVPPcS}kjZz^$kn z-m17e*7U>+YHfP0M{?5UUX@a$Wk+1Z8k+yg>{?a>S?TmC7FUMbT*X?3&!V1*mCa&F zXIfE!cbjbAyM1eb7=8K9N*nb)8x$0Vq8X_Ls}M-i8xf`x3%3?k7ek@eV+Bmja!VfT81Bt%e8&gOz+m5y?7*+(6 zQB5db7>CJQ%^E7N`E|9v-?XWf&*hcl%LAWe>z17J5QaAJAcPe-1&zYJFwa z{`xCq=!l6J*97TQ8h1Bx6{QEKM|xX7W^Q_=15pTmRhB-4WoHbU`pE@?2uHV%91eL4 zu}3#zftbZ2|Ae=Xu}^IovD{FRY2^~A1~T_t9^XKa{{cbxL3=Raj${vTJrO3M_Mq-* z76{aY=Rce_20;No@$!R)`$FhA90K`5dSxypY9-tR7m6o?;|ea%E3Slk9 z1aAZ!Ojw0K=tTh3bqjYD^UgKKailIgbQDNGpS!~o^HQIgYI}yj!^}p6!xMW5vgV0c z2C~jOKy>r|1`Tq`=?;j~K6g5lo&o`i`-4|skdeEmMw$?w%-b#X`?bJXe}Q6LV^h ziZ^o*7XGmvy4ploTn6(~f;2u4=BAl?;Ir6*FrR%n#egUENgFJ42cGYH`hK4veWu9GTJ?VoTG-7eX zji;gY_DZz#dncL{Kd}8_0H`>zI8NKGP#82iZFds1)($W_?XRsUwwiq#EVeyHzOAn3 z*Xb@cCccmNrIjDF`W%tew3zfa5jfqHnV2ArZPb}7Fd03xVyaGE`TH3$=P;*O&#V~3 zDc5&2HqC7-b<2glw^*teQRC}x0hgXVol`d-4VR%YWK|jX5ixTfbuwG&Wv4-j=oqw# zrIwI*!c&nob;1}>bPjG*O~7+@{o!}_%D zxDh8?*{xG>Z18R&620}*!!=|{a?HZSX=@!)U6^#JNtS4_xoDO!6^7=K0(JHe44_$R z6|kY!9Xr%${^SojwmSYKRdvfQ2pMppfocN`>$m=i$eKb6H$9t9AxccPzO(DQ--sq1 z81)#uj7IIjG!-vxZl*z$BaYs>J##Q)->opa8C^TG5~%pu|9H5l_PpUwgNBP)UGwL{ z-JKk{kln-p1{Il9RQe!pg~7HU0t`8_P2T{xRC;qTAx0A>@~`YLrYL@qQ?-lgYJ5y9 z#?jB=TJjI0(hV`*6um;LSsL!wGEYfYhMJRz>+s8pZIyId6nxqq>Ke=^cBU+GyUMM2 z5_(ROvNGLY@uD(JVp3Frk79mhS5T-izq&N^``k zu_aWwW3mV;wU{JWX^LGL9?bFgkMTm*jJv`X7zzbFCC8Yr7)s_lM<1>aatd%%AxE7T z5(kKN6gv494!flgg%;7rJ7;Y#1*8;REby1*%H9v&A_Zm304NC${P|~yFN1kVL z@uCT%wFhq-y@W$TBCH9*K4dF=KhY>~Dfh_2KO|~=VW}0aBC6(_Q@-3O7$3L5XBY5^ zvJ+mEWaIx{Q8@HOPLG^4p1oNRtr&Ng!W;NH{dmvqTRVo+`~6p+G1EM-ai+4Aa!uKw zk;mnVzh&#*>uL2p483D8XoY?AIVLUr28*SuYCX~o>&|liM6)BJbg}iB^oVioKg{8m zNNC8@-{fZg-;$gEkumaH@n`*C1|4nHO(m2+t|n>p=6S}FK<1W}3a@GNX4d62*1>Sg z1+(zxa|+ESf*8O|W6WcVd#zv4KK^vxv&~KwE;Oko@Y;0u57v0z2 zk)OLWzkNPodo5p7hV(aS^$=V+?WK#44al|>8T_76H}8!UJ9}i$7F#C}_|Cap>@W(s7&*lgsJf)mgnT--7;4)tQ>D0W zlr2)@U1W$_&)ryk(MGrHEs;hz0w%9wLGw9NujbtS8+@=mlFvCM6=!!*-M~;sEZUnP_*9CJa-PRmIZsY=h}i=NJjxg00U|5%m!uhT#iq`H8D_8P z)1KZ`sGb5i(qYBDUk-$3-{#1mCz?dT0SHmd=_?6>U6RJJyuUM&`fU%=&C~Rslg$#% zCg0||45e2)>e=`dANpi{66_JVM5HNpbg<=W-Ef>+%N|o zjJnQRza7+*&*3{gi+Wf;8Qrvgnntb}o$RWau|n}+2Di9tj*)0(}Q9wat(KwJ@NYBFqRm-ybY?_y>Fphii- zvLsOH{T&${1eN$T4qh=lNeyOpoZtG_XoWEpjSh9z70F$5^BNZg3Bp}CLP|u;ut-VP zMYJMj)5OPIM2!9Ixj#Aph}(dOAV!0Cu??Q`YTGEK^30P_UYp9zXEiNy(-X9^mDzCh zvb4zZ%gD61qIEW56h*MPBw`H$_jWn$_+OX-vZG78)GtyT-}3uIgg&BS}2 za8k(&hs{ojQBKNaaQ(Nb@&z*e2}5xRJo8GACPXVN4w~T3-yF-LRUu@;acr^(FbJbf zuZw=e%>#bQuib=4l8cGeWqSneN%sN!kHECWi17>i+a=ldZ(WlABP{oiIh`0F z3vvxYHlD!+1BdS}xli6M+ZM&o_*-A_ zJ2N_>%X9sMm-!3|b;{{a=T?yL&1 znD}#OtmUjc*~YN^osSKEA43CzMig59&=`_Y>|Ux&MEfi_9GVW{>(BCoNv;d?4Um~a zZV>$_n|dTN@TIm1#sn)@O5l4p0mJ=lW@kpvJr2& zL>~F~y)xhTyy*ww%hIgG2#1CiKJMNDd+r1~hFT{VYu%XZcjl?&MYWk*R|9j)a|L6+;SIgJ`=L%1JH=}Sy zexEmY*LSuAN`M@y2M|25UWSB-Nxez#7r|$NB98k1CmGY|v=rlT*s>5){{BzY!zwVbbBEjV`Ca;eP*4J@M+f_jLPuxj)tgn$#x=HcSHujY#!#QiZe| zx?$E9jd>`m)fU^s9S1*lsAaC$$q$ggs-g^PAK8Juj?*mbnU1H{{`U5j%wxV_BbIQ+XwJM;m(&sgFhm**}XO-pLHWujDnLm}` ze|q168??!$X|<6rvaqW^PziSQFOwJTKPE2)1hl^($6sNhkOfTw9O@4iNr_rRF0U3F z;h9v8W-f+#X8#-6)CUtSDTiZf@Ji8I9>FyM^KMqjv3T65}#M#j>WulM?Q zEGOW0phT^5Yfq&tzhGx?^aVAX&WX?4;>gx<9IAP4F>oWAQRR4dNkkgRf z;?LQKkgA0LE1i_z@d?3#K&qc)wg|3BtiBF2Dm^c)NA!__FYt(YR*^ag!{8~Ge%5-R z!KTP$+FGDR)|Su*xJK+Q!x#eZHBm5p*c*X8Z~uOifz!+$Xbx}@2{Vd0P>*Eg z;!OM*$2y{p`aap#DQn;?xM|4HH#DN8F3-ROMLk)B4=gpXP$`q*aM&@_9uoX z5~Q;$CzsHk+dnx24?qeIuBkEQ3KmF^SbPNUiU}`KH@S*fu0`K?Mz02c3+GZg{^j0i z1d%I0Ui(DXl%qrDOT4+S*9Ly}-rIw>fXZzbKYcxZ(iX4RtA0kSFid0;GrlHM)ZD`n z|5WHZAFhWal?%yTLFd8)MgMXszhlDCEn-v}#fW zS6F4}&_&7Kh`-Xo+sP*XEmD|qO;}Y@Nd0fT{vIyQ4UGP;y(fexy23_TeNuze@al)v zwfu|ipI=fuPdtMQ-g{M(oVd&l&xUFgyIn4uqUAp~n_= z|EV%>WihE2-&H2<-;y=)|2xs=zf_pwq#4<7E5pd|eO>5{AyO2fg}5ZvqScT(W^01q z*uBJ(gRzpt<%8B;cx%{Qoo24lgVpBn-46*;NECciafBT9Dow)mnP9rm3n&G&7G`fDmNp6!g^^dMTY>SdmAa-gh#= z%3K)fM(k2KF%)h1Dl_c;C<4DWXOEhDA4G=W1a~vfy%xT!3ZniJ6*v?#4JP_`ToWBr z)gc_T`(MI$@SNWOiM0Fiq@YRQcABN^gd5vC1wipoquV9xvo%L78uDEM48Hhil(D-r zn-P6YXU)yAMHX=J)E>bAzPbN6RFVc|UNXD(L;=KJyI1@$f1Dkm>SV3LQQHDU&={@` zEt3=2qr!<}BwA;d2Tjw8rLaWuC9LLFOXql?`%0y11q=@rLF+QwtA~?F^iv93kSy6) z$6-ow`9@zt+0E>hSCidr}4Z6sA|ca6uXhal=8e;pi#+0cofFb^2wM1{N9 zAgc6+dT5S6BOEaL?P2d>8vpWH!*pM3=(RhEspW@M!lZJF(osH$@7GFPuCbKD$eqJn zu4uu0q9Xce?q~MvK4{geKb%qiUfX=Prj*Knb7^COx!P6JN-mdGjCO64!KHPEIr5c; z;Votp2KNREQ#3BGdU$&n8wc+0ZrEXFGy4sXKffy5NNFHG>+7p;1zmN6Rp0-Dwimph zDc)7|h|v&1;N3&^rd{yKU+O#fqZ$Rvlp!n@$XEilgt{D0ahYL0c7d{4p@>t2Ykq?K zBOLT|uQtwWPD!e~J2xp{?j{oDq<(-5(GX3d0Ql5;m|R}r_hrFH6*&lHf)mp;a|ng% zgT!9rr~A6iRyT+nS!UPuiEzSKW3cK;M?LIRtcpuWIn|=KgLmHS0A-jJa(48rgybcH zI%7N$ctq7D$z7UOt`oJx89$;eUA*bRo74zlE}KY7S#puDXhamR8z{{!6_R~;Z0o^a zcd0KXfD@@;Y(lnh)o}#1NDc10Irh_acH_PEDm;Fx{@*!{PQUtp+?g9Dr5g>ptzHxx z7r2ABr1n}Y6w1^+o%P!-{04}`Aqy5+z4DI`gC{`jk+F*)jzFmjfBpjhbNjiRdtJi5 zZ~yMU#Tb(RliUBlM&AFs;HwO<#a2e)nZd`5Wdc}{SwmT`BLLU`VP4>r&=l7cPYek< z3QTB8lH<*}jOVE~CC$JT8~3gFN9?8U5ZMF2A*k0M2!VxQ{l&k@m4mfne~wVk(R07W zbKKSb+;gky>w62)i^8kG;8!UDv&RynBWnP+!k%$#=D+KK6zLYIAFiLi3kbo6p@OM| zv4lB?v1Pa{34jG_McG7@Gb%q=wAR%#Dn3x_;J99mX)g5S%CS{@V=?DTvoxB7BCe3B zwpvG()oW9HQfLE|^Y|=13{OL9!63n&zAXh9pM)G^w%Cqmly-^^5oc7|j^Re4IZxbF z%B&eKVWzZMt(W*J>oIwXN88vY6#@?)Wj7Ga{x(=2*7!q-bw#6IH798@L@~CGdz$fq zLp%J^4EiSCBqGkQ*O{%@N_2146mkmvCCi?6taNTZvskiUL}e#ZAE0$@@WEu*%qc=VCwaJxnuYG^bb4XQp;?yOu#Dpl* z$6*I#E{IdI7X&SlFQrYWeW(1SqAx5;UV*$`QhVF_K`NqHP7Qb<0b$m{2)96lD8GYJ zg}AbP-05=u!pzBL?D6#NJ^SY^i$j2c!CQ;d1|5JVKF=;p|IH81HM=w4;<`@`wf?~8 zx;xEbevK#P>j@nkvHr;Ayqhs#JlHN&u&@7__LpRDE)*x~S|IvXzJSL03lqvGU*m5C zvk$aUY&@!brZZliMh?;LJ&Tr2iIc@S2zR;Vld^N zcw|l>C&1Np{)yu;AyHJu`(V*mt~C8hM(l|LHeo^D0gJG7AKbZP)~N%DvpiowcSAg4 z7Y)!{ULKMW@OxG^{>(NN>yps{sj_1L4{R7=TQj1Aw6EtuD^&I z;)#Ji3bZ_Y10jn+at)+gJh@0vbtdFOEF;|>C_s;!s=Z%2O2^n}AZ1n&kBMk}9f$P^ zWyZl1Mp`GcugP7fERHW6Yzj@v#~SI`A+Zb z4}Kee)w$3-17r=k-@$?U5S88GHCAswZ4{D_^hYy7kx{m^I+@LyT|#?Y}&d znIBF#3P3-8Fnnj&{O`#r>;L&<{C`v3EuBzIF@1Wvr>=|~^sx<6K!HhS5g?@6p&-Q} zg$pF|U;&zo%VQ?1xDBawOp&t|=fx`JG)pZl0FQbR>xyACB%1Jgo!G?%yqVk7M~4_b z?ze5t*zsMATw4=5iMGW!{Ozv$X;0tW=TBDK&u4Hx;5x`-Wh+0_pz2?x{m@b(C?lv| zf+GBPvgGXLgv4W>sGFsNfv5$eWPvYAm{%hp0$v(@rbhIcOwPG6|*+%-GljNIY1DZ3QhG#oQ!W`lJ}Sn-RE z^OKHHIjZ&3uy0^sx{5aieh!>*`Fnwx~DiqIY3_?9>P+ ztQW#2{5wZAYNV(v4^`Q#X^aIS#+c?Ci-{`CmV~ zGb-8@q%tS%BP%A%OBO4N70cm;j_e66V9z5TYt6b1ZRWB|mXN3izxbH+pFA~Lw)YKL z#R_XQE!87P9=-}^pzD)O=GRC!tktK666;JLAyI#%v3c5+e#i3=gBb%cG4QOFngU*P zOy4eoB(Sm3vATxnKc2-$fGdnwy@Oe4Y&y72FjLrNf~y4NDF;m{l-R1<6-=qVjmE5z zPyvl^^%lI>l&A{^>O!s2z``Aw9gJ&kO?+(ZX6tkLMzl61h2Ys@=NadIvcHnqaO|uh zsoOh1{O@#HZ0j`f9WwHENPwmAG025i?1PbL*~!77%z1|JLXkR@>i|)9DuPx*{tIr8 z8cyftJT^v}#Suso_T2LqI&!YF$5E2w$p~tdQ|()>W?5)-5#}V4E5qH0tt>^)#u|b6J|%5+{bE z;1uEFQ*y%}8FgUsdu>vNt!9dt$`gS#zpi_=P}JosY?kc6uexLoX`*ar{I|U8y+Ae5 zt%NOX4f`);77SOCMO@!6Tg}Y|T)u04YSUBz1K9TL4WMgM<>~a}SDkm?Fs=w`*{+Gz zqT93eavhi^m|LlJVwU!5jXp{zOP8)f?T%&^6YTb|7_%3+A@Cg7p2&c!fNSj@3v6g{ zvdsg8(o`rpLG>>6G~x=@aPg+VW`(|>!nROq$n}0%$cph(q-3V$ZyS=fZe}O(3oEq~ z#vJ4k|F1&PC=uAyNmm82R;H|lkY@}<|Mg0Vx@bognpDWtj7J)^Q1@>L+On@m9d`Q-Ws|!X`^->x?!!*xIA22F=R) zD#5~f>a;E7_bBA(ku*8;+J4n4<-S@B>{(PPlX{_c>nN1No7Ep_O|?FJX6zRbfIsD& zq-3(6bIxGZ{pQh4s(78C9=JKY#_JaAxi{Ii>(r}`K*mPMG0lPS>%ouSZ7;mNETV=` z(_a1MLR<%S9H5IK-Vtjt`BzY1y7Awi`ZLU3uGyisNInwa;#3K6GDN}}$xds`%=3pu zBl3tfS%S&nu0iMkBIzesBdNdrx4)ypL1-Sj@tR>8;)hmy1)CTT;TsSLa^COdttdnUuBJURJGl+LCl8tW!3j zn1>pvlq{wF5<3{mjb$OqPU0e)hs@#%^DM{WHPh;L$-e9C7PS1g(f!A`nW5|N*$AIE zWu3)$Vz&&cYmQ_?5L5!7TkJ5uzw<*QLlF~jpJUuNy0}DUh*daI|LjJ-+_7|PD#*xV zyT0H~^^$XD5`9rr-Q|@Y_D^!rD5}xW_ro*Uwo31n;QEX20A8Pl*)4R%7U;(bfeb8A zP=%FF`Vex*g%9v5HMfdh<(JI{!UVALFob|^6@Cg?sIT3 z^0NfBjW#*mx^8m?6E)RwmkWE_O&2pWtbzz*GTU>HQ1(ij^-1F4obo-xGxWtXwawYV z;gy)>77^#2nsX1~`CcgO8}sRrBjSVj=@u@>8Ccj=O4Akf?&i-sIB}0MY__Xx(Iqev;Y13g|Z}HOUeU9alu&1|FS)NuzaIVb4>+ z{<;jcJe75&~c4u-1+d(QjCSoAX9VMxNPB0rA)x(N({`BqM!^;J(K6wu~RYc&NHW zWlZ!@$#1}@gtD4`g+yRG&te+a98IvEF)!P%wMysJh%2L%j}kAZs$5ze0aF|2r_8y5 zc+(wMX!~<+hAFF!Y1d_lbcD~3WWmOL;{QWm|GvR<5PnnF#eX}gA@qNaLjDs>{ukXU zIc`d3fF5Qfn_>M5`e)QNRp_N4F*_k#n12xH1-<=lO0!C4IiQ5Nx=D4v7vx3`!ZkW* zFdFBhk!Hh}OLrST_lF(qF#%4n-S{u9Fs(8SOsi-z#RfFoz$Z6O_fmdh$iUGQXj5V7 z*D`WPGS$}%fw)mg(#4grAaA)2X{HR(uPQ;IceCkgk&?)VY5h&65`uRLf~kqp^?Ym-dvmxo1z!4mJ}05 z35#xCM7!!9kZDgAF4ht_SXsXVf~EW~dN8wCdY#HT0)tSi3Jr=p<)6?hY305;On6b#y~dq% za)mD+2U6tc1OnnQuK0<_fO@71afw;dK5=w&8jHCrVXR8#;)`6Ycy^5lt1^W{>H!OG zb`uDh<}omqI#l>n(r#YVmOBM8uOilrK+1y|Kgl`5p?-4+PIkzj5T4DO z3&TH-AZ$Er^@r}2yVjexn>J4yZRhUr&pfU-z4ruo?!3duXL?|rU%x{w2Vpg;6=dq)NC>s-f*OoZnC0q;54i2|Vo*lUm&^qhp2K>bs89)C3xeu1HO8%^Ot#{00bAbcf#7n{Px;Gu{283EG^6vBeuTX@omZf1Xp=ru*mEgehwo2Q=lg$Hd#j+z zg0@Suio&&Uhr-?69SV1s!rk57-R0o!?(Xg!+~MG^g%%87|J@N29W(#*#YAN6yPY=~ znLF2h*SnsvhrybtV%SJ5WDSo`Gw7*L{Byv5(?{!2kFNd;A6?JDp6vRpmMx?ng#>|D zzpwE*(vTe@UYoUq@(t?9sv0wx6qea6?hurz=Iyc0MfjgjO7%aK**aVaBdWIi5#?R~ z_`Qy&Vb3i>)-Kp<^$T%IUV8lFEZ7I(d1ml796cL6`&L>0v&Mh^{+>@wAGYrI)R0!4d+^xi{3h0kTUgoC5H&%vSco(iGz<1g})psV{`tk_95 z3LQ?Wr|s)K#yug}Ql0dNT~>nlM9^^hKoAbWT^^ztt9J<&5~xw>`k0k>UkDYk{ie*@ zcROU1*SrsO2jVY(g`@YL51}|v{F7+eL+j!#=Igr@QagUU!saaka1uw{Ngix1ir7hg z?F9|Ev3bu1U4x(qnm}QWM-q-JafdgkT<FV?~I%O<}Qvz&zDiEk{zuWT4vy=7UW{gG%}quJo-J?Qk5djHk;^Iof|& zhQ$0H*lG6EZA!87;(mMEV0Zhg?DB*#!aqpJR6yj{i;g5AlEnZsl+0|^7fxDUXS}*; zL`tIOMr$rQbx~4;9{X&Qv56)#0^+4?{EbA8s%G89hmD__yTs*nB1Mah1o(^hbcWna z)yVFoceKGHMHn65PK80pR^^Y3mv65ZJ3wF*t+n}YPhqhx(P73movU+Chr=eqBv$() zN9VB`w|qh#HxrfMblH>P&zGi*f8*EgS7* zv~*XLSF4NLwdKz8#{3qQLK6`lf;KKhD(h5DuY+J8b~pl!#Gqm$2Uo{Nv>lu4#Gv?-|p`>qE{ zxN+%TD~>JsX}n!J^?1DjaYjHFFJVr!${v>VU+c_9el86XoGX2Hhz#0PWEd!1UN1q8bo4{8<}85ExuZp-V~vmI0pg#lWNs zI1_E1J3aYczJ&}5w{M&fg5TV&#Jl9^Bx8|LDW0(7Dp8oP_0p}`+~Ofa&M#-f4lLGp zvC*%77zDqSTcmg8JhJXu@}%NTrN))bKaJjEh90t<+#)?;oQqYzYVK!e!0|r^lDI$U zkYA8;jOU!YV4<9OLq1^z!y@>&QR-OV?sXP8oS2q;%*C!RiSV2T+Mf>4@j7dwoeN`<$&}!ChN@jIij}9Q1<-_H zoW!Lwgh6!NFsF!Su)1!uqr+tOqtAS_Czkx(?36);b5W$HE;eojZm}}8ui5wo!Y)2ni+D7COYa?s4#|?(qZohT$ejqej<{iY0QVv%yy^U%X| z0`O{G;>oitI^SifbCTYjn@->!Q&$`x=XB1wRYHgUQ*_QP&UdSp+xu8^_erw(=>9rK!I+U5e zX+~(2ncgz76<|06h&^UStD!L!5?P6c6h!$%p>K=~#ccRU>khVu9mJR`#zSn5{N%>% z!1>W21?F_fDSsNfmCQAq{rhT$6>zwj%VFXk5?!um5$ibtTmcDxbW|Pu^P`L0OZbQ2 zhpcXd3rV>#^8_Y!om!2tW0$g(>e+y;G@E_q(Rz`x$dO5Z#j@D5mE8EL^tu{UX7;=K z-hLW-0MBlBg^05ar)|Iuc7P)y5Qfvc=WQ?DAIK3h(63Ah@ISHw_)i``W(nSsKENc8 zv5}!tK4$lI!AuF%AZ|_8$I^d)v@gh#Q@z1-V@tiGxD_)GCgj(d_*02H9}TUpx+-C$ z!bQJRG~PfINu0`FC+71bq$f#((I;BM=J7r~DusGWFIkO@(X|FFK|%-)y=uC0S9}Nv z`>qLh6?U(oCX|3uGuhZK$nJeQEiXti&_`~Yvy&Y7q=B>}b;)r(Aeo#i7~-b5CsKyz z%v!3jByf@pr&K1l7x*DbTVfvpu5F{(p%dID!#DZ7f>7(povgal1P8t<%gEQ3c;`wh z`Yo+cMDwh0@a~f}aaDo`(@^#`2E%l)4u+!~9Iz?SH*pZSfET(5#sr@|Di|mFKnPW=~x+v^PL9se8(KfjtEM+b&35DO} z`{D+TgVQ<&1?*;&eUx>b4b9MSvZNoSx{KCC0BUZFYEOuOotYEJ_9!i`bi@3=X+ zk8idnt}++Nxe^=X-VAo4&;APv_&vc6B^In^QyvS_U5hKAEoAswyqG zcK$|-tp`zf@H|&Y@aPm5O9Ho>2iX2%4m860_3a$7@QYTa3487ZnB|OPv{g38w|1@K z3PC6eI${ZtsAD9ta#iwfN5RDJFTitfA~IulG)=5xmL)nh?p@e8QW>YOq{`k02W%2U zMCwSz6|{|#r!F*k!(ImIxxs$N?o~cX7p2fN^TdZK`_{Tgf2WCkHB4I4fLiMSxe zZ@eZ-btU6V_aSLm`^g{4VPaJQw%%9a4gXBmGrD_QTzASS`Amreul8qB@qimBd3&z(@8!m)sj`_pnZIjQq-EsE(;{FNFr#mz&+D=+0N7@B^t*n^03=} zy9RmL?P}X~->H7fH2&o;hQ)N_$fehB{*BDN8D9Dpo$akc3m0y;^|txjik`AnuhFg> z!n@u#a`AU}-Izb>=Q|24{1dm+-+DrJ7zPPZmr1oo=E?XcW%Kz^|Mqd)t8o4j>{^!?dq`QBadoDcXHMEF@Y;-?hn z$9_}z%{ST)CXe8=0?W66KtQ$j6Qi#eB(QkyN4*eb>8cpfUN-fQfpAk`65+iyAQz%e z%p#hS zQcHt*bo=UY%steHJofVp-+Pl;7!6;G0||Z?6FFhgl`|XLe&c)YA?p8zXi%h6VWKB! zY0S^Ywzam<;Pl7rygwVv0$qi*G%=$pd&+e!A`A3g_^10D2u4C-%{A9&3UO3<52MEp zIoURb0<>lmXkXo#QkPV3Z^n)GXdPnVEa@xlwi@r<7qKTslqI$HrV)o& z0+(#&7xh=`folOVL9q)ubC|ZRNv>0;G+3AFGo+V7)mDHdFeEOBC{vDHp|h#=d6LV& z@$7MAW@BI?7!9!yPKD+9sBc*^)M>HY8!YqgI(3dEH!=~$u#!~MktR@_r_+y5JQf{W zKw3t~izz`XW}5WtJNWgr0DEQL5jKjWB2|Jb`O(HmgK?8`FUPffozxCIuN(huRcD{u z^rZZvVtU;inx%-|B~lLk079igiQS+#uk1&C4}XKU&9%~ESE-h`F| zlUE;4CpaPD$105uNk9GF?;;rW)C{F*8R@9__5~7JN~iP`*?SA3oKgLm1e+Z}V1KS7 zs*)6itPOt_mOHOUn5s6PK-1>V7fWJL$HlheG=C4g8?Xu_ljfqPt18J?A6dBLJ6Nz5XPOIC&`{O7N5oxq0l zq%FmL?5^f&zS869VRFXGhw^S)itG-T-$8k0)jVuSvI6CL&(=+@z8)>>Tb zKLf?(068WSOz9-6X;vE310x}qvkB{YMm07V zq-7dMR3^;DU-W#NX+Wb}rGc-4}sR5o({z&LT!Y2}N!hhDrlALy5+vq)K(bs9`4FQyIs&o5(=9CJCX$ zI+-ohn%SgLN4^g+lQX~#*?Dz0DC20VK31iLZrJdwFcY=o>0x_xougrE+> z5KnvxY#f=#;Wv=npRy-W$~1=sBA&Hl3@agv@V6!&WkMV&PS+8b!_Zf23}@Fog~cFO zW-|&DisekhNp3^!x7c&p(-cac=j^>W<^(eQEW8)Pel_`D{;>^#--$!0V)596ZEy$S zlsoz_MN>i66yEjUOhcy&#ObU)1-V^%;S5rg6T)qmE0nv1zc*wzYb)7;)X|x&_HiB& zXINbL>|>R!#U~GM)yfaJGt9a5`T#CySyH0|-R&e2`)fA}#F$YOgIu$fL zE{X~!C9b;)9+j_Uis?fg43QAHBugp`LTP55m%;EVv^CjPr=+K4s^I%JCCNEX`}wZc zmFm-b-etHDP;|)5R=2j4tT)QNW|%013VGaIFE>Zw>ex_w3)c2S^A(`PNHc|y8V4bS zoGz;hOgmxaswpmS6W8k6Tn1xg#3fTlc34H4Jjvt$ zIo5V=ON@6;=CY+@*$WaRDJFxe)yyP&HI>PQLa6lWO4D)%(+j&IOtxOjYYAMT38KKW zE6UKs37Jz!9e@0also`cZyFS;a7je;XDn+lr?>)aOpYE|%+4wjR<0JVURcWPToR(vdS;D!2AIn;>-+?rajFU|^WoFwqJivfJLo1e zy9#Q#81K=4BE{Yv8TNqU4887!uhmF|svH6{J~~kb{+omYC{ zk%-)}wiyOn|4QE+Dtba@TaM6)#E1ETo0!#YZ^82hs1{OQ6NIesMMvtJ5IAjSQ_tL` z^F;5ia)I-REBu3)vKlK4?Y)Of%*Wa$ zZHjzO+|p-_P;hzL6LyE^CC-LCj173xk}oN3Mw=Ar3Z4A~)#Hh1$ktemx29$_yW_dI z6FhPX&rC;)GnkMv{*H(%>|iwVju(~s%pCKO;+!}s*TlhIPdxO7@dl}YnBrONr~3X0 zCIx^}{&}ku%52$4j)$i$DoAi~iA&TM@w7SH5KM+T$i6`f;}>eoFxH%y-l(&~8>tTQ zL@sTmx?x!n_p}prokb-tYZrUyY?v=%nJJpQR4K{FBuHGg-x6x~=<5<#(S^EfQJ!^n zN23>4#bKqcBuT8^sZ~#bxF@Z!Rb{3_dD)NZB@^uU!y?1~%+h|QA5Mcjo0Uq;)Yde7 z2x5-)#lb8MAx7x)&FvAx8P4Wq6$DU!+^HG< z2weSLGwp44u!CEVz>%LpWqoYTVB7z7AL*>m_LhbBU=isE;?}-_c2zWjdu-mPx+rN; zJF^^&I_T=VMRz_i-kz?r8^p^pmO`*xjdBBh*YYJydZckjS{aZT^Sb3HC;e@Kv`?hf z9?31YXRw7!)BRQQnfF)%*&y5c z)O6Mse`Na7@;<2cm4`QG`!y7&*0=ihZ@r;-9bKF@jt^T8h2j^HfNdLRXHVQN=E*?J z`Ss%2O~S#7qte)G$m|7HDvK8o2?Uxc>{-y7>}Og@mAgx{Qfp6+CgP9G{4W2p@u;QW za&Ol~@7D0z@&wswL(-I{OwyKb(MRmu^~M@Z5_ah(b?LuUf<=~0Q5ykU`2rdN={7%M zq6@OAtNIwZi4WH^D-L~XUr9<-Z8JPBxbh~nRc{&pic>pRYX=C|t81ZS5S_%bXzbc# z8KoT8%VW=#^QAlG*eeZX{(~*kNrv4%-IpWK1&FBnrA%tGm8>mI=@t>JxF}0D*WDDZ)X3xaVIov>S{>F`7lWs5k}*ja5R@G$%R7 zjguqIHpPa6lC9U7g&^fO+CdF@6t zzh(Hok*IzWH}{Q$mbQ>=>n>`R>O$NCu&CYIUfYbZ;kqq+tGdvum zky8NE54yU_y7TrfIGNGt*}Z#u(>g)kSN9570<3;rhOHVzGveWXrtUK%tPZ$g)$+I& ziMBffN*$#LW=RtTy})!>{6r<_B|ZVk%$pOh{-qJa8=-%0LTOP5d|PK11S4CbVJ(Vy zhNWA;8A!WR^XCrXyouM)GzU8v#4OxTNgpT*(VG=5su`SC}1FXtB4)~@0NJ`UL2=02fRNEtxXIfy0wee&uRY=p)4pn_VkF~ zz6Im_cXe0l|3-w0*&3M}*gF4*u=c-H00V0HyAe!!AR#BP+7qmP)X+{gGsI-2hcV($x<=GXS*^hcgS*- z08g9nzaGvd$p%N86l>SrkiNa|M@Z7gZ!?awTu<9iv5Bn$+;=$sUuj2dQqMwczTt$b zAi^7v<>D@d>NAzET1+m858|^PmSGyt; zg|n-6%+KgO_Vzk@hvg&a7OMDJeuNPFbNJbABo~X2@@h633Hx*K`FH-O2^cDqM|zhG zKY8z55femudU<5I7BZU*HxRr;t0Y1u35_FzYK%3+f*QzLavJ%D281t3N|!U`7DHyq zkTU@cJL3SY#j<8t!z}25yd^J@8hy@?%J@Lx5;2)5^w!{0nUZ3eM;SA!ed`hvnPWye zGw!rg-je$aHO6X{300ZOjIXGjzNXYu;bGmO#lFR{#i7M1G($@Rty0!%8H18X85>x! z^!1Da8Kw~Kbb8ZB78hnRwE5wtfbvWW5+J#lwP{E2sZz;gI=#9m5)gwth-!RsaeqWzy3Obc4sZ6gi?Fe;< zwx9qu%d9Z@04y+pk1`yLTVu|sK(lmP(~gi+wGp=;&f5OA6es!S%2pz*^8}IP+%Tvl z+A%ibKK1cZE3LRBl`yK=GpPy*8m*O1pVMUY3@hqYGjS|GJc>}al_;g6k*U!> zS%t_~gE~PB6eyxK78uNk&ajfgRcdP*eEvF(ujsPO+W&oWDA^RV8>cE~e!@g?fvBPM zfSENHP1|O%Xpkv2vs02RZ%%98`5V8HsL&g&v>=gvr5xOs2RuXtO8 zc~H)t@dOLEs@}4r(wuofJx@wOr1J-8pB%;~@Qy-I-t(SpS20N2U7ESx3ut)&Rs7}% z8{^zDi^UEplT9$JnB5~7CnL+he`2o&Z$g-bK$lY<6GK58DX)UGAr8L5UgiND+ zDMfO_`o*>UV@Z)Amxbz}BLiJE)?W-b^!Y-yr^x*DCv+!q<`g+}*OP}L*j?pl%E%1k zuQr>iZZd}j*q}8X@>(Fj$#774K>xOmRBZB&Qg~RwluiceOXZckB)Dc{YaY;-ro~W2 z%XFP}($PgzPTOr7$UvixVA9YnBH8|j+h@FD1*`yHN@|yAsjW%l0JvsNlrfD)R$7{@ zngd%g2KlW#qiE=~Zx5dt-Yt!9fEN`^8@)apy8;-k7G?<~(|b1^Ce{FSn=uZSGFM`dK9E8TrTO4UNlT18Zb zd~q1;n&EYx9GQti%IsfET4CC|iW0>_{Uh;4E)TWShs1{Y7@EjXA~#V2+p|y&j59#^ z>|RYoRSx?1pdgVd@AQeiA)h7H5$Dzw$6ij>bJi7Mss z(nh^`#ibA}I?9x|j3HDUTLkPXCI#rDOn#+ZDz7rnN*0GzPtmDu?ZQmw$BJ6Xn-LS( zA`XvkW4_csh3o|GGtNxa?{Mxpuj4T;AhZV*coKxQJVn;K1U{s?SFy|kw|-hE3r*T( z&rfKN+7Yz}8HoyxBpum1XBz{tT8eT?YTV7neCZxjcZ5}8)eZ#3$U>+jJDT!|aIUOf z+&Ap%Bjsf?u%g&&QgtR800gqm=9ydz5GA*x`{Ut}!#Z2hN%I(ElU#f{s#!SnmGVT-?H?Cn`oS`k_*|ymm zm37?5P+V!cVDDd2^Eg8&%eM$M4p1StG8ijyoBV3MZI58L&?)~~; zaG22ozWkF=dtMAx0a%=(MGLv5k=Wl=%B1Mi{jD0Z4or#Z8|p)kQqjSS!C0|PkEDjW zvX0OXSD~Vm+d%v%ZTXvg<|)Y$T0hk zcRYsiSq~&RHDyw02JI8{ekk2lhKA_kI}g!x&lmESzYN^a9s*QJ>W9jWUp=%9-e)F1 zydlnZ;3^i2v>f=sYgd0 zHe@-j@K3zI9!&(7{);!%_YBLRXLh;a9jWZmIy}EP^k@3@8$O!;HA4Z#kDk~&Zhwvv`7~-{t<+6b^ipj(r3_LJEL3RfAC66X5-Ho=B(^)R z;H~SREnh8%H(V;vh7m$-4o!q-K;MKqlLJsl#uJ8@{uG6pvpsm%K<2hUy8|`rOb{>Y zXhGI3U%s8zEZIIWM$YvYpL-BGMc*_Z!rne-3bnsWM!!`|@2m-v zwvoz5-!vTXkhdo+iFrnsKPz7H!=Y}c7}x$3Qnw=+&c;O(F(tlbzV2)GXz4UMgP~>J zJz=h|se6J0V~`Tz9{oX7PkAD~WyIG(wRF#QKoD}+(lP#BAv)JH#Ch>M zBsul@C^Zd7|O3h?fI!Ej@rD(t;U#J7YPDi?kBFImcF zuC}2z?{)ki4MVdR;;wc0YB4yY+7`Wy>MgPzFR;lU$3}J@wl`Iy1Rl4`!vDgCR5I|6 z^dn`!l*7=Ok*fy`Er(Io{figFJSX;OI}pu)wzP%a8glY`IxkF~1lewI9`pFDja|KKNt^bsoZZe%*pj%>0+2=zHnc(fS`uO(D} zh8=rz&EM@r726?MJ@SIw@R6t+e8Q-C=#HxV(nxGQJ4U61ZOeb6&fi(;Cwrk+-qd#? z{orgLDD0C2A~OGxv<>&7w!Yep+I&DcbovQg#n;=le!6U)3WRpP3k(u`zO`+95?w7- zIOMYbK(cJSiD#E^b)zC!R@+0ahKRE~zinF%plAZmS!~hIO&#&I;mKKc-N&}U%vo{; zdDtN7EnJO$w_(s*{tH6C{Dx@xXOQR;A8$T(PxVsQThj~a&;0hN)jHI(rQqPo5AIk< z@;%&u40k?-FgwUp&~zVc#^a)QI|krDDeQWT7Dm&jdMaOPJwlQ>X2P4Q@^W}bbCZeG zgd1IsczHb9Qw36x&4)hV!>qcP$=~gkXeOEH;fG9RUP|CZuHQfg1_l34qxk4GsP?c^ zOMJ995%}Dq_UQK?fw)*-e>nb?5Y&wOUjp%~VEN^y{@*d)B>#;-bT)B!b~G_C{+}T4 z|7T=2_y5@h(k32mc8fWsk~sQ?RZX+9vI z#c7e>l-$vx92z}ZGb%~BSDJJi-zIZmZrz%Uj-vDJKjXJ`0CDioig^714WfRCU;i06 zx81Ils6-gX0S6x2_fy`-X0dTcVZA*a2>LKQlDwg#sGPABC<}m6Qv_NCj0n7XQCif} zaNtnVkn#}rzQz7miOoHfQ=V5^=hxkkSb-o~1WLW(ZsK?4J(-dA`3p}T6E_A>vl~kf zuB)44r|-zM^SfH>DP*?HieDk_tL-2XOXbHj?q!`~Z~HL~yv@Y7TPM9aYqri~bmB&* zbJ%&|P9mhyD$~hUuTE`W4YyXXb{5-aJ`N4HLGphy(~70%p0$$~K4~@zzqv2lEbne0k#oW29hJb<{XV z=-2veY|JiOfcLIy0N**v5Ca~W{1N7`GE}P}?s}mvK^-DJQuc_nFQ|%oxOzlou(UNY z!Tc}peKtc}^bnJ^{fjNSnX~^fK0qNXQLt2vOLv39yHa7X!dkrwCg*@_7j#D`LJfnD zUN@Zgz4~+8IS_2B=`nkC&?7(1R;Aj9RC!6A{nw^v&7|Wv$z|qpCHcx^v3Kp!Nfc>2 zO12CtabU7LybNp#o%8@Yl5$Y9RhGq{9OqH1)zbk@ji%WdYU}6ys1L{csp){_lLj@J zv~d{sE)fa72zGQwf38BGlQo~JQMl~mrJjGNryN)-l zX)!F}H5!(h9W>hKdXuYo0!Gv6hM0n&$Oyqgdn81)6uKGmZT+&lLh@&yqr3ymo9>tj zDt%%i5UtomjkG`oq07PMI#x=o-L;;b^5z1f@|J{!apv+s<#i;WL~|Sv z$s#u|&LX#{w3#rUaM?GRzs4t$Ki>zyU;dBa75Q@XM51{|I`{0YG+h`hX}~}R1Wu5^ z8-XV$nIldhHlFD1gg4&djmkR?`FAeiVxO*y?geps*emfG^uwF-1)0B}ZhZC@p(o`X zQDC29JogsPH{~6n7lbq}fUW{QNL{gDDeR~;U51*7-JF+7nzjU?8c$nMk@%vjtEyG}=FW_IV5QcL@Z@A`^r1)*w4Oe?&!w@L( z_vk0&e@+lww{rQ6uXbJ*sQ>O46X*Zg0ibMQV{dJu@^z$0+SIfyf{(}WN4QfN%wj=OS>hwKSJX^J!R-C}2jys^ zwg_Y++r=bwk13&IH>elst~?EQF^6Lo=x3$6-92jR$N5%)8xRjIj4+{DcGj~R@hb@ z@csoKGmykEeNSjj4VT4!vi~EhID$bCzM6XbGfwnkY;`y~8U+Kq>fdMn0^6nO$NO%$ zs-)6qK;tN~&%7_iNn#VAWX~0;?RuaG+trCVfBzH@#WSi^u&-bpci&6{&++}#Hw4wP z86SwoxaBo3)nb9tUsrAT!Pc!Zm=o_4$p*NJK$7xw;&z={P!|mKSA6x^4HNmqe$^6X zj0K-Ymzm>~ltNcj3V0cy3LZcb)ypP+g{U7e8&XStRwteL;t&ztW)Pd>Fet8{j%&Kg7Wo$|22$K2Fy;~KkXxLKd7n+M zgsXN#eS}B#&#h7$&SICea}NcoRKB)8z}0`>=g;u{LwiP_a^DyGhs;7RLNIIPrv8Vd zyI~6jCjt1IP?YzhE=}?|m`M|7V-$f7>?I>M-7DOW2=&jhWe7jrZ+FyP5uPDpkHXM>Ehaben#T5B#@nxESM{Bkuy?4I*Bzl3 zqiY4?nge#b&+h(~XKyHzlOBx#v&4@fv{lshX<3>u6`XEif>L-DZQ;fp$UY<%&laPSyFN#5Ee$3yy3bJ@lX?rj@#y|5?e zRco}5+SJ@eOu8RSQcQyRK!skv-&(&trQr~a81_-7utQXuX^i2ay@a_vROdsP$&f}w z=`^dG%Xz)745sOYoVYeyqSM(44oT{~#gH|elt!Gki|*7B?>u*4B{>?5CJpq4x6z1> znXB7*!rw1{KOD}|T1yLu7`(K##>Gk@ksk=~uzVI-4Q`gbW*bh)$u}Kw#ZJc<@G{Fy8&f@3 z!L_30r)hP3$^#z_LY9nI0u8&bM2$(Q`A@|lXW~_F5<6+njH|5p(;Z_ccX=W00uc?n zo#e!fpEg3=|in-aHGDsyDXQ;dDnfd*wxCc3)$qav~_HTCd9 z2L~ye4JY|VG0sBbcI0mDU|eIHR7E?pjealaq)}Tec0iT1&^lFpqn0~YfwpIX2!7+< zr)MGzNQ;)QEh;XhdM9+#%{VLm)(+AYHwM!9U1Fp&8o*4<{6PaMitffc1NaD$ScXjf z)*1O_mJh50B<3mXSB`~-aA{64`4i=$FBR7d9co@O@}kAfC4z^W6nc~*AzuOXIYVF& zb2)pZ8Y;%YFp8X-6|B|kQK7g5sNI;$NfUyAMTtpwtJ70p6$iu_3f${a>!OrXWD4W5 z1j`QjGLcd*MH8%Y#bDG2z8dD2jVjc{DKU!mQe*=Q?l}wKcNJd+-m-mfYb6Wf6qJ&z z0_@;1(t-CUAc}W-7-~B;2GC11TgAFx4IR_}UOCHUqs)BRb+5W)!5C1m4|$PhQ6Xi* zDmyH@TDxz$S+L+tO<~R@cRXjnFfC&+(lO@)8KgLHrcoy&V|w#476WJKQX^+GlYSsY#8@K^ z1nanGQ*|+s*j*{Schzl^G~Id}ZOjbbFb!o)a2kwo|FenE?G(PC=`?$MPO6NCV2-k_ zzXti+S+_?%bySYl1C~09S2Fhw_&9>)22ZXQ3Ke@ypy9mNeyb)7OZ7wAWqDF>j6(x1 zz03m{v}GTuxP|ae+@);cfETVhW;*b?h9U+^r&+)|wY&-wM3-Tiov~dfbA1(uwHSPP zJz@kV7Gx7q^x9SgQ?D`-N6E zl3OLWfBF}n55LT9Y>b}NT#BS;pkdbX#A@jQH|G{t8`%F1&1j%A5KUS$KjGAK^W`|a zGn+V)_tP{G;zRBd`9(Eu3tsdS@MSTw-^B$)kVvyVNbT22u%>Mv&fVK{w3%(+L6I^{jO915B0gtm9N>jJlLqei+1 zGQ@M#A}#oOt2i<5ae|cw`&)hUs0Q3a>jZxvs}9@C*@2Re7zjE#6Y&*LVImwAA%sON zWQ;F8e9S))SLq&I-p|sGBNAx#o56Z(l({U;q=ry*ga%y?1~2=+bNYdgZiGd|6|n9u zZ;mp`Iz1UI6wYb=$T6Z^;6>8+Cj0EYGOa4Z>oaC&Jp5ULm}DX&XXN-wl#E1$Cul)q zb{@??wR%+L_*l@OWMpUh*C=(B=46ds*A(dV%9Q5DQ=tQR7iGBn0qe(hShmtkSc}xR z!tEcaMt99fEq#PP^6t;;4^a*9#)A7{E0H4Mez6m$J@h2AUC9f>?om8K#XIT2QvldM z87wHsfHE+TY($EBt1CLNPS~qREcVgB7(4zp+2lQ1;7cnI_^mZGl~950F`>dCwgSv9 zz-_a-Y*EFozd(>ED%C3FDZc}W?H}jp`RQmRiNgxs@Z~ z4Ej~|nV4jrxqAgV{^jsi3PFveiGZb;Bh zRHXLyQ2P9~{0Yz_o`1AAh zXuhc>zbAu^dk!}xxI#Gb-zQJ1Uu-wXmhm{3*WXX6PRTxcNV{o!?1jy!Aev>oJk(&Z zlN9Isp$uuyhc{>GG-?f^0WH ztt`n*2Mpa{F|;9+^_WHrq>2+q+T!#2EL%Z;!~%e)qKMl*UI#ACDNL4htv-5ph!z!+ z%YyUAjCgkwIKqNbRSK8}MfH%U1si}9;G)C=)SjnpHY{vHJ(h%=NgG%t9iAt?95y}G zvQ9wM&vb^OkG~SGbQWllMluR}Ky#Iv-4i~A&>7NPrRtt|z@5YQFqgnJ+n1dgL=*ja z&<jX5}7KOk}=p4@Sn^5O|&E&r*jy zVQzrEGSMbC@UtklDE!R)dAu_}eh%fElhBq7-mq!3qv8!{g9C4zydq_z zim#BrWA9Ax;5bxKV%L&d-Q83*%p zm&~k!e)p{Ebzc2nM3&sD)Qf(&Z{Pf|{(le%zfG*||8KfFTfy1o)QY6U!a>x?hvC(&daM(YYe}a8H+p=e!M%F0_>q%0&%&|3~SE=LD*Bp9;d^z3N}F-wdL- zA@%dt9pPwuP$p2>&t&cy-jSbl7awVq^Ujp!Jsxt)dZvFm^dj&k6tLe9d;iyk%5d|D znXQohoDfaugrv702jV?3$~vWB_MM;-aN0j+_U$kHR}9xXP@DZFD0X&R<=$g^{TM(< z@HuRB2}g8$vf6{V8(3Y{olD)8j3pyHLCC;4P<9M_$aIAJgbL`0oh@}4Yco@;#Tr_I zI5n7pBZ86BFk(h-T0h;8Mk>>jcFdxPYSpqjVIVM_U_}X@Y%pExFvb+ZU21H zsEZTXV5p##L;*!vdFWbmn*^L?c`^ov3tK9zUNZ3!FAfMWzLpBUR73#ZY7Bv6)xz|9 zI-+bux7fR>*lV55sB)bE=#GzqZ)u%rdE%WzB;^p5NhZE*Vf1EO9ds=B_0eLIqUE6) z_qw$7NCeCmmMU?hC#ZE;6qDKFKw*6)TGwDtGo@q|knM~;sA%cL=m^ouK3X+fk&88} zK#9m&4V=KYly-Kyu$Z%eb7CS6o78R1aHb9)w$YL=Cg-mS7YbGDEL_ zR4LNLr~bnSkV!Dpj(eH&;_8&I6(=pcI=~rPzR8Lx7XpxVYKIf|+?l77NQ;%b1k7Y~ zeoHCES-Ltig*Of9Vz^mC;A1TS{<@YjFKSOTLBeFNhXE=^OuoKIa<0 zuYryA{&YprK^;JDP>gM)OG>;|m+~t$HC?zySd11+t6&;(U>p{S1T@wa%vrl2YD!6% z*Vmi8n6IxDMm3g`r1oPn^(pq_OBTf-##|GG7FgdeJ2^mX*kg)l&MZ?8Dj?k`pfwp3 z2GXtmraxLo~@A!QQxxIgYO>}#*F!tOT=(n2-`w_BIjsp7; z^Evih8_01}5{(MGJs?RP9jMGHyQF9j=|iGQ;)`_WgfVT*%mQtqQ3YNxLjG0DF1BRwJRUthsg{ms+ zMf`xQ6An$SpPb5?`40oOjfR1*90MNFsKS$+LdZH9;0IrbtbuZQI2Vx?Ax6qTN&P8v zW`12p*H1My_gQLd3>r{fLWot!^vHSgg6COaf^KCU7wDI09&tmVt! z$f}RXIX?L zEBD0fPaaJ-Z=c&hQCfq+C3*xQlI;TUTG;BY{sAnIh|>jXH%N zCaTJsrBIgSwARQ>NHl07m*9HQ-60zBwj6BONfxGr(}w|F?X=h}pl40lEJx{$j%9me zpTDnc)+xA*sLn0GkcqQ^iaw2;u24MJ&$*aF67g;!aJG!aeU&kYmvwV^svp_!znDAn1oi_bktrV;b=~q)Q0jwF@O>n`QA55i5$` zEUl!3wJAN>Z2X9}axIe_ZeD6`qZnv1!6-L#wIuE`dQ3~Gi$dP}ZX#F5(u%ug7k+Jm z%30YY6rrP|1QC#JClPxh;9rYOG7n$MX&##=wbN2g)|u3WmGlryUT6mm-f`Lg#o9Xs zX99I?+8x`rZQHhO+a0T8+qTiMojkGaPM+9iC!NXr&o@=`pL{h_HK+S<*Iu<3u65rs z@$e815abtC>G`EHCDDum)ee(GezCC|pop9OHKyR8|Mq8=aw7rMtN~2NIN7Nu!?Ig7 zNvS>lE9q^{TfE70FHe9hZo&8$6Uit_P%$@S{WF*wcD?S{5y52_AnZ(`qJ3O90 zP^6YiR5hUCt%+x1J_M^v-0}s_ptd#vgAH$}*+$&2z1Mo=SDP#Jwj`bvG z&ID8Qj6y+iorXPdjo`=sPTZ3V+h%`3uYZ^!d+>wanMikI7iXFvQ+%jQBD=olC2)0&K(^0a zx$V#qKJocq14!l)O#wGJp&75RpJ8Csa2OWHVAM!FAMwMt2!*8Ne~-FAAK5n<0-10|@WT!F z2?f9X#_`jN7K^Msb)HY2_DKWJh^t?1Td%Se3@0W)6zlI+5sMWE&?>Jbj`EyWM(7nBdahdUq*8xTS=dWUpAFA|~Hi!Yt+3=p>%kb?-1&AfYve~<0*=STl*qH3tcx_QbV7;6%tw?cm-Y%JnuGZLYAeDn8!Q5lv}A5sqM zAF2-dy=uhrE74+^f+O|iVMOSL?gsGD><+T#j3uqrymrJ?Vt6?mtt;5j+E&n-e8WAs9yfiY1G7%YEw$UJ{W|2Wk8|R7ycXd;W%Td$0#~@Cyh9HBrtXSI z=E?iW^N*eEt_QqVb9WOPz>L|TAAShU_)$wjm~4_ymstH!YlL2cJ}NhZur%hdME%0Y z7pHI}kKa;}K+!r71oDUCPVV^e%VfU6pWo7+XGMn9W@o?p(3@}-1?@zA+ZC3bLDV9P zv%?~?!yFy{rLRRl2J(|cK7_e7%0ip9HelF=Ud)r?59#jH)S~5&`s`zbhP68fIpbnQ z!{dp=I26O-0m9bl+l*s6a8T}O?a`bDJnoPgOW^fo$2;Ztqo)8=E@7|u>URloXk|`0hRfDi)arIXT+J&-<4K_16r+g@UYT<7%2Xr!o1*i| zptB?aHx+cFCn7dZC1YO^qhCs(T)bX8e}N|-LJ(aAiC94qm5pN!;$}&Ui3`(?87`8V zBpnV4HfjDUOOE{!-|RnhThPS%EVwLJR4^XtV@J1vIC1>os^NT4mXhyAv>Xh1HQ4M6xBzsuC|P$^j%d zFfJA;Z$#dw4`v@B`qVOCee#6i@h`Ju>zo<5jU-RGS_bDj$;EhioT$vd}xCxPdo3J|~U@Z2SB8-_|Sy4yO8F3Z8?2jfk4i8W8~15qgq zUU_A%xS%D>GpVc-mkOPYlqa|T|Ewgc#BMpyzblE8|F)7~{68Bt$oyy4@IR+>4)Jn| z!@}_40uDBtE&ND9li^9mA?hQ+veIe6+M#fn#tIb*lxbrkxp5Fsd&d>FZLeYU5vT(ZM3eHL&5_6Lz`(+%lrJ>xN* z70|5B{!mt%ME5RtT&6n6UOp2XIMU|ypzdQu$IB`#F#a}LA#*dvKF*fQ=Y-Q6~(L={jT>*|?Ma|?H3PvMZ zr$4OfJEr=(WNOyX@B|)kATz6xCwr<-rlP2Zp)d~#w(rbZoN_H|eGsyMoj^${BY>Nr zQihtRRA>i50E3gIV@5k>;9?aMCF-$2tpdv;V7+rc7DRA>CL`M%h)RmL0oI;?=eh(N3+g(y58LEVceoHlcq&Q6dXe)5r9hUbD=D-|Tp1n7{r&411t9Rqrc$0nDYI4hoavfg4l#T^QCu z<}HvqzVo&WYi%P7l7Tzekm-Hh51=cQ0BRp>FKRzzPihaj4&U_Fl}mg9K<-xI9JZHS zx3-tu7+D|LAYYGdlxbSnC>8#!?e0%{oS8a2e%MC#G5?wcRLo{&p>jBUEly!f;s8uv zT$zBMIyChzopKWiO=d?g!G@{I#O&xW;2iJlK4y2zs9FnSA@@rwe#p?T z3dr(|AJK&8VB7&WNKne*74dz+3FQcZ`i|Js%OOlI>BS+>g4l)9L2PRuoCfRAfm_Q* zWVWyK?R)j#RXq0RbS)ED93CaEbb2dnF^(t9N~ewPC&pZcy7qnBsy>7xNs6QdtjH4Q zXtPQTn@UqvN{3Q!*byCXVZu9<8Wu7#D~qgJjbrdLj$AvNEXXldcSYsA6!jDIbAXMG z6(8Wf)?mzPr7`EMfi}NHOfV>S1y?8u$zbUoOdrX^!d6Dhwss^qd4>V4*6&65cEchV zop#{1La3(wV?`=ZfJ(+@0>@X@Bv;p(ahX0; zQoV-xEL|jHU#^RqfcmX7F`N3LBYBv{;?Cw2=N@`oHXEx^=A^GKy z4)aUf6AIvqZOGDok;1*3l7)y@B z$JUh!dx^;B!;#ReGj`q?BJt8P{9y5Hyh3*y4ehb~t^Frb0UFAEU`iW=zpl$l^7+aHIY%8C|JFuB41{vvg8snr$AbNd?Vo=zf zwgK8bj1jnKP8w^~p%AAC*G0xQy{2xB1Eg;u!{ZvJK2spY)8OkR(;XLf$t;fnt+Ik` zcJ6Ez8{40k8Tr3YClzx)j$MR63C@^{nTyAX@gxwJRHltJ3CqJDQ1l0Kf6h&ri41>> zJ!6aJdmXcw!}S3qG-2WRWYBNjr{h@0UN5oc zfVZjs!GymHwupI>bdcl5^Q)1~7cVjdt|(k<-(T~I83J5!FuMk+bz2Q&$;ZSDF%gq4 z-RPbw?nQzB6x_-TYg~N0wVk*r7J%9muE`6CfkQL2?NgQuZuH&sVQPd$ET!G_e>95O^(iea_9qY%+d`9U_SyMsY%%Gz+PL&vCOKbl5f?Jgp|#J++vH`kjZ#T0 z4%q_9=I-H>Fn?>vJ#%@N+BCDuNa1V!d?YL1uZ~~hF4@nHm!L=SBv@;#J%Ds%g~tz@ zca|G-s6Fin>E_jRNiezolJcy)52+(iDSndwI1|}LLwq?$$6`P1iFM>kB=P7-VTY+P zu)kF+=!D0OL=V8}-o*jO=S7C)k_TjIbP#}!BsDWNy8ljSCLoir1vJj#qL!qgrZ_8wLaQJcf}rs7D-4Zkl2F);wt)6 zQKjg~>XTPM094MmPg>SiH);%3VI`d;-T-6j)7)>A&Z}BlPkiZug^bh8_t_&?t^Q;R z;-IQPLp`0EJTY@5wYLSZEBW@;Qkg$IMsmpXGRLJr<|n-WM9?0XCjIs|2ebGcMgLDY znEyR?v}}H&tzrDzot9=>j16T-6oD90w4Z{@lti$k-%9yd>EI&2S*Iwh7=@U z3;yaomcG}HV5iB~bgVz4Xx}Aj01i|Sb~yMNUnLMZ|8Q6hHvf2P?smTc%i=XY)~a*% zKPCaUpzTivjz^KfSQvf@HGW2eNa!E)AsNo8{X*qHi=LqfEere;Tp{2T)$6Spgv0i; z9jhX%bb8~KDRrHle2XTo&!laYEeCDf&&^1^azZ(+`xhE9Csx(81r72!<3uzUv#?!z z=7uNu>nzLd7E88NETmoO30zl$9BWcMvGeJUMti9XOR`qkKlmkS!Un}E33Ura<*pHN$J=kI|icXQc zh?8tr>fXBX;z}(jfh{7@C|jvRqvG4emE*w{y19Rf@ZRBmWj$h*ImqN7Yi*LM!xy7C z6;t&|^CZ2=>tTPyG59R9s?xc_*_MQOW$oHJH?+(Z9{q)yKz`f1OHKf#>LN(Tsi|dK z>VZ$IW%Ie%$d$IYTT$Cu?8)!q$T*+C;fI!57%V($<5BL}kit_@2{^ivIj(jxWqM)z zo6M2JFLCexQnF%3A&axeG0F9Q&d}?E=g{~$@fsCdpc=d^_tA#% zC2lc7j-H@q@t-$|RX-@L$M@h-Y)0G3Z3+7B*)yDWZP|5Mzg^A}5MeckbG%|qUJYoq zh9UIHopBlWQ^Wu4v!*$3Xd^fsM2G)5K*HS})Cgw*LvIPU^U9b-Ot5qJ)8lWX+r=Ox za|;}CN4VKnGVk@FPlH)IurK52Nf1&aFtVXih~o;f&>^+>kQjz~RUVe=5Yd^x)%u8Y zdtebWDLAxw1;4R<OoacsMQ!}3VqHFjVZMoxe_*9<>CWd+Q<&x3loW0e_*d-9a z8IZDCv^IuqAw4g-b%skzzHM2{7~FJ``5OLZuUO00gd48x28mJhXI3mT24I)J99W7O zO;LPuNTjtlmYJ_zQ++~C-=H+pF-dsCAKn9OtQVH1?8D1C1Q6)1vGVnlD6b$jb_<$) zw~?aL#`A!FO9sZNrTMaW3mxuQi z+Yp!F-sX-&l*}-<{srBj4y^sQp3c%-(a%95 zpS(1co6U5kD}0C{`H`5*!MmKx^M@|;v=GCa`?R<0Ek*R?76;JslqujEQzB(j5xroz zK|QD9hLa|(CZHhLV%ImG8`o2vb`rLGv(3VQNL3FEvZ+Y-Dw?V8aqmC~$80gzSN3Q& z>NDXg;nszm3c{OV{_H0B$+Gash}*|$1@D_}b7dF&FcOXF!Y1RPsB7}x0V8Wht2J5BTUCz=dJ=!~mgYtHn3VgwMAQEiVS2@FPPp3&6Dc2biXa@bO#@CUO;ByK zh#s^_j+^$iM<$UimKri=%5E-j=`G|MbL$3S+hC9y8MG%nO7aOtY@hj8o0hc49E}D3 z<{s;LiQk%)C`T)ZVk?M3z!$;Jh;p={4q=)g$`?Uyg@#4K#55YL|4KC`Wv~Y@nh-rh zOEqY52T6sodC8B@KS1!4_(l2;QLQt5KtY9WaZ`7>NW%kVT+s7TPxf#cK_UR3>_Tx? zfQ-9bF9N1p%qd!DA{Vw`&AtRO_^=PLW;#( zh{;KB^2r@_5gkT+IPR#(mbIoq3pXPV5IJdH00RYWHLAVGLw?M9L8T zz-KLZS}rk=P<}*lEf|OIYQyu;IRxMF(FCiHF5;%DV*(CgZE9kM@N$&FFm||3a65cU zV|#xzkM{Z=_`TT{Lwud|;j8g65W{@^V1g7t9r0J=GR+ogd|!l#a7YkC;NG_%4@vGA zgyuOiqYtUeR*+3BxaK${<7ONA^8-U`#z-h*8LK`!A*TJyVL}a1pWQ#l{-w`Rpc@)3 z)tgCjupKhycM3>2yzMv?Ac-KF3ZsI^l{Bp(Q8px+Ytf>7tX<$O5m3oGy_7GFE6qQz zO}*F%-Ax_WT&*J)kP^O{*F&9ptOEs-27PSGcP-5?joJ#Vr0v=EXv}5T*wSXrPOQ*u z|DxQ>&XK2zdjnl6uDEHm=QyaHVPELz&!^1rY~`YCqI()e=NWvL*H@}rZI|QKYP_qooF!_MX=~(^OPG(WOuI+zu>yidz?(ocdW8!ZkqTxmCG8lVnME!_B5fG z1y`|M5^EaT@M|%th{TgKMV90Ijx$-ZxVL0i{k9xO#D9nxRVQekX0vrVpO98E(lRs3YRB?ZqMXL#@%F;h*>{4m^e!z3MuYQMy zp;YCSEyB2qtMn6FhLh)IJJDX|LQ*T;WkxU#5{FDv$xMrNg)6i#M=rfW zFRr{CZ71E-JoHLpv3g}Jiy`WJ4PfMozZ!@W^zP(?!_l;q#8Ps{Y2LN2jzwh=1bd0b zZZK(A2_QjmV^I=|!^bo(3b&nBxvLE?0P-M2+~o={BsPa_)b=U(EYC-f(Z<`Jjy>SU z?_1G_gkw4TDeuCMGQuDkvhL*Sq&do2buG1OCNxGxh-~|mAmSPhU(ol48|}H%JdHA|X~MGCrpNS;gTf7nK;rly44l7}%ALQZ!Z$?-*NQg~xMYW)%8z57 z-c3{|!0AdNQHzoth|6c>*Q?9|3p4(S9{cFhyE=*-*DN76kAhup5+t=xLrG3M-e=U~ zC*yB0Ou@OF-$ZMGo%Js7Nvc=lsrtHoDxKA|fV_z{SBfBzb*-PhE{QGpB(4|7Cgt(B zqfu4GbI`u6a9A2fJuVpXLW+e;7rkg9F_c0%v#Mw&)`D`(6eszaU>bGx&hcE{QAzs2 zy=1ccP@?yH?Hj$)BD!7r2xA6x-`ZgVTPsXR*0%&Ce@}n-#7JJ2&w{%<95&;|F7m2YH{1K!Wg7e}7AdH|39R2&JP)=g<%4 zeMsXTj7@$GmTOGyJ5|dQ$3qeB{Qbe>^}dgxZK)y{bTn32ClLH$TLGX&uAGfIRPe|A zCy4$`wl`piP9)~+&>-y%0+2%C4Nk^VN}_g0)*bebKVmY zFDGE2tG}gb3r9hGYDmb^qr-;6B6533wkZG7OaRuNqb`b^nE(Th{4Dg`6QkJz3#??vg!cXRn%1r6XT`1*rqmhEtys5tV@@~9xWYGN4jUI4iNGK zaJN@iVlf^|IU49&WYfq$7mgN}zwC*|RG$v2$7C;u$Y5&hgs8@3lg(r=xBf**oQMvO z*#v6*Gu&@|rO|ul*Yi+QY~!bj5z_mJYGWFH*08$x-Tw4@`b-P{{HFPJMxbM{c++Rz zSS7_**-GW;`MVo^J!zk?wodrFSzxwRV0O+sSMaoP2*}hx;c-YlOO$#W{<%-8$~s8( z8|g3H^X0I&Wf`1gO^fNbjCTU8ntXZ6GzZEH8)esRZ47pL7S(2qs;Oe86@M^wAcAI6 zSE}@KWU~uLxiQr2KGU?D3)6|OO1u;^MuG`0q6u&O0jQvv?aP)XnuNB!{ul{eR9}FadjXn3z~cEiE1OJ8~}1TMv@*& zrWX0CL;h!x$mNKv3!G+@fHuQ35cUpvH7cUf5Pt;n4xBUEsxU@tfqGX=-!GQ(4v9S` zut>u%ywr@4lP|q^CP{p9ALL}7MPVZjFV)w%Br3#+O^YwH+vj+G=Cr#pms)>P09#vxb~a%VE`}Q%wdSl;aB8#^e!)HF1~eC;+XouMJwVxvH2UILeH#a+%~g_wBN$1=wM!p1y| zofsv4VF2GG-WXjWwY~mirvHe()t(R=U!!O`UfG&RN^n)}5e^%5O3Ot!cqty}+Jb->Bd^EjT~5Zz{N;WkO+5?kof}0~8XLgP}zv z6GLyL6{1vEcq(Vh+c$udI|wGi0jwit;ta6lJvm3ejkw=l zcf@_?gQ9*jF~1K;U) z4-8We6d@vxR`XB;#YO)--cPGc+{3{5%OU5n&^Wq4>nt-?On>62kfE|`vO~@6{wk8H%P;Gd9Eb$OMq(@u zH~zAC)Kd|=VJ{AXT-x45Ka0_Gr+X_2-d7%pgh4NjazX^qJ2GHLOcuuY}oH4M?hT*TrwPbeW;Rk8^2xym+<3bvJniEfxVZp2`oUr|PQ8514pjLm#DL zv9swY*;zE%;jsiX^XD)uXxpk=k-KsmyTm$rqqusX__*}UcK6OnVvF-1sqo%Sie2nv znp=M*4_dFkbcsRLbQuIX(l%@#+Pmk7Fz~H>)o-aFm}olW2d6w*k!W7ox?$t=cZk^E zYZGyzXuQInJ@GW%nkJ(^Fwib){XkulWv9qWM%5du^f_Wz^h_W#%mEBU3BD&BCx$5S z3FtcUMyqk{E3r}`WJOa--c`DUT8%L6Rj+V{Wx8iY#Wm_Z;r+1F*i0QHgs@A0X#a(; z;hfsm{87F0>>=^~6axs|F&%62{(b}|iGNvwtLF~nz=uSC?J;0D$uazkNugKt9->mF zd3)zoAUlr9OrJZg@cdRPV1=s+nTy5lV`MwuavZI}fUl{gDFUjt&paSVw9kui?_%@}AP7fgULe z!XW2~SNDl?79hP<@pYi7wc<)s7`c+&D>lAksv$pIQ%yaHS4)r4m02H+V_Htj&LW3W zR-MUkTxnX*9fzac=Pk3c;iIv($^fbyrZlZK;-`@s1re=X8SU!Ai*|N8umBR?s9*mX zU8yWlraiJ~&V}dp7#=?rN9+#_go<~tCChc;%^HxOo8VouhGy-hWM0Z;)+&UU|U?ldz$+0qV z?Y_-=oK!FDqMTA@4?cVbn}u*AV&>ZMEPVqfk42sy0GZtFUJ^$&MF-rdWW%>ipYZ)P6t^pASBkpBISp#wo~o4NZfR9XXZ~}Oq0i+5Qu^m{`Bhc`pNsSMiCbW4dZGOXpR6RYm$^8BcWEO_O{vD2>^%V0 zfulZh>-YS`tUmEl^Kytg_j(uZd2*1ByrzT}GLyd4)NHg5BqH&Q={ zgnJ8WUpMua>fv$XFDqn28Ar8U7GEyMs!7qG$li#{yb*{g)P^ltT2ECa`!Nwr3*YE5P4qJ861vMCxh z&cbD`>|B8SZ~k96e_7agY;rBHq|T5n+Y?wb*(QlCwzr4Vk^wgSpU{3+t@S0j%b5rpPJaAff4cT^+V~u#WTEo?LTlL_myHRe|YN;llY9Cj)U$SClHv%D>iYllp zxJf`;LQIwei9`PmdRE5RVxd#wMxn58#Qz5Z)Iw&6oOBTd4eTTwOX5Iv@rr~UD)$ZX zD(~f0RyNhes$x4f_AaH^COHO=ktDa1ebo`cE*zGRGu|_^)yrN0Pt2RCGCt5x8o%x2 zAil#4s@XHbtRgolh5_G5j9^T(KDx*lH;|%o5WaRqo?V!1hTb(F0nKebp|bk@C2T|S` z<=*_rCID!kaHCxiICRXL07<3L8REG&@wN6%$2iud?Y8jOQ2N3+J_B@pL))^KU%)zI zIbTZ9d3pEB>sY`SCTMT==Y+BJi$Nep+=m(Jr4SoQxU0Sp_2cW5EAP(8y8m86kME#$ zz?wV`i5WPFi@TOT!^mEe^&fa4YY|U2OWn!ehh9>rZX>KG0-A@yf!pru^J(jnXVC|c zw%vJ+UD2hqzRId8NQ==(C~iLh!|;V_gDbFt(@L>+=zidtT(Lf0tckFK)y5IQ2`ckB zAK+RIY+nkmyP}^mxpIzcw6CvQl}A}7qv{jfQ)jxynLbv)BNpUc9{KS!Z*cA?SBP$O zKhd7Jvu$sb*5xP7ncp(F7FP(voR~65<1`4z zwysJ%Kal>D4D*Capqn^4-Z(b5L4RMi01Ntuvqj zqb(-xBbkJh_KqWxgflA+5a{mk=b7wDW9T_HVE&X86*zax13&)afN}atjnxX* ztJd4sXRK9UfW~P2Hgrpk1s=R*yQ-HI4XtO03`ec}gqnOuv5^G(lC8)HH zU@K+Z-wj}B(5cKHS33h|<#*lYz8@}8ZR~dRXuX~=R+1ESYT>gfs->CzTnVGpe-;xm zM8WQo9C-i|YK)Bu<_XU}C5Ym1k(tV3ahuTligbIGlz0f(ucmja^ozR6x9`UCx9&Gz z4{`#_eDI`|B-pk`h7kHJLNJe+nV7%6;^^Vc28RT;+vg(!;K1zdAK?yv$CD)91^bMv z!UEz^+L07fu~N3nX2oj2n--`IUTA(drE6N9{X023SA`RLyZ_Y(?f)FAL5VS1jU{)-Sr%{`3eD>vott zu$){-1yd`J`e@m&lIplnwzZ~v>hi+I@Yr>NY!!IinxzVUiop>ZiHt^0x#B1oKNb~u z5BHx3dzohMAomTsl>N6ZxBqt!_J2vH{ZCx1m-j!us4FMi-fT|k8KLkn%qB6|#Be6W z#FOCjwa79*WI(~4aVQhar_Cv6LB*?E>vyo~>Wp_Pvo&obQWHB0*J)R}S~Rw7YgRS& z?7m5+I=JNghuxeBc~-RHuRtRqZ_jJj>x~z|z|bykq+2LP(ki^FFI%`j#_9zD>n3J!XA$j%~UZ4b!rA<7&9Owo?SC zKFzl>vsc6S`R=xHNY0)8bzPen8mH^h$P6xDJ-~gNZ!G?zG0T_1!ybTuxE`u7y)Oyn zIK&C%ILfeXpLVAo&YQ3{>$wL}s{9D#Bz(VIkEcaye`pvE$~(2%-!kt>v^Z}v9f;oP z5gJz*j~DPtiZ$WOP2jZT0uE4zjCpM#(p{TJ8uTnqwOAjSLcQvM26bC}z%O-<#Ag7l zu8;?&%s+AoeC9_(raC)=C#;9`ZN_SDZ5`|P_fI-sAm{>AMwuE1j4a>!hkAdzK5&e_ zxsU!s;4_R_Ys~Mn8N0aCL;T>}H69b_$WZw+zU?;_&$U0}(GwQufyQXj>EyoW&@mVE z2e5VJ1y$38cGF^7fYEOSxM|M11|B=&yfoYW`;|kadq?=34W`+nH5$UYOLg!GEi1-c z8EyxT@zlOj_Uv5qE>YpYuPs%8RDb9i4aWp; z7FtJ(Ax-6c7u|7O!Hf6M{8{6erVLpU;6x0JukJ23S=p)&-$7tlrovxs*hIU1U-k%v zktxOfL@{jT_{$f(YfWEEiXNwJSe^j3YaG$dgZm7{N2@iDiMAj{Z4FQ` zcaAELEZrt_3OBO3;%@SV=#;9QG8d$A{hkj;I$zY@0^+cE<1R4N>139!mPb>CiB`HIvj5VdjKt zpef$6)~k3B?{e;U&h7Rj@(U6sT-DVOvd(uTT5N_h}Nt>Hlm8SG&#!d zhgWVjPqk0wYLbias0b~#^lt*&Z@Fikbsc?HUamPDjw})~K4=w%igv1M?-?jJ9-w+0<~z+L9qYUlN>DOuG$aCn+mV!@F;BsyoP?W%#7eMX4u z@K4z7;Tf`9Y7G7Z8d3CDkPqcSGV7!}6bK?f39MkaQ1aavtYEy-{F(U_Rz19LJB=57 zVDVncEBcBq8AkO$opVmCkj5UiphA(#pcVE?^J^~X-#t!BySP);)BNKev{82ZwuUsE+paxz4>i2|h3t;;qzKXRo zfa0+Ka^8H1zDo9>O8q|)z5hk#B;0kx7EpVEMxcW*lP}H0V|yv0h-RL)P>Z5kN@$1D z!_|=52VVz9VC)n7iK6JJL&dvaq9@J#;xP@TceU789}!Qgi1cHT!A!wm3G+f>R4I(C zGR>whr!$3wPYRQSbds1Ji9jCd5rtJ8CO>v#&izvbVJU$gt%lA5moN!bmq3r&pb6-m z#5*&Wh~zP?r;n~eRut%urXDOoABMwFp`Ao$QA#C~pFp4X_7}{fL4YEH_GG}|dMaW* za+Bx)fa=hzi-&2KMgo8>=%(=FtV}8+XFzs|T$1$3p^`}1)uHbXDW)u1n`D-p>|Ip< zH+is6^2vEwJ?X5eT^~&~y2?yf?S8rDGEK2zZ7P6Pf<3YsqfwWAvRDSiZbVn7R&9hw z{%0>~c9tRBKWUUY(-3;j`x{D~78=v$b<&u+Xl|`sDG?QvlNdPjeT@-LzoellTu%%g zGdch>zY&U{2&5{&BUDEwi3VAjuP3P5S*kYYr&jw^#k2FQCNd8sG<%Y6+co2^>$gs_ z9urS{t@#B-^eJ*)>{^Jj%l#9x=$#jx9BqdZVc^2hs|le&nM#kGT7mL2cDPd^{$5-- z^w0D3#`}*{dAmcW365+JlNBd?lrKOv=3}Qcz2hE_8@cQd$uyx>p4`MR(Sm{A@UW-o zq{dyAO={|BrCqssb$?YkF@2rx$~nz!Z1Ld|t!@+>B}R~qtvcqaxVl$sk@=$qbKFd< z9{*4=y1$3d@XWac3&*(o7xqy{%MMZLu=T2Jzlu4UL_Nd{FD4i-Qgi zFI$V^dRwMulYna(d$TIst_Q_E(~?zw6V0@Q87nYKTX(r?HjP(&`OhRUt&H%L;R2 zymeB6t6Ff(6{V8$E;zF&PhJSgSFFB7^G{lXeiH{)t&Ekm8xTTe(H5V$pz{j4@U#$ISRqu?xQ>oz}n`+jh&9Xt| z-P()ms6~?2I|IP{XSz!hCveAv-#ZZw`fB4QmfgfFH^^J&UNZn0`$jU}2LW!b&`p_J z^GXCc&1@Ub9o`TB2^lM{BD7~&E5nO+d>{S%Ml&KoOUFfQ)Q=h1CiyoeIR)x>sTN(z z{)!1}lZZB5)|{j^w+HfX4YEG>U1xEJyT4sPm%(bH;V_ISM}Vn-?(!HY2thZQEFLLC zkuHOSf_(0pN%)hR76J5I7pIH5e3kTplemnqgN#3~2dS*Lg-teFr-l7+MJeLJjg*C% zcEEc3L7;dxpQ19aj(Bl2Xl%QfgU(uQRZluFy1sc+SzZp|4bW=ymczy`l|d*vsHMs~ zcjqVo$WiXldg*#32mJ=djP@U)&b{u#t=zf)YQ=u`*)4?N(`-d5uj16Y`^`M)ycz5{aZXkj7xD z-CBc+J0wROd-}B?K*>lQM^A2B{?XuhN$S(7I>r>ZY7hh^epE{xc*b6+WeeF4)7%oQ zBS3QnA;7*Gp#KVZvFTsCpQ?ZMh1!;3_Fu-j6~GN7x?ViK3IBZb<>{ZYJ@9R5OeqLM zyM=;b8}fG+YK^eA6q0@<5_UK<8CZl8Y2i_b5a9(sUThLGF2d=odkkoR55_P-wug=w z41mTjJBkpdq3EbpT_PE0%=5%{y>pvvFKk&Nm-5* zEQg#1n(!03ysI=I^O&W3`jgooDYbjLJRozwv11zbYZA(&T<$tTG@*5wqLZGH?(7&n zVVUdEZRo^VCWKjTV3bZ_o$HY!?xRZF@TAEa!Ho;LIV*w(+Sj;EkOk}P6kQ0Kf?T~S zWxYU4(MU*{uVBS-ak(!G9pP{T(G`V?hC3mZ9YZtugewuQu3Uv|kX?kYHta`j2z4%4 zLC}*k2m7%5Jm{ZbO;lfwymN)0mRpe#Gq>pWLH$FW*;Q>JdC$|KC5POYn>;uH;sROE zR)Y!qE)A$3v|gfaH6E;&EUz#)<}6p<$+rz}yWcDQ1T!6}y8nZ*cMOs&inevT+-2Lg zZQHhO+qP}9%eGxzwrzJQ%dgHk7x8}Fb8r6Ikr6v%$BvA(<{D$pZ|so*D0yVfa7f0@ zE$SfiN}nR08DkKH?H!dD5Ljo+Cc*Hc42VBf!Jo)klT9|GQ(uQ)^m<6@Z=f%Qf#C zZfe=+zzE>VyE#6mkYDw#rn^KwT3_+g@Pw(JS$rpu#)cWB0tL5Yp>4Q`+v?AgJ!ZPJ zK~QUomOs@aPU_9#aZB&PU%3LBN>$^+t2_5z`IqOavZuM}dQf%<;t#yD`bl?$DGdf#eiilI@N4!`lp>T7kD^NB(9zHRDpjo(O=8b;f&yP7xy1;0_`%RP z@ZEa>HHhYTWlq=*o1{@s88oJOVx|>>8 zIOkmavcV65Lq<3SakModJx{zj458gDP#ofo4ckpFE}lCmvJ2@gOxMv2b83V+HennN zbv%aYyqa0WEYl&cvJQ=1Ye}4$tw|XBH8fTTpVoO5NoVK_-o1^!?&qCRE=j-)Q1P;GRuP1YG>g6&n!7JdkZ_X`|& zN1|YFDx?W{@Rd=*xP+8t>ko{)2mIP&*!!@lLti`A z+X(Glz#2S!l<-}G2P7Vve-QD3ugCCFKyjH3puv)f$4(1QK4YbyaS}^DYh#Zx89k2; zY#(z`^sf4x$z$fx)MLkmw%g#1u3KXLD80;lU%d={Z?!CakG+h2zpbooPgOE#l>}2S zT`qK2+IbJQ5@sg_Yj1V|%R?KgziUDCj@=T!Tio$he*u1fcVX(T_Yum6q6ZpZ@;l&g z0TM7A!(h^ypqN%{QY+Tv$-VKHusQpsXs8<=^+7ko)-PZ*{s8phr)K64MV_WN&U;18 zG4aEN{%gOl^5D&}7^Gn_F-RoMH`5?9u$~4?bK(R>u5jO!OvgaqAFYDQrX=_%O+{aA z5{!9A4PbqWQ>uJKLdAD$6h-cq5sgZ1=Ed~`=>vl}??u%MR39L7Q&jwiW!Ml+UGc(Q z#f@9CPUMkWE5uoH3N<+yFUV%;M)(1=Q_!JZ(LcZcym*`4tWLN+wih2lFO4%O%Eh-Z z%@d0r?n#fbu){AH$01t|vAjb`-WcpCHnlmev?~i2aRtF$P#2ZW=A(yCOeu*-V8MeZF ze<3*Wfo`&R*Pheh5Fw&q?!*^=!KeB{GI?pTfR+onnIT~E5g6ekxCO);lFomGWX?}0 zqP`L$PQCtuB1_%i54gf)CS#Fc@<$)Pn@8XbXC<~0L`d3ZW;{i)q?MIS#_GTgT2EjG zAHzD2PsHGdTQue11AR4?lDMNe)QAaKOu57&Qq~X){ss9BnUp7ofK-?oX(v#Va|C+K zk4Eh0r>+PDW2Z!S&NJ~F9~NZ72qaRs57HOgkfbb%MCMsB12k*FxYLlOY?0Y0 z>8vDc-e^m6iuHGZ&S@Udnm4|T>rTbzOt<<&%1{1^K32J+LcZLlDQqOF-MpFtb(vw% zQ{R6G?oNC(WYFlper^4L)c?=Zr2_vAwnNm}`6mF=($L14;s@Q4?ZBVWQ|{cw~uR{8e0CwhI#_=DC@% zyJ>uT@OQELdrhiZ^*kDYi@G~^jWn+=_aOmA>{g$8rSp!LnRD;k4&Snump=S2C<9=8 zQwId(ZH@r-CJ$KjMh{%{mM1Z^bcII7%)nUoruLXhnw>$^o^D&?jnQQqoD>$f(b4Ky zcN?81MYDPl6h@q36Kyx0c z23n~-Fzj=7(K@47*w`l+Hpnm=#=)yFp*&Ix6CQ#bwsrs5+e#WW3ukZ1KUu#pT8Kfw z*3og|R>Wh5ZMrF}{GwVgWn#=ZXW$l|b^1%K?c8lvW^~9kw5OE2U>A*wDH)}!NEP8p z1A=;vmM3Y$qoT#`}hR3SLDXy+t!M_lbp zQl9jg>3KA&H@;j#*HdG`IODt>hVK2%6FYnJ-2fW4i(cWEY^Iq)-4EpOD*9!!U5vub z4+5pLF=zvT;AQU38_PNfhs-77KeKb+sJzTU-}=FI{e-v3ZWM6K>rgNaBui`L?G>~* zC7XiCQE3i13~6)IM|PPfC9+eHe+!Q~G#@c4AZWrMmYwLatED}@vbTs=5No>v>_b}` zAedp^7(~QVcfV&o0QP4c;Wzi-UYLF#r|{dErd-@|eWLZik6NraO?(3>s75PMdz!8^ z8r)@zh=X#45abR@4+ZevZKtB$F^U)WDC=<5eGF!Yk9YY?pO{gPbJ;kbr(jSV(xVuo z-{wa82o3a+Yw99b)q}D-Re-pP2_ip+9g)i%F2q?pVpQxS4(T{_hsPJTmPHvOqoF$fxcS^=Ud;GJnxwf z^FH*v_q(om#Ca9gpC*0I+38ms44cmN5j*zS17P$rT1%)>$|SP{mf%uMB>^}(x;-R3 zs$wN{_(NqFzGd0qj((H)$02AB(0CTl6rUKk2g@r|CF77K4NYwGJC9^}c8{QJa;MB} za>tHrF^A9qRVWcvAbGR=?6P}IFrLs^7SF1LY_)##dl&ZEy-Z*(>5RPV6HcDhBTu@{ z$kVCEbuxMe&%y+4lJP27y{i)}y@Mj`R~+{Kv@9L#e@p}X8%NHj4RRDK+1*=5;K}MJ zcb?r!Wmu-oRRQV`S-^Tzr_xPwY_;wW;9nsF=;LFd3pz(9(d+vCvN#MKnjDZ&_OxVe zSzBgK5*ZyLt+8(RVsKNO8?td3IH`u=Igd)o#zd{{6OhT=y3N7tl1-Xfv~)O@fBNl` zPm+tmreu1zj^s0aLMQUkfb$t&n;IQTS=1wEYS{o-!F8xWeltgxTP~FTJF>VRV8MMB z|I$SS_0f3!M8))3U%is;835LHojGmTKE>I!d%&-N&I$HRpQZ`!kRk1(@m+>FtFrbI6DHvKXE*=l3K~mcA&W)8T!1JrN9#sOdBIo1nK`{ z6AmxFt(aeKgTN?HHEIv`i)X955iMeP_~&V0u3_n_aWfFCGHpLHq9lLHkRQByQ1b=m zPB0pn7Xk*;(k!YquPh~5MqQ*d`(pnb3Y4|E7?H5$o8rRNU{=1klgKXWHjyG+NnFg$ z@9$2u*4Oh=9khGo&6XIpCLnKJz>%-%(kar-Pf3+&G2?3V8fOEvtfCdEyB!MFDZ_74t z>S&K4V`+7Kh4s#f;$7_cMACMm+_rIJX&UCPH#rWha&Zbh|UMh1|jO;pdQhWahJ zntz_=shYS|pP4bc$M(XTX zk=@g={UtR10r?`df8Za8b^50ub=QK)w0=?fEC9>sol|p~H|8EwM|k{30K^B);;@cY z^-9+wRlqh;@v2BsZjG&EANJOik?hLi-L4?3mj{i6!lp{0P!oMFx(euWRdIK9d#cF?@|{^;p#Cxrg%? zsQ6aB`;5gD%N0`s_F+Wy!8Zx+&K8bjvuDB7?}^w)>l;fL;RocS_04`W0sLvc*!=?> z?C$-Cqu?G8qrWD_VZZ7|@S%o=8qGPQ;{_R`P>69gq$tA+bJ8Z2U+ekki;~+o(XP)B zz7}9K9_cSlkNb>3U|<|7SKqeRuPfh zM&Auh60oi*39B&rY(+cJkJd;v511FZc^fw3?h{B!NW-d@reTpyQ!eB{;Va{@ZYdEj zNo2%gg<3&Kvd&?qB`s!m&wET2v`Xqt(CD>8C2;k8adam3z%g(l$qGTQnW!wLVb#b9 zdrUwYQ_`~(j7E&ykZsjP#rJ9NabzZ^Vf`5;1hbyXiOGP=S3E4`#1%^D~r!4 zB-5}W;s-xf<3Ld-0#}P0DSTQHagZKt!yp&ejSw-al&r$(JeQqoG^>OPwT)|Nl#d;m z!-;PAKm}9Lv}*jPc>xniZ$)EJJ-O5wP(c|%dLd(37S+P2!VPOzHzNd4UL5%=4x2&c z;EcoJDQ8H<{|ampkg!6JKJ@+$dhhj(hP%#WqPtd}7AO=izoej?rjowUvjb%x{fexV z1wWm(m^pgX?Z66-d|+_TH@_nH`>s;<%fY<95R6T;mBSpC<*5AtjIgkp&0A49;GiV^ zs*2+ZFO!PN&dc|Io`f15Oon2NEkKZGjT|Sb+ zT-o^WgrY@##l#fwD5{zl1(KXozq;JCZ|uV%VQ9JWNWDjB+gM6-=LQV4^N`Ja>ZSjHtWCkoxfSG!u zXX#fqNSK+62xWgmI{tu0%uW`C!Mc7yP;f!KVooZ@UJpf`(il^o*uGkNC(2(Tmp!ij)E5#2d@urB~IpT<&Ix7ZJB zJS>+Z;MCG}Jz&paOEO>}lW1e3JU1b^x--y!m0fNY=UKIJu;pEs#Mbj=dD*T96XQ|!^71)s|YF&ZkIHgt%b z+48t1c9iYSc#iF(p?`O)n*pb`Wj9Lg1W9K@jV-6dgc*;125UFsjczWi?tahNCu;V- z$0u$!ZEp!&VpL%1w0tx0 zetDk9=&^SGA1*97kVIH!md)-A1uk5;%O=iLvXQ-wkNaZ^y=f9>cM<IWAzo-A;4k?@WRzLfPg6R= zn$OaAkk=%qe^eZKqM>8)`a>T%bs)b-4f46O(c1iMlgz)ej!&1C+2~~XAIz(xL`jNV z=cflWTH*$fC*#5=@R*DQO9=Pv9m}pKY8n|mEX(Wp$X9*TLT)tbabFO$n-{0}lDcT0 z#x`xz|8NBoKhmS%u%6Z#yiv?@&upl&KGpwu3p-}LyzA&SGZp^FX>GXBS~ar8m3=Uw zp|;V6A)VjOX=pD6g3O*S$!qd$#zcN^gZ_8d`ge}gngyDQd4tCBaV1YG}$zx$4Z_6$wu3QKI~zm%Rc9Oqs3aSt~8g-u&+_ z3RE~rQxTDkNCRDb@WeumqqVm(i_I!n^x%B|=mYcUCDZ7f^^RGGZjn8t`{?FXJsSK1 z#)e#R#CQSr5h+wL_7S7hOWXW)XJ7Em(xULclMYDNPz7)K{QH$U?cUD162-pfSVG+v(L~_L{aLb~YF65G` zrh>dUzi=^Kn_yGXPVmp)93o`eC-n6JnuMXy<~P zu!HyFFFT~CD3S{z!D(W+BxdYq=Zb_hGXr`lWBMRY-l7I{(gtczep#b$vR;@+|AR(`OHfYZ)@ zzAAIFXu?6EGTh_l@+gcj#&g6h9@{`zN;+Gjq^R30Dl|nU?I^P7u$M*3lU-*^cv+;n z=$>wgbwXj=EIRYFEYFBo4YeL64~keVGlUO8uLQAnJQC%&1h+4YtYzV9K(`u&d~lLR z_#vVC=&`qDi@5!ax`!DF>4S{m(sTNUT;;mYi5<(#E7j*yTl@}hizpXem4;}t4IR9a$)lxQ7M0sNCj)<{=DDWi;DIe7uk zc}vf^?DjW^KfUW!<@3rJ4n~Hce)5aVtyYFyaJDGIlhn@(M|A&iiH16|bK>3?KaQ>6 zA+0-yZ1!R@=A>!kmkPjg$`*^yaT*Wh^?pqS2Q*B!20<^X)mQb&PEVRCn?E*GQd-!6 znwQm3TgoV>t~kbbau2B#v|6@`3YePH)?FwrJ}*2@(q%EeYTwmEaycZrLBjjh0D4yQ zYhKsavev_EG}*Kny4L@3l22^9G-+w9UQ zEp{layMKOjRAKBTSlQKVpuUhn=a*t-t{rzCS{hn=)+vo!;=SC| ztc_dzj$`-MYW#cqwn9K90mG3Q7Wn%2XFwh)IRjkzX@Y4KKv<;nG!gsfFqcOS3ZK3R z&v*(Y{}(G{hinMcU0S6QE% z{^ca;FEK(EbF)dBpFKwvsnuUgWS-dmb0lNrjXE$fdQasbL9;1NDt_j(s#wK%)*l*pK*|sNV@mas{ zUYk!wbu3}ic>#nUe@^t`H!Y`(oxRxEXKpQyU;I73lIGUErV3m_LT5`KWx6@@@dJ}A zCv%|xR|$`yDZaeLU)*|EuNs;1VB}?>3Ee+QhIw$lFm~YorX1a36RPo&LPv78LPNg< z5OjLdS6t>d4j!UcUFY9e+BA!8*=-e?TkW^R5t-!E@t)4JjD(d-I5ksC;~Ec@8)PH4%2i2p*TbWump;vDquCbE zTf7h*@yakePHqUa0F0azFNm*)^Z z%)C=wXPkZsdE&o41O27=Pt?yv{j&Xv#O9@~h(2YeOVd?(dy43a)KwvR%G?&{mDy>p za>e{pkf0No&*gthN#RhS8ZlhZ`j0B^|0P!OPlKLD)Z*Qzm}WYg9!l{KNy8<@_wgLx z;uBrVKd(8e=?~X~O5l;0+)Acw35M zW4=7;Ti8v?rkAn9v&+tJNT=H|_9hMc;`Oeyl-J50dOSYB1+8;eO#6zBI_LfS$s9a* zM-ocj5}^`^-E=#@Ypa#hpR;6McUvmZb4|~^DEba-nVd{1j?N1Iyd8&)!Tkf9{Xz4XzL5Z5mLrnA#4xSolqiOo8-GK3UYO+=@j~O}w{EALn(@CR z?*OD3kfm1!QFrAD8}<8>;AT^LTT^(e0b5DVX*W-uW1=8&KB@zdtiGh2rgCU0%wlh#Y7R#bn!^-b~V z%R=C*@k{5t55Ln1`F!$kz{8O_ue{%==fB0%iEoPk`f~V`(I&0WpsAb4moI%xfOj_* zO0{btwI^ABk_WW6Z|nA*8gq9*?DXb+}36MX$)a|deq zV+#30(EK0H7ff%I`9D{l=(Y!(oeAex!Mw5AJ0HJD^t;RMgx!G~_;#(14l&dRB-XT9 zMLxYMv%3x}y46Z&j}EIn@a4bMDnYZ#>i1GDx$2d<-D1}#Ef+v~bu-|0q8`(G=BkPKsw@Z~bki$fuNg?z83`$-u7{uXtpFj;`mEz(I>E+_` z#&r7eC35VK5_;(}A_uT8DPPgQ9!mVSsW7#KfP(pOTvF1oU9M7I7pcRgn14H31phq@ z6Hwy29Bz_5Rk#X{^R{SSd0cf{OmJR|61!R(jbMNWqQfu8PFcCP*bk;J@#)2A#p%}_ zkq_>O6mw*b-A{87!jcKqf^rjLnwbB^28G)mSiyo{%z`cv$3{63cYZZNcHsdz6_xww zn!AhRQY-+^c22e-$4-Cu6Hr{Pjpp%%{vUF@cAmHl-;Zra%lcn({LhTnk1!vmt0niN z!2hog-p`e>y)C_|p_7XRldUPe>HqTT=$$Ri?VNvz2_T>-zkdJz{Y$z-^Z$1*_5bx= z<)2@Ww)`Ja2Q}*N{y3_r-#b@_a%_t%G?ojp(u?kkc1fj>@oa%au$G#V$~HpQzY-^I zSTfDr%`$Ukv3&@rfQcxmtPb8W@#nRylhdG-1*FA7) zav}_XF(a!(a0jS35SNI{_aRHqt;VhIP&6Y9kjP2pMCW2CVdbk%$Cmy%lD>xg15EtR z8!RWuiz`6QSDP|l`ls2#Q*4sIcvl^En(}aZdFR<(kfER8p*SRsq#v^5*|Ab!#NK`ZfX*TRa?3v{kMSK z?ikDsrX3pj!Jjw^CfeK2D z6p|aQ=g+1vc4ZUgo3+MG{*i^x_D?mBYFiHqJ1*W3au~^CM8<2zk%Y4?R}DKrn~y14 z?t|l+kw>c8J>2+c6^!zb)taq;zEvjwdZrmOC(UJCqBv2}Q&%(5d-9iU?#RQ?NYWY0 zWY+eFUEKe+0OPYIo>Bs(K((mENesxT?-tbeTuv}AA%nx@?2ALvCl&xBlD?l;@@-I( z++@}zKAs11hu%`Umly$7hs*q^HY|UL6fC#jav1x2ybe?DlO|w2@;OwS$mZ?4_VdbI zBkd(*kT;Q-dEOF~9h6Uiqzjek_iL0@!yw2ji=lUy?rD9r$K3C9BX7?Ee184ot{({e z3-`t!B4aduliTU$i(3tfrLM_w`TM6XrHAMl$$-*0{r%?tX;TJ5gg!rX8p}&S%fGcy z=4zwwl5;uE*2+V64r+zVzId*4%D~R4CSCQBz7fu_T4TLRR(lZ&z*_8ZQ1XQ9xrgAg?3RC?`HK#$J440fe^bcs*>U~H_%;0W zUkw_F+dk!oBnm#ovYMn&QoUb!&FNMo418Pi&@{9w1J}J(wS$e@lYB&-R-0>bw5;Ch zvRIhZvWh!Q?#JJ=1}CVDQ{|2_&MPlPafv&cwg5C{HG7(wA^w*Ns?YFvI1+H%eJl>? zk{!h}&fq!8-TW~;scmgFOO%%s5<$Ur4K>v&TCZO=Gui)c#daW=`aJH+T1{R-tJZ$g zp;;5#s##L9##0j&S`g|qlh&8&w4{lSbIMsGR^b;R3dhdtnzqs$!o+vYNV2|t3bSX( zqnxpEnsL`^{x#4HU;x`Mx?qJGaeG89F-_lKusL!n%SAh@@cBp`lGe4#Yg(i3Ozmsi zi{-9;Dv^}N5~d+!e(@JSaiznPBf&cXIF8Bw8OC*3`!j93y7o|Knz|s;@u7YlC1JHC zBfDk(?*e^Ig|m|s9V&Jxt#kVFuQF%ce2KZ)!wAXsEJr1zA1p#}9CsQ9t;`*`L=2VP zU^-(?**~N#<N z_Z2Pj9kFSaVJRBhJ+UAAQs1wT&eD#Z(Y8%RVW@v`ReU{kM4f-Na6Cms22G8aSnYO>i+dM1s#M)KMw7g7Yo2L!?L|WoTg&Gb(*xt<< zVk>0++gEkkKBYDDwu*?`JA_M*(4FNOKy?R9z=+N{(wk*tv16J3^>3XRZzM0tOUbl z+W|*m9^r6##%y`T6O8pc@ShhZMeebUJTkbMf^@Z;LC%v;ShaWAl?z(6XZ`9*At5-| zt=-rmkAw^k;qUi5LZwrwv$?ZlM=yM(HS{+kE{W7R!Kx5AB~q6Jsv_d3HtDmq0RJ?G zG6yH}qrQgpy}j@0Z&imBj5H64gNj)mH55r73?ZWu`NDJCh!FTvhTP>t!`gU&?FYq> zax4wTjoo9I_3nRq?ho;{;tCMIe#s&Hcb+@L|I( z>7zYF1OBKkvcCHPjqG&t0mZo)OQ0&CEx5E$BjT$}yN-x{WMr!&=M_;7z%h-k^sdGbii3Zr5$t>7aMb$)ks0J{P zgO)&EbXv8Jp$HLd8SiKYfM^0~>rW|aLDinOs5FtfC}1joFp9>%4YgLD&!;8SZrE&y z^)Xew1}|pNx`G@PjnHno(5E4E6*HRZu!7O#u2TWsfcm-;MJoD+$D-hA5fzlxH-I9R z9y{XoaT;nz#<)-w^C%GMArpYbi7Y8JCg0fU)LBKHMsa?zUHtlAI8xF<1K_C+oW39_sJh%JPpZ*9lI0q~|i zA<4i#P35*}ELD)QrGuW@s^9F*ghS40QM#ng44`O2E?V-UC&6)%rc^3v~Vdy(&ZV(=Z5M!{A-B9MnYtN6Au1112F{Lui> zQBj?wduqSr`9NnCNwf!z(OU^9gq5lG7)ea!cA`V7F9P2XRoqIp@%Auk6c1C2m@P8N zoIC;7(}J1X?jjI+&i?R)F=Xk6<;VOtuK)95 zV0SFE#@_Ul=4*3IsZ$DWEKy>T!VAt`_i?S%Y=LPs^flI2eXNm&$rz~3Eb{ng;U;x6 zX`QBN*0NhbTmzw-)(z8m1=X!B$(?c5eD>sMNX^K{hZITHh=95{1;$P;Z>Mu}h@KTT z;UUAeb(CoGs>f|k@@hqp9J8_#WM?oj9a*h8hY&j2LZWF1qwbVy+riP++QUNx<-85C za=bI7MY&nSW^MGYVX4Wr0y$<)y>w{lQCtQhX5r%3iY$2M(yVKxj*ZUZ5F*v>^EgI<@Z!B0n81v3Qx<9}r|W zFJ2st8VV;FJ@-Ls~B@L+$Hj!&iUV`1HUy4|Z z6xgtg+|b4R6Ka-4pJYa4o87gZ*~%Z8WTxH{-Bo`^RpKXKd5CrNWpql?b4bSc!Zc~8 z!i}Ajp{{@38S;;Whb6-w6B>&LRgNz;wp@V{K||F_jB&!!wtZKyGZcm_(n>zIe6XoP z(W2Vzt*l<7AbbD`XgN-j<`|o1im*Bl=a(XhA?kc9mUKgypW6~5A)i+}%O1tZ3ySD7 z%}82eJNL0(+HfRIB(f$Fc_WEjiDb$d>58CrZu6KUsO05=OPUY>TU&%D#c)aV7ZP4s znx5>r3?RAH#2{_9i6;`(oC1W0I$6UN%M>?I8c&!boO6LrKTUvO-;Xd4NF(V zyR75^C2je4RSpl;Af6t%H)N7(lz=vi(Vss@`u}lkJ#D0gZ~_1ID+=zv+tL0zyu*JT zTmR$e`Jeq{B!af~u68c}J1Fjd@<`||S87~f#&YcTxI58PpkNp=32BT)l0r${5@`JH zYjp}sE@f5|0d*!MMl4u-@5M2vX<&p%#g|FWZa+X0&mSPk+kXN{((ahR!N6ce|5i%; z@hCF{eptXzBw>-lLb~UPqC7`0l924HFp4DHvSFci1+Q5+f7b1L-S07&YtvEpPz`_a zDjHL$(%z0EY(K@PaSI_lTY9p+d5p>HxqXI7wpl#%HhOkXW(t1mY-s9H+%!|for3ryNCS!91udT-Kf2;V=SpdY*1Y*wfgQa z!;X*?yLsXL5!t3hT$Y`}MzYhbtnK=mxT4-zlZrF9d(9(dwJ-A81E!~*x$Gugr7tNA zHAkSsM!wDG8Dmj#U+x9OfhBR37fKRHI{z@w)oRJDlHykS>@WDlJ{Q*eEM&clyJ_`J zxnoy*zIL+vrS^6A3g}OR`Z`T|iCKY-%ftFgy-ieiBSi|pv^ikIU`F93rN^`VdJkz} z4&hT8P9Vijbkj8+fYA#Xwh`GZ=iNx;;>J$Ecaz?p1&`T(nCZXo0ArRpg zpq-h{A#(aicS=18NO#fgN3oyaFZ2k_W|I?vZ0Qj)DQ_x*G~ zLi|3$VyZU!!IWJ7x0n)||EJ1K($38Of3!uaYr7+>qI}6^AIX$2M(-12oN6=!5Z9;lH`^NCueeGHj63>-v4NMfBO0%eD6yms!MM_$kN|(B_o8A5j0Nr z|7JQre?9N)u6xf;^z`|?IIi0B#V5jd_r zZQVr(m|Fpg1Z)=aT|wWTjLo5SB;{T?yBy}>be{CIV?rP7GznN!AEMKY zA@)Cdi;Ovs8xKQkbt$w>*>6*8EaNQgXYvskeB^s%!Q*hbkZJ{ZYS7w~pLxhLXx5g< zPNu~J^D5{mK6Mc%MU-=)P02GdI<4q8)CQjat+-&c>-iZ?It!7u?lwx-rhcJ28v&Sx zsKxVeJ${Nkn@R(HXW+n^njWM%DjzR5#v;$ycpj{(-!^tP)d7A+oTn*5t1lGm+N7M< zp>hVNLY)WdgG!;viDk7RGfv~enXbUpx%)X8_er_xU$?g6lIJjEGSiKhf}11c^3GT58VD2< zD8x+nBmpF58+D+ZrzP4Ek5-xO>aQXktnBq*q#*bN3<_crt{|v1SQ>*&g0MP6YJt4A zP6=v-*Z>54#GRS}ee|`}pGy36BMJX+o_hu-C%Hlvew#g~k^Z@l(Vp@ag2rlqN8r5p zs+I0WzpPIg0Y5uKoT!*ejq0_Z6=r)VJxMRi9cnMz9c(WuhE*MA^Y3a!%@%`tPgE$F zRw~}Wukb&z2FguT$ZHEsit7-Yv~+>n(<0=>Re)JfTZtN5$SUO*nhh}bG~H&ij}K(l zzb?^m62w|Nkk)|GZ`|)h*WJ^!_?hVjB9+wqM^8PF%J91)xGJ91M-|^@6vOjTd@GMC;+pO8zYt$ZQu$t7_|$-l zJ9gw5_nY&(c&YMP_b3N0)Uc*E^|g}rNF`87v7$x2Inmdi?> zKA~cEZBnQQOo7pstNLN>=g@;Su(049NW(g7Qn-+nX5ti#ePD18y+j&Pf^naW5# z2={A@A-YnE0)jdKO&yE47?Qa)YG!Q~zR>0<)SWXx>9z_jzt(w{5ZAcDoC+!4x6e+M;jqYV|J3n_8n>B+YMe z6Ki27Vnv6* zkF}+@OFLbt)Gbx&RVw!=m3x(nwZz?es%GplX0`_oZOI}SLee{volnhV#S$-J3Xbi% zC?|V}9;ikZBaM-ek;aK98zUf*e~I)BPn`WmZq6LG#?g;Q5)u6ar^)ap2t(TWU(teg zM1=IzKcQ&yu>V~#@iW)*f6>7IqnJ=|vUf2xcCoa#`yZ4j&7ThSr`+#PCi|1=`*vVt z420r{jAREf8I|9J0xTpM4qz%cN#aa|nUT!MM;0~W)f#nPOK8%(3jM(=5o{67)tk00 z*KVuZ*R5T=YF%A+wzgee*LZ4CWxKoIJ)X>xWDNw*ARoK8{+~CO{5~(i>GBBkK7OOp z-$&&&kF#8#t9cE z^d^8(xm$qaw>s0uhWPX&Hs;r&^!IW3ciFDjxx3yQe(u+*{I~cwz4Yzm#O~CcUVzhi zNxsw>Ja8`3#qHE61Q3=%f@d&iKj&4F;Nm)Nfzb1K!R1w|cOPi@)sX4)CC=P>!Yc;< z^l^h<*3h93PagU2ls^w5{JJvsK)muukAi{!K(lDl%f=BFJgf529#}AE5vpD5@kXWkf2MU7UiQmLE5iXDOhJpnP3nP>tOne z41NOP0n{`DeQeP&gAQSVoPT&Ms@FRVkKBEI2vv)+mG1S*WO(UBPru?BIio6roK0jq zzkIK;U?VAJG+$=IVabHqGGBpNcLPI?WENzp)8^W5qq~7=y-r5$io1Wk-rd9Jocm+>`q@3J+e93`e?I>CYe?P9Oyx^rRm8@=SdeULOd~*sRI^znbCZq z@rQDpSh1Bmv)U>KD zVZ}dk&4dTZhMFciYqFD#pJqF^l3Mntre-^0Hwg_g4KHnjnHeLo$TE^tEtokGTJ_>K z=8olP<_xZ`2$?;6@4Q1g(=tP#p`MOm7FXkujB&s7RIBQ~ovCg+b8?@Vc=S5$KN6SP z6;I5fjmB-IH9PD@z_UY9RSWSJFv}z}p_O1+lWpP%Q;TYcWeMzjCs0X4`}MAjvKZIY zu(m-l?MeeNt=gF7$maU`1osK+I#vfO)wwM|p>ZgVO+?+cWsk-Q1ljtax1k zb`sr58SF+p9%6#yIvCQ=r^Kap-m_zdI)kh^bK(Mnsmf%IOj;a!HY=4K4Nkd@Y(D}Z zn?Xy3{~(sDexWnxu?%awtzL&)$C|$MCUTr7%36-Cifvxn zggo#sYlLmwaj*{GE{$p8tcVRdcaUb9PTt0+#mOvJw2Wz)U%EQGQNi^j2yG+(8SY3f z+6+74HFkHE2ZmhOMY)V@%a|fo+70KSH;b<4X#9H>mpvX@G_7C^FX5hfNfi0pE2zqX zB~3+>iO^SAi~F3LA(lUOv4E}@IHgfT@st|2_D~gEv|?z_%WlrIWkB7rctCc`;0_CO z#R&w*rUEnVS%gb_nxh_B#Lf3`4mf!A-YfWLXnX+MGkHM$fz^PqD-3o+*d61M^{sPY zbwMte9hs{<)ADjw&5)^!yC!?hjTtY#x#&gL^3L^OwSWuV)|segXyfeJ!Muc3RRZD2 zvKPD6WiMn#8^&&5Em*d9umJt6LXdvZF}Tesd*GVLE2J>SHsB1>3&}TXAoo!=xQiny zZe$Om$IO9UA3oR2at0>u;R&34$uDig%t0w-V`ww8EPg}tKsV8mA1Rd}dc-|#nQWTw z34;LuUJ&HzK3=bUstfKP#BX^Q`#}lnp4E}MFT#z1;+e+^AWOUg^P1nwenktmM|JZW z89g>vlL`UYg8OILvwOg^7soRJ;DEXF83A&=Q+r(_YB~mYyigP@06jSD56#}$z4uq3 zVEmNx)1ygYaR0nMgF8LHwLN;MX8ADsiMt4x_{lpA{@Mq>GE#ij5v&hT{z#EDR!^e9 z{yw(Sy8di(5o4M8j- zr<|#Yeht0wtyWiUsl{Bv?>2cvP>Bkr-rnN+TVBmbDb;jqp(XaI<%yb&eypvkGfdK* zV7GCjY?<{*mNj;dd28EN?8gSrb{I;#GNHv4WlCF^Dhb+$a1@fynBZErJ4RhHTg_o# z7AANFo`}FrEAK6=bQ9%GS*q{VTVo@NtjaU-rome`g&kAVV9kyIBCyc~>)vOhoJ}CpWgvq`qc|)*6buF-D6T=ak%U(V!1?qp=$D3Ww?zY>ErkXe4+IZ9$T~D{U2F%6-P{*RkucO)$ zlL|`vU5a9CBL9_Yu0fXk73>M4!)8t|4fr0frw}PdYsZYOFx%!jVq5=*6->UxBnGxB z;YRG|&IAGO4Y!6HhE`jZA(*}@fd^J*(2ohC_|oF6qYFG#BbhW@{6%2Yop1j8cnLO< z)BB?8{G3he7^7rT&x|t{HFF?vy*if{jXcv+1+Y?`pB?NRd)XT7JM@Wla&9xO7&w7N zv6Tny28w(IC=~;6#@5P2f(wUndaP&yDpB)kP|t+}5be`_U??f#3GvMXU|`NNC|8bo zoeW?bxW#W?V*QKE?Lb6pANRyTqsupvpgkOXx6eQPhjHmH%Jidm7C7f^qS^~q=jy*q=o)9=pqW)vR1zbX2JESJljh_B z=2_zgh#Yw`8&aauk0Zo@8@4IO@}zr!0~>$F&=h&2m^&S{fGNI~JWj@tK4`*Ii*eJST z%78jC$xgtw0pyFr5!piQDBe-ZIq&4?O~x;lR+OK2i%mwXo5I3m&V zYCOv=-uVi_0yFyqwZ!AF=nXEc{rHx3ZO^K4aK$*RZk$bz56f!OIV$7<1$1B!Ne#xb z-4A47s%lP}s+;g8!ZELE z6aNw1=flEu4Eu4m3L^N?$QjR4U%==6?6c?a{OO?}ATPXc{2Hdz$XO8XinPtOeI=+y z7}IbTXi@}ScvaNCU7A5n0k=0s!Cx|}0+w2*`JduAQKm><0e8Wtx2B{UAks?=r)A{) z)*mC#E#Vg-9{9lXCVy=y(#bJq0c44lGrpYbl{3H#`hyVwA_4~Mt<3T7w?6V0$;@EH zKX-Ty!ugmepZ(q9G?!db%)>*Yr$UHcXv!hv!E@c=gnnHDpfYs|1|f8nl!i*ZdgMul zYZPZ?3s827V^xIOnL5L=5E)?=#jg<4d}1b?&e_K-_+=f_;^w)o$;V*~H08G;-lXE@ z2K*^?{4BS-4-<2R8$`n^j?vWSY|W~YEzY3d)`ip+sG8fNRl8_adqwJ$U%Iebmw(T~ zP9OYh{YhN~({wj=#P#ySQc7PqGPe)RJ>w4Iy>P-djkt^Psr8C|=GM~cGsBe8TE+dR z*S-F^E<+xA=9Qj4rpv|s1hnQ1%_q-ZgMWhXT7>=MR%jm*`*!HWI5SWT=_=xQu)q1B|O z#KfWy?;cCKFD!HR#KL>T=uoDP(})62qzlcthv7`A1ev9H%WJ`<16zt2c(+Au+Sl8c zC7VIq(_~tsAi}~WQv_Hp{wE> z3vuo~2HlFA1IeZvxXahF3eolQf!Ou2z|V@2AX$efN_ zLupe>j+VVGWh?opsrN?wykPLbY^$=M^8uxt?EfM|o!@Wi!kxTyrD@VS;}aJ&Bu)z) z63YzCE#g}h1gDK~i!&m=I4)|ZWXlv@2aqNCQP3$v9{6BUzT)}8Q1a%m{a9*%WHY*dkj>k*k$bW&f9((FL{w<)in4OF&SCF`*5jGz+$aE>uP}o+_|;A!Mi#cj4;qyKK2xg?+8inmeS~rhPfst9{;r zYF$y4Zdu?nSLgZkoGPA251r8h<;0${3S=6Gs4U)7}yK{mGye`TQ2Bpr%uMW{Tnz^M)=Bx^R#rQ3 zekFky$va5P%J=@7coc=eWoZ&SfzK+#BB?o{02N5f)JQlh91_1Vt$=0*jnYZDh4y&x zNpK1EN#Ht3P1rHbTY_3Mac&<9O%{&a__mw5{wzXyE<`Q0UTi@>_!#kUI)Qv$sTV@f z&A2%~|K*}`Tah;lVZcsg(S5*tUxl_ju~FiqY=Bhf&iZF1$}gdNUxAZK76)poMaps5(^s-WKFl(6nA92W3ap2^ zdA(J!H_YS2d_8qYPgO~uvk1p&)oZxUpmkr*4wlngGZ)Z`A;#?t0;g>Hq?p1<*+PRA z#!jv<$2!HmAULTK3whH_TS_R8Vuan>IXWAYN@-|gr2h<#q3C$Vpcm(SoKgigNkgnp=`(xO@xlaHbEI%NH0F2Mpg&lS^OFh&N7(vbb*~tGd0J9fG(B zUTlM|lH{m%Z%~U5PHZN7JH(ktAEV}gUO@SI!4nNt91^#l>pveZ8|!%Qu~P49kvlTm zfIOx=8PnM$&&n*&4`;xqT);sup*UR-4@tp6*LxDhL=0c3K8v>E6DkskPjJ{+S}dx z{O)4X9|2FUpJ=+#b^9?-HpaU*`Imlat@<^%YG^a+`!aw;dPGZMNvx}V%EQ)SM#FIA zrrgo*^NUVD*2a=7hWn9Y?A!;EbkY|o~LC5^mI*vE+;cV$net< z&x6badc}h6T>=W@zg#5eNnxkSQz^{C=$kLc9WgA@WC~S^?5kP` zzK&9_Q_Q3tHGYL?)i0Y`yZ0yV!F@5tU(m&KdV=?Q2dMYh-2%SQE3Z1CY;r5GpY{#S zY(T|1g%xw5ew#zl;;+8>Z+JX&k+mFf()97_DpNF274)i>W8YwY=tSLR7&MKxoG{0~ zgVNN|-Z9#6B*oWGzHxg)#?LGCk)Hrx!rS@1E)Ua3Ogy0ae*Wxd3v+>8!0%Ec|L4U_ z!jI?_oS(@j=3CI@@@A30vWvf-`5pewM!kLOpA1A5}5nden{KRG*YC zp1hO$OX3_p;D2fXAq+1%iXENI_T#M6Defxk;e2GF;qJ5n9x)479YYmENZ0BN;;R|~;3z!d^iW@66L$=~Bp|&sczTF&)zM%3J^}-R zo5=md?kd3_s(0=(G(2>B@qx@CH9oJI(RI+$@?-8w>0hDIWyU}>ponBV(->soAa0DZ9!m*CDbkSPV8FcoN~tjdo2twTm zyFQ5I#@psh4cwL_SM4T^vGfL)Oi0z(gvpp)kjzj(&JTSPQcvfu1xhXfQzN;_OXQIQ z58KU2!_3=q%NP*j!P|Dl5X#~+1cEcS8~?m;RkGvd#gM8H$YAsS)Hd(^E!f)fU0POh z{jEgxREwwU{0Rs|-JWZ}7m}7I`So)()!dl@L|UQ`Jy~b)t$c|_KIlNldG!w zi9zou>D;6@EPtE$Yiw;cwW{n-Nq!pDXN&gsh5#O3s;Ix10PAr{*4$ePDcEoOuVv`hDum&^sy&Ktb3IciS zh}=Sm{MrBxeULe;2*Y~z!hR|hif-A;1NQtAW?Hky=0vhvu2 z?na6!J*bB!K9CJ#5ThsKaWa%SJ2Sxw#gDN*7GOCNZWS2Pc-RNA(~#D#QOvUYsmYAX zc5XPR$F$@Fmdc@3O2z{k+CxlPvlUI!APp@dnbIMu?Ac#HDh_Kv*$>O#a3{{RN4D1# zae|x`WeZ{=1TDrMZ+{Ewt6Xrx>1Jx~3KA7p(&lJAz7Sd}G2x)SshaBK23s}q{H9IK z21~i=N4CwfRl+yy20Zk#rF!ReS%h?kZ9*CG0BRy*P^XRvSTunV*l$Ig(Ld9kZ>GSBhEe{6B`a9>K`&p!?6uU&z~huG7Gpp2P)f1H`Kb8M)9@e*5#pd zD3lvJ-Zi+FDXjFw-3A5JWXlxSg~#Ie~u-jh#V6w2)Idw8>EII;5vUb68tB z3mzk-)e-Bw=J3*5KLcM$B>zk`nu*z(mN79ieah<;sH_st#YrkBNRD6tB=FQT0#nx` z?au-uxyk$1?&(D-j1UV{!Y}wH^9~I%iM&?aVnh6mqsks7UP2wzY<}2?a^c7$T@_iI z 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�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

    Ls&7bU??5@d<{xb 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 defaultFactionPermissions; + // Custom Ranks + //public static boolean enableCustomRanks = false; // We will disable it by default to avoid any migration error + //public static int maxCustomRanks = 2; // Setting this to -1 will allow unlimited custom ranks // -------------------------------------------- // // Persistance // -------------------------------------------- // @@ -430,6 +441,12 @@ public class Conf { safeZoneNerfedCreatureTypes.add(EntityType.WITCH); safeZoneNerfedCreatureTypes.add(EntityType.WITHER); safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE); + // Is this called lazy load? + defaultFactionPermissions.put("LEADER", new DefaultPermissions(true)); + defaultFactionPermissions.put("COLEADER", new DefaultPermissions(true)); + defaultFactionPermissions.put("MODERATOR", new DefaultPermissions(true)); + defaultFactionPermissions.put("MEMBER", new DefaultPermissions(false)); + defaultFactionPermissions.put("RECRUIT", new DefaultPermissions(false)); } public static void load() { diff --git a/src/main/java/com/massivecraft/factions/Faction.java b/src/main/java/com/massivecraft/factions/Faction.java index a24ef6fb..be6412c6 100644 --- a/src/main/java/com/massivecraft/factions/Faction.java +++ b/src/main/java/com/massivecraft/factions/Faction.java @@ -203,6 +203,7 @@ public interface Faction extends EconomyParticipator { void setPermission(Permissable permissable, PermissableAction permissableAction, Access access); void resetPerms(); + void setDefaultPerms(); void disband(Player disbander); diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java index 1914a5da..ad7455b1 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java @@ -103,6 +103,11 @@ public class CmdCreate extends FCommand { if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { this.fme.msg(TL.COMMAND_PAYPALSET_CREATED); } + if (Conf.useCustomDefaultPermissions) { + faction.setDefaultPerms(); + if (Conf.usePermissionHints) + this.fme.msg(TL.COMMAND_HINT_PERMISSION); + } } @Override diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java b/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java new file mode 100644 index 00000000..be3f7f3c --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java @@ -0,0 +1,147 @@ +package com.massivecraft.factions.zcore.fperms; + +public class DefaultPermissions { + public DefaultPermissions() { } + public DefaultPermissions(boolean def) { + this.ban = def; + this.build = def; + this.destroy = def; + this.frostwalk = def; + this.painbuild = def; + this.door = def; + this.button = def; + this.lever = def; + this.container = def; + this.invite = def; + this.kick = def; + this.items = def; + this.sethome = def; + this.territory = def; + this.access = def; + this.home = def; + this.disband = def; + this.promote = def; + this.setwarp = def; + this.warp = def; + this.fly = def; + this.vault = def; + this.tntbank = def; + this.tntfill = def; + this.withdraw = def; + this.chest = def; + this.spawner = def; + } + public DefaultPermissions(boolean canBan, + boolean canBuild, + boolean canDestory, + boolean canFrostwalk, + boolean canPainbuild, + boolean canDoor, + boolean canButton, + boolean canLever, + boolean canContainer, + boolean canInvite, + boolean canKick, + boolean canItems, + boolean canSethome, + boolean canTerritory, + boolean canAccess, + boolean canHome, + boolean canDisband, + boolean canPromote, + boolean canSetwarp, + boolean canWarp, + boolean canFly, + boolean canVault, + boolean canTntbank, + boolean canTntfill, + boolean canWithdraw, + boolean canChest, + boolean canSpawners) { + this.ban = canBan; + this.build = canBuild; + this.destroy = canDestory; + this.frostwalk = canFrostwalk; + this.painbuild = canPainbuild; + this.door = canDoor; + this.button = canButton; + this.lever = canLever; + this.container = canContainer; + this.invite = canInvite; + this.kick = canKick; + this.items = canItems; + this.sethome = canSethome; + this.territory = canTerritory; + this.access = canAccess; + this.home = canHome; + this.disband = canDisband; + this.promote = canPromote; + this.setwarp = canSetwarp; + this.warp = canWarp; + this.fly = canFly; + this.vault = canVault; + this.tntbank = canTntbank; + this.tntfill = canTntfill; + this.withdraw = canWithdraw; + this.chest = canChest; + this.spawner = canSpawners; + } + public boolean ban; + public boolean build; + public boolean destroy; + public boolean frostwalk; + public boolean painbuild; + public boolean door; + public boolean button; + public boolean lever; + public boolean container; + public boolean invite; + public boolean kick; + public boolean items; + public boolean sethome; + public boolean territory; + public boolean access; + public boolean home; + public boolean disband; + public boolean promote; + public boolean setwarp; + public boolean warp; + public boolean fly; + public boolean vault; + public boolean tntbank; + public boolean tntfill; + public boolean withdraw; + public boolean chest; + public boolean spawner; + @Deprecated + public boolean getbyName(String name) { + if (name == "ban") return this.ban; + else if (name == "build") return this.build; + else if (name == "destroy") return this.destroy; + else if (name == "frostwalk") return this.frostwalk; + else if (name == "painbuild") return this.painbuild; + else if (name == "door") return this.door; + else if (name == "button") return this.button; + else if (name == "lever") return this.lever; + else if (name == "container") return this.container; + else if (name == "invite") return this.invite; + else if (name == "kick") return this.kick; + else if (name == "items") return this.items; + else if (name == "sethome") return this.sethome; + else if (name == "territory") return this.territory; + else if (name == "access") return this.access; + else if (name == "home") return this.disband; + else if (name == "disband") return this.disband; + else if (name == "promote") return this.promote; + else if (name == "setwarp") return this.setwarp; + else if (name == "warp") return this.warp; + else if (name == "fly") return this.fly; + else if (name == "vault") return this.vault; + else if (name == "tntbank") return this.tntbank; + else if (name == "tntfill") return this.tntfill; + else if (name == "withdraw") return this.withdraw; + else if (name == "chest") return this.chest; + else if (name == "spawner") return this.spawner; + else return false; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java index 2f8a77be..3fc99e83 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java @@ -10,7 +10,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Level; public enum PermissableAction { @@ -171,4 +173,12 @@ public enum PermissableAction { return string; } + public static Map fromDefaults(DefaultPermissions defaultPermissions) { + Map defaultMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + defaultMap.put(permissableAction, defaultPermissions.getbyName(permissableAction.name) ? Access.ALLOW : Access.DENY); + } + return defaultMap; + } + } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java index f1c4030b..306826d4 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java @@ -671,6 +671,33 @@ public abstract class MemoryFaction implements Faction, EconomyParticipator { } } + public void setDefaultPerms() { + if (!Conf.useCustomDefaultPermissions) return; + Map defaultMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + defaultMap.put(permissableAction, Access.UNDEFINED); + } + // Put the map in there for each relation. + for (Relation relation : Relation.values()) { + if (relation != Relation.MEMBER) { + if (!Conf.defaultFactionPermissions.containsKey(relation.nicename)) + permissions.put(relation, new HashMap<>(defaultMap)); + else + permissions.put(relation, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(relation.nicename))); + } + } + + // And each role. + for (Role role : Role.values()) { + if (role != Role.LEADER) { + if (!Conf.defaultFactionPermissions.containsKey(role.nicename)) + permissions.put(role, new HashMap<>(defaultMap)); + else + permissions.put(role, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(role.nicename))); + } + } + } + /** * Read only map of Permissions. * diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TL.java b/src/main/java/com/massivecraft/factions/zcore/util/TL.java index 6b1b6bb0..8edff483 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TL.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TL.java @@ -308,6 +308,8 @@ public enum TL { COMMAND_FWARP_PASSWORD_REQUIRED("&c&l[!]&c Warp Password:"), COMMAND_FWARP_PASSWORD_TIMEOUT("&c&l[!]&7 Warp password &ccanceled"), + COMMAND_HINT_PERMISSION("&aYou can manage your factions permissions using &7/f perms"), + COMMAND_HOME_DISABLED("&c&l[!]&7 Sorry, Faction homes are &cdisabled on this server."), COMMAND_HOME_TELEPORTDISABLED("&c&l[!]&7 Sorry, the ability to &cteleport &7to Faction homes is &cdisabled &7on this server."), COMMAND_HOME_NOHOME("&c&l[!]&7 Your faction does &cnot &7have a home. "), From bb7d32bb92f74e46559fddecd604af9f7adb43a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SvenjaRei=C3=9Faus?= Date: Tue, 26 Feb 2019 13:01:27 -0500 Subject: [PATCH 2/5] Configurable Tntfill enable/disable --- src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java | 4 ++++ src/main/resources/config.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java b/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java index 915cb06c..b6237e59 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java @@ -35,6 +35,10 @@ public class CmdTntFill extends FCommand { @Override public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("Tntfill.enabled")) { + this.fme.msg(TL.GENERIC_DISABLED); + return; + } if (!fme.isAdminBypassing()) { Access access = myFaction.getAccess(fme, PermissableAction.TNTFILL); if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6173ade1..79057828 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1035,6 +1035,7 @@ see-chunk: Tntfill: + enabled: true max-radius: 32 max-amount: 64 From c6512bf316631c7c330dafcb0cd0e590f1b68598 Mon Sep 17 00:00:00 2001 From: Liz3 Date: Sun, 3 Mar 2019 04:51:21 +0100 Subject: [PATCH 3/5] Fixed Indents on all files using the reformat option and optimized imports --- .../java/com/massivecraft/factions/Board.java | 104 +- .../java/com/massivecraft/factions/Conf.java | 851 +++-- .../com/massivecraft/factions/FLocation.java | 386 +- .../com/massivecraft/factions/FPlayer.java | 410 +-- .../com/massivecraft/factions/FPlayers.java | 82 +- .../com/massivecraft/factions/Faction.java | 351 +- .../com/massivecraft/factions/Factions.java | 110 +- .../massivecraft/factions/MassiveStats.java | 750 ++-- .../massivecraft/factions/SavageFactions.java | 1402 ++++---- .../massivecraft/factions/cmd/CmdAHome.java | 70 +- .../massivecraft/factions/cmd/CmdAdmin.java | 138 +- .../factions/cmd/CmdAnnounce.java | 58 +- .../factions/cmd/CmdAutoClaim.java | 72 +- .../factions/cmd/CmdAutoHelp.java | 96 +- .../com/massivecraft/factions/cmd/CmdBan.java | 132 +- .../massivecraft/factions/cmd/CmdBanlist.java | 90 +- .../massivecraft/factions/cmd/CmdBanner.java | 200 +- .../massivecraft/factions/cmd/CmdBoom.java | 68 +- .../massivecraft/factions/cmd/CmdBypass.java | 58 +- .../massivecraft/factions/cmd/CmdChat.java | 132 +- .../massivecraft/factions/cmd/CmdChatSpy.java | 54 +- .../factions/cmd/CmdCheckpoint.java | 108 +- .../massivecraft/factions/cmd/CmdChest.java | 62 +- .../massivecraft/factions/cmd/CmdClaim.java | 130 +- .../massivecraft/factions/cmd/CmdClaimAt.java | 50 +- .../factions/cmd/CmdClaimLine.java | 106 +- .../factions/cmd/CmdColeader.java | 130 +- .../massivecraft/factions/cmd/CmdConfig.java | 396 +-- .../massivecraft/factions/cmd/CmdConvert.java | 58 +- .../massivecraft/factions/cmd/CmdCoords.java | 50 +- .../massivecraft/factions/cmd/CmdCreate.java | 166 +- .../factions/cmd/CmdDeinvite.java | 94 +- .../factions/cmd/CmdDelFWarp.java | 62 +- .../massivecraft/factions/cmd/CmdDemote.java | 8 +- .../factions/cmd/CmdDescription.java | 78 +- .../massivecraft/factions/cmd/CmdDisband.java | 156 +- .../massivecraft/factions/cmd/CmdFWarp.java | 126 +- .../com/massivecraft/factions/cmd/CmdFly.java | 402 +-- .../massivecraft/factions/cmd/CmdFocus.java | 74 +- .../factions/cmd/CmdGetVault.java | 102 +- .../massivecraft/factions/cmd/CmdHelp.java | 360 +- .../massivecraft/factions/cmd/CmdHome.java | 206 +- .../massivecraft/factions/cmd/CmdInspect.java | 52 +- .../massivecraft/factions/cmd/CmdInvite.java | 130 +- .../massivecraft/factions/cmd/CmdJoin.java | 188 +- .../massivecraft/factions/cmd/CmdKick.java | 208 +- .../factions/cmd/CmdKillHolograms.java | 42 +- .../massivecraft/factions/cmd/CmdLeave.java | 42 +- .../massivecraft/factions/cmd/CmdList.java | 194 +- .../massivecraft/factions/cmd/CmdLock.java | 46 +- .../massivecraft/factions/cmd/CmdLogins.java | 40 +- .../factions/cmd/CmdLowPower.java | 50 +- .../com/massivecraft/factions/cmd/CmdMap.java | 92 +- .../factions/cmd/CmdMapHeight.java | 44 +- .../com/massivecraft/factions/cmd/CmdMod.java | 124 +- .../factions/cmd/CmdModifyPower.java | 66 +- .../massivecraft/factions/cmd/CmdMoney.java | 68 +- .../factions/cmd/CmdMoneyBalance.java | 66 +- .../factions/cmd/CmdMoneyDeposit.java | 58 +- .../factions/cmd/CmdMoneyTransferFf.java | 68 +- .../factions/cmd/CmdMoneyTransferFp.java | 66 +- .../factions/cmd/CmdMoneyTransferPf.java | 66 +- .../factions/cmd/CmdMoneyWithdraw.java | 66 +- .../massivecraft/factions/cmd/CmdNear.java | 70 +- .../massivecraft/factions/cmd/CmdOpen.java | 68 +- .../massivecraft/factions/cmd/CmdOwner.java | 148 +- .../factions/cmd/CmdOwnerList.java | 94 +- .../factions/cmd/CmdPaypalSee.java | 66 +- .../factions/cmd/CmdPaypalSet.java | 52 +- .../factions/cmd/CmdPeaceful.java | 82 +- .../massivecraft/factions/cmd/CmdPerm.java | 168 +- .../factions/cmd/CmdPermanent.java | 126 +- .../factions/cmd/CmdPermanentPower.java | 118 +- .../massivecraft/factions/cmd/CmdPower.java | 70 +- .../factions/cmd/CmdPowerBoost.java | 176 +- .../massivecraft/factions/cmd/CmdPromote.java | 10 +- .../factions/cmd/CmdRelationAlly.java | 8 +- .../factions/cmd/CmdRelationEnemy.java | 8 +- .../factions/cmd/CmdRelationNeutral.java | 8 +- .../factions/cmd/CmdRelationTruce.java | 8 +- .../massivecraft/factions/cmd/CmdReload.java | 60 +- .../massivecraft/factions/cmd/CmdRules.java | 138 +- .../com/massivecraft/factions/cmd/CmdSB.java | 44 +- .../factions/cmd/CmdSafeunclaimall.java | 70 +- .../massivecraft/factions/cmd/CmdSaveAll.java | 86 +- .../factions/cmd/CmdSeeChunk.java | 214 +- .../factions/cmd/CmdSetBanner.java | 42 +- .../factions/cmd/CmdSetDefaultRole.java | 60 +- .../factions/cmd/CmdSetFWarp.java | 106 +- .../factions/cmd/CmdSetMaxVaults.java | 64 +- .../massivecraft/factions/cmd/CmdSethome.java | 102 +- .../massivecraft/factions/cmd/CmdShow.java | 168 +- .../factions/cmd/CmdShowClaims.java | 70 +- .../factions/cmd/CmdShowInvites.java | 42 +- .../massivecraft/factions/cmd/CmdStatus.java | 50 +- .../massivecraft/factions/cmd/CmdStealth.java | 46 +- .../massivecraft/factions/cmd/CmdStuck.java | 160 +- .../com/massivecraft/factions/cmd/CmdTag.java | 118 +- .../massivecraft/factions/cmd/CmdTitle.java | 68 +- .../com/massivecraft/factions/cmd/CmdTnt.java | 306 +- .../massivecraft/factions/cmd/CmdTntFill.java | 432 +-- .../factions/cmd/CmdToggleAllianceChat.java | 54 +- .../com/massivecraft/factions/cmd/CmdTop.java | 296 +- .../factions/cmd/CmdTpBanner.java | 66 +- .../massivecraft/factions/cmd/CmdUnban.java | 74 +- .../massivecraft/factions/cmd/CmdUnclaim.java | 268 +- .../factions/cmd/CmdUnclaimall.java | 82 +- .../factions/cmd/CmdUpgrades.java | 52 +- .../massivecraft/factions/cmd/CmdVault.java | 102 +- .../massivecraft/factions/cmd/CmdVersion.java | 42 +- .../factions/cmd/CmdWarunclaimall.java | 68 +- .../massivecraft/factions/cmd/FCmdRoot.java | 458 +-- .../massivecraft/factions/cmd/FCommand.java | 652 ++-- .../factions/cmd/FPromoteCommand.java | 134 +- .../factions/cmd/FRelationCommand.java | 184 +- .../event/FPlayerEnteredFactionEvent.java | 52 +- .../factions/event/FPlayerJoinEvent.java | 50 +- .../factions/event/FPlayerLeaveEvent.java | 52 +- .../factions/event/FPlayerStoppedFlying.java | 32 +- .../factions/event/FactionCreateEvent.java | 58 +- .../factions/event/FactionDisbandEvent.java | 62 +- .../factions/event/FactionEvent.java | 40 +- .../factions/event/FactionPlayerEvent.java | 16 +- .../factions/event/FactionRelationEvent.java | 58 +- .../event/FactionRelationWishEvent.java | 54 +- .../factions/event/FactionRenameEvent.java | 84 +- .../factions/event/LandClaimEvent.java | 106 +- .../factions/event/LandUnclaimAllEvent.java | 84 +- .../factions/event/LandUnclaimEvent.java | 96 +- .../factions/event/PowerLossEvent.java | 118 +- .../factions/event/PowerRegenEvent.java | 24 +- .../factions/iface/EconomyParticipator.java | 6 +- .../factions/iface/RelationParticipator.java | 10 +- .../factions/integration/Econ.java | 686 ++-- .../factions/integration/Essentials.java | 48 +- .../factions/integration/Worldguard.java | 172 +- .../integration/dynmap/DynmapStyle.java | 164 +- .../integration/dynmap/EngineDynmap.java | 1492 ++++---- .../integration/dynmap/TempAreaMarker.java | 170 +- .../integration/dynmap/TempMarker.java | 100 +- .../integration/dynmap/TempMarkerSet.java | 72 +- .../listeners/FactionsBlockListener.java | 970 ++--- .../listeners/FactionsChatListener.java | 316 +- .../listeners/FactionsEntityListener.java | 1396 ++++---- .../listeners/FactionsExploitListener.java | 82 +- .../listeners/FactionsPlayerListener.java | 1960 +++++------ .../scoreboards/BufferedObjective.java | 242 +- .../factions/scoreboards/FScoreboard.java | 216 +- .../scoreboards/FSidebarProvider.java | 44 +- .../factions/scoreboards/FTeamWrapper.java | 350 +- .../scoreboards/sidebar/FDefaultSidebar.java | 48 +- .../scoreboards/sidebar/FInfoSidebar.java | 34 +- .../player/PlayerFactionExpression.java | 120 +- .../player/PlayerPowerExpression.java | 116 +- .../player/PlayerRoleExpression.java | 112 +- .../massivecraft/factions/struct/BanInfo.java | 66 +- .../factions/struct/ChatMode.java | 60 +- .../factions/struct/Permission.java | 250 +- .../factions/struct/Relation.java | 370 +- .../massivecraft/factions/struct/Role.java | 216 +- .../factions/util/AsciiCompass.java | 172 +- .../factions/util/AutoLeaveProcessTask.java | 132 +- .../factions/util/AutoLeaveTask.java | 32 +- .../util/ClipPlaceholderAPIManager.java | 272 +- .../factions/util/EnumTypeAdapter.java | 86 +- .../factions/util/FactionGUI.java | 4 +- .../factions/util/InventoryTypeAdapter.java | 22 +- .../factions/util/InventoryUtil.java | 130 +- .../factions/util/LazyLocation.java | 140 +- .../factions/util/LocationTypeAdapter.java | 60 +- .../util/MapFLocToStringSetTypeAdapter.java | 142 +- .../massivecraft/factions/util/MiscUtil.java | 176 +- .../factions/util/MultiversionMaterials.java | 1898 +++++----- .../factions/util/MyLocationTypeAdapter.java | 80 +- .../util/Particles/ParticleEffect.java | 3110 ++++++++--------- .../util/Particles/ReflectionUtils.java | 1078 +++--- .../util/PermissionsMapTypeAdapter.java | 138 +- .../factions/util/RelationUtil.java | 152 +- .../factions/util/SpiralTask.java | 296 +- .../massivecraft/factions/util/UtilFly.java | 168 +- .../factions/util/VisualizeUtil.java | 102 +- .../factions/util/WarmUpUtil.java | 62 +- .../massivecraft/factions/util/WarpGUI.java | 388 +- .../factions/zcore/CommandVisibility.java | 14 +- .../massivecraft/factions/zcore/MCommand.java | 918 ++--- .../massivecraft/factions/zcore/MPlugin.java | 516 +-- .../zcore/MPluginSecretPlayerListener.java | 52 +- .../factions/zcore/fperms/Access.java | 62 +- .../zcore/fperms/DefaultPermissions.java | 291 +- .../factions/zcore/fperms/Permissable.java | 6 +- .../zcore/fperms/PermissableAction.java | 276 +- .../fperms/gui/PermissableActionGUI.java | 472 +-- .../fperms/gui/PermissableRelationGUI.java | 286 +- .../zcore/fupgrades/CropUpgrades.java | 96 +- .../factions/zcore/fupgrades/EXPUpgrade.java | 62 +- .../zcore/fupgrades/FUpgradesGUI.java | 464 +-- .../zcore/fupgrades/SpawnerUpgrades.java | 50 +- .../factions/zcore/fupgrades/Upgrade.java | 18 +- .../factions/zcore/nbtapi/NBTCompound.java | 290 +- .../factions/zcore/nbtapi/NBTContainer.java | 42 +- .../factions/zcore/nbtapi/NBTEntity.java | 20 +- .../factions/zcore/nbtapi/NBTFile.java | 58 +- .../factions/zcore/nbtapi/NBTItem.java | 44 +- .../factions/zcore/nbtapi/NBTList.java | 210 +- .../zcore/nbtapi/NBTListCompound.java | 164 +- .../zcore/nbtapi/NBTReflectionUtil.java | 1798 +++++----- .../factions/zcore/nbtapi/NBTTileEntity.java | 20 +- .../factions/zcore/nbtapi/NBTType.java | 50 +- .../zcore/nbtapi/utils/GsonWrapper.java | 32 +- .../zcore/nbtapi/utils/MethodNames.java | 32 +- .../zcore/nbtapi/utils/MinecraftVersion.java | 90 +- .../factions/zcore/persist/MemoryBoard.java | 624 ++-- .../factions/zcore/persist/MemoryFPlayer.java | 2366 ++++++------- .../zcore/persist/MemoryFPlayers.java | 82 +- .../factions/zcore/persist/MemoryFaction.java | 2414 ++++++------- .../zcore/persist/MemoryFactions.java | 278 +- .../factions/zcore/persist/SaveTask.java | 34 +- .../zcore/persist/json/FactionsJSON.java | 64 +- .../zcore/persist/json/JSONBoard.java | 136 +- .../zcore/persist/json/JSONFPlayer.java | 26 +- .../zcore/persist/json/JSONFPlayers.java | 288 +- .../zcore/persist/json/JSONFaction.java | 16 +- .../zcore/persist/json/JSONFactions.java | 506 +-- .../factions/zcore/util/DiscUtil.java | 240 +- .../factions/zcore/util/PermUtil.java | 98 +- .../factions/zcore/util/Persist.java | 210 +- .../factions/zcore/util/SmokeUtil.java | 164 +- .../massivecraft/factions/zcore/util/TL.java | 2028 +++++------ .../factions/zcore/util/TagReplacer.java | 528 +-- .../factions/zcore/util/TagUtil.java | 468 +-- .../factions/zcore/util/TextUtil.java | 366 +- .../factions/zcore/util/UUIDFetcher.java | 140 +- 232 files changed, 26900 insertions(+), 26895 deletions(-) diff --git a/src/main/java/com/massivecraft/factions/Board.java b/src/main/java/com/massivecraft/factions/Board.java index 1857fab2..dbd7d8f4 100644 --- a/src/main/java/com/massivecraft/factions/Board.java +++ b/src/main/java/com/massivecraft/factions/Board.java @@ -9,82 +9,82 @@ import java.util.Set; public abstract class Board { - protected static Board instance = getBoardImpl(); + protected static Board instance = getBoardImpl(); - private static Board getBoardImpl() { - switch (Conf.backEnd) { - case JSON: - return new JSONBoard(); - } - return null; - } + private static Board getBoardImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONBoard(); + } + return null; + } - public static Board getInstance() { - return instance; - } + public static Board getInstance() { + return instance; + } - //----------------------------------------------// - // Get and Set - //----------------------------------------------// - public abstract String getIdAt(FLocation flocation); + //----------------------------------------------// + // Get and Set + //----------------------------------------------// + public abstract String getIdAt(FLocation flocation); - public abstract Faction getFactionAt(FLocation flocation); + public abstract Faction getFactionAt(FLocation flocation); - public abstract void setIdAt(String id, FLocation flocation); + public abstract void setIdAt(String id, FLocation flocation); - public abstract void setFactionAt(Faction faction, FLocation flocation); + public abstract void setFactionAt(Faction faction, FLocation flocation); - public abstract void removeAt(FLocation flocation); + public abstract void removeAt(FLocation flocation); - public abstract Set getAllClaims(String factionId); + public abstract Set getAllClaims(String factionId); - public abstract Set getAllClaims(Faction faction); + public abstract Set getAllClaims(Faction faction); - // not to be confused with claims, ownership referring to further member-specific ownership of a claim - public abstract void clearOwnershipAt(FLocation flocation); + // not to be confused with claims, ownership referring to further member-specific ownership of a claim + public abstract void clearOwnershipAt(FLocation flocation); - public abstract void unclaimAll(String factionId); + public abstract void unclaimAll(String factionId); - public abstract void unclaimAllInWorld(String factionId, World world); + public abstract void unclaimAllInWorld(String factionId, World world); - // Is this coord NOT completely surrounded by coords claimed by the same faction? - // Simpler: Is there any nearby coord with a faction other than the faction here? - public abstract boolean isBorderLocation(FLocation flocation); + // Is this coord NOT completely surrounded by coords claimed by the same faction? + // Simpler: Is there any nearby coord with a faction other than the faction here? + public abstract boolean isBorderLocation(FLocation flocation); - // Is this coord connected to any coord claimed by the specified faction? - public abstract boolean isConnectedLocation(FLocation flocation, Faction faction); + // Is this coord connected to any coord claimed by the specified faction? + public abstract boolean isConnectedLocation(FLocation flocation, Faction faction); - public abstract boolean hasFactionWithin(FLocation flocation, Faction faction, int radius); + public abstract boolean hasFactionWithin(FLocation flocation, Faction faction, int radius); - //----------------------------------------------// - // Cleaner. Remove orphaned foreign keys - //----------------------------------------------// + //----------------------------------------------// + // Cleaner. Remove orphaned foreign keys + //----------------------------------------------// - public abstract void clean(); + public abstract void clean(); - //----------------------------------------------// - // Coord count - //----------------------------------------------// + //----------------------------------------------// + // Coord count + //----------------------------------------------// - public abstract int getFactionCoordCount(String factionId); + public abstract int getFactionCoordCount(String factionId); - public abstract int getFactionCoordCount(Faction faction); + public abstract int getFactionCoordCount(Faction faction); - public abstract int getFactionCoordCountInWorld(Faction faction, String worldName); + public abstract int getFactionCoordCountInWorld(Faction faction, String worldName); - //----------------------------------------------// - // Map generation - //----------------------------------------------// + //----------------------------------------------// + // Map generation + //----------------------------------------------// - /* - * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction - * of decreasing z - */ - public abstract ArrayList getMap(FPlayer fPlayer, FLocation flocation, double inDegrees); + /* + * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction + * of decreasing z + */ + public abstract ArrayList getMap(FPlayer fPlayer, FLocation flocation, double inDegrees); - public abstract void forceSave(); + public abstract void forceSave(); - public abstract void forceSave(boolean sync); + public abstract void forceSave(boolean sync); - public abstract boolean load(); + public abstract boolean load(); } diff --git a/src/main/java/com/massivecraft/factions/Conf.java b/src/main/java/com/massivecraft/factions/Conf.java index 45082931..9a4989eb 100644 --- a/src/main/java/com/massivecraft/factions/Conf.java +++ b/src/main/java/com/massivecraft/factions/Conf.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap; import com.massivecraft.factions.integration.dynmap.DynmapStyle; import com.massivecraft.factions.util.MultiversionMaterials; import com.massivecraft.factions.zcore.fperms.DefaultPermissions; -import com.massivecraft.factions.zcore.fperms.PermissableAction; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.EntityType; @@ -13,454 +12,454 @@ import java.util.*; public class Conf { - // Region Style - public static final transient String DYNMAP_STYLE_LINE_COLOR = "#00FF00"; - public static final transient double DYNMAP_STYLE_LINE_OPACITY = 0.8D; - public static final transient int DYNMAP_STYLE_LINE_WEIGHT = 3; - public static final transient String DYNMAP_STYLE_FILL_COLOR = "#00FF00"; - public static final transient double DYNMAP_STYLE_FILL_OPACITY = 0.35D; - public static final transient String DYNMAP_STYLE_HOME_MARKER = "greenflag"; - public static final transient boolean DYNMAP_STYLE_BOOST = false; - public static List baseCommandAliases = new ArrayList<>(); - public static boolean allowNoSlashCommand = true; - public static Set allowedStealthFactions = new LinkedHashSet<>(); + // Region Style + public static final transient String DYNMAP_STYLE_LINE_COLOR = "#00FF00"; + public static final transient double DYNMAP_STYLE_LINE_OPACITY = 0.8D; + public static final transient int DYNMAP_STYLE_LINE_WEIGHT = 3; + public static final transient String DYNMAP_STYLE_FILL_COLOR = "#00FF00"; + public static final transient double DYNMAP_STYLE_FILL_OPACITY = 0.35D; + public static final transient String DYNMAP_STYLE_HOME_MARKER = "greenflag"; + public static final transient boolean DYNMAP_STYLE_BOOST = false; + public static List baseCommandAliases = new ArrayList<>(); + public static boolean allowNoSlashCommand = true; + public static Set allowedStealthFactions = new LinkedHashSet<>(); - // Colors - public static ChatColor colorMember = ChatColor.GREEN; - public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE; - public static ChatColor colorTruce = ChatColor.DARK_PURPLE; - public static ChatColor colorNeutral = ChatColor.WHITE; - public static ChatColor colorEnemy = ChatColor.RED; - public static ChatColor colorPeaceful = ChatColor.GOLD; - public static ChatColor colorWilderness = ChatColor.GRAY; - public static ChatColor colorSafezone = ChatColor.GOLD; - public static ChatColor colorWar = ChatColor.DARK_RED; - // Power - public static double powerPlayerMax = 10.0; - public static double powerPlayerMin = -10.0; - public static double powerPlayerStarting = 0.0; - public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power - public static double powerPerDeath = 4.0; // A death makes you lose 4 power - public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline? - public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline - public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less - public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts) - public static String prefixLeader = "***"; - public static String prefixCoLeader = "**"; - public static String prefixMod = "*"; - public static String prefixRecruit = "-"; - public static String prefixNormal = "+"; - public static int factionTagLengthMin = 3; - public static int factionTagLengthMax = 10; - public static boolean factionTagForceUpperCase = false; - public static boolean newFactionsDefaultOpen = false; - // when faction membership hits this limit, players will no longer be able to join using /f join; default is 0, no limit - public static int factionMemberLimit = 0; - // what faction ID to start new players in when they first join the server; default is 0, "no faction" - public static String newPlayerStartingFactionID = "0"; - public static boolean showMapFactionKey = true; - public static boolean showNeutralFactionsOnMap = true; - public static boolean showEnemyFactionsOnMap = true; - public static boolean showTrucesFactionsOnMap = true; - // Disallow joining/leaving/kicking while power is negative - public static boolean canLeaveWithNegativePower = true; - // Configuration for faction-only chat - public static boolean factionOnlyChat = true; - // Configuration on the Faction tag in chat messages. - public static boolean chatTagEnabled = true; - public static transient boolean chatTagHandledByAnotherPlugin = false; - public static boolean chatTagRelationColored = true; - public static String chatTagReplaceString = "[FACTION]"; - public static String chatTagInsertAfterString = ""; - public static String chatTagInsertBeforeString = ""; - public static int chatTagInsertIndex = 0; - public static boolean chatTagPadBefore = false; - public static boolean chatTagPadAfter = true; - public static String chatTagFormat = "%s" + ChatColor.WHITE; - public static String factionChatFormat = "%s:" + ChatColor.WHITE + " %s"; - public static String allianceChatFormat = ChatColor.LIGHT_PURPLE + "%s:" + ChatColor.WHITE + " %s"; - public static String truceChatFormat = ChatColor.DARK_PURPLE + "%s:" + ChatColor.WHITE + " %s"; - public static String modChatFormat = ChatColor.RED + "%s:" + ChatColor.WHITE + " %s"; - public static int stealthFlyCheckRadius = 32; - public static boolean noEnderpearlsInFly = false; - public static boolean broadcastDescriptionChanges = false; - public static boolean broadcastTagChanges = false; - public static double saveToFileEveryXMinutes = 30.0; - public static double autoLeaveAfterDaysOfInactivity = 10.0; - public static double autoLeaveRoutineRunsEveryXMinutes = 5.0; - public static int autoLeaveRoutineMaxMillisecondsPerTick = 5; // 1 server tick is roughly 50ms, so default max 10% of a tick - public static boolean removePlayerDataWhenBanned = true; - public static boolean autoLeaveDeleteFPlayerData = true; // Let them just remove player from Faction. - public static boolean worldGuardChecking = false; - public static boolean worldGuardBuildPriority = false; - // server logging options - public static boolean logFactionCreate = true; - public static boolean logFactionDisband = true; - public static boolean logFactionJoin = true; - public static boolean logFactionKick = true; - public static boolean logFactionLeave = true; - public static boolean logLandClaims = true; - public static boolean logLandUnclaims = true; - public static boolean logMoneyTransactions = true; - public static boolean logPlayerCommands = true; - // prevent some potential exploits - public static boolean handleExploitObsidianGenerators = true; - public static boolean handleExploitEnderPearlClipping = true; - public static boolean handleExploitInteractionSpam = true; - public static boolean handleExploitTNTWaterlog = false; - public static boolean handleExploitLiquidFlow = false; - public static boolean homesEnabled = true; - public static boolean homesMustBeInClaimedTerritory = true; - public static boolean homesTeleportToOnDeath = true; - public static boolean homesRespawnFromNoPowerLossWorlds = true; - public static boolean homesTeleportCommandEnabled = true; - public static boolean homesTeleportCommandEssentialsIntegration = true; - public static boolean homesTeleportCommandSmokeEffectEnabled = true; - public static float homesTeleportCommandSmokeEffectThickness = 3f; - public static boolean homesTeleportAllowedFromEnemyTerritory = true; - public static boolean homesTeleportAllowedFromDifferentWorld = true; - public static double homesTeleportAllowedEnemyDistance = 32.0; - public static boolean homesTeleportIgnoreEnemiesIfInOwnTerritory = true; - public static boolean disablePVPBetweenNeutralFactions = false; - public static boolean disablePVPForFactionlessPlayers = false; - public static boolean enablePVPAgainstFactionlessInAttackersLand = false; - public static int noPVPDamageToOthersForXSecondsAfterLogin = 3; - public static boolean peacefulTerritoryDisablePVP = true; - public static boolean peacefulTerritoryDisableMonsters = false; - public static boolean peacefulTerritoryDisableBoom = false; - public static boolean peacefulMembersDisablePowerLoss = true; - public static boolean permanentFactionsDisableLeaderPromotion = false; - public static boolean claimsMustBeConnected = false; - public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true; - public static int claimsRequireMinFactionMembers = 1; - public static int claimedLandsMax = 0; - public static int lineClaimLimit = 5; - // if someone is doing a radius claim and the process fails to claim land this many times in a row, it will exit - public static int radiusClaimFailureLimit = 9; - public static double considerFactionsReallyOfflineAfterXMinutes = 0.0; - public static int actionDeniedPainAmount = 1; - // commands which will be prevented if the player is a member of a permanent faction - public static Set permanentFactionMemberDenyCommands = new LinkedHashSet<>(); - // commands which will be prevented when in claimed territory of another faction - public static Set territoryNeutralDenyCommands = new LinkedHashSet<>(); - public static Set territoryEnemyDenyCommands = new LinkedHashSet<>(); - public static Set territoryAllyDenyCommands = new LinkedHashSet<>(); - public static Set warzoneDenyCommands = new LinkedHashSet<>(); - public static Set wildernessDenyCommands = new LinkedHashSet<>(); - public static boolean territoryDenyBuild = true; - public static boolean territoryDenyBuildWhenOffline = true; - public static boolean territoryPainBuild = false; - public static boolean territoryPainBuildWhenOffline = false; - public static boolean territoryDenyUseage = true; - public static boolean territoryEnemyDenyBuild = true; - public static boolean territoryEnemyDenyBuildWhenOffline = true; - public static boolean territoryEnemyPainBuild = false; - public static boolean territoryEnemyPainBuildWhenOffline = false; - public static boolean territoryEnemyDenyUseage = true; - public static boolean territoryEnemyProtectMaterials = true; - public static boolean territoryAllyDenyBuild = true; - public static boolean territoryAllyDenyBuildWhenOffline = true; - public static boolean territoryAllyPainBuild = false; - public static boolean territoryAllyPainBuildWhenOffline = false; - public static boolean territoryAllyDenyUseage = true; - public static boolean territoryAllyProtectMaterials = true; - public static boolean territoryTruceDenyBuild = true; - public static boolean territoryTruceDenyBuildWhenOffline = true; - public static boolean territoryTrucePainBuild = false; - public static boolean territoryTrucePainBuildWhenOffline = false; - public static boolean territoryTruceDenyUseage = true; - public static boolean territoryTruceProtectMaterials = true; - public static boolean territoryBlockCreepers = false; - public static boolean territoryBlockCreepersWhenOffline = false; - public static boolean territoryBlockFireballs = false; - public static boolean territoryBlockFireballsWhenOffline = false; - public static boolean territoryBlockTNT = false; - public static boolean territoryBlockTNTWhenOffline = false; - public static boolean territoryDenyEndermanBlocks = true; - public static boolean territoryDenyEndermanBlocksWhenOffline = true; - public static boolean safeZoneDenyBuild = true; - public static boolean safeZoneDenyUseage = true; - public static boolean safeZoneBlockTNT = true; - public static boolean safeZonePreventAllDamageToPlayers = false; - public static boolean safeZoneDenyEndermanBlocks = true; - public static boolean warZoneDenyBuild = true; - public static boolean warZoneDenyUseage = true; - public static boolean warZoneBlockCreepers = false; - public static boolean warZoneBlockFireballs = false; - public static boolean warZoneBlockTNT = true; - public static boolean warZonePowerLoss = true; - public static boolean warZoneFriendlyFire = false; - public static boolean warZoneDenyEndermanBlocks = true; - public static boolean wildernessDenyBuild = false; - public static boolean wildernessDenyUseage = false; - public static boolean wildernessBlockCreepers = false; - public static boolean wildernessBlockFireballs = false; - public static boolean wildernessBlockTNT = false; - public static boolean wildernessPowerLoss = true; - public static boolean wildernessDenyEndermanBlocks = false; - // for claimed areas where further faction-member ownership can be defined - public static boolean ownedAreasEnabled = true; - public static int ownedAreasLimitPerFaction = 0; - public static boolean ownedAreasModeratorsCanSet = false; - public static boolean ownedAreaModeratorsBypass = true; - public static boolean ownedAreaDenyBuild = true; - public static boolean ownedAreaPainBuild = false; - public static boolean ownedAreaProtectMaterials = true; - public static boolean ownedAreaDenyUseage = true; - public static boolean ownedMessageOnBorder = true; - public static boolean ownedMessageInsideTerritory = true; - public static boolean ownedMessageByChunk = false; - public static boolean pistonProtectionThroughDenyBuild = true; - public static Set territoryProtectedMaterials = EnumSet.noneOf(Material.class); - public static Set territoryDenyUseageMaterials = EnumSet.noneOf(Material.class); - public static Set territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class); - public static Set territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class); - public static transient Set safeZoneNerfedCreatureTypes = EnumSet.noneOf(EntityType.class); + // Colors + public static ChatColor colorMember = ChatColor.GREEN; + public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE; + public static ChatColor colorTruce = ChatColor.DARK_PURPLE; + public static ChatColor colorNeutral = ChatColor.WHITE; + public static ChatColor colorEnemy = ChatColor.RED; + public static ChatColor colorPeaceful = ChatColor.GOLD; + public static ChatColor colorWilderness = ChatColor.GRAY; + public static ChatColor colorSafezone = ChatColor.GOLD; + public static ChatColor colorWar = ChatColor.DARK_RED; + // Power + public static double powerPlayerMax = 10.0; + public static double powerPlayerMin = -10.0; + public static double powerPlayerStarting = 0.0; + public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power + public static double powerPerDeath = 4.0; // A death makes you lose 4 power + public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline? + public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline + public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less + public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts) + public static String prefixLeader = "***"; + public static String prefixCoLeader = "**"; + public static String prefixMod = "*"; + public static String prefixRecruit = "-"; + public static String prefixNormal = "+"; + public static int factionTagLengthMin = 3; + public static int factionTagLengthMax = 10; + public static boolean factionTagForceUpperCase = false; + public static boolean newFactionsDefaultOpen = false; + // when faction membership hits this limit, players will no longer be able to join using /f join; default is 0, no limit + public static int factionMemberLimit = 0; + // what faction ID to start new players in when they first join the server; default is 0, "no faction" + public static String newPlayerStartingFactionID = "0"; + public static boolean showMapFactionKey = true; + public static boolean showNeutralFactionsOnMap = true; + public static boolean showEnemyFactionsOnMap = true; + public static boolean showTrucesFactionsOnMap = true; + // Disallow joining/leaving/kicking while power is negative + public static boolean canLeaveWithNegativePower = true; + // Configuration for faction-only chat + public static boolean factionOnlyChat = true; + // Configuration on the Faction tag in chat messages. + public static boolean chatTagEnabled = true; + public static transient boolean chatTagHandledByAnotherPlugin = false; + public static boolean chatTagRelationColored = true; + public static String chatTagReplaceString = "[FACTION]"; + public static String chatTagInsertAfterString = ""; + public static String chatTagInsertBeforeString = ""; + public static int chatTagInsertIndex = 0; + public static boolean chatTagPadBefore = false; + public static boolean chatTagPadAfter = true; + public static String chatTagFormat = "%s" + ChatColor.WHITE; + public static String factionChatFormat = "%s:" + ChatColor.WHITE + " %s"; + public static String allianceChatFormat = ChatColor.LIGHT_PURPLE + "%s:" + ChatColor.WHITE + " %s"; + public static String truceChatFormat = ChatColor.DARK_PURPLE + "%s:" + ChatColor.WHITE + " %s"; + public static String modChatFormat = ChatColor.RED + "%s:" + ChatColor.WHITE + " %s"; + public static int stealthFlyCheckRadius = 32; + public static boolean noEnderpearlsInFly = false; + public static boolean broadcastDescriptionChanges = false; + public static boolean broadcastTagChanges = false; + public static double saveToFileEveryXMinutes = 30.0; + public static double autoLeaveAfterDaysOfInactivity = 10.0; + public static double autoLeaveRoutineRunsEveryXMinutes = 5.0; + public static int autoLeaveRoutineMaxMillisecondsPerTick = 5; // 1 server tick is roughly 50ms, so default max 10% of a tick + public static boolean removePlayerDataWhenBanned = true; + public static boolean autoLeaveDeleteFPlayerData = true; // Let them just remove player from Faction. + public static boolean worldGuardChecking = false; + public static boolean worldGuardBuildPriority = false; + // server logging options + public static boolean logFactionCreate = true; + public static boolean logFactionDisband = true; + public static boolean logFactionJoin = true; + public static boolean logFactionKick = true; + public static boolean logFactionLeave = true; + public static boolean logLandClaims = true; + public static boolean logLandUnclaims = true; + public static boolean logMoneyTransactions = true; + public static boolean logPlayerCommands = true; + // prevent some potential exploits + public static boolean handleExploitObsidianGenerators = true; + public static boolean handleExploitEnderPearlClipping = true; + public static boolean handleExploitInteractionSpam = true; + public static boolean handleExploitTNTWaterlog = false; + public static boolean handleExploitLiquidFlow = false; + public static boolean homesEnabled = true; + public static boolean homesMustBeInClaimedTerritory = true; + public static boolean homesTeleportToOnDeath = true; + public static boolean homesRespawnFromNoPowerLossWorlds = true; + public static boolean homesTeleportCommandEnabled = true; + public static boolean homesTeleportCommandEssentialsIntegration = true; + public static boolean homesTeleportCommandSmokeEffectEnabled = true; + public static float homesTeleportCommandSmokeEffectThickness = 3f; + public static boolean homesTeleportAllowedFromEnemyTerritory = true; + public static boolean homesTeleportAllowedFromDifferentWorld = true; + public static double homesTeleportAllowedEnemyDistance = 32.0; + public static boolean homesTeleportIgnoreEnemiesIfInOwnTerritory = true; + public static boolean disablePVPBetweenNeutralFactions = false; + public static boolean disablePVPForFactionlessPlayers = false; + public static boolean enablePVPAgainstFactionlessInAttackersLand = false; + public static int noPVPDamageToOthersForXSecondsAfterLogin = 3; + public static boolean peacefulTerritoryDisablePVP = true; + public static boolean peacefulTerritoryDisableMonsters = false; + public static boolean peacefulTerritoryDisableBoom = false; + public static boolean peacefulMembersDisablePowerLoss = true; + public static boolean permanentFactionsDisableLeaderPromotion = false; + public static boolean claimsMustBeConnected = false; + public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true; + public static int claimsRequireMinFactionMembers = 1; + public static int claimedLandsMax = 0; + public static int lineClaimLimit = 5; + // if someone is doing a radius claim and the process fails to claim land this many times in a row, it will exit + public static int radiusClaimFailureLimit = 9; + public static double considerFactionsReallyOfflineAfterXMinutes = 0.0; + public static int actionDeniedPainAmount = 1; + // commands which will be prevented if the player is a member of a permanent faction + public static Set permanentFactionMemberDenyCommands = new LinkedHashSet<>(); + // commands which will be prevented when in claimed territory of another faction + public static Set territoryNeutralDenyCommands = new LinkedHashSet<>(); + public static Set territoryEnemyDenyCommands = new LinkedHashSet<>(); + public static Set territoryAllyDenyCommands = new LinkedHashSet<>(); + public static Set warzoneDenyCommands = new LinkedHashSet<>(); + public static Set wildernessDenyCommands = new LinkedHashSet<>(); + public static boolean territoryDenyBuild = true; + public static boolean territoryDenyBuildWhenOffline = true; + public static boolean territoryPainBuild = false; + public static boolean territoryPainBuildWhenOffline = false; + public static boolean territoryDenyUseage = true; + public static boolean territoryEnemyDenyBuild = true; + public static boolean territoryEnemyDenyBuildWhenOffline = true; + public static boolean territoryEnemyPainBuild = false; + public static boolean territoryEnemyPainBuildWhenOffline = false; + public static boolean territoryEnemyDenyUseage = true; + public static boolean territoryEnemyProtectMaterials = true; + public static boolean territoryAllyDenyBuild = true; + public static boolean territoryAllyDenyBuildWhenOffline = true; + public static boolean territoryAllyPainBuild = false; + public static boolean territoryAllyPainBuildWhenOffline = false; + public static boolean territoryAllyDenyUseage = true; + public static boolean territoryAllyProtectMaterials = true; + public static boolean territoryTruceDenyBuild = true; + public static boolean territoryTruceDenyBuildWhenOffline = true; + public static boolean territoryTrucePainBuild = false; + public static boolean territoryTrucePainBuildWhenOffline = false; + public static boolean territoryTruceDenyUseage = true; + public static boolean territoryTruceProtectMaterials = true; + public static boolean territoryBlockCreepers = false; + public static boolean territoryBlockCreepersWhenOffline = false; + public static boolean territoryBlockFireballs = false; + public static boolean territoryBlockFireballsWhenOffline = false; + public static boolean territoryBlockTNT = false; + public static boolean territoryBlockTNTWhenOffline = false; + public static boolean territoryDenyEndermanBlocks = true; + public static boolean territoryDenyEndermanBlocksWhenOffline = true; + public static boolean safeZoneDenyBuild = true; + public static boolean safeZoneDenyUseage = true; + public static boolean safeZoneBlockTNT = true; + public static boolean safeZonePreventAllDamageToPlayers = false; + public static boolean safeZoneDenyEndermanBlocks = true; + public static boolean warZoneDenyBuild = true; + public static boolean warZoneDenyUseage = true; + public static boolean warZoneBlockCreepers = false; + public static boolean warZoneBlockFireballs = false; + public static boolean warZoneBlockTNT = true; + public static boolean warZonePowerLoss = true; + public static boolean warZoneFriendlyFire = false; + public static boolean warZoneDenyEndermanBlocks = true; + public static boolean wildernessDenyBuild = false; + public static boolean wildernessDenyUseage = false; + public static boolean wildernessBlockCreepers = false; + public static boolean wildernessBlockFireballs = false; + public static boolean wildernessBlockTNT = false; + public static boolean wildernessPowerLoss = true; + public static boolean wildernessDenyEndermanBlocks = false; + // for claimed areas where further faction-member ownership can be defined + public static boolean ownedAreasEnabled = true; + public static int ownedAreasLimitPerFaction = 0; + public static boolean ownedAreasModeratorsCanSet = false; + public static boolean ownedAreaModeratorsBypass = true; + public static boolean ownedAreaDenyBuild = true; + public static boolean ownedAreaPainBuild = false; + public static boolean ownedAreaProtectMaterials = true; + public static boolean ownedAreaDenyUseage = true; + public static boolean ownedMessageOnBorder = true; + public static boolean ownedMessageInsideTerritory = true; + public static boolean ownedMessageByChunk = false; + public static boolean pistonProtectionThroughDenyBuild = true; + public static Set territoryProtectedMaterials = EnumSet.noneOf(Material.class); + public static Set territoryDenyUseageMaterials = EnumSet.noneOf(Material.class); + public static Set territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class); + public static Set territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class); + public static transient Set safeZoneNerfedCreatureTypes = EnumSet.noneOf(EntityType.class); - // Economy settings - public static boolean econEnabled = false; - public static String econUniverseAccount = ""; - public static double econCostClaimWilderness = 30.0; - public static double econCostClaimFromFactionBonus = 30.0; - public static double econOverclaimRewardMultiplier = 0.0; - public static double econClaimAdditionalMultiplier = 0.5; - public static double econClaimRefundMultiplier = 0.7; - public static double econClaimUnconnectedFee = 0.0; - public static double econCostCreate = 100.0; - public static double econCostOwner = 15.0; - public static double econCostSethome = 30.0; - public static double econCostJoin = 0.0; - public static double econCostLeave = 0.0; - public static double econCostKick = 0.0; - public static double econCostInvite = 0.0; - public static double econCostHome = 0.0; - public static double econCostTag = 0.0; - public static double econCostDesc = 0.0; - public static double econCostTitle = 0.0; - public static double econCostList = 0.0; - public static double econCostMap = 0.0; - public static double econCostPower = 0.0; - public static double econCostShow = 0.0; + // Economy settings + public static boolean econEnabled = false; + public static String econUniverseAccount = ""; + public static double econCostClaimWilderness = 30.0; + public static double econCostClaimFromFactionBonus = 30.0; + public static double econOverclaimRewardMultiplier = 0.0; + public static double econClaimAdditionalMultiplier = 0.5; + public static double econClaimRefundMultiplier = 0.7; + public static double econClaimUnconnectedFee = 0.0; + public static double econCostCreate = 100.0; + public static double econCostOwner = 15.0; + public static double econCostSethome = 30.0; + public static double econCostJoin = 0.0; + public static double econCostLeave = 0.0; + public static double econCostKick = 0.0; + public static double econCostInvite = 0.0; + public static double econCostHome = 0.0; + public static double econCostTag = 0.0; + public static double econCostDesc = 0.0; + public static double econCostTitle = 0.0; + public static double econCostList = 0.0; + public static double econCostMap = 0.0; + public static double econCostPower = 0.0; + public static double econCostShow = 0.0; - // -------------------------------------------- // - // INTEGRATION: DYNMAP - // -------------------------------------------- // - public static double econCostStuck = 0.0; - public static double econCostOpen = 0.0; - public static double econCostAlly = 0.0; - public static double econCostTruce = 0.0; - public static double econCostEnemy = 0.0; - public static double econCostNeutral = 0.0; - public static double econCostNoBoom = 0.0; - // Should the dynmap intagration be used? - public static boolean dynmapUse = false; - // Name of the Factions layer - public static String dynmapLayerName = "Factions"; - // Should the layer be visible per default - public static boolean dynmapLayerVisible = true; - // Ordering priority in layer menu (low goes before high - default is 0) - public static int dynmapLayerPriority = 2; - // (optional) set minimum zoom level before layer is visible (0 = default, always visible) - public static int dynmapLayerMinimumZoom = 0; - // Format for popup - substitute values for macros - public static String dynmapDescription = - "

    "; - // Enable the %money% macro. Only do this if you know your economy manager is thread-safe. - public static boolean dynmapDescriptionMoney = false; - // Allow players in faction to see one another on Dynmap (only relevant if Dynmap has 'player-info-protected' enabled) - public static boolean dynmapVisibilityByFaction = true; - // Optional setting to limit which regions to show. - // If empty all regions are shown. - // Specify Faction either by name or UUID. - // To show all regions on a given world, add 'world:' to the list. - public static Set dynmapVisibleFactions = new HashSet<>(); - // Optional setting to hide specific Factions. - // Specify Faction either by name or UUID. - // To hide all regions on a given world, add 'world:' to the list. - public static Set dynmapHiddenFactions = new HashSet<>(); - public static DynmapStyle dynmapDefaultStyle = new DynmapStyle() - .setStrokeColor(DYNMAP_STYLE_LINE_COLOR) - .setLineOpacity(DYNMAP_STYLE_LINE_OPACITY) - .setLineWeight(DYNMAP_STYLE_LINE_WEIGHT) - .setFillColor(DYNMAP_STYLE_FILL_COLOR) - .setFillOpacity(DYNMAP_STYLE_FILL_OPACITY) - .setHomeMarker(DYNMAP_STYLE_HOME_MARKER) - .setBoost(DYNMAP_STYLE_BOOST); + // -------------------------------------------- // + // INTEGRATION: DYNMAP + // -------------------------------------------- // + public static double econCostStuck = 0.0; + public static double econCostOpen = 0.0; + public static double econCostAlly = 0.0; + public static double econCostTruce = 0.0; + public static double econCostEnemy = 0.0; + public static double econCostNeutral = 0.0; + public static double econCostNoBoom = 0.0; + // Should the dynmap intagration be used? + public static boolean dynmapUse = false; + // Name of the Factions layer + public static String dynmapLayerName = "Factions"; + // Should the layer be visible per default + public static boolean dynmapLayerVisible = true; + // Ordering priority in layer menu (low goes before high - default is 0) + public static int dynmapLayerPriority = 2; + // (optional) set minimum zoom level before layer is visible (0 = default, always visible) + public static int dynmapLayerMinimumZoom = 0; + // Format for popup - substitute values for macros + public static String dynmapDescription = + "
    \n" + + "%name%
    \n" + + "%description%
    " + + "
    \n" + + "Leader: %players.leader%
    \n" + + "Admins: %players.admins.count%
    \n" + + "Moderators: %players.moderators.count%
    \n" + + "Members: %players.normals.count%
    \n" + + "TOTAL: %players.count%
    \n" + + "
    \n" + + "Bank: %money%
    \n" + + "
    \n" + + "
    "; + // Enable the %money% macro. Only do this if you know your economy manager is thread-safe. + public static boolean dynmapDescriptionMoney = false; + // Allow players in faction to see one another on Dynmap (only relevant if Dynmap has 'player-info-protected' enabled) + public static boolean dynmapVisibilityByFaction = true; + // Optional setting to limit which regions to show. + // If empty all regions are shown. + // Specify Faction either by name or UUID. + // To show all regions on a given world, add 'world:' to the list. + public static Set dynmapVisibleFactions = new HashSet<>(); + // Optional setting to hide specific Factions. + // Specify Faction either by name or UUID. + // To hide all regions on a given world, add 'world:' to the list. + public static Set dynmapHiddenFactions = new HashSet<>(); + public static DynmapStyle dynmapDefaultStyle = new DynmapStyle() + .setStrokeColor(DYNMAP_STYLE_LINE_COLOR) + .setLineOpacity(DYNMAP_STYLE_LINE_OPACITY) + .setLineWeight(DYNMAP_STYLE_LINE_WEIGHT) + .setFillColor(DYNMAP_STYLE_FILL_COLOR) + .setFillOpacity(DYNMAP_STYLE_FILL_OPACITY) + .setHomeMarker(DYNMAP_STYLE_HOME_MARKER) + .setBoost(DYNMAP_STYLE_BOOST); - // Optional per Faction style overrides. Any defined replace those in dynmapDefaultStyle. - // Specify Faction either by name or UUID. - public static Map dynmapFactionStyles = ImmutableMap.of( - "SafeZone", new DynmapStyle().setStrokeColor("#FF00FF").setFillColor("#FF00FF").setBoost(false), - "WarZone", new DynmapStyle().setStrokeColor("#FF0000").setFillColor("#FF0000").setBoost(false) - ); + // Optional per Faction style overrides. Any defined replace those in dynmapDefaultStyle. + // Specify Faction either by name or UUID. + public static Map dynmapFactionStyles = ImmutableMap.of( + "SafeZone", new DynmapStyle().setStrokeColor("#FF00FF").setFillColor("#FF00FF").setBoost(false), + "WarZone", new DynmapStyle().setStrokeColor("#FF0000").setFillColor("#FF0000").setBoost(false) + ); - //Faction banks, to pay for land claiming and other costs instead of individuals paying for them - public static boolean bankEnabled = true; - public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction - public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome - public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs. + //Faction banks, to pay for land claiming and other costs instead of individuals paying for them + public static boolean bankEnabled = true; + public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction + public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome + public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs. - // mainly for other plugins/mods that use a fake player to take actions, which shouldn't be subject to our protections - public static Set playersWhoBypassAllProtection = new LinkedHashSet<>(); + // mainly for other plugins/mods that use a fake player to take actions, which shouldn't be subject to our protections + public static Set playersWhoBypassAllProtection = new LinkedHashSet<>(); - public static Set worldsNoClaiming = new LinkedHashSet<>(); - public static Set worldsNoPowerLoss = new LinkedHashSet<>(); - public static Set worldsIgnorePvP = new LinkedHashSet<>(); - public static Set worldsNoWildernessProtection = new LinkedHashSet<>(); + public static Set worldsNoClaiming = new LinkedHashSet<>(); + public static Set worldsNoPowerLoss = new LinkedHashSet<>(); + public static Set worldsIgnorePvP = new LinkedHashSet<>(); + public static Set worldsNoWildernessProtection = new LinkedHashSet<>(); - // faction- - public static String vaultPrefix = "faction-%s"; - public static int defaultMaxVaults = 0; + // faction- + public static String vaultPrefix = "faction-%s"; + public static int defaultMaxVaults = 0; - public static Backend backEnd = Backend.JSON; + public static Backend backEnd = Backend.JSON; - // Taller and wider for "bigger f map" - public static int mapHeight = 17; - public static int mapWidth = 49; - public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray(); + // Taller and wider for "bigger f map" + public static int mapHeight = 17; + public static int mapWidth = 49; + public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray(); - // Default Options - public static boolean useCustomDefaultPermissions = false; - public static boolean usePermissionHints = false; - public static HashMap defaultFactionPermissions; - // Custom Ranks - //public static boolean enableCustomRanks = false; // We will disable it by default to avoid any migration error - //public static int maxCustomRanks = 2; // Setting this to -1 will allow unlimited custom ranks - // -------------------------------------------- // - // Persistance - // -------------------------------------------- // - private static transient Conf i = new Conf(); + // Default Options + public static boolean useCustomDefaultPermissions = false; + public static boolean usePermissionHints = false; + public static HashMap defaultFactionPermissions; + // Custom Ranks + //public static boolean enableCustomRanks = false; // We will disable it by default to avoid any migration error + //public static int maxCustomRanks = 2; // Setting this to -1 will allow unlimited custom ranks + // -------------------------------------------- // + // Persistance + // -------------------------------------------- // + private static transient Conf i = new Conf(); - static { - baseCommandAliases.add("f"); + static { + baseCommandAliases.add("f"); - territoryEnemyDenyCommands.add("home"); - territoryEnemyDenyCommands.add("sethome"); - territoryEnemyDenyCommands.add("spawn"); - territoryEnemyDenyCommands.add("tpahere"); - territoryEnemyDenyCommands.add("tpaccept"); - territoryEnemyDenyCommands.add("tpa"); + territoryEnemyDenyCommands.add("home"); + territoryEnemyDenyCommands.add("sethome"); + territoryEnemyDenyCommands.add("spawn"); + territoryEnemyDenyCommands.add("tpahere"); + territoryEnemyDenyCommands.add("tpaccept"); + territoryEnemyDenyCommands.add("tpa"); - territoryProtectedMaterials.add(SavageFactions.plugin.WOODEN_DOOR); - territoryProtectedMaterials.add(SavageFactions.plugin.TRAP_DOOR); - territoryProtectedMaterials.add(SavageFactions.plugin.FENCE_GATE); - territoryProtectedMaterials.add(Material.DISPENSER); - territoryProtectedMaterials.add(Material.CHEST); - territoryProtectedMaterials.add(Material.FURNACE); - territoryProtectedMaterials.add(SavageFactions.plugin.BURNING_FURNACE); - territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_OFF); - territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_ON); - territoryProtectedMaterials.add(Material.JUKEBOX); - territoryProtectedMaterials.add(Material.BREWING_STAND); - territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); - territoryProtectedMaterials.add(Material.CAULDRON); - territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); - territoryProtectedMaterials.add(Material.BEACON); - territoryProtectedMaterials.add(Material.ANVIL); - territoryProtectedMaterials.add(Material.TRAPPED_CHEST); - territoryProtectedMaterials.add(Material.DROPPER); - territoryProtectedMaterials.add(Material.HOPPER); + territoryProtectedMaterials.add(SavageFactions.plugin.WOODEN_DOOR); + territoryProtectedMaterials.add(SavageFactions.plugin.TRAP_DOOR); + territoryProtectedMaterials.add(SavageFactions.plugin.FENCE_GATE); + territoryProtectedMaterials.add(Material.DISPENSER); + territoryProtectedMaterials.add(Material.CHEST); + territoryProtectedMaterials.add(Material.FURNACE); + territoryProtectedMaterials.add(SavageFactions.plugin.BURNING_FURNACE); + territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_OFF); + territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_ON); + territoryProtectedMaterials.add(Material.JUKEBOX); + territoryProtectedMaterials.add(Material.BREWING_STAND); + territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); + territoryProtectedMaterials.add(Material.CAULDRON); + territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); + territoryProtectedMaterials.add(Material.BEACON); + territoryProtectedMaterials.add(Material.ANVIL); + territoryProtectedMaterials.add(Material.TRAPPED_CHEST); + territoryProtectedMaterials.add(Material.DROPPER); + territoryProtectedMaterials.add(Material.HOPPER); - territoryDenyUseageMaterials.add(SavageFactions.plugin.FIREBALL); - territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL); - territoryDenyUseageMaterials.add(Material.BUCKET); - territoryDenyUseageMaterials.add(Material.WATER_BUCKET); - territoryDenyUseageMaterials.add(Material.LAVA_BUCKET); - territoryDenyUseageMaterials.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); - if (!SavageFactions.plugin.mc17) { - territoryDenyUseageMaterials.add(Material.ARMOR_STAND); - } + territoryDenyUseageMaterials.add(SavageFactions.plugin.FIREBALL); + territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL); + territoryDenyUseageMaterials.add(Material.BUCKET); + territoryDenyUseageMaterials.add(Material.WATER_BUCKET); + territoryDenyUseageMaterials.add(Material.LAVA_BUCKET); + territoryDenyUseageMaterials.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); + if (!SavageFactions.plugin.mc17) { + territoryDenyUseageMaterials.add(Material.ARMOR_STAND); + } - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.WOODEN_DOOR); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.TRAP_DOOR); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.FENCE_GATE); - territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER); - territoryProtectedMaterialsWhenOffline.add(Material.CHEST); - territoryProtectedMaterialsWhenOffline.add(Material.FURNACE); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.BURNING_FURNACE); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); - territoryProtectedMaterialsWhenOffline.add(Material.JUKEBOX); - territoryProtectedMaterialsWhenOffline.add(Material.BREWING_STAND); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.ENCHANTMENT_TABLE); - territoryProtectedMaterialsWhenOffline.add(Material.CAULDRON); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.SOIL); - territoryProtectedMaterialsWhenOffline.add(Material.BEACON); - territoryProtectedMaterialsWhenOffline.add(Material.ANVIL); - territoryProtectedMaterialsWhenOffline.add(Material.TRAPPED_CHEST); - territoryProtectedMaterialsWhenOffline.add(Material.DROPPER); - territoryProtectedMaterialsWhenOffline.add(Material.HOPPER); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.WOODEN_DOOR); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.TRAP_DOOR); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.FENCE_GATE); + territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER); + territoryProtectedMaterialsWhenOffline.add(Material.CHEST); + territoryProtectedMaterialsWhenOffline.add(Material.FURNACE); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.BURNING_FURNACE); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); + territoryProtectedMaterialsWhenOffline.add(Material.JUKEBOX); + territoryProtectedMaterialsWhenOffline.add(Material.BREWING_STAND); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.ENCHANTMENT_TABLE); + territoryProtectedMaterialsWhenOffline.add(Material.CAULDRON); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.SOIL); + territoryProtectedMaterialsWhenOffline.add(Material.BEACON); + territoryProtectedMaterialsWhenOffline.add(Material.ANVIL); + territoryProtectedMaterialsWhenOffline.add(Material.TRAPPED_CHEST); + territoryProtectedMaterialsWhenOffline.add(Material.DROPPER); + territoryProtectedMaterialsWhenOffline.add(Material.HOPPER); - territoryDenyUseageMaterialsWhenOffline.add(SavageFactions.plugin.FIREBALL); - territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL); - territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET); - territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET); - territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); - if (!SavageFactions.plugin.mc17) { - territoryDenyUseageMaterialsWhenOffline.add(Material.ARMOR_STAND); - } - safeZoneNerfedCreatureTypes.add(EntityType.BLAZE); - safeZoneNerfedCreatureTypes.add(EntityType.CAVE_SPIDER); - safeZoneNerfedCreatureTypes.add(EntityType.CREEPER); - safeZoneNerfedCreatureTypes.add(EntityType.ENDER_DRAGON); - safeZoneNerfedCreatureTypes.add(EntityType.ENDERMAN); - safeZoneNerfedCreatureTypes.add(EntityType.GHAST); - safeZoneNerfedCreatureTypes.add(EntityType.MAGMA_CUBE); - safeZoneNerfedCreatureTypes.add(EntityType.PIG_ZOMBIE); - safeZoneNerfedCreatureTypes.add(EntityType.SILVERFISH); - safeZoneNerfedCreatureTypes.add(EntityType.SKELETON); - safeZoneNerfedCreatureTypes.add(EntityType.SPIDER); - safeZoneNerfedCreatureTypes.add(EntityType.SLIME); - safeZoneNerfedCreatureTypes.add(EntityType.WITCH); - safeZoneNerfedCreatureTypes.add(EntityType.WITHER); - safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE); - // Is this called lazy load? - defaultFactionPermissions.put("LEADER", new DefaultPermissions(true)); - defaultFactionPermissions.put("COLEADER", new DefaultPermissions(true)); - defaultFactionPermissions.put("MODERATOR", new DefaultPermissions(true)); - defaultFactionPermissions.put("MEMBER", new DefaultPermissions(false)); - defaultFactionPermissions.put("RECRUIT", new DefaultPermissions(false)); - } + territoryDenyUseageMaterialsWhenOffline.add(SavageFactions.plugin.FIREBALL); + territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL); + territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET); + territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET); + territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); + if (!SavageFactions.plugin.mc17) { + territoryDenyUseageMaterialsWhenOffline.add(Material.ARMOR_STAND); + } + safeZoneNerfedCreatureTypes.add(EntityType.BLAZE); + safeZoneNerfedCreatureTypes.add(EntityType.CAVE_SPIDER); + safeZoneNerfedCreatureTypes.add(EntityType.CREEPER); + safeZoneNerfedCreatureTypes.add(EntityType.ENDER_DRAGON); + safeZoneNerfedCreatureTypes.add(EntityType.ENDERMAN); + safeZoneNerfedCreatureTypes.add(EntityType.GHAST); + safeZoneNerfedCreatureTypes.add(EntityType.MAGMA_CUBE); + safeZoneNerfedCreatureTypes.add(EntityType.PIG_ZOMBIE); + safeZoneNerfedCreatureTypes.add(EntityType.SILVERFISH); + safeZoneNerfedCreatureTypes.add(EntityType.SKELETON); + safeZoneNerfedCreatureTypes.add(EntityType.SPIDER); + safeZoneNerfedCreatureTypes.add(EntityType.SLIME); + safeZoneNerfedCreatureTypes.add(EntityType.WITCH); + safeZoneNerfedCreatureTypes.add(EntityType.WITHER); + safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE); + // Is this called lazy load? + defaultFactionPermissions.put("LEADER", new DefaultPermissions(true)); + defaultFactionPermissions.put("COLEADER", new DefaultPermissions(true)); + defaultFactionPermissions.put("MODERATOR", new DefaultPermissions(true)); + defaultFactionPermissions.put("MEMBER", new DefaultPermissions(false)); + defaultFactionPermissions.put("RECRUIT", new DefaultPermissions(false)); + } - public static void load() { - SavageFactions.plugin.persist.loadOrSaveDefault(i, Conf.class, "conf"); - } + public static void load() { + SavageFactions.plugin.persist.loadOrSaveDefault(i, Conf.class, "conf"); + } - public static void save() { - SavageFactions.plugin.persist.save(i); - } + public static void save() { + SavageFactions.plugin.persist.save(i); + } - public enum Backend { - JSON, - //MYSQL, TODO add MySQL storage - ; - } + public enum Backend { + JSON, + //MYSQL, TODO add MySQL storage + ; + } } diff --git a/src/main/java/com/massivecraft/factions/FLocation.java b/src/main/java/com/massivecraft/factions/FLocation.java index 1c684ce0..0f9c71fd 100644 --- a/src/main/java/com/massivecraft/factions/FLocation.java +++ b/src/main/java/com/massivecraft/factions/FLocation.java @@ -11,247 +11,247 @@ import java.util.LinkedHashSet; import java.util.Set; public class FLocation implements Serializable { - private static final long serialVersionUID = -8292915234027387983L; - private static final boolean worldBorderSupport; + private static final long serialVersionUID = -8292915234027387983L; + private static final boolean worldBorderSupport; - static { - boolean worldBorderClassPresent = false; - try { - Class.forName("org.bukkit.WorldBorder"); - worldBorderClassPresent = true; - } catch (ClassNotFoundException ignored) { - } + static { + boolean worldBorderClassPresent = false; + try { + Class.forName("org.bukkit.WorldBorder"); + worldBorderClassPresent = true; + } catch (ClassNotFoundException ignored) { + } - worldBorderSupport = worldBorderClassPresent; - } + worldBorderSupport = worldBorderClassPresent; + } - private String worldName = "world"; - private int x = 0; - private int z = 0; + private String worldName = "world"; + private int x = 0; + private int z = 0; - //----------------------------------------------// - // Constructors - //----------------------------------------------// + //----------------------------------------------// + // Constructors + //----------------------------------------------// - public FLocation() { + public FLocation() { - } + } - public FLocation(String worldName, int x, int z) { - this.worldName = worldName; - this.x = x; - this.z = z; - } + public FLocation(String worldName, int x, int z) { + this.worldName = worldName; + this.x = x; + this.z = z; + } - public FLocation(Location location) { - this(location.getWorld().getName(), blockToChunk(location.getBlockX()), blockToChunk(location.getBlockZ())); - } + public FLocation(Location location) { + this(location.getWorld().getName(), blockToChunk(location.getBlockX()), blockToChunk(location.getBlockZ())); + } - public FLocation(Player player) { - this(player.getLocation()); - } + public FLocation(Player player) { + this(player.getLocation()); + } - public FLocation(FPlayer fplayer) { - this(fplayer.getPlayer()); - } + public FLocation(FPlayer fplayer) { + this(fplayer.getPlayer()); + } - public FLocation(Block block) { - this(block.getLocation()); - } + public FLocation(Block block) { + this(block.getLocation()); + } - //----------------------------------------------// - // Getters and Setters - //----------------------------------------------// + //----------------------------------------------// + // Getters and Setters + //----------------------------------------------// - public static FLocation fromString(String string) { - int index = string.indexOf(","); - int start = 1; - String worldName = string.substring(start, index); - start = index + 1; - index = string.indexOf(",", start); - int x = Integer.valueOf(string.substring(start, index)); - int y = Integer.valueOf(string.substring(index + 1, string.length() - 1)); - return new FLocation(worldName, x, y); - } + public static FLocation fromString(String string) { + int index = string.indexOf(","); + int start = 1; + String worldName = string.substring(start, index); + start = index + 1; + index = string.indexOf(",", start); + int x = Integer.valueOf(string.substring(start, index)); + int y = Integer.valueOf(string.substring(index + 1, string.length() - 1)); + return new FLocation(worldName, x, y); + } - // bit-shifting is used because it's much faster than standard division and multiplication - public static int blockToChunk(int blockVal) { // 1 chunk is 16x16 blocks - return blockVal >> 4; // ">> 4" == "/ 16" - } + // bit-shifting is used because it's much faster than standard division and multiplication + public static int blockToChunk(int blockVal) { // 1 chunk is 16x16 blocks + return blockVal >> 4; // ">> 4" == "/ 16" + } - public static int blockToRegion(int blockVal) { // 1 region is 512x512 blocks - return blockVal >> 9; // ">> 9" == "/ 512" - } + public static int blockToRegion(int blockVal) { // 1 region is 512x512 blocks + return blockVal >> 9; // ">> 9" == "/ 512" + } - public static int chunkToRegion(int chunkVal) { // 1 region is 32x32 chunks - return chunkVal >> 5; // ">> 5" == "/ 32" - } + public static int chunkToRegion(int chunkVal) { // 1 region is 32x32 chunks + return chunkVal >> 5; // ">> 5" == "/ 32" + } - public static int chunkToBlock(int chunkVal) { - return chunkVal << 4; // "<< 4" == "* 16" - } + public static int chunkToBlock(int chunkVal) { + return chunkVal << 4; // "<< 4" == "* 16" + } - public static int regionToBlock(int regionVal) { - return regionVal << 9; // "<< 9" == "* 512" - } + public static int regionToBlock(int regionVal) { + return regionVal << 9; // "<< 9" == "* 512" + } - public static int regionToChunk(int regionVal) { - return regionVal << 5; // "<< 5" == "* 32" - } + public static int regionToChunk(int regionVal) { + return regionVal << 5; // "<< 5" == "* 32" + } - public static HashSet getArea(FLocation from, FLocation to) { - HashSet ret = new HashSet<>(); + public static HashSet getArea(FLocation from, FLocation to) { + HashSet ret = new HashSet<>(); - for (long x : MiscUtil.range(from.getX(), to.getX())) { - for (long z : MiscUtil.range(from.getZ(), to.getZ())) { - ret.add(new FLocation(from.getWorldName(), (int) x, (int) z)); - } - } + for (long x : MiscUtil.range(from.getX(), to.getX())) { + for (long z : MiscUtil.range(from.getZ(), to.getZ())) { + ret.add(new FLocation(from.getWorldName(), (int) x, (int) z)); + } + } - return ret; - } + return ret; + } - public Chunk getChunk() { - return Bukkit.getWorld(worldName).getChunkAt(x, z); - } + public Chunk getChunk() { + return Bukkit.getWorld(worldName).getChunkAt(x, z); + } - public String getWorldName() { - return worldName; - } + public String getWorldName() { + return worldName; + } - public void setWorldName(String worldName) { - this.worldName = worldName; - } + public void setWorldName(String worldName) { + this.worldName = worldName; + } - //----------------------------------------------// - // Block/Chunk/Region Value Transformation - //----------------------------------------------// + //----------------------------------------------// + // Block/Chunk/Region Value Transformation + //----------------------------------------------// - public World getWorld() { - return Bukkit.getWorld(worldName); - } + public World getWorld() { + return Bukkit.getWorld(worldName); + } - public long getX() { - return x; - } + public long getX() { + return x; + } - public void setX(int x) { - this.x = x; - } + public void setX(int x) { + this.x = x; + } - public long getZ() { - return z; - } + public long getZ() { + return z; + } - public void setZ(int z) { - this.z = z; - } + public void setZ(int z) { + this.z = z; + } - public String getCoordString() { - return "" + x + "," + z; - } + public String getCoordString() { + return "" + x + "," + z; + } - //----------------------------------------------// - // Misc Geometry - //----------------------------------------------// + //----------------------------------------------// + // Misc Geometry + //----------------------------------------------// - @Override - public String toString() { - return "[" + this.getWorldName() + "," + this.getCoordString() + "]"; - } + @Override + public String toString() { + return "[" + this.getWorldName() + "," + this.getCoordString() + "]"; + } - public FLocation getRelative(int dx, int dz) { - return new FLocation(this.worldName, this.x + dx, this.z + dz); - } + public FLocation getRelative(int dx, int dz) { + return new FLocation(this.worldName, this.x + dx, this.z + dz); + } - public double getDistanceTo(FLocation that) { - double dx = that.x - this.x; - double dz = that.z - this.z; - return Math.sqrt(dx * dx + dz * dz); - } + public double getDistanceTo(FLocation that) { + double dx = that.x - this.x; + double dz = that.z - this.z; + return Math.sqrt(dx * dx + dz * dz); + } - public double getDistanceSquaredTo(FLocation that) { - double dx = that.x - this.x; - double dz = that.z - this.z; - return dx * dx + dz * dz; - } + public double getDistanceSquaredTo(FLocation that) { + double dx = that.x - this.x; + double dz = that.z - this.z; + return dx * dx + dz * dz; + } - public boolean isInChunk(Location loc) { - if (loc == null) { - return false; - } - Chunk chunk = loc.getChunk(); - return loc.getWorld().getName().equalsIgnoreCase(getWorldName()) && chunk.getX() == x && chunk.getZ() == z; - } + public boolean isInChunk(Location loc) { + if (loc == null) { + return false; + } + Chunk chunk = loc.getChunk(); + return loc.getWorld().getName().equalsIgnoreCase(getWorldName()) && chunk.getX() == x && chunk.getZ() == z; + } - /** - * Checks if the chunk represented by this FLocation is outside the world border - * - * @param buffer the number of chunks from the border that will be treated as "outside" - * @return whether this location is outside of the border - */ - public boolean isOutsideWorldBorder(int buffer) { - if (!worldBorderSupport) { - return false; - } + /** + * Checks if the chunk represented by this FLocation is outside the world border + * + * @param buffer the number of chunks from the border that will be treated as "outside" + * @return whether this location is outside of the border + */ + public boolean isOutsideWorldBorder(int buffer) { + if (!worldBorderSupport) { + return false; + } - WorldBorder border = getWorld().getWorldBorder(); - Chunk chunk = border.getCenter().getChunk(); + WorldBorder border = getWorld().getWorldBorder(); + Chunk chunk = border.getCenter().getChunk(); - int lim = FLocation.chunkToRegion((int) border.getSize()) - buffer; - int diffX = chunk.getX() - x; - int diffZ = chunk.getZ() - z; - return diffX > lim || diffZ > lim || -diffX > lim - 1 || -diffZ > lim - 1; - } + int lim = FLocation.chunkToRegion((int) border.getSize()) - buffer; + int diffX = chunk.getX() - x; + int diffZ = chunk.getZ() - z; + return diffX > lim || diffZ > lim || -diffX > lim - 1 || -diffZ > lim - 1; + } - //----------------------------------------------// - // Some Geometry - //----------------------------------------------// - public Set getCircle(double radius) { - double radiusSquared = radius * radius; + //----------------------------------------------// + // Some Geometry + //----------------------------------------------// + public Set getCircle(double radius) { + double radiusSquared = radius * radius; - Set ret = new LinkedHashSet<>(); - if (radius <= 0) { - return ret; - } + Set ret = new LinkedHashSet<>(); + if (radius <= 0) { + return ret; + } - int xfrom = (int) Math.floor(this.x - radius); - int xto = (int) Math.ceil(this.x + radius); - int zfrom = (int) Math.floor(this.z - radius); - int zto = (int) Math.ceil(this.z + radius); + int xfrom = (int) Math.floor(this.x - radius); + int xto = (int) Math.ceil(this.x + radius); + int zfrom = (int) Math.floor(this.z - radius); + int zto = (int) Math.ceil(this.z + radius); - for (int x = xfrom; x <= xto; x++) { - for (int z = zfrom; z <= zto; z++) { - FLocation potential = new FLocation(this.worldName, x, z); - if (this.getDistanceSquaredTo(potential) <= radiusSquared) { - ret.add(potential); - } - } - } + for (int x = xfrom; x <= xto; x++) { + for (int z = zfrom; z <= zto; z++) { + FLocation potential = new FLocation(this.worldName, x, z); + if (this.getDistanceSquaredTo(potential) <= radiusSquared) { + ret.add(potential); + } + } + } - return ret; - } + return ret; + } - //----------------------------------------------// - // Comparison - //----------------------------------------------// + //----------------------------------------------// + // Comparison + //----------------------------------------------// - @Override - public int hashCode() { - // should be fast, with good range and few hash collisions: (x * 512) + z + worldName.hashCode - return (this.x << 9) + this.z + (this.worldName != null ? this.worldName.hashCode() : 0); - } + @Override + public int hashCode() { + // should be fast, with good range and few hash collisions: (x * 512) + z + worldName.hashCode + return (this.x << 9) + this.z + (this.worldName != null ? this.worldName.hashCode() : 0); + } - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof FLocation)) { - return false; - } + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof FLocation)) { + return false; + } - FLocation that = (FLocation) obj; - return this.x == that.x && this.z == that.z && (this.worldName == null ? that.worldName == null : this.worldName.equals(that.worldName)); - } + FLocation that = (FLocation) obj; + return this.x == that.x && this.z == that.z && (this.worldName == null ? that.worldName == null : this.worldName.equals(that.worldName)); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/FPlayer.java b/src/main/java/com/massivecraft/factions/FPlayer.java index 48d1a44a..359f09ba 100644 --- a/src/main/java/com/massivecraft/factions/FPlayer.java +++ b/src/main/java/com/massivecraft/factions/FPlayer.java @@ -26,354 +26,354 @@ import java.util.List; public interface FPlayer extends EconomyParticipator { - /** - * Used to know if stealth is toggled on or off - * - * @return if stealth mode is on or not. - */ - boolean isStealthEnabled(); + /** + * Used to know if stealth is toggled on or off + * + * @return if stealth mode is on or not. + */ + boolean isStealthEnabled(); - /** - * Toggles the stealth of the FPlayer depending on the parameter - * - * @param stealthToggle - toggles stealth - */ - void setStealth(boolean stealthToggle); + /** + * Toggles the stealth of the FPlayer depending on the parameter + * + * @param stealthToggle - toggles stealth + */ + void setStealth(boolean stealthToggle); - /** - * Sets the kills and deaths of a player. - */ - void login(); + /** + * Sets the kills and deaths of a player. + */ + void login(); - /** - * Caches the kills and deaths of a player. - */ - void logout(); + /** + * Caches the kills and deaths of a player. + */ + void logout(); - /** - * gets the faction of a FPlayer. - * - * @return Faction of the FPlayer. - */ - Faction getFaction(); + /** + * gets the faction of a FPlayer. + * + * @return Faction of the FPlayer. + */ + Faction getFaction(); - /** - * Sets the faction of the FPlayer - * - * @param faction faction to set. - */ - void setFaction(Faction faction); + /** + * Sets the faction of the FPlayer + * + * @param faction faction to set. + */ + void setFaction(Faction faction); - /** - * Gets the faction ID of the player. - * - * @return FactionsID string - */ - String getFactionId(); + /** + * Gets the faction ID of the player. + * + * @return FactionsID string + */ + String getFactionId(); - /** - * Check if a player has a faction - * - * @return boolean - */ - boolean hasFaction(); + /** + * Check if a player has a faction + * + * @return boolean + */ + boolean hasFaction(); - /** - * Gets autoleave status - * - * @return boolean of the autoleave - */ - boolean willAutoLeave(); + /** + * Gets autoleave status + * + * @return boolean of the autoleave + */ + boolean willAutoLeave(); - void setAutoLeave(boolean autoLeave); + void setAutoLeave(boolean autoLeave); - long getLastFrostwalkerMessage(); + long getLastFrostwalkerMessage(); - void setLastFrostwalkerMessage(); + void setLastFrostwalkerMessage(); - void setMonitorJoins(boolean monitor); + void setMonitorJoins(boolean monitor); - boolean isMonitoringJoins(); + boolean isMonitoringJoins(); - Role getRole(); + Role getRole(); - void setRole(Role role); + void setRole(Role role); - boolean shouldTakeFallDamage(); + boolean shouldTakeFallDamage(); - void setTakeFallDamage(boolean fallDamage); + void setTakeFallDamage(boolean fallDamage); - double getPowerBoost(); + double getPowerBoost(); - void setPowerBoost(double powerBoost); + void setPowerBoost(double powerBoost); - Faction getAutoClaimFor(); + Faction getAutoClaimFor(); - void setAutoClaimFor(Faction faction); + void setAutoClaimFor(Faction faction); - boolean isAutoSafeClaimEnabled(); + boolean isAutoSafeClaimEnabled(); - void setIsAutoSafeClaimEnabled(boolean enabled); + void setIsAutoSafeClaimEnabled(boolean enabled); - boolean isAutoWarClaimEnabled(); + boolean isAutoWarClaimEnabled(); - void setIsAutoWarClaimEnabled(boolean enabled); + void setIsAutoWarClaimEnabled(boolean enabled); - boolean isAdminBypassing(); + boolean isAdminBypassing(); - boolean isVanished(); + boolean isVanished(); - void setIsAdminBypassing(boolean val); + void setIsAdminBypassing(boolean val); - ChatMode getChatMode(); + ChatMode getChatMode(); - void setChatMode(ChatMode chatMode); + void setChatMode(ChatMode chatMode); - boolean isIgnoreAllianceChat(); + boolean isIgnoreAllianceChat(); - void setIgnoreAllianceChat(boolean ignore); + void setIgnoreAllianceChat(boolean ignore); - boolean isSpyingChat(); + boolean isSpyingChat(); - void setSpyingChat(boolean chatSpying); + void setSpyingChat(boolean chatSpying); - boolean showScoreboard(); + boolean showScoreboard(); - void setShowScoreboard(boolean show); + void setShowScoreboard(boolean show); - // FIELD: account - String getAccountId(); + // FIELD: account + String getAccountId(); - void resetFactionData(boolean doSpoutUpdate); + void resetFactionData(boolean doSpoutUpdate); - void resetFactionData(); + void resetFactionData(); - long getLastLoginTime(); + long getLastLoginTime(); - void setLastLoginTime(long lastLoginTime); + void setLastLoginTime(long lastLoginTime); - boolean isMapAutoUpdating(); + boolean isMapAutoUpdating(); - void setMapAutoUpdating(boolean mapAutoUpdating); + void setMapAutoUpdating(boolean mapAutoUpdating); - boolean hasLoginPvpDisabled(); + boolean hasLoginPvpDisabled(); - FLocation getLastStoodAt(); + FLocation getLastStoodAt(); - void setLastStoodAt(FLocation flocation); + void setLastStoodAt(FLocation flocation); - String getTitle(); + String getTitle(); - void setTitle(CommandSender sender, String title); + void setTitle(CommandSender sender, String title); - String getName(); + String getName(); - String getTag(); + String getTag(); - // Base concatenations: + // Base concatenations: - String getNameAndSomething(String something); + String getNameAndSomething(String something); - String getNameAndTitle(); + String getNameAndTitle(); - String getNameAndTag(); + String getNameAndTag(); - // Colored concatenations: - // These are used in information messages + // Colored concatenations: + // These are used in information messages - String getNameAndTitle(Faction faction); + String getNameAndTitle(Faction faction); - String getNameAndTitle(FPlayer fplayer); + String getNameAndTitle(FPlayer fplayer); - // Chat Tag: - // These are injected into the format of global chat messages. + // Chat Tag: + // These are injected into the format of global chat messages. - String getChatTag(); + String getChatTag(); - // Colored Chat Tag - String getChatTag(Faction faction); + // Colored Chat Tag + String getChatTag(Faction faction); - String getChatTag(FPlayer fplayer); + String getChatTag(FPlayer fplayer); - int getKills(); + int getKills(); - int getDeaths(); + int getDeaths(); - void takeMoney(int amt); + void takeMoney(int amt); - boolean hasMoney(int amt); + boolean hasMoney(int amt); - //inspect Stuff + //inspect Stuff - boolean isInspectMode(); + boolean isInspectMode(); - void setInspectMode(boolean status); + void setInspectMode(boolean status); - // Fly Checks + // Fly Checks - Boolean canflyinWilderness(); + Boolean canflyinWilderness(); - Boolean canflyinWarzone(); + Boolean canflyinWarzone(); - Boolean canflyinSafezone(); + Boolean canflyinSafezone(); - Boolean canflyinEnemy(); + Boolean canflyinEnemy(); - Boolean canflyinAlly(); + Boolean canflyinAlly(); - Boolean canflyinTruce(); + Boolean canflyinTruce(); - Boolean canflyinNeutral(); + Boolean canflyinNeutral(); - // ------------------------------- - // Relation and relation colors - // ------------------------------- + // ------------------------------- + // Relation and relation colors + // ------------------------------- - @Override - String describeTo(RelationParticipator that, boolean ucfirst); + @Override + String describeTo(RelationParticipator that, boolean ucfirst); - @Override - String describeTo(RelationParticipator that); + @Override + String describeTo(RelationParticipator that); - @Override - Relation getRelationTo(RelationParticipator rp); + @Override + Relation getRelationTo(RelationParticipator rp); - @Override - Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); + @Override + Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); - Relation getRelationToLocation(); + Relation getRelationToLocation(); - @Override - ChatColor getColorTo(RelationParticipator rp); + @Override + ChatColor getColorTo(RelationParticipator rp); - String getRolePrefix(); + String getRolePrefix(); - //----------------------------------------------// - // Health - //----------------------------------------------// - void heal(int amnt); + //----------------------------------------------// + // Health + //----------------------------------------------// + void heal(int amnt); - //----------------------------------------------// - // Power - //----------------------------------------------// - double getPower(); + //----------------------------------------------// + // Power + //----------------------------------------------// + double getPower(); - void alterPower(double delta); + void alterPower(double delta); - double getPowerMax(); + double getPowerMax(); - double getPowerMin(); + double getPowerMin(); - int getPowerRounded(); + int getPowerRounded(); - int getPowerMaxRounded(); + int getPowerMaxRounded(); - int getPowerMinRounded(); + int getPowerMinRounded(); - void updatePower(); + void updatePower(); - void losePowerFromBeingOffline(); + void losePowerFromBeingOffline(); - void onDeath(); + void onDeath(); - //----------------------------------------------// - // Territory - //----------------------------------------------// - boolean isInOwnTerritory(); + //----------------------------------------------// + // Territory + //----------------------------------------------// + boolean isInOwnTerritory(); - boolean isInOthersTerritory(); + boolean isInOthersTerritory(); - boolean isInAllyTerritory(); + boolean isInAllyTerritory(); - boolean isInNeutralTerritory(); + boolean isInNeutralTerritory(); - boolean isInEnemyTerritory(); + boolean isInEnemyTerritory(); - void sendFactionHereMessage(Faction from); + void sendFactionHereMessage(Faction from); - // ------------------------------- - // Actions - // ------------------------------- + // ------------------------------- + // Actions + // ------------------------------- - void leave(boolean makePay); + void leave(boolean makePay); - boolean canClaimForFaction(Faction forFaction); + boolean canClaimForFaction(Faction forFaction); - boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure); + boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure); - boolean canClaimForFactionAtLocation(Faction forFaction, FLocation location, boolean notifyFailure); + boolean canClaimForFactionAtLocation(Faction forFaction, FLocation location, boolean notifyFailure); - boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure); + boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure); - boolean attemptClaim(Faction forFaction, FLocation location, boolean notifyFailure); + boolean attemptClaim(Faction forFaction, FLocation location, boolean notifyFailure); - boolean isInVault(); + boolean isInVault(); - void setInVault(boolean status); + void setInVault(boolean status); - void msg(String str, Object... args); + void msg(String str, Object... args); - String getId(); + String getId(); - void setId(String id); + void setId(String id); - Player getPlayer(); + Player getPlayer(); - boolean isOnline(); + boolean isOnline(); - void sendMessage(String message); + void sendMessage(String message); - void sendMessage(List messages); + void sendMessage(List messages); - void sendFancyMessage(FancyMessage message); + void sendFancyMessage(FancyMessage message); - void sendFancyMessage(List message); + void sendFancyMessage(List message); - int getMapHeight(); + int getMapHeight(); - void setMapHeight(int height); + void setMapHeight(int height); - boolean isOnlineAndVisibleTo(Player me); + boolean isOnlineAndVisibleTo(Player me); - void remove(); + void remove(); - boolean isOffline(); + boolean isOffline(); - boolean isFlying(); + boolean isFlying(); - void setFlying(boolean fly); + void setFlying(boolean fly); - void setFFlying(boolean fly, boolean damage); + void setFFlying(boolean fly, boolean damage); - boolean canFlyAtLocation(); + boolean canFlyAtLocation(); - boolean canFlyAtLocation(FLocation location); + boolean canFlyAtLocation(FLocation location); - boolean isEnteringPassword(); + boolean isEnteringPassword(); - void setEnteringPassword(boolean toggle, String warp); + void setEnteringPassword(boolean toggle, String warp); - String getEnteringWarp(); + String getEnteringWarp(); - boolean checkIfNearbyEnemies(); + boolean checkIfNearbyEnemies(); - // ------------------------------- - // Warmups - // ------------------------------- + // ------------------------------- + // Warmups + // ------------------------------- - boolean isWarmingUp(); + boolean isWarmingUp(); - WarmUpUtil.Warmup getWarmupType(); + WarmUpUtil.Warmup getWarmupType(); - void addWarmup(WarmUpUtil.Warmup warmup, int taskId); + void addWarmup(WarmUpUtil.Warmup warmup, int taskId); - void stopWarmup(); + void stopWarmup(); - void clearWarmup(); + void clearWarmup(); } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/FPlayers.java b/src/main/java/com/massivecraft/factions/FPlayers.java index aca12183..a11917e7 100644 --- a/src/main/java/com/massivecraft/factions/FPlayers.java +++ b/src/main/java/com/massivecraft/factions/FPlayers.java @@ -1,41 +1,41 @@ -package com.massivecraft.factions; - -import com.massivecraft.factions.zcore.persist.json.JSONFPlayers; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.util.Collection; - -public abstract class FPlayers { - protected static FPlayers instance = getFPlayersImpl(); - - public static FPlayers getInstance() { - return instance; - } - - private static FPlayers getFPlayersImpl() { - switch (Conf.backEnd) { - case JSON: - return new JSONFPlayers(); - } - return null; - } - - public abstract void clean(); - - public abstract Collection getOnlinePlayers(); - - public abstract FPlayer getByPlayer(Player player); - - public abstract Collection getAllFPlayers(); - - public abstract void forceSave(); - - public abstract void forceSave(boolean sync); - - public abstract FPlayer getByOfflinePlayer(OfflinePlayer player); - - public abstract FPlayer getById(String string); - - public abstract void load(); -} +package com.massivecraft.factions; + +import com.massivecraft.factions.zcore.persist.json.JSONFPlayers; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public abstract class FPlayers { + protected static FPlayers instance = getFPlayersImpl(); + + public static FPlayers getInstance() { + return instance; + } + + private static FPlayers getFPlayersImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONFPlayers(); + } + return null; + } + + public abstract void clean(); + + public abstract Collection getOnlinePlayers(); + + public abstract FPlayer getByPlayer(Player player); + + public abstract Collection getAllFPlayers(); + + public abstract void forceSave(); + + public abstract void forceSave(boolean sync); + + public abstract FPlayer getByOfflinePlayer(OfflinePlayer player); + + public abstract FPlayer getById(String string); + + public abstract void load(); +} diff --git a/src/main/java/com/massivecraft/factions/Faction.java b/src/main/java/com/massivecraft/factions/Faction.java index be6412c6..5e97f012 100644 --- a/src/main/java/com/massivecraft/factions/Faction.java +++ b/src/main/java/com/massivecraft/factions/Faction.java @@ -21,327 +21,328 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; public interface Faction extends EconomyParticipator { - HashMap> getAnnouncements(); + HashMap> getAnnouncements(); - ConcurrentHashMap getWarps(); + ConcurrentHashMap getWarps(); - LazyLocation getWarp(String name); + LazyLocation getWarp(String name); - void setWarp(String name, LazyLocation loc); + void setWarp(String name, LazyLocation loc); - boolean isWarp(String name); + boolean isWarp(String name); - boolean hasWarpPassword(String warp); + boolean hasWarpPassword(String warp); - boolean isWarpPassword(String warp, String password); + boolean isWarpPassword(String warp, String password); - void setWarpPassword(String warp, String password); + void setWarpPassword(String warp, String password); - boolean removeWarp(String name); + boolean removeWarp(String name); - void clearWarps(); + void clearWarps(); - int getMaxVaults(); + int getMaxVaults(); - void setMaxVaults(int value); + void setMaxVaults(int value); - void addAnnouncement(FPlayer fPlayer, String msg); + void addAnnouncement(FPlayer fPlayer, String msg); - void sendUnreadAnnouncements(FPlayer fPlayer); + void sendUnreadAnnouncements(FPlayer fPlayer); - void removeAnnouncements(FPlayer fPlayer); + void removeAnnouncements(FPlayer fPlayer); - Set getInvites(); + Set getInvites(); - String getFocused(); + String getFocused(); - void setFocused(String setFocused); + void setFocused(String setFocused); - String getId(); + String getId(); - void setId(String id); + void setId(String id); - void invite(FPlayer fplayer); + void invite(FPlayer fplayer); - void deinvite(FPlayer fplayer); + void deinvite(FPlayer fplayer); - void setUpgrade(Upgrade upgrade, int level); + void setUpgrade(Upgrade upgrade, int level); - int getUpgrade(Upgrade upgrade); + int getUpgrade(Upgrade upgrade); - boolean isInvited(FPlayer fplayer); + boolean isInvited(FPlayer fplayer); - void ban(FPlayer target, FPlayer banner); + void ban(FPlayer target, FPlayer banner); - void unban(FPlayer player); + void unban(FPlayer player); - boolean isBanned(FPlayer player); + boolean isBanned(FPlayer player); - Set getBannedPlayers(); + Set getBannedPlayers(); - HashMap getRulesMap(); + HashMap getRulesMap(); - void setRule(int index, String rule); + void setRule(int index, String rule); - void addRule(String rule); + void addRule(String rule); - void removeRule(int index); + void removeRule(int index); - void clearRules(); + void clearRules(); - Location getCheckpoint(); + Location getCheckpoint(); - void setCheckpoint(Location location); + void setCheckpoint(Location location); - void addTnt(int amt); + void addTnt(int amt); - void takeTnt(int amt); + void takeTnt(int amt); - Location getVault(); + Location getVault(); - void setVault(Location vaultLocation); + void setVault(Location vaultLocation); - Inventory getChestInventory(); + Inventory getChestInventory(); - void setChestSize(int chestSize); + void setChestSize(int chestSize); - void setBannerPattern(ItemStack banner); + void setBannerPattern(ItemStack banner); - ItemStack getBanner(); + ItemStack getBanner(); - int getTnt(); + int getTnt(); - String getRule(int index); + String getRule(int index); - boolean getOpen(); + boolean getOpen(); - void setOpen(boolean isOpen); + void setOpen(boolean isOpen); - boolean isPeaceful(); + boolean isPeaceful(); - void setPeaceful(boolean isPeaceful); + void setPeaceful(boolean isPeaceful); - boolean getPeacefulExplosionsEnabled(); + boolean getPeacefulExplosionsEnabled(); - void setPeacefulExplosionsEnabled(boolean val); + void setPeacefulExplosionsEnabled(boolean val); - boolean noExplosionsInTerritory(); + boolean noExplosionsInTerritory(); - boolean isPermanent(); + boolean isPermanent(); - void setPermanent(boolean isPermanent); + void setPermanent(boolean isPermanent); - String getTag(); + String getTag(); - void setTag(String str); + void setTag(String str); - String getTag(String prefix); + String getTag(String prefix); - String getTag(Faction otherFaction); + String getTag(Faction otherFaction); - String getTag(FPlayer otherFplayer); + String getTag(FPlayer otherFplayer); - String getComparisonTag(); + String getComparisonTag(); - String getDescription(); + String getDescription(); - void setDescription(String value); + void setDescription(String value); - boolean hasHome(); + boolean hasHome(); - Location getHome(); + Location getHome(); - void setHome(Location home); + void setHome(Location home); - long getFoundedDate(); + long getFoundedDate(); - void setFoundedDate(long newDate); + void setFoundedDate(long newDate); - void confirmValidHome(); + void confirmValidHome(); - String getAccountId(); + String getAccountId(); - Integer getPermanentPower(); + Integer getPermanentPower(); - void setPermanentPower(Integer permanentPower); + void setPermanentPower(Integer permanentPower); - boolean hasPermanentPower(); + boolean hasPermanentPower(); - double getPowerBoost(); + double getPowerBoost(); - void setPowerBoost(double powerBoost); + void setPowerBoost(double powerBoost); - boolean noPvPInTerritory(); + boolean noPvPInTerritory(); - boolean noMonstersInTerritory(); + boolean noMonstersInTerritory(); - boolean isNormal(); + boolean isNormal(); - @Deprecated - boolean isNone(); + @Deprecated + boolean isNone(); - boolean isWilderness(); + boolean isWilderness(); - boolean isSafeZone(); + boolean isSafeZone(); - boolean isWarZone(); + boolean isWarZone(); - boolean isPlayerFreeType(); + boolean isPlayerFreeType(); - boolean isPowerFrozen(); + boolean isPowerFrozen(); - void setLastDeath(long time); + void setLastDeath(long time); - int getKills(); + int getKills(); - int getDeaths(); + int getDeaths(); - Access getAccess(Permissable permissable, PermissableAction permissableAction); + Access getAccess(Permissable permissable, PermissableAction permissableAction); - Access getAccess(FPlayer player, PermissableAction permissableAction); + Access getAccess(FPlayer player, PermissableAction permissableAction); - void setPermission(Permissable permissable, PermissableAction permissableAction, Access access); + void setPermission(Permissable permissable, PermissableAction permissableAction, Access access); - void resetPerms(); - void setDefaultPerms(); + void resetPerms(); - void disband(Player disbander); + void setDefaultPerms(); - void disband(Player disbander, PlayerDisbandReason reason); + void disband(Player disbander); - // ------------------------------- - // Relation and relation colors - // ------------------------------- + void disband(Player disbander, PlayerDisbandReason reason); - Map> getPermissions(); + // ------------------------------- + // Relation and relation colors + // ------------------------------- - @Override - String describeTo(RelationParticipator that, boolean ucfirst); + Map> getPermissions(); - @Override - String describeTo(RelationParticipator that); + @Override + String describeTo(RelationParticipator that, boolean ucfirst); - @Override - Relation getRelationTo(RelationParticipator rp); + @Override + String describeTo(RelationParticipator that); - @Override - Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); + @Override + Relation getRelationTo(RelationParticipator rp); - @Override - ChatColor getColorTo(RelationParticipator rp); + @Override + Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); - Relation getRelationWish(Faction otherFaction); + @Override + ChatColor getColorTo(RelationParticipator rp); - void setRelationWish(Faction otherFaction, Relation relation); + Relation getRelationWish(Faction otherFaction); - int getRelationCount(Relation relation); + void setRelationWish(Faction otherFaction, Relation relation); - // ----------------------------------------------// - // Power - // ----------------------------------------------// - double getPower(); + int getRelationCount(Relation relation); - double getPowerMax(); + // ----------------------------------------------// + // Power + // ----------------------------------------------// + double getPower(); - int getPowerRounded(); + double getPowerMax(); - int getPowerMaxRounded(); + int getPowerRounded(); - int getLandRounded(); + int getPowerMaxRounded(); - int getLandRoundedInWorld(String worldName); + int getLandRounded(); - // ------------------------------- - // FPlayers - // ------------------------------- + int getLandRoundedInWorld(String worldName); - boolean hasLandInflation(); + // ------------------------------- + // FPlayers + // ------------------------------- - // maintain the reference list of FPlayers in this faction - void refreshFPlayers(); + boolean hasLandInflation(); - boolean addFPlayer(FPlayer fplayer); + // maintain the reference list of FPlayers in this faction + void refreshFPlayers(); - boolean removeFPlayer(FPlayer fplayer); + boolean addFPlayer(FPlayer fplayer); - int getSize(); + boolean removeFPlayer(FPlayer fplayer); - Set getFPlayers(); + int getSize(); - Set getFPlayersWhereOnline(boolean online); + Set getFPlayers(); - Set getFPlayersWhereOnline(boolean online, FPlayer viewer); + Set getFPlayersWhereOnline(boolean online); - FPlayer getFPlayerAdmin(); + Set getFPlayersWhereOnline(boolean online, FPlayer viewer); - FPlayer getFPlayerLeader(); + FPlayer getFPlayerAdmin(); - ArrayList getFPlayersWhereRole(Role role); + FPlayer getFPlayerLeader(); - ArrayList getOnlinePlayers(); + ArrayList getFPlayersWhereRole(Role role); - // slightly faster check than getOnlinePlayers() if you just want to see if - // there are any players online - boolean hasPlayersOnline(); + ArrayList getOnlinePlayers(); - void memberLoggedOff(); + // slightly faster check than getOnlinePlayers() if you just want to see if + // there are any players online + boolean hasPlayersOnline(); - // used when current leader is about to be removed from the faction; - // promotes new leader, or disbands faction if no other members left - void promoteNewLeader(); + void memberLoggedOff(); - void promoteNewLeader(boolean autoLeave); + // used when current leader is about to be removed from the faction; + // promotes new leader, or disbands faction if no other members left + void promoteNewLeader(); - Role getDefaultRole(); + void promoteNewLeader(boolean autoLeave); - void setDefaultRole(Role role); + Role getDefaultRole(); - // ----------------------------------------------// - // Messages - // ----------------------------------------------// - void msg(String message, Object... args); + void setDefaultRole(Role role); - void sendMessage(String message); + // ----------------------------------------------// + // Messages + // ----------------------------------------------// + void msg(String message, Object... args); - // ----------------------------------------------// - // Ownership of specific claims - // ----------------------------------------------// + void sendMessage(String message); - void sendMessage(List messages); + // ----------------------------------------------// + // Ownership of specific claims + // ----------------------------------------------// - Map> getClaimOwnership(); + void sendMessage(List messages); - void clearAllClaimOwnership(); + Map> getClaimOwnership(); - void clearClaimOwnership(FLocation loc); + void clearAllClaimOwnership(); - void clearClaimOwnership(FPlayer player); + void clearClaimOwnership(FLocation loc); - int getCountOfClaimsWithOwners(); + void clearClaimOwnership(FPlayer player); - boolean doesLocationHaveOwnersSet(FLocation loc); + int getCountOfClaimsWithOwners(); - boolean isPlayerInOwnerList(FPlayer player, FLocation loc); + boolean doesLocationHaveOwnersSet(FLocation loc); - void setPlayerAsOwner(FPlayer player, FLocation loc); + boolean isPlayerInOwnerList(FPlayer player, FLocation loc); - void removePlayerAsOwner(FPlayer player, FLocation loc); + void setPlayerAsOwner(FPlayer player, FLocation loc); - Set getOwnerList(FLocation loc); + void removePlayerAsOwner(FPlayer player, FLocation loc); - String getOwnerListString(FLocation loc); + Set getOwnerList(FLocation loc); - boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc); + String getOwnerListString(FLocation loc); - // ----------------------------------------------// - // Persistance and entity management - // ----------------------------------------------// - void remove(); + boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc); - Set getAllClaims(); + // ----------------------------------------------// + // Persistance and entity management + // ----------------------------------------------// + void remove(); - String getPaypal(); + Set getAllClaims(); - void paypalSet(String paypal); + String getPaypal(); + + void paypalSet(String paypal); } diff --git a/src/main/java/com/massivecraft/factions/Factions.java b/src/main/java/com/massivecraft/factions/Factions.java index 285da06c..b573c3cf 100644 --- a/src/main/java/com/massivecraft/factions/Factions.java +++ b/src/main/java/com/massivecraft/factions/Factions.java @@ -1,55 +1,55 @@ -package com.massivecraft.factions; - -import com.massivecraft.factions.zcore.persist.json.JSONFactions; - -import java.util.ArrayList; -import java.util.Set; - -public abstract class Factions { - protected static Factions instance = getFactionsImpl(); - - public static Factions getInstance() { - return instance; - } - - private static Factions getFactionsImpl() { - switch (Conf.backEnd) { - case JSON: - return new JSONFactions(); - } - return null; - } - - public abstract Faction getFactionById(String id); - - public abstract Faction getByTag(String str); - - public abstract Faction getBestTagMatch(String start); - - public abstract boolean isTagTaken(String str); - - public abstract boolean isValidFactionId(String id); - - public abstract Faction createFaction(); - - public abstract void removeFaction(String id); - - public abstract Set getFactionTags(); - - public abstract ArrayList getAllFactions(); - - @Deprecated - public abstract Faction getNone(); - - public abstract Faction getWilderness(); - - public abstract Faction getSafeZone(); - - public abstract Faction getWarZone(); - - public abstract void forceSave(); - - public abstract void forceSave(boolean sync); - - public abstract void load(); -} +package com.massivecraft.factions; + +import com.massivecraft.factions.zcore.persist.json.JSONFactions; + +import java.util.ArrayList; +import java.util.Set; + +public abstract class Factions { + protected static Factions instance = getFactionsImpl(); + + public static Factions getInstance() { + return instance; + } + + private static Factions getFactionsImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONFactions(); + } + return null; + } + + public abstract Faction getFactionById(String id); + + public abstract Faction getByTag(String str); + + public abstract Faction getBestTagMatch(String start); + + public abstract boolean isTagTaken(String str); + + public abstract boolean isValidFactionId(String id); + + public abstract Faction createFaction(); + + public abstract void removeFaction(String id); + + public abstract Set getFactionTags(); + + public abstract ArrayList getAllFactions(); + + @Deprecated + public abstract Faction getNone(); + + public abstract Faction getWilderness(); + + public abstract Faction getSafeZone(); + + public abstract Faction getWarZone(); + + public abstract void forceSave(); + + public abstract void forceSave(boolean sync); + + public abstract void load(); +} diff --git a/src/main/java/com/massivecraft/factions/MassiveStats.java b/src/main/java/com/massivecraft/factions/MassiveStats.java index babb89a8..a1f01e56 100644 --- a/src/main/java/com/massivecraft/factions/MassiveStats.java +++ b/src/main/java/com/massivecraft/factions/MassiveStats.java @@ -34,464 +34,464 @@ import java.net.URL; @SuppressWarnings("all") public class MassiveStats implements Listener { - /* START: MASSIVESTATS SETTINGS */ - public static final int CLIENT_VERSION = 0; // v3.0 - public static final String API_URL = "https://report.massivestats.com/v2/"; + /* START: MASSIVESTATS SETTINGS */ + public static final int CLIENT_VERSION = 0; // v3.0 + public static final String API_URL = "https://report.massivestats.com/v2/"; - public static final String MASSIVE_UPDATE_PERMISSION = "massivestats.update"; - /* END: MASSIVESTATS SETTINGS */ - private final JavaPlugin plugin; - private MassiveStatsUpdateTask task = null; - private int pingInterval; - private MassiveStatsDataResponse lastResponse; - private boolean listenerDisabled; - private Class jsonElement; - private Class jsonParser; - private Class jsonObject; - private Class jsonPrimitive; + public static final String MASSIVE_UPDATE_PERMISSION = "massivestats.update"; + /* END: MASSIVESTATS SETTINGS */ + private final JavaPlugin plugin; + private MassiveStatsUpdateTask task = null; + private int pingInterval; + private MassiveStatsDataResponse lastResponse; + private boolean listenerDisabled; + private Class jsonElement; + private Class jsonParser; + private Class jsonObject; + private Class jsonPrimitive; - /** - * @param plugin The plugin you wish to collect data for. - * @author Sam Jakob Harker - */ - public MassiveStats(JavaPlugin plugin) { - this(plugin, 900); // default value: 900 seconds (= 15 minutes) - } + /** + * @param plugin The plugin you wish to collect data for. + * @author Sam Jakob Harker + */ + public MassiveStats(JavaPlugin plugin) { + this(plugin, 900); // default value: 900 seconds (= 15 minutes) + } - /** - * @param plugin The plugin you wish to collect data for. - * @param pingInterval Duration between requests. - * @author Sam Jakob Harker - */ - public MassiveStats(JavaPlugin plugin, int pingInterval) { - try { - jsonElement = Class.forName("com.google.gson.JsonElement"); - jsonParser = Class.forName("com.google.gson.JsonParser"); - jsonObject = Class.forName("com.google.gson.JsonObject"); - jsonPrimitive = Class.forName("com.google.gson.JsonPrimitive"); - } catch (ClassNotFoundException ex) { - // Gson not included in classpath (so use NMS version) - try { - jsonElement = Class.forName("net.minecraft.util.com.google.gson.JsonElement"); - jsonParser = Class.forName("net.minecraft.util.com.google.gson.JsonParser"); - jsonObject = Class.forName("net.minecraft.util.com.google.gson.JsonObject"); - jsonPrimitive = Class.forName("net.minecraft.util.com.google.gson.JsonPrimitive"); - } catch (ClassNotFoundException ignored) { - Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use."); - this.plugin = null; - return; - } - } + /** + * @param plugin The plugin you wish to collect data for. + * @param pingInterval Duration between requests. + * @author Sam Jakob Harker + */ + public MassiveStats(JavaPlugin plugin, int pingInterval) { + try { + jsonElement = Class.forName("com.google.gson.JsonElement"); + jsonParser = Class.forName("com.google.gson.JsonParser"); + jsonObject = Class.forName("com.google.gson.JsonObject"); + jsonPrimitive = Class.forName("com.google.gson.JsonPrimitive"); + } catch (ClassNotFoundException ex) { + // Gson not included in classpath (so use NMS version) + try { + jsonElement = Class.forName("net.minecraft.util.com.google.gson.JsonElement"); + jsonParser = Class.forName("net.minecraft.util.com.google.gson.JsonParser"); + jsonObject = Class.forName("net.minecraft.util.com.google.gson.JsonObject"); + jsonPrimitive = Class.forName("net.minecraft.util.com.google.gson.JsonPrimitive"); + } catch (ClassNotFoundException ignored) { + Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use."); + this.plugin = null; + return; + } + } - // Ensure the pingInterval that is set is reasonable. - if (pingInterval < 10 || pingInterval > 86400) { - pingInterval = 900; - } + // Ensure the pingInterval that is set is reasonable. + if (pingInterval < 10 || pingInterval > 86400) { + pingInterval = 900; + } - // Ensure that a plugin instance has been provided. - if (plugin == null) { - throw new IllegalArgumentException("You must provide a plugin for MassiveStats to collect data for!"); - } + // Ensure that a plugin instance has been provided. + if (plugin == null) { + throw new IllegalArgumentException("You must provide a plugin for MassiveStats to collect data for!"); + } - // Set the ping interval. - this.pingInterval = pingInterval; - // Set the plugin reference. - this.plugin = plugin; - // and start sending data to the MassiveStats server immediately. - start(); + // Set the ping interval. + this.pingInterval = pingInterval; + // Set the plugin reference. + this.plugin = plugin; + // and start sending data to the MassiveStats server immediately. + start(); - // Register join/leave events for the plugin - Bukkit.getServer().getPluginManager().registerEvents(this, plugin); - } + // Register join/leave events for the plugin + Bukkit.getServer().getPluginManager().registerEvents(this, plugin); + } - /** - * Gets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. - * - * @return Whether or not the MassiveStats listener is enabled. - */ - public boolean isListenerDisabled() { - return listenerDisabled; - } + /** + * Gets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. + * + * @return Whether or not the MassiveStats listener is enabled. + */ + public boolean isListenerDisabled() { + return listenerDisabled; + } - /** - * Sets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. - * - * @param listenerDisabled Whether or not the MassiveStats listener is enabled. - */ - public void setListenerDisabled(boolean listenerDisabled) { - this.listenerDisabled = listenerDisabled; - } + /** + * Sets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. + * + * @param listenerDisabled Whether or not the MassiveStats listener is enabled. + */ + public void setListenerDisabled(boolean listenerDisabled) { + this.listenerDisabled = listenerDisabled; + } - /** - * Start the MassiveStats reporting timer. - * If the timer is already running, this method will do nothing. - * - * @author Sam Jakob Harker - */ - public void start() { - if (this.plugin == null) { - Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use and thus cannot start."); - return; - } + /** + * Start the MassiveStats reporting timer. + * If the timer is already running, this method will do nothing. + * + * @author Sam Jakob Harker + */ + public void start() { + if (this.plugin == null) { + Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use and thus cannot start."); + return; + } - if (task == null) { - // If the API endpoint URL is invalid, don't start a new task to prevent the user from being spammed. - try { - new URL(MassiveStats.API_URL); - } catch (MalformedURLException ex) { - getPlugin() - .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); - return; - } + if (task == null) { + // If the API endpoint URL is invalid, don't start a new task to prevent the user from being spammed. + try { + new URL(MassiveStats.API_URL); + } catch (MalformedURLException ex) { + getPlugin() + .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); + return; + } - task = new MassiveStatsUpdateTask(this); - task.runTaskTimerAsynchronously(plugin, 0L, pingInterval * 20L); - } - } + task = new MassiveStatsUpdateTask(this); + task.runTaskTimerAsynchronously(plugin, 0L, pingInterval * 20L); + } + } - /** - * Stop the MassiveStats reporting timer. - * Requests will no longer be sent to the server - or until {@link #start()} is invoked. - * - * @author Sam Jakob Harker - */ - public void stop() { - if (task == null) { - return; - } + /** + * Stop the MassiveStats reporting timer. + * Requests will no longer be sent to the server - or until {@link #start()} is invoked. + * + * @author Sam Jakob Harker + */ + public void stop() { + if (task == null) { + return; + } - task.cancel(); - task = null; - } + task.cancel(); + task = null; + } - /** - * Returns the duration, in seconds, that MassiveStats will wait before sending another request to the server. - * - * @return Duration between requests. - * @author Sam Jakob Harker - */ - public int getPingInterval() { - return pingInterval; - } + /** + * Returns the duration, in seconds, that MassiveStats will wait before sending another request to the server. + * + * @return Duration between requests. + * @author Sam Jakob Harker + */ + public int getPingInterval() { + return pingInterval; + } - /** - * Sets the duration, in seconds, that MassiveStats should wait before sending another request to the server. - * - * @param pingInterval Duration between requests. - * @author Sam Jakob Harker - */ - public void setPingInterval(int pingInterval) { - this.pingInterval = pingInterval; + /** + * Sets the duration, in seconds, that MassiveStats should wait before sending another request to the server. + * + * @param pingInterval Duration between requests. + * @author Sam Jakob Harker + */ + public void setPingInterval(int pingInterval) { + this.pingInterval = pingInterval; - stop(); - start(); - } + stop(); + start(); + } - /** - * Returns the plugin that this MassiveStats instance is collecting data for. - * - * @return MassiveStats instance plugin. - * @author Sam Jakob Harker - */ - public JavaPlugin getPlugin() { - return plugin; - } + /** + * Returns the plugin that this MassiveStats instance is collecting data for. + * + * @return MassiveStats instance plugin. + * @author Sam Jakob Harker + */ + public JavaPlugin getPlugin() { + return plugin; + } - /** - * Returns the contents of the last response from the MassiveStats server. - * - * @return MassiveStats server response. - * @author Sam Jakob Harker - */ - public MassiveStatsDataResponse getLastResponse() { - return lastResponse; - } + /** + * Returns the contents of the last response from the MassiveStats server. + * + * @return MassiveStats server response. + * @author Sam Jakob Harker + */ + public MassiveStatsDataResponse getLastResponse() { + return lastResponse; + } - void setLastResponse(MassiveStatsDataResponse lastResponse) { - this.lastResponse = lastResponse; - } + void setLastResponse(MassiveStatsDataResponse lastResponse) { + this.lastResponse = lastResponse; + } - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - // Ensure the listener should be active - if (lastResponse == null || listenerDisabled) { - return; - } + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + // Ensure the listener should be active + if (lastResponse == null || listenerDisabled) { + return; + } - // Of course, only notify the user if the plugin is not up to date. - if (lastResponse.isUpToDate()) { - return; - } + // Of course, only notify the user if the plugin is not up to date. + if (lastResponse.isUpToDate()) { + return; + } - // and only notify operators - or players with the correct permission. - if (!event.getPlayer().isOp() && !event.getPlayer().hasPermission(MassiveStats.MASSIVE_UPDATE_PERMISSION)) { - return; - } + // and only notify operators - or players with the correct permission. + if (!event.getPlayer().isOp() && !event.getPlayer().hasPermission(MassiveStats.MASSIVE_UPDATE_PERMISSION)) { + return; + } - event.getPlayer().sendMessage(lastResponse.getUpdateMessage()); - } + event.getPlayer().sendMessage(lastResponse.getUpdateMessage()); + } - Class getJsonElement() { - return jsonElement; - } + Class getJsonElement() { + return jsonElement; + } - Class getJsonParser() { - return jsonParser; - } + Class getJsonParser() { + return jsonParser; + } - Class getJsonObject() { - return jsonObject; - } + Class getJsonObject() { + return jsonObject; + } - Class getJsonPrimitive() { - return jsonPrimitive; - } + Class getJsonPrimitive() { + return jsonPrimitive; + } } class MassiveStatsUpdateTask extends BukkitRunnable { - private final MassiveStats instance; + private final MassiveStats instance; - MassiveStatsUpdateTask(MassiveStats requester) { - instance = requester; - } + MassiveStatsUpdateTask(MassiveStats requester) { + instance = requester; + } - @Override - @SuppressWarnings("all") - public void run() { - try { - // Generate the request payload and serialize it as JSON. - String payload = new MassiveStatsDataRequest(instance).serialize(); + @Override + @SuppressWarnings("all") + public void run() { + try { + // Generate the request payload and serialize it as JSON. + String payload = new MassiveStatsDataRequest(instance).serialize(); - // Then create a new HttpsUrlConnection to the API server and open it. - HttpsURLConnection connection = (HttpsURLConnection) new URL(MassiveStats.API_URL).openConnection(); + // Then create a new HttpsUrlConnection to the API server and open it. + HttpsURLConnection connection = (HttpsURLConnection) new URL(MassiveStats.API_URL).openConnection(); - // Ensure that we don't hang the server with our 'dang shenanigans'. - connection.setConnectTimeout(2500); - connection.setReadTimeout(3500); + // Ensure that we don't hang the server with our 'dang shenanigans'. + connection.setConnectTimeout(2500); + connection.setReadTimeout(3500); - // Set the all-important request headers before we begin POSTing... - connection.setRequestMethod("POST"); - connection.setRequestProperty("Accept", "application/json"); - connection.setRequestProperty("Content-Type", "application/json; charset=utf-8"); - connection.setRequestProperty("User-Agent", "Massive/" + MassiveStats.CLIENT_VERSION); + // Set the all-important request headers before we begin POSTing... + connection.setRequestMethod("POST"); + connection.setRequestProperty("Accept", "application/json"); + connection.setRequestProperty("Content-Type", "application/json; charset=utf-8"); + connection.setRequestProperty("User-Agent", "Massive/" + MassiveStats.CLIENT_VERSION); - // Open the output stream, write the payload, and then close the stream. - connection.setDoOutput(true); - DataOutputStream output = new DataOutputStream(connection.getOutputStream()); - output.writeBytes(payload); - output.flush(); - output.close(); + // Open the output stream, write the payload, and then close the stream. + connection.setDoOutput(true); + DataOutputStream output = new DataOutputStream(connection.getOutputStream()); + output.writeBytes(payload); + output.flush(); + output.close(); - // Ensure that the server was happy with our data. - int responseCode = connection.getResponseCode(); - if (responseCode != 200) { - throw new IOException(); - } + // Ensure that the server was happy with our data. + int responseCode = connection.getResponseCode(); + if (responseCode != 200) { + throw new IOException(); + } - // Now, read the server's response to our payload... - BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream())); - StringBuilder response = new StringBuilder(); + // Now, read the server's response to our payload... + BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder response = new StringBuilder(); - // ...line by line. - String line; - while ((line = input.readLine()) != null) { - response.append(line); - } - input.close(); + // ...line by line. + String line; + while ((line = input.readLine()) != null) { + response.append(line); + } + input.close(); - // Now, we parse the JSON object. - try { - if (response.toString().contains("ERR_DATA_MISSING")) { - Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " - + instance.getPlugin().getName()); - instance.stop(); - return; - } + // Now, we parse the JSON object. + try { + if (response.toString().contains("ERR_DATA_MISSING")) { + Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " + + instance.getPlugin().getName()); + instance.stop(); + return; + } - Object parser = instance.getJsonParser().newInstance(); + Object parser = instance.getJsonParser().newInstance(); - // JsonElement - Object serverResponseRaw = - parser.getClass().getMethod("parse", String.class).invoke(parser, response.toString()); + // JsonElement + Object serverResponseRaw = + parser.getClass().getMethod("parse", String.class).invoke(parser, response.toString()); - // JsonObject - Object serverResponse = serverResponseRaw.getClass().getMethod("getAsJsonObject", null) - .invoke(serverResponseRaw, null); + // JsonObject + Object serverResponse = serverResponseRaw.getClass().getMethod("getAsJsonObject", null) + .invoke(serverResponseRaw, null); - Method serverResponseGet = instance.getJsonObject().getMethod("get", String.class); + Method serverResponseGet = instance.getJsonObject().getMethod("get", String.class); - Method getAsBoolean = - instance.getJsonPrimitive().getMethod("getAsBoolean", null); - Method getAsString = - instance.getJsonPrimitive().getMethod("getAsString", null); + Method getAsBoolean = + instance.getJsonPrimitive().getMethod("getAsBoolean", null); + Method getAsString = + instance.getJsonPrimitive().getMethod("getAsString", null); - if (serverResponseGet.invoke(serverResponse, "upToDate") == null) { - Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " - + instance.getPlugin().getName()); - instance.stop(); - return; - } + if (serverResponseGet.invoke(serverResponse, "upToDate") == null) { + Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " + + instance.getPlugin().getName()); + instance.stop(); + return; + } - if (serverResponseGet.invoke(serverResponse, "notice") != null) { - Bukkit.getLogger().severe( - (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "notice")) - ); - instance.stop(); - return; - } + if (serverResponseGet.invoke(serverResponse, "notice") != null) { + Bukkit.getLogger().severe( + (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "notice")) + ); + instance.stop(); + return; + } - boolean upToDate = (boolean) getAsBoolean.invoke(serverResponseGet.invoke(serverResponse, "upToDate"), null); - String latestVersion = (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "latestVersion"), null); - String updateMessage = ChatColor.translateAlternateColorCodes( - '&', (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "updateMessage"), null) - ); + boolean upToDate = (boolean) getAsBoolean.invoke(serverResponseGet.invoke(serverResponse, "upToDate"), null); + String latestVersion = (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "latestVersion"), null); + String updateMessage = ChatColor.translateAlternateColorCodes( + '&', (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "updateMessage"), null) + ); - instance.setLastResponse(new MassiveStatsDataResponse( - upToDate, latestVersion, updateMessage - )); + instance.setLastResponse(new MassiveStatsDataResponse( + upToDate, latestVersion, updateMessage + )); - } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { - instance.getPlugin() - .getLogger().warning("MassiveStats returned an invalid response for this plugin."); - } + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { + instance.getPlugin() + .getLogger().warning("MassiveStats returned an invalid response for this plugin."); + } - // Finally, call an event to mark the update. - } catch (MalformedURLException ex) { - instance.getPlugin() - .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); - } catch (IOException ex) { - instance.getPlugin() - .getLogger().warning("MassiveStats was unable to communicate with its API endpoint."); - } - } + // Finally, call an event to mark the update. + } catch (MalformedURLException ex) { + instance.getPlugin() + .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); + } catch (IOException ex) { + instance.getPlugin() + .getLogger().warning("MassiveStats was unable to communicate with its API endpoint."); + } + } } class MassiveStatsDataRequest { - private Object jsonObject; + private Object jsonObject; - MassiveStatsDataRequest(MassiveStats requester) { - try { - jsonObject = requester.getJsonObject().newInstance(); + MassiveStatsDataRequest(MassiveStats requester) { + try { + jsonObject = requester.getJsonObject().newInstance(); - Method add = - requester.getJsonObject().newInstance().getClass().getMethod("add", String.class, requester.getJsonElement()); - Method addPropertyString = - requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, String.class); - Method addPropertyNumber = - requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Number.class); - Method addPropertyBoolean = - requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Boolean.class); + Method add = + requester.getJsonObject().newInstance().getClass().getMethod("add", String.class, requester.getJsonElement()); + Method addPropertyString = + requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, String.class); + Method addPropertyNumber = + requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Number.class); + Method addPropertyBoolean = + requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Boolean.class); - addPropertyNumber.invoke(jsonObject, "now", System.currentTimeMillis()); + addPropertyNumber.invoke(jsonObject, "now", System.currentTimeMillis()); - /* PLUGIN DATA */ - Object pluginObject = jsonObject.getClass().newInstance(); - addPropertyString.invoke(pluginObject, "name", requester.getPlugin().getDescription().getName()); - addPropertyString.invoke(pluginObject, "version", requester.getPlugin().getDescription().getVersion()); - add.invoke(jsonObject, "plugin", pluginObject); + /* PLUGIN DATA */ + Object pluginObject = jsonObject.getClass().newInstance(); + addPropertyString.invoke(pluginObject, "name", requester.getPlugin().getDescription().getName()); + addPropertyString.invoke(pluginObject, "version", requester.getPlugin().getDescription().getVersion()); + add.invoke(jsonObject, "plugin", pluginObject); - /* SERVER DATA */ - Object minecraftServerObject = jsonObject.getClass().newInstance(); - addPropertyNumber.invoke(minecraftServerObject, "players", Bukkit.getServer().getOnlinePlayers().size()); - addPropertyBoolean.invoke(minecraftServerObject, "onlineMode", Bukkit.getServer().getOnlineMode()); - addPropertyString.invoke(minecraftServerObject, "version", Bukkit.getServer().getVersion()); + /* SERVER DATA */ + Object minecraftServerObject = jsonObject.getClass().newInstance(); + addPropertyNumber.invoke(minecraftServerObject, "players", Bukkit.getServer().getOnlinePlayers().size()); + addPropertyBoolean.invoke(minecraftServerObject, "onlineMode", Bukkit.getServer().getOnlineMode()); + addPropertyString.invoke(minecraftServerObject, "version", Bukkit.getServer().getVersion()); - Object javaServerObject = jsonObject.getClass().newInstance(); - addPropertyString.invoke(javaServerObject, "version", System.getProperty("java.version")); + Object javaServerObject = jsonObject.getClass().newInstance(); + addPropertyString.invoke(javaServerObject, "version", System.getProperty("java.version")); - Object osServerObject = jsonObject.getClass().newInstance(); - addPropertyString.invoke(osServerObject, "name", System.getProperty("os.name")); - addPropertyString.invoke(osServerObject, "arch", System.getProperty("os.arch")); - addPropertyString.invoke(osServerObject, "version", System.getProperty("os.version")); + Object osServerObject = jsonObject.getClass().newInstance(); + addPropertyString.invoke(osServerObject, "name", System.getProperty("os.name")); + addPropertyString.invoke(osServerObject, "arch", System.getProperty("os.arch")); + addPropertyString.invoke(osServerObject, "version", System.getProperty("os.version")); - Object hardwareServerObject = jsonObject.getClass().newInstance(); - addPropertyNumber.invoke(hardwareServerObject, "cores", Runtime.getRuntime().availableProcessors()); + Object hardwareServerObject = jsonObject.getClass().newInstance(); + addPropertyNumber.invoke(hardwareServerObject, "cores", Runtime.getRuntime().availableProcessors()); - Object serverObject = jsonObject.getClass().newInstance(); - add.invoke(serverObject, "minecraft", minecraftServerObject); - add.invoke(serverObject, "java", javaServerObject); - add.invoke(serverObject, "os", osServerObject); - add.invoke(serverObject, "hardware", hardwareServerObject); + Object serverObject = jsonObject.getClass().newInstance(); + add.invoke(serverObject, "minecraft", minecraftServerObject); + add.invoke(serverObject, "java", javaServerObject); + add.invoke(serverObject, "os", osServerObject); + add.invoke(serverObject, "hardware", hardwareServerObject); - add.invoke(jsonObject, "server", serverObject); + add.invoke(jsonObject, "server", serverObject); - /* MASSIVE DATA */ - Object massiveObject = jsonObject.getClass().newInstance(); - addPropertyNumber.invoke(massiveObject, "version", MassiveStats.CLIENT_VERSION); - addPropertyNumber.invoke(massiveObject, "pingInterval", requester.getPingInterval()); + /* MASSIVE DATA */ + Object massiveObject = jsonObject.getClass().newInstance(); + addPropertyNumber.invoke(massiveObject, "version", MassiveStats.CLIENT_VERSION); + addPropertyNumber.invoke(massiveObject, "pingInterval", requester.getPingInterval()); - //object.add("Massive", massiveObject); - add.invoke(jsonObject, "Massive", massiveObject); - } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { - e.printStackTrace(); - } - } + //object.add("Massive", massiveObject); + add.invoke(jsonObject, "Massive", massiveObject); + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + } + } - @SuppressWarnings("all") - public String serialize() { - //return object.toString(); - try { - Method toString = jsonObject.getClass().getMethod("toString", null); - return (String) toString.invoke(jsonObject); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } + @SuppressWarnings("all") + public String serialize() { + //return object.toString(); + try { + Method toString = jsonObject.getClass().getMethod("toString", null); + return (String) toString.invoke(jsonObject); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } - return null; - } + return null; + } } final class MassiveStatsDataResponse { - private final boolean isUpToDate; - private final String newVersion; - private final String updateMessage; + private final boolean isUpToDate; + private final String newVersion; + private final String updateMessage; - MassiveStatsDataResponse(boolean isUpToDate, String newVersion, String updateMessage) { - this.isUpToDate = isUpToDate; + MassiveStatsDataResponse(boolean isUpToDate, String newVersion, String updateMessage) { + this.isUpToDate = isUpToDate; - if (!isUpToDate) { - this.newVersion = newVersion; - this.updateMessage = updateMessage; - return; - } + if (!isUpToDate) { + this.newVersion = newVersion; + this.updateMessage = updateMessage; + return; + } - this.newVersion = null; - this.updateMessage = null; - } + this.newVersion = null; + this.updateMessage = null; + } - /** - * Indicates whether or not this version of the plugin is the latest. - * True = This is the latest version of the plugin. - * False = There is an update available. - * - * @return Whether or not there is an update available. - */ - public boolean isUpToDate() { - return isUpToDate; - } + /** + * Indicates whether or not this version of the plugin is the latest. + * True = This is the latest version of the plugin. + * False = There is an update available. + * + * @return Whether or not there is an update available. + */ + public boolean isUpToDate() { + return isUpToDate; + } - /** - * Gets the name of the latest version. If this is the latest version, it returns null. - * - * @return The name of the latest version. - */ - public String getLatestVersion() { - return newVersion; - } + /** + * Gets the name of the latest version. If this is the latest version, it returns null. + * + * @return The name of the latest version. + */ + public String getLatestVersion() { + return newVersion; + } - /** - * Gets the message to display, convincing the user to update to the new version of the plugin. - * - * @return The update message to display. - */ - public String getUpdateMessage() { - return updateMessage; - } + /** + * Gets the message to display, convincing the user to update to the new version of the plugin. + * + * @return The update message to display. + */ + public String getUpdateMessage() { + return updateMessage; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/SavageFactions.java b/src/main/java/com/massivecraft/factions/SavageFactions.java index c580400f..bb7f7e2e 100644 --- a/src/main/java/com/massivecraft/factions/SavageFactions.java +++ b/src/main/java/com/massivecraft/factions/SavageFactions.java @@ -52,705 +52,705 @@ import java.util.stream.Collectors; public class SavageFactions extends MPlugin { - // Our single plugin instance. - // Single 4 life. - public static SavageFactions plugin; - public static Permission perms = null; - // Persistence related - public static ArrayList playersFlying = new ArrayList(); - public Essentials ess; - public boolean PlaceholderApi; - // Commands - public FCmdRoot cmdBase; - public CmdAutoHelp cmdAutoHelp; - public boolean mc17 = false; - public boolean mc18 = false; - public boolean mc113 = false; - public boolean useNonPacketParticles = false; - public boolean factionsFlight = false; - //multiversion material fields - public Material SUGAR_CANE_BLOCK, BANNER, CROPS, REDSTONE_LAMP_ON, - STAINED_GLASS, STATIONARY_WATER, STAINED_CLAY, WOOD_BUTTON, - SOIL, MOB_SPANWER, THIN_GLASS, IRON_FENCE, NETHER_FENCE, FENCE, - WOODEN_DOOR, TRAP_DOOR, FENCE_GATE, BURNING_FURNACE, DIODE_BLOCK_OFF, - DIODE_BLOCK_ON, ENCHANTMENT_TABLE, FIREBALL; - SkriptAddon skriptAddon; - private boolean locked = false; - private Integer AutoLeaveTask = null; - private boolean hookedPlayervaults; - private ClipPlaceholderAPIManager clipPlaceholderAPIManager; - private boolean mvdwPlaceholderAPIManager = false; - private Listener[] eventsListener; - - public SavageFactions() { - plugin = this; - } - - public boolean getLocked() { - return this.locked; - } - - public void setLocked(boolean val) { - this.locked = val; - this.setAutoSave(val); - } - - public void playSoundForAll(String sound) { - for (Player pl : Bukkit.getOnlinePlayers()) { - playSound(pl, sound); - } - } - - public void playSoundForAll(List sounds) { - for (Player pl : Bukkit.getOnlinePlayers()) { - playSound(pl, sounds); - } - } - - public void playSound(Player p, List sounds) { - for (String sound : sounds) { - playSound(p, sound); - } - } - - public void playSound(Player p, String sound) { - float pitch = Float.valueOf(sound.split(":")[1]); - sound = sound.split(":")[0]; - p.playSound(p.getLocation(), Sound.valueOf(sound), pitch, 5.0F); - } - - @Override - public void onEnable() { - log("==== Setup ===="); - - - // Vault dependency check. - if (getServer().getPluginManager().getPlugin("Vault") == null) { - log("Vault is not present, the plugin will not run properly."); - getServer().getPluginManager().disablePlugin(plugin); - return; - } - - int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); - if (version == 7) { - SavageFactions.plugin.log("Minecraft Version 1.7 found, disabling banners, itemflags inside GUIs, and Titles."); - mc17 = true; - } else if (version == 8) { - SavageFactions.plugin.log("Minecraft Version 1.8 found, Title Fadeouttime etc will not be configurable."); - mc18 = true; - } else if (version == 13) { - SavageFactions.plugin.log("Minecraft Version 1.13 found, New Items will be used."); - mc113 = true; - changeItemIDSInConfig(); - } - setupMultiversionMaterials(); - migrateFPlayerLeaders(); - log("==== End Setup ===="); - - if (!preEnable()) { - return; - } - this.loadSuccessful = false; - - saveDefaultConfig(); - - // Load Conf from disk - Conf.load(); - com.massivecraft.factions.integration.Essentials.setup(); - hookedPlayervaults = setupPlayervaults(); - FPlayers.getInstance().load(); - Factions.getInstance().load(); - - for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { - Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); - if (faction == null) { - log("Invalid faction id on " + fPlayer.getName() + ":" + fPlayer.getFactionId()); - fPlayer.resetFactionData(false); - continue; - } - faction.addFPlayer(fPlayer); - } - playersFlying.clear(); - for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { - playersFlying.add(fPlayer); - } - UtilFly.run(); - - Board.getInstance().load(); - Board.getInstance().clean(); - - // Add Base Commands - this.cmdBase = new FCmdRoot(); - this.cmdAutoHelp = new CmdAutoHelp(); - this.getBaseCommands().add(cmdBase); - - Econ.setup(); - setupPermissions(); - - if (Conf.worldGuardChecking || Conf.worldGuardBuildPriority) { - Worldguard.init(this); - } - - EngineDynmap.getInstance().init(); - - // start up task which runs the autoLeaveAfterDaysOfInactivity routine - startAutoLeaveTask(false); - - if (getConfig().getBoolean("MassiveStats")) { - // massive stats - new MassiveStats(this); - } - - if (version > 8) { - useNonPacketParticles = true; - log("Minecraft Version 1.9 or higher found, using non packet based particle API"); - } - - if (getConfig().getBoolean("enable-faction-flight")) { - factionsFlight = true; - } - - if (getServer().getPluginManager().getPlugin("Skript") != null) { - log("Skript was found! Registering SavageFactions Addon..."); - skriptAddon = Skript.registerAddon(this); - try { - skriptAddon.loadClasses("com.massivecraft.factions.skript", "expressions"); - } catch (IOException ex) { - ex.printStackTrace(); - } - log("Skript addon registered!"); - } - - - // Register Event Handlers - eventsListener = new Listener[]{ - new FactionsPlayerListener(), - new FactionsChatListener(), - new FactionsEntityListener(), - new FactionsExploitListener(), - new FactionsBlockListener(), - new FUpgradesGUI(), - new EXPUpgrade(), - new CropUpgrades(), - new SpawnerUpgrades(), - }; - - for (Listener eventListener : eventsListener) - getServer().getPluginManager().registerEvents(eventListener, this); - - // since some other plugins execute commands directly through this command interface, provide it - getCommand(this.refCommand).setExecutor(this); - getCommand(this.refCommand).setTabCompleter(this); - - setupEssentials(); - - if (getDescription().getFullName().contains("BETA")) { - divider(); - System.out.println("You are using a BETA version of the plugin!"); - System.out.println("This comes with risks of small bugs in newer features!"); - System.out.println("For support head to: https://github.com/ProSavage/SavageFactions/issues"); - divider(); - } - - this.setupPlaceholderAPI(); - this.postEnable(); - this.loadSuccessful = true; - } - - public SkriptAddon getSkriptAddon() { - return skriptAddon; - } - - private void setupMultiversionMaterials() { - if (mc113) { - BANNER = Material.valueOf("LEGACY_BANNER"); - CROPS = Material.valueOf("LEGACY_CROPS"); - SUGAR_CANE_BLOCK = Material.valueOf("LEGACY_SUGAR_CANE_BLOCK"); - REDSTONE_LAMP_ON = Material.valueOf("LEGACY_REDSTONE_LAMP_ON"); - STAINED_GLASS = Material.valueOf("LEGACY_STAINED_GLASS"); - STATIONARY_WATER = Material.valueOf("LEGACY_STATIONARY_WATER"); - STAINED_CLAY = Material.valueOf("LEGACY_STAINED_CLAY"); - WOOD_BUTTON = Material.valueOf("LEGACY_WOOD_BUTTON"); - SOIL = Material.valueOf("LEGACY_SOIL"); - MOB_SPANWER = Material.valueOf("LEGACY_MOB_SPAWNER"); - THIN_GLASS = Material.valueOf("LEGACY_THIN_GLASS"); - IRON_FENCE = Material.valueOf("LEGACY_IRON_FENCE"); - NETHER_FENCE = Material.valueOf("LEGACY_NETHER_FENCE"); - FENCE = Material.valueOf("LEGACY_FENCE"); - WOODEN_DOOR = Material.valueOf("LEGACY_WOODEN_DOOR"); - TRAP_DOOR = Material.valueOf("LEGACY_TRAP_DOOR"); - FENCE_GATE = Material.valueOf("LEGACY_FENCE_GATE"); - BURNING_FURNACE = Material.valueOf("LEGACY_BURNING_FURNACE"); - DIODE_BLOCK_OFF = Material.valueOf("LEGACY_DIODE_BLOCK_OFF"); - DIODE_BLOCK_ON = Material.valueOf("LEGACY_DIODE_BLOCK_ON"); - ENCHANTMENT_TABLE = Material.valueOf("LEGACY_ENCHANTMENT_TABLE"); - FIREBALL = Material.valueOf("LEGACY_FIREBALL"); - - } else { - if (!mc17) { - BANNER = Material.valueOf("BANNER"); - } - CROPS = Material.valueOf("CROPS"); - SUGAR_CANE_BLOCK = Material.valueOf("SUGAR_CANE_BLOCK"); - REDSTONE_LAMP_ON = Material.valueOf("REDSTONE_LAMP_ON"); - STAINED_GLASS = Material.valueOf("STAINED_GLASS"); - STATIONARY_WATER = Material.valueOf("STATIONARY_WATER"); - STAINED_CLAY = Material.valueOf("STAINED_CLAY"); - WOOD_BUTTON = Material.valueOf("WOOD_BUTTON"); - SOIL = Material.valueOf("SOIL"); - MOB_SPANWER = Material.valueOf("MOB_SPAWNER"); - THIN_GLASS = Material.valueOf("THIN_GLASS"); - IRON_FENCE = Material.valueOf("IRON_FENCE"); - NETHER_FENCE = Material.valueOf("NETHER_FENCE"); - FENCE = Material.valueOf("FENCE"); - WOODEN_DOOR = Material.valueOf("WOODEN_DOOR"); - TRAP_DOOR = Material.valueOf("TRAP_DOOR"); - FENCE_GATE = Material.valueOf("FENCE_GATE"); - BURNING_FURNACE = Material.valueOf("BURNING_FURNACE"); - DIODE_BLOCK_OFF = Material.valueOf("DIODE_BLOCK_OFF"); - DIODE_BLOCK_ON = Material.valueOf("DIODE_BLOCK_ON"); - ENCHANTMENT_TABLE = Material.valueOf("ENCHANTMENT_TABLE"); - FIREBALL = Material.valueOf("FIREBALL"); - } - - } - - private void setupPlaceholderAPI() { - Plugin clip = getServer().getPluginManager().getPlugin("PlaceholderAPI"); - if (clip != null && clip.isEnabled()) { - this.clipPlaceholderAPIManager = new ClipPlaceholderAPIManager(); - if (this.clipPlaceholderAPIManager.register()) { - PlaceholderApi = true; - log(Level.INFO, "Successfully registered placeholders with PlaceholderAPI."); - } else { - PlaceholderApi = false; - } - } else { - PlaceholderApi = false; - } - - Plugin mvdw = getServer().getPluginManager().getPlugin("MVdWPlaceholderAPI"); - if (mvdw != null && mvdw.isEnabled()) { - this.mvdwPlaceholderAPIManager = true; - log(Level.INFO, "Found MVdWPlaceholderAPI. Adding hooks."); - } - } - - private void migrateFPlayerLeaders() { - List lines = new ArrayList<>(); - File fplayerFile = new File("plugins\\Factions\\players.json"); - - try { - BufferedReader br = new BufferedReader(new FileReader(fplayerFile)); - System.out.println("Migrating old players.json file."); - - String line; - while ((line = br.readLine()) != null) { - if (line.contains("\"role\": \"ADMIN\"")) { - line = line.replace("\"role\": \"ADMIN\"", "\"role\": " + "\"LEADER\""); - } - lines.add(line); - } - br.close(); - BufferedWriter bw = new BufferedWriter(new FileWriter(fplayerFile)); - for (String newLine : lines) { - bw.write(newLine + "\n"); - } - bw.flush(); - bw.close(); - } catch (IOException ex) { - System.out.println("File was not found for players.json, assuming" - + " there is no need to migrate old players.json file."); - } - } - - public void changeItemIDSInConfig() { - log("Starting conversion of legacy material in config to 1.13 materials."); - - replaceStringInConfig("fperm-gui.relation.materials.recruit", "WOOD_SWORD", "WOODEN_SWORD"); - replaceStringInConfig("fperm-gui.relation.materials.normal", "GOLD_SWORD", "GOLDEN_SWORD"); - replaceStringInConfig("fperm-gui.relation.materials.ally", "GOLD_AXE", "GOLDEN_AXE"); - replaceStringInConfig("fperm-gui.relation.materials.neutral", "WOOD_AXE", "WOODEN_AXE"); - - ConfigurationSection actionMaterialsConfigSection = getConfig().getConfigurationSection("fperm-gui.action.materials"); - Set actionMaterialKeys = actionMaterialsConfigSection.getKeys(true); - - - for (String key : actionMaterialKeys) { - replaceStringInConfig("fperm-gui.action.materials." + key, "STAINED_GLASS", "GRAY_STAINED_GLASS"); - } - - replaceStringInConfig("fperm-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); - replaceStringInConfig("fwarp-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); - - replaceStringInConfig("fupgrades.MainMenu.DummyItem.Type", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); - replaceStringInConfig("fupgrades.MainMenu.EXP.EXPItem.Type", "EXP_BOTTLE", "EXPERIENCE_BOTTLE"); - replaceStringInConfig("fupgrades.MainMenu.Spawners.SpawnerItem.Type", "MOB_SPAWNER", "SPAWNER"); - - replaceStringInConfig("fperm-gui.action.access.allow", "LIME", "LIME_STAINED_GLASS"); - replaceStringInConfig("fperm-gui.action.access.deny", "RED", "RED_STAINED_GLASS"); - replaceStringInConfig("fperm-gui.action.access.undefined", "CYAN", "CYAN_STAINED_GLASS"); - } - - public void replaceStringInConfig(String path, String stringToReplace, String replacementString) { - if (getConfig().getString(path).equals(stringToReplace)) { - // SavageFactions.plugin.log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); - // log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); - - getConfig().set(path, replacementString); - } - } - - public boolean isClipPlaceholderAPIHooked() { - return this.clipPlaceholderAPIManager != null; - } - - public boolean isMVdWPlaceholderAPIHooked() { - return this.mvdwPlaceholderAPIManager; - } - - private boolean setupPermissions() { - try { - RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Permission.class); - if (rsp != null) { - perms = rsp.getProvider(); - } - } catch (NoClassDefFoundError ex) { - return false; - } - return perms != null; - } - - private boolean setupPlayervaults() { - Plugin plugin = getServer().getPluginManager().getPlugin("PlayerVaults"); - return plugin != null && plugin.isEnabled(); - } - - @Override - public GsonBuilder getGsonBuilder() { - Type mapFLocToStringSetType = new TypeToken>>() { - }.getType(); - - Type accessTypeAdatper = new TypeToken>>() { - }.getType(); - - return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().enableComplexMapKeySerialization().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) - .registerTypeAdapter(accessTypeAdatper, new PermissionsMapTypeAdapter()) - .registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter()) - .registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()) - .registerTypeAdapter(Inventory.class, new InventoryTypeAdapter()) - .registerTypeAdapter(Location.class, new LocationTypeAdapter()) - .registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY); - } - - private void divider() { - System.out.println(" .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-"); - System.out.println(" / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\"); - System.out.println("`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'"); - } - - @Override - public void onDisable() { - // only save data if plugin actually completely loaded successfully - if (this.loadSuccessful) { - // Dont save, as this is kind of pointless, as the /f config command manually saves. - // So any edits done are saved, this way manual edits to json can go through. - - // Conf.save(); - } - - if (AutoLeaveTask != null) { - this.getServer().getScheduler().cancelTask(AutoLeaveTask); - AutoLeaveTask = null; - } - - super.onDisable(); - } - - public void startAutoLeaveTask(boolean restartIfRunning) { - if (AutoLeaveTask != null) { - if (!restartIfRunning) { - return; - } - this.getServer().getScheduler().cancelTask(AutoLeaveTask); - } - - if (Conf.autoLeaveRoutineRunsEveryXMinutes > 0.0) { - long ticks = (long) (20 * 60 * Conf.autoLeaveRoutineRunsEveryXMinutes); - AutoLeaveTask = getServer().getScheduler().scheduleSyncRepeatingTask(this, new AutoLeaveTask(), ticks, ticks); - } - } - - @Override - public void postAutoSave() { - //Board.getInstance().forceSave(); Not sure why this was there as it's called after the board is already saved. - Conf.save(); - } - - public ItemStack createItem(Material material, int amount, short datavalue, String name, List lore) { - ItemStack item = new ItemStack(material, amount, datavalue); - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(color(name)); - meta.setLore(colorList(lore)); - item.setItemMeta(meta); - return item; - } - - public ItemStack createLazyItem(Material material, int amount, short datavalue, String name, String lore) { - ItemStack item = new ItemStack(material, amount, datavalue); - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(color(SavageFactions.plugin.getConfig().getString(name))); - meta.setLore(colorList(SavageFactions.plugin.getConfig().getStringList(lore))); - item.setItemMeta(meta); - return item; - } - - public Economy getEcon() { - RegisteredServiceProvider rsp = SavageFactions.plugin.getServer().getServicesManager().getRegistration(Economy.class); - Economy econ = rsp.getProvider(); - return econ; - } - - private boolean setupEssentials() { - SavageFactions.plugin.ess = (Essentials) this.getServer().getPluginManager().getPlugin("Essentials"); - return SavageFactions.plugin.ess == null; - } - - @Override - public boolean logPlayerCommands() { - return Conf.logPlayerCommands; - } - - @Override - public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { - return sender instanceof Player && FactionsPlayerListener.preventCommand(commandString, (Player) sender) || super.handleCommand(sender, commandString, testOnly); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] split) { - if (split.length == 0) { - return handleCommand(sender, "/f help", false); - } - - // otherwise, needs to be handled; presumably another plugin directly ran the command - String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); - return handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false); - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer((Player) sender); - List completions = new ArrayList<>(); - String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); - List argsList = new ArrayList<>(Arrays.asList(args)); - argsList.remove(argsList.size() - 1); - String cmdValid = (cmd + " " + TextUtil.implode(argsList, " ")).trim(); - MCommand commandEx = cmdBase; - List> commandsList = cmdBase.subCommands; - - if (Board.getInstance().getFactionAt(new FLocation(fPlayer.getPlayer().getLocation())) == Factions.getInstance().getWarZone()) { - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou cannot use autocomplete in warzone.")); - return new ArrayList<>(); - } - - for (; !commandsList.isEmpty() && !argsList.isEmpty(); argsList.remove(0)) { - String cmdName = argsList.get(0).toLowerCase(); - MCommand commandFounded = commandsList.stream() - .filter(c -> c.aliases.contains(cmdName)) - .findFirst().orElse(null); - - if (commandFounded != null) { - commandEx = commandFounded; - commandsList = commandFounded.subCommands; - } else break; - } - - if (argsList.isEmpty()) { - for (MCommand subCommand : commandEx.subCommands) { - subCommand.setCommandSender(sender); - if (handleCommand(sender, cmdValid + " " + subCommand.aliases.get(0), true) - && subCommand.visibility != CommandVisibility.INVISIBLE - && subCommand.validSenderType(sender, false) - && subCommand.validSenderPermissions(sender, false)) - completions.addAll(subCommand.aliases); - } - } - - String lastArg = args[args.length - 1].toLowerCase(); - - completions = completions.stream() - .filter(m -> m.toLowerCase().startsWith(lastArg)) - .collect(Collectors.toList()); - - return completions; - } - - public void createTimedHologram(final Location location, String text, Long timeout) { - ArmorStand as = (ArmorStand) location.add(0.5, 1, 0.5).getWorld().spawnEntity(location, EntityType.ARMOR_STAND); //Spawn the ArmorStand - as.setVisible(false); //Makes the ArmorStand invisible - as.setGravity(false); //Make sure it doesn't fall - as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it - as.setCustomName(SavageFactions.plugin.color(text)); //Set this to the text you want - as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not - final ArmorStand armorStand = as; - - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, () -> { - armorStand.remove(); - getLogger().info("Removing Hologram."); - } - , timeout * 20); - } - - - // -------------------------------------------- // - // Functions for other plugins to hook into - // -------------------------------------------- // - - // This value will be updated whenever new hooks are added - public int hookSupportVersion() { - return 3; - } - - // If another plugin is handling insertion of chat tags, this should be used to notify Factions - public void handleFactionTagExternally(boolean notByFactions) { - Conf.chatTagHandledByAnotherPlugin = notByFactions; - } - - // Simply put, should this chat event be left for Factions to handle? For now, that means players with Faction Chat - // enabled or use of the Factions f command without a slash; combination of isPlayerFactionChatting() and isFactionsCommand() - - public boolean shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent event) { - return event != null && (isPlayerFactionChatting(event.getPlayer()) || isFactionsCommand(event.getMessage())); - } - - - // Does player have Faction Chat enabled? If so, chat plugins should preferably not do channels, - // local chat, or anything else which targets individual recipients, so Faction Chat can be done - public boolean isPlayerFactionChatting(Player player) { - if (player == null) { - return false; - } - FPlayer me = FPlayers.getInstance().getByPlayer(player); - - return me != null && me.getChatMode().isAtLeast(ChatMode.ALLIANCE); - } - - // Is this chat message actually a Factions command, and thus should be left alone by other plugins? - - // TODO: GET THIS BACK AND WORKING - - public boolean isFactionsCommand(String check) { - return !(check == null || check.isEmpty()) && this.handleCommand(null, check, true); - } - - // Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat - public String getPlayerFactionTag(Player player) { - return getPlayerFactionTagRelation(player, null); - } - - // Same as above, but with relation (enemy/neutral/ally) coloring potentially added to the tag - public String getPlayerFactionTagRelation(Player speaker, Player listener) { - String tag = "~"; - - if (speaker == null) { - return tag; - } - - FPlayer me = FPlayers.getInstance().getByPlayer(speaker); - if (me == null) { - return tag; - } - - // if listener isn't set, or config option is disabled, give back uncolored tag - if (listener == null || !Conf.chatTagRelationColored) { - tag = me.getChatTag().trim(); - } else { - FPlayer you = FPlayers.getInstance().getByPlayer(listener); - if (you == null) { - tag = me.getChatTag().trim(); - } else // everything checks out, give the colored tag - { - tag = me.getChatTag(you).trim(); - } - } - if (tag.isEmpty()) { - tag = "~"; - } - - return tag; - } - - // Get a player's title within their faction, mainly for usage by chat plugins for local/channel chat - public String getPlayerTitle(Player player) { - if (player == null) { - return ""; - } - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - if (me == null) { - return ""; - } - - return me.getTitle().trim(); - } - - public String color(String line) { - line = ChatColor.translateAlternateColorCodes('&', line); - return line; - } - - //colors a string list - public List colorList(List lore) { - for (int i = 0; i <= lore.size() - 1; i++) { - lore.set(i, color(lore.get(i))); - } - return lore; - } - - // Get a list of all faction tags (names) - public Set getFactionTags() { - return Factions.getInstance().getFactionTags(); - } - - // Get a list of all players in the specified faction - public Set getPlayersInFaction(String factionTag) { - Set players = new HashSet<>(); - Faction faction = Factions.getInstance().getByTag(factionTag); - if (faction != null) { - for (FPlayer fplayer : faction.getFPlayers()) { - players.add(fplayer.getName()); - } - } - return players; - } - - // Get a list of all online players in the specified faction - public Set getOnlinePlayersInFaction(String factionTag) { - Set players = new HashSet<>(); - Faction faction = Factions.getInstance().getByTag(factionTag); - if (faction != null) { - for (FPlayer fplayer : faction.getFPlayersWhereOnline(true)) { - players.add(fplayer.getName()); - } - } - return players; - } - - public boolean isHookedPlayervaults() { - return hookedPlayervaults; - } - - public String getPrimaryGroup(OfflinePlayer player) { - return perms == null || !perms.hasGroupSupport() ? " " : perms.getPrimaryGroup(Bukkit.getWorlds().get(0).toString(), player); - } - - public void debug(Level level, String s) { - if (getConfig().getBoolean("debug", false)) { - getLogger().log(level, s); - } - } - - public void debug(String s) { - debug(Level.INFO, s); - } + // Our single plugin instance. + // Single 4 life. + public static SavageFactions plugin; + public static Permission perms = null; + // Persistence related + public static ArrayList playersFlying = new ArrayList(); + public Essentials ess; + public boolean PlaceholderApi; + // Commands + public FCmdRoot cmdBase; + public CmdAutoHelp cmdAutoHelp; + public boolean mc17 = false; + public boolean mc18 = false; + public boolean mc113 = false; + public boolean useNonPacketParticles = false; + public boolean factionsFlight = false; + //multiversion material fields + public Material SUGAR_CANE_BLOCK, BANNER, CROPS, REDSTONE_LAMP_ON, + STAINED_GLASS, STATIONARY_WATER, STAINED_CLAY, WOOD_BUTTON, + SOIL, MOB_SPANWER, THIN_GLASS, IRON_FENCE, NETHER_FENCE, FENCE, + WOODEN_DOOR, TRAP_DOOR, FENCE_GATE, BURNING_FURNACE, DIODE_BLOCK_OFF, + DIODE_BLOCK_ON, ENCHANTMENT_TABLE, FIREBALL; + SkriptAddon skriptAddon; + private boolean locked = false; + private Integer AutoLeaveTask = null; + private boolean hookedPlayervaults; + private ClipPlaceholderAPIManager clipPlaceholderAPIManager; + private boolean mvdwPlaceholderAPIManager = false; + private Listener[] eventsListener; + + public SavageFactions() { + plugin = this; + } + + public boolean getLocked() { + return this.locked; + } + + public void setLocked(boolean val) { + this.locked = val; + this.setAutoSave(val); + } + + public void playSoundForAll(String sound) { + for (Player pl : Bukkit.getOnlinePlayers()) { + playSound(pl, sound); + } + } + + public void playSoundForAll(List sounds) { + for (Player pl : Bukkit.getOnlinePlayers()) { + playSound(pl, sounds); + } + } + + public void playSound(Player p, List sounds) { + for (String sound : sounds) { + playSound(p, sound); + } + } + + public void playSound(Player p, String sound) { + float pitch = Float.valueOf(sound.split(":")[1]); + sound = sound.split(":")[0]; + p.playSound(p.getLocation(), Sound.valueOf(sound), pitch, 5.0F); + } + + @Override + public void onEnable() { + log("==== Setup ===="); + + + // Vault dependency check. + if (getServer().getPluginManager().getPlugin("Vault") == null) { + log("Vault is not present, the plugin will not run properly."); + getServer().getPluginManager().disablePlugin(plugin); + return; + } + + int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); + if (version == 7) { + SavageFactions.plugin.log("Minecraft Version 1.7 found, disabling banners, itemflags inside GUIs, and Titles."); + mc17 = true; + } else if (version == 8) { + SavageFactions.plugin.log("Minecraft Version 1.8 found, Title Fadeouttime etc will not be configurable."); + mc18 = true; + } else if (version == 13) { + SavageFactions.plugin.log("Minecraft Version 1.13 found, New Items will be used."); + mc113 = true; + changeItemIDSInConfig(); + } + setupMultiversionMaterials(); + migrateFPlayerLeaders(); + log("==== End Setup ===="); + + if (!preEnable()) { + return; + } + this.loadSuccessful = false; + + saveDefaultConfig(); + + // Load Conf from disk + Conf.load(); + com.massivecraft.factions.integration.Essentials.setup(); + hookedPlayervaults = setupPlayervaults(); + FPlayers.getInstance().load(); + Factions.getInstance().load(); + + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); + if (faction == null) { + log("Invalid faction id on " + fPlayer.getName() + ":" + fPlayer.getFactionId()); + fPlayer.resetFactionData(false); + continue; + } + faction.addFPlayer(fPlayer); + } + playersFlying.clear(); + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + playersFlying.add(fPlayer); + } + UtilFly.run(); + + Board.getInstance().load(); + Board.getInstance().clean(); + + // Add Base Commands + this.cmdBase = new FCmdRoot(); + this.cmdAutoHelp = new CmdAutoHelp(); + this.getBaseCommands().add(cmdBase); + + Econ.setup(); + setupPermissions(); + + if (Conf.worldGuardChecking || Conf.worldGuardBuildPriority) { + Worldguard.init(this); + } + + EngineDynmap.getInstance().init(); + + // start up task which runs the autoLeaveAfterDaysOfInactivity routine + startAutoLeaveTask(false); + + if (getConfig().getBoolean("MassiveStats")) { + // massive stats + new MassiveStats(this); + } + + if (version > 8) { + useNonPacketParticles = true; + log("Minecraft Version 1.9 or higher found, using non packet based particle API"); + } + + if (getConfig().getBoolean("enable-faction-flight")) { + factionsFlight = true; + } + + if (getServer().getPluginManager().getPlugin("Skript") != null) { + log("Skript was found! Registering SavageFactions Addon..."); + skriptAddon = Skript.registerAddon(this); + try { + skriptAddon.loadClasses("com.massivecraft.factions.skript", "expressions"); + } catch (IOException ex) { + ex.printStackTrace(); + } + log("Skript addon registered!"); + } + + + // Register Event Handlers + eventsListener = new Listener[]{ + new FactionsPlayerListener(), + new FactionsChatListener(), + new FactionsEntityListener(), + new FactionsExploitListener(), + new FactionsBlockListener(), + new FUpgradesGUI(), + new EXPUpgrade(), + new CropUpgrades(), + new SpawnerUpgrades(), + }; + + for (Listener eventListener : eventsListener) + getServer().getPluginManager().registerEvents(eventListener, this); + + // since some other plugins execute commands directly through this command interface, provide it + getCommand(this.refCommand).setExecutor(this); + getCommand(this.refCommand).setTabCompleter(this); + + setupEssentials(); + + if (getDescription().getFullName().contains("BETA")) { + divider(); + System.out.println("You are using a BETA version of the plugin!"); + System.out.println("This comes with risks of small bugs in newer features!"); + System.out.println("For support head to: https://github.com/ProSavage/SavageFactions/issues"); + divider(); + } + + this.setupPlaceholderAPI(); + this.postEnable(); + this.loadSuccessful = true; + } + + public SkriptAddon getSkriptAddon() { + return skriptAddon; + } + + private void setupMultiversionMaterials() { + if (mc113) { + BANNER = Material.valueOf("LEGACY_BANNER"); + CROPS = Material.valueOf("LEGACY_CROPS"); + SUGAR_CANE_BLOCK = Material.valueOf("LEGACY_SUGAR_CANE_BLOCK"); + REDSTONE_LAMP_ON = Material.valueOf("LEGACY_REDSTONE_LAMP_ON"); + STAINED_GLASS = Material.valueOf("LEGACY_STAINED_GLASS"); + STATIONARY_WATER = Material.valueOf("LEGACY_STATIONARY_WATER"); + STAINED_CLAY = Material.valueOf("LEGACY_STAINED_CLAY"); + WOOD_BUTTON = Material.valueOf("LEGACY_WOOD_BUTTON"); + SOIL = Material.valueOf("LEGACY_SOIL"); + MOB_SPANWER = Material.valueOf("LEGACY_MOB_SPAWNER"); + THIN_GLASS = Material.valueOf("LEGACY_THIN_GLASS"); + IRON_FENCE = Material.valueOf("LEGACY_IRON_FENCE"); + NETHER_FENCE = Material.valueOf("LEGACY_NETHER_FENCE"); + FENCE = Material.valueOf("LEGACY_FENCE"); + WOODEN_DOOR = Material.valueOf("LEGACY_WOODEN_DOOR"); + TRAP_DOOR = Material.valueOf("LEGACY_TRAP_DOOR"); + FENCE_GATE = Material.valueOf("LEGACY_FENCE_GATE"); + BURNING_FURNACE = Material.valueOf("LEGACY_BURNING_FURNACE"); + DIODE_BLOCK_OFF = Material.valueOf("LEGACY_DIODE_BLOCK_OFF"); + DIODE_BLOCK_ON = Material.valueOf("LEGACY_DIODE_BLOCK_ON"); + ENCHANTMENT_TABLE = Material.valueOf("LEGACY_ENCHANTMENT_TABLE"); + FIREBALL = Material.valueOf("LEGACY_FIREBALL"); + + } else { + if (!mc17) { + BANNER = Material.valueOf("BANNER"); + } + CROPS = Material.valueOf("CROPS"); + SUGAR_CANE_BLOCK = Material.valueOf("SUGAR_CANE_BLOCK"); + REDSTONE_LAMP_ON = Material.valueOf("REDSTONE_LAMP_ON"); + STAINED_GLASS = Material.valueOf("STAINED_GLASS"); + STATIONARY_WATER = Material.valueOf("STATIONARY_WATER"); + STAINED_CLAY = Material.valueOf("STAINED_CLAY"); + WOOD_BUTTON = Material.valueOf("WOOD_BUTTON"); + SOIL = Material.valueOf("SOIL"); + MOB_SPANWER = Material.valueOf("MOB_SPAWNER"); + THIN_GLASS = Material.valueOf("THIN_GLASS"); + IRON_FENCE = Material.valueOf("IRON_FENCE"); + NETHER_FENCE = Material.valueOf("NETHER_FENCE"); + FENCE = Material.valueOf("FENCE"); + WOODEN_DOOR = Material.valueOf("WOODEN_DOOR"); + TRAP_DOOR = Material.valueOf("TRAP_DOOR"); + FENCE_GATE = Material.valueOf("FENCE_GATE"); + BURNING_FURNACE = Material.valueOf("BURNING_FURNACE"); + DIODE_BLOCK_OFF = Material.valueOf("DIODE_BLOCK_OFF"); + DIODE_BLOCK_ON = Material.valueOf("DIODE_BLOCK_ON"); + ENCHANTMENT_TABLE = Material.valueOf("ENCHANTMENT_TABLE"); + FIREBALL = Material.valueOf("FIREBALL"); + } + + } + + private void setupPlaceholderAPI() { + Plugin clip = getServer().getPluginManager().getPlugin("PlaceholderAPI"); + if (clip != null && clip.isEnabled()) { + this.clipPlaceholderAPIManager = new ClipPlaceholderAPIManager(); + if (this.clipPlaceholderAPIManager.register()) { + PlaceholderApi = true; + log(Level.INFO, "Successfully registered placeholders with PlaceholderAPI."); + } else { + PlaceholderApi = false; + } + } else { + PlaceholderApi = false; + } + + Plugin mvdw = getServer().getPluginManager().getPlugin("MVdWPlaceholderAPI"); + if (mvdw != null && mvdw.isEnabled()) { + this.mvdwPlaceholderAPIManager = true; + log(Level.INFO, "Found MVdWPlaceholderAPI. Adding hooks."); + } + } + + private void migrateFPlayerLeaders() { + List lines = new ArrayList<>(); + File fplayerFile = new File("plugins\\Factions\\players.json"); + + try { + BufferedReader br = new BufferedReader(new FileReader(fplayerFile)); + System.out.println("Migrating old players.json file."); + + String line; + while ((line = br.readLine()) != null) { + if (line.contains("\"role\": \"ADMIN\"")) { + line = line.replace("\"role\": \"ADMIN\"", "\"role\": " + "\"LEADER\""); + } + lines.add(line); + } + br.close(); + BufferedWriter bw = new BufferedWriter(new FileWriter(fplayerFile)); + for (String newLine : lines) { + bw.write(newLine + "\n"); + } + bw.flush(); + bw.close(); + } catch (IOException ex) { + System.out.println("File was not found for players.json, assuming" + + " there is no need to migrate old players.json file."); + } + } + + public void changeItemIDSInConfig() { + log("Starting conversion of legacy material in config to 1.13 materials."); + + replaceStringInConfig("fperm-gui.relation.materials.recruit", "WOOD_SWORD", "WOODEN_SWORD"); + replaceStringInConfig("fperm-gui.relation.materials.normal", "GOLD_SWORD", "GOLDEN_SWORD"); + replaceStringInConfig("fperm-gui.relation.materials.ally", "GOLD_AXE", "GOLDEN_AXE"); + replaceStringInConfig("fperm-gui.relation.materials.neutral", "WOOD_AXE", "WOODEN_AXE"); + + ConfigurationSection actionMaterialsConfigSection = getConfig().getConfigurationSection("fperm-gui.action.materials"); + Set actionMaterialKeys = actionMaterialsConfigSection.getKeys(true); + + + for (String key : actionMaterialKeys) { + replaceStringInConfig("fperm-gui.action.materials." + key, "STAINED_GLASS", "GRAY_STAINED_GLASS"); + } + + replaceStringInConfig("fperm-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); + replaceStringInConfig("fwarp-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); + + replaceStringInConfig("fupgrades.MainMenu.DummyItem.Type", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); + replaceStringInConfig("fupgrades.MainMenu.EXP.EXPItem.Type", "EXP_BOTTLE", "EXPERIENCE_BOTTLE"); + replaceStringInConfig("fupgrades.MainMenu.Spawners.SpawnerItem.Type", "MOB_SPAWNER", "SPAWNER"); + + replaceStringInConfig("fperm-gui.action.access.allow", "LIME", "LIME_STAINED_GLASS"); + replaceStringInConfig("fperm-gui.action.access.deny", "RED", "RED_STAINED_GLASS"); + replaceStringInConfig("fperm-gui.action.access.undefined", "CYAN", "CYAN_STAINED_GLASS"); + } + + public void replaceStringInConfig(String path, String stringToReplace, String replacementString) { + if (getConfig().getString(path).equals(stringToReplace)) { + // SavageFactions.plugin.log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); + // log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); + + getConfig().set(path, replacementString); + } + } + + public boolean isClipPlaceholderAPIHooked() { + return this.clipPlaceholderAPIManager != null; + } + + public boolean isMVdWPlaceholderAPIHooked() { + return this.mvdwPlaceholderAPIManager; + } + + private boolean setupPermissions() { + try { + RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Permission.class); + if (rsp != null) { + perms = rsp.getProvider(); + } + } catch (NoClassDefFoundError ex) { + return false; + } + return perms != null; + } + + private boolean setupPlayervaults() { + Plugin plugin = getServer().getPluginManager().getPlugin("PlayerVaults"); + return plugin != null && plugin.isEnabled(); + } + + @Override + public GsonBuilder getGsonBuilder() { + Type mapFLocToStringSetType = new TypeToken>>() { + }.getType(); + + Type accessTypeAdatper = new TypeToken>>() { + }.getType(); + + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().enableComplexMapKeySerialization().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) + .registerTypeAdapter(accessTypeAdatper, new PermissionsMapTypeAdapter()) + .registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter()) + .registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()) + .registerTypeAdapter(Inventory.class, new InventoryTypeAdapter()) + .registerTypeAdapter(Location.class, new LocationTypeAdapter()) + .registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY); + } + + private void divider() { + System.out.println(" .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-"); + System.out.println(" / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\"); + System.out.println("`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'"); + } + + @Override + public void onDisable() { + // only save data if plugin actually completely loaded successfully + if (this.loadSuccessful) { + // Dont save, as this is kind of pointless, as the /f config command manually saves. + // So any edits done are saved, this way manual edits to json can go through. + + // Conf.save(); + } + + if (AutoLeaveTask != null) { + this.getServer().getScheduler().cancelTask(AutoLeaveTask); + AutoLeaveTask = null; + } + + super.onDisable(); + } + + public void startAutoLeaveTask(boolean restartIfRunning) { + if (AutoLeaveTask != null) { + if (!restartIfRunning) { + return; + } + this.getServer().getScheduler().cancelTask(AutoLeaveTask); + } + + if (Conf.autoLeaveRoutineRunsEveryXMinutes > 0.0) { + long ticks = (long) (20 * 60 * Conf.autoLeaveRoutineRunsEveryXMinutes); + AutoLeaveTask = getServer().getScheduler().scheduleSyncRepeatingTask(this, new AutoLeaveTask(), ticks, ticks); + } + } + + @Override + public void postAutoSave() { + //Board.getInstance().forceSave(); Not sure why this was there as it's called after the board is already saved. + Conf.save(); + } + + public ItemStack createItem(Material material, int amount, short datavalue, String name, List lore) { + ItemStack item = new ItemStack(material, amount, datavalue); + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(color(name)); + meta.setLore(colorList(lore)); + item.setItemMeta(meta); + return item; + } + + public ItemStack createLazyItem(Material material, int amount, short datavalue, String name, String lore) { + ItemStack item = new ItemStack(material, amount, datavalue); + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(color(SavageFactions.plugin.getConfig().getString(name))); + meta.setLore(colorList(SavageFactions.plugin.getConfig().getStringList(lore))); + item.setItemMeta(meta); + return item; + } + + public Economy getEcon() { + RegisteredServiceProvider rsp = SavageFactions.plugin.getServer().getServicesManager().getRegistration(Economy.class); + Economy econ = rsp.getProvider(); + return econ; + } + + private boolean setupEssentials() { + SavageFactions.plugin.ess = (Essentials) this.getServer().getPluginManager().getPlugin("Essentials"); + return SavageFactions.plugin.ess == null; + } + + @Override + public boolean logPlayerCommands() { + return Conf.logPlayerCommands; + } + + @Override + public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { + return sender instanceof Player && FactionsPlayerListener.preventCommand(commandString, (Player) sender) || super.handleCommand(sender, commandString, testOnly); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] split) { + if (split.length == 0) { + return handleCommand(sender, "/f help", false); + } + + // otherwise, needs to be handled; presumably another plugin directly ran the command + String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); + return handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false); + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer((Player) sender); + List completions = new ArrayList<>(); + String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); + List argsList = new ArrayList<>(Arrays.asList(args)); + argsList.remove(argsList.size() - 1); + String cmdValid = (cmd + " " + TextUtil.implode(argsList, " ")).trim(); + MCommand commandEx = cmdBase; + List> commandsList = cmdBase.subCommands; + + if (Board.getInstance().getFactionAt(new FLocation(fPlayer.getPlayer().getLocation())) == Factions.getInstance().getWarZone()) { + sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou cannot use autocomplete in warzone.")); + return new ArrayList<>(); + } + + for (; !commandsList.isEmpty() && !argsList.isEmpty(); argsList.remove(0)) { + String cmdName = argsList.get(0).toLowerCase(); + MCommand commandFounded = commandsList.stream() + .filter(c -> c.aliases.contains(cmdName)) + .findFirst().orElse(null); + + if (commandFounded != null) { + commandEx = commandFounded; + commandsList = commandFounded.subCommands; + } else break; + } + + if (argsList.isEmpty()) { + for (MCommand subCommand : commandEx.subCommands) { + subCommand.setCommandSender(sender); + if (handleCommand(sender, cmdValid + " " + subCommand.aliases.get(0), true) + && subCommand.visibility != CommandVisibility.INVISIBLE + && subCommand.validSenderType(sender, false) + && subCommand.validSenderPermissions(sender, false)) + completions.addAll(subCommand.aliases); + } + } + + String lastArg = args[args.length - 1].toLowerCase(); + + completions = completions.stream() + .filter(m -> m.toLowerCase().startsWith(lastArg)) + .collect(Collectors.toList()); + + return completions; + } + + public void createTimedHologram(final Location location, String text, Long timeout) { + ArmorStand as = (ArmorStand) location.add(0.5, 1, 0.5).getWorld().spawnEntity(location, EntityType.ARMOR_STAND); //Spawn the ArmorStand + as.setVisible(false); //Makes the ArmorStand invisible + as.setGravity(false); //Make sure it doesn't fall + as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it + as.setCustomName(SavageFactions.plugin.color(text)); //Set this to the text you want + as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not + final ArmorStand armorStand = as; + + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, () -> { + armorStand.remove(); + getLogger().info("Removing Hologram."); + } + , timeout * 20); + } + + + // -------------------------------------------- // + // Functions for other plugins to hook into + // -------------------------------------------- // + + // This value will be updated whenever new hooks are added + public int hookSupportVersion() { + return 3; + } + + // If another plugin is handling insertion of chat tags, this should be used to notify Factions + public void handleFactionTagExternally(boolean notByFactions) { + Conf.chatTagHandledByAnotherPlugin = notByFactions; + } + + // Simply put, should this chat event be left for Factions to handle? For now, that means players with Faction Chat + // enabled or use of the Factions f command without a slash; combination of isPlayerFactionChatting() and isFactionsCommand() + + public boolean shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent event) { + return event != null && (isPlayerFactionChatting(event.getPlayer()) || isFactionsCommand(event.getMessage())); + } + + + // Does player have Faction Chat enabled? If so, chat plugins should preferably not do channels, + // local chat, or anything else which targets individual recipients, so Faction Chat can be done + public boolean isPlayerFactionChatting(Player player) { + if (player == null) { + return false; + } + FPlayer me = FPlayers.getInstance().getByPlayer(player); + + return me != null && me.getChatMode().isAtLeast(ChatMode.ALLIANCE); + } + + // Is this chat message actually a Factions command, and thus should be left alone by other plugins? + + // TODO: GET THIS BACK AND WORKING + + public boolean isFactionsCommand(String check) { + return !(check == null || check.isEmpty()) && this.handleCommand(null, check, true); + } + + // Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat + public String getPlayerFactionTag(Player player) { + return getPlayerFactionTagRelation(player, null); + } + + // Same as above, but with relation (enemy/neutral/ally) coloring potentially added to the tag + public String getPlayerFactionTagRelation(Player speaker, Player listener) { + String tag = "~"; + + if (speaker == null) { + return tag; + } + + FPlayer me = FPlayers.getInstance().getByPlayer(speaker); + if (me == null) { + return tag; + } + + // if listener isn't set, or config option is disabled, give back uncolored tag + if (listener == null || !Conf.chatTagRelationColored) { + tag = me.getChatTag().trim(); + } else { + FPlayer you = FPlayers.getInstance().getByPlayer(listener); + if (you == null) { + tag = me.getChatTag().trim(); + } else // everything checks out, give the colored tag + { + tag = me.getChatTag(you).trim(); + } + } + if (tag.isEmpty()) { + tag = "~"; + } + + return tag; + } + + // Get a player's title within their faction, mainly for usage by chat plugins for local/channel chat + public String getPlayerTitle(Player player) { + if (player == null) { + return ""; + } + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + if (me == null) { + return ""; + } + + return me.getTitle().trim(); + } + + public String color(String line) { + line = ChatColor.translateAlternateColorCodes('&', line); + return line; + } + + //colors a string list + public List colorList(List lore) { + for (int i = 0; i <= lore.size() - 1; i++) { + lore.set(i, color(lore.get(i))); + } + return lore; + } + + // Get a list of all faction tags (names) + public Set getFactionTags() { + return Factions.getInstance().getFactionTags(); + } + + // Get a list of all players in the specified faction + public Set getPlayersInFaction(String factionTag) { + Set players = new HashSet<>(); + Faction faction = Factions.getInstance().getByTag(factionTag); + if (faction != null) { + for (FPlayer fplayer : faction.getFPlayers()) { + players.add(fplayer.getName()); + } + } + return players; + } + + // Get a list of all online players in the specified faction + public Set getOnlinePlayersInFaction(String factionTag) { + Set players = new HashSet<>(); + Faction faction = Factions.getInstance().getByTag(factionTag); + if (faction != null) { + for (FPlayer fplayer : faction.getFPlayersWhereOnline(true)) { + players.add(fplayer.getName()); + } + } + return players; + } + + public boolean isHookedPlayervaults() { + return hookedPlayervaults; + } + + public String getPrimaryGroup(OfflinePlayer player) { + return perms == null || !perms.hasGroupSupport() ? " " : perms.getPrimaryGroup(Bukkit.getWorlds().get(0).toString(), player); + } + + public void debug(Level level, String s) { + if (getConfig().getBoolean("debug", false)) { + getLogger().log(level, s); + } + } + + public void debug(String s) { + debug(Level.INFO, s); + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java b/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java index f9a2bdc1..ba413640 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java @@ -8,45 +8,45 @@ import org.bukkit.event.player.PlayerTeleportEvent; public class CmdAHome extends FCommand { - public CmdAHome() { - super(); - this.aliases.add("ahome"); + public CmdAHome() { + super(); + this.aliases.add("ahome"); - this.requiredArgs.add("player name"); + this.requiredArgs.add("player name"); - this.permission = Permission.AHOME.node; - this.disableOnLock = false; + this.permission = Permission.AHOME.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer target = argAsBestFPlayerMatch(0); - if (target == null) { - msg(TL.GENERIC_NOPLAYERMATCH, argAsString(0)); - return; - } + @Override + public void perform() { + FPlayer target = argAsBestFPlayerMatch(0); + if (target == null) { + msg(TL.GENERIC_NOPLAYERMATCH, argAsString(0)); + return; + } - if (target.isOnline()) { - Faction faction = target.getFaction(); - if (faction.hasHome()) { - target.getPlayer().teleport(faction.getHome(), PlayerTeleportEvent.TeleportCause.PLUGIN); - msg(TL.COMMAND_AHOME_SUCCESS, target.getName()); - target.msg(TL.COMMAND_AHOME_TARGET); - } else { - msg(TL.COMMAND_AHOME_NOHOME, target.getName()); - } - } else { - msg(TL.COMMAND_AHOME_OFFLINE, target.getName()); - } - } + if (target.isOnline()) { + Faction faction = target.getFaction(); + if (faction.hasHome()) { + target.getPlayer().teleport(faction.getHome(), PlayerTeleportEvent.TeleportCause.PLUGIN); + msg(TL.COMMAND_AHOME_SUCCESS, target.getName()); + target.msg(TL.COMMAND_AHOME_TARGET); + } else { + msg(TL.COMMAND_AHOME_NOHOME, target.getName()); + } + } else { + msg(TL.COMMAND_AHOME_OFFLINE, target.getName()); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_AHOME_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_AHOME_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java b/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java index ed21beb0..5c03529f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java @@ -11,90 +11,90 @@ import org.bukkit.Bukkit; public class CmdAdmin extends FCommand { - public CmdAdmin() { - super(); - this.aliases.add("admin"); - this.aliases.add("setadmin"); - this.aliases.add("leader"); - this.aliases.add("setleader"); + public CmdAdmin() { + super(); + this.aliases.add("admin"); + this.aliases.add("setadmin"); + this.aliases.add("leader"); + this.aliases.add("setleader"); - this.requiredArgs.add("player name"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("player name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.ADMIN.node; - this.disableOnLock = true; + this.permission = Permission.ADMIN.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer fyou = this.argAsBestFPlayerMatch(0); - if (fyou == null) { - return; - } + @Override + public void perform() { + FPlayer fyou = this.argAsBestFPlayerMatch(0); + if (fyou == null) { + return; + } - boolean permAny = Permission.ADMIN_ANY.has(sender, false); - Faction targetFaction = fyou.getFaction(); + boolean permAny = Permission.ADMIN_ANY.has(sender, false); + Faction targetFaction = fyou.getFaction(); - if (targetFaction != myFaction && !permAny) { - msg(TL.COMMAND_ADMIN_NOTMEMBER, fyou.describeTo(fme, true)); - return; - } + if (targetFaction != myFaction && !permAny) { + msg(TL.COMMAND_ADMIN_NOTMEMBER, fyou.describeTo(fme, true)); + return; + } - if (fme != null && fme.getRole() != Role.LEADER && !permAny) { - msg(TL.COMMAND_ADMIN_NOTADMIN); - return; - } + if (fme != null && fme.getRole() != Role.LEADER && !permAny) { + msg(TL.COMMAND_ADMIN_NOTADMIN); + return; + } - if (fyou == fme && !permAny) { - msg(TL.COMMAND_ADMIN_TARGETSELF); - return; - } + if (fyou == fme && !permAny) { + msg(TL.COMMAND_ADMIN_TARGETSELF); + return; + } - // only perform a FPlayerJoinEvent when newLeader isn't actually in the faction - if (fyou.getFaction() != targetFaction) { - FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER); - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - } + // only perform a FPlayerJoinEvent when newLeader isn't actually in the faction + if (fyou.getFaction() != targetFaction) { + FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } - FPlayer admin = targetFaction.getFPlayerAdmin(); + FPlayer admin = targetFaction.getFPlayerAdmin(); - if (fyou == admin && fyou.getFaction().getSize() == 1) { - msg(TL.COMMAND_ADMIN_NOMEMBERS); - return; - } + if (fyou == admin && fyou.getFaction().getSize() == 1) { + msg(TL.COMMAND_ADMIN_NOMEMBERS); + return; + } - // if target player is currently admin, demote and replace him - if (fyou == admin) { - targetFaction.promoteNewLeader(); - msg(TL.COMMAND_ADMIN_DEMOTES, fyou.describeTo(fme, true)); - fyou.msg(TL.COMMAND_ADMIN_DEMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fyou, true)); - return; - } + // if target player is currently admin, demote and replace him + if (fyou == admin) { + targetFaction.promoteNewLeader(); + msg(TL.COMMAND_ADMIN_DEMOTES, fyou.describeTo(fme, true)); + fyou.msg(TL.COMMAND_ADMIN_DEMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fyou, true)); + return; + } - // promote target player, and demote existing admin if one exists - if (admin != null) { - admin.setRole(Role.COLEADER); - } - fyou.setRole(Role.LEADER); - msg(TL.COMMAND_ADMIN_PROMOTES, fyou.describeTo(fme, true)); + // promote target player, and demote existing admin if one exists + if (admin != null) { + admin.setRole(Role.COLEADER); + } + fyou.setRole(Role.LEADER); + msg(TL.COMMAND_ADMIN_PROMOTES, fyou.describeTo(fme, true)); - // Inform all players - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg(TL.COMMAND_ADMIN_PROMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true), fyou.describeTo(fplayer), targetFaction.describeTo(fplayer)); - } - } + // Inform all players + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg(TL.COMMAND_ADMIN_PROMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true), fyou.describeTo(fplayer), targetFaction.describeTo(fplayer)); + } + } - public TL getUsageTranslation() { - return TL.COMMAND_ADMIN_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_ADMIN_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java b/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java index 296891d7..952d9d38 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java @@ -9,41 +9,41 @@ import org.bukkit.entity.Player; public class CmdAnnounce extends FCommand { - public CmdAnnounce() { - super(); - this.aliases.add("ann"); - this.aliases.add("announce"); + public CmdAnnounce() { + super(); + this.aliases.add("ann"); + this.aliases.add("announce"); - this.requiredArgs.add("message"); - this.errorOnToManyArgs = false; + this.requiredArgs.add("message"); + this.errorOnToManyArgs = false; - this.permission = Permission.ANNOUNCE.node; - this.disableOnLock = false; + this.permission = Permission.ANNOUNCE.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + } - @Override - public void perform() { - String prefix = ChatColor.GREEN + myFaction.getTag() + ChatColor.YELLOW + " [" + ChatColor.GRAY + me.getName() + ChatColor.YELLOW + "] " + ChatColor.RESET; - String message = StringUtils.join(args, " "); + @Override + public void perform() { + String prefix = ChatColor.GREEN + myFaction.getTag() + ChatColor.YELLOW + " [" + ChatColor.GRAY + me.getName() + ChatColor.YELLOW + "] " + ChatColor.RESET; + String message = StringUtils.join(args, " "); - for (Player player : myFaction.getOnlinePlayers()) { - player.sendMessage(prefix + message); - } + for (Player player : myFaction.getOnlinePlayers()) { + player.sendMessage(prefix + message); + } - // Add for offline players. - for (FPlayer fp : myFaction.getFPlayersWhereOnline(false)) { - myFaction.addAnnouncement(fp, prefix + message); - } - } + // Add for offline players. + for (FPlayer fp : myFaction.getFPlayersWhereOnline(false)) { + myFaction.addAnnouncement(fp, prefix + message); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_ANNOUNCE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_ANNOUNCE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java index 5aa47e72..61742f98 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java @@ -7,50 +7,50 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdAutoClaim extends FCommand { - public CmdAutoClaim() { - super(); - this.aliases.add("autoclaim"); + public CmdAutoClaim() { + super(); + this.aliases.add("autoclaim"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction", "your"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction", "your"); - this.permission = Permission.AUTOCLAIM.node; - this.disableOnLock = true; + this.permission = Permission.AUTOCLAIM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction forFaction = this.argAsFaction(0, myFaction); - if (forFaction == null || forFaction == fme.getAutoClaimFor()) { - fme.setAutoClaimFor(null); - msg(TL.COMMAND_AUTOCLAIM_DISABLED); - return; - } + @Override + public void perform() { + Faction forFaction = this.argAsFaction(0, myFaction); + if (forFaction == null || forFaction == fme.getAutoClaimFor()) { + fme.setAutoClaimFor(null); + msg(TL.COMMAND_AUTOCLAIM_DISABLED); + return; + } - if (!fme.canClaimForFaction(forFaction)) { - if (myFaction == forFaction) { - msg(TL.COMMAND_AUTOCLAIM_REQUIREDRANK, Role.MODERATOR.getTranslation()); - } else { - msg(TL.COMMAND_AUTOCLAIM_OTHERFACTION, forFaction.describeTo(fme)); - } + if (!fme.canClaimForFaction(forFaction)) { + if (myFaction == forFaction) { + msg(TL.COMMAND_AUTOCLAIM_REQUIREDRANK, Role.MODERATOR.getTranslation()); + } else { + msg(TL.COMMAND_AUTOCLAIM_OTHERFACTION, forFaction.describeTo(fme)); + } - return; - } + return; + } - fme.setAutoClaimFor(forFaction); + fme.setAutoClaimFor(forFaction); - msg(TL.COMMAND_AUTOCLAIM_ENABLED, forFaction.describeTo(fme)); - fme.attemptClaim(forFaction, me.getLocation(), true); - } + msg(TL.COMMAND_AUTOCLAIM_ENABLED, forFaction.describeTo(fme)); + fme.attemptClaim(forFaction, me.getLocation(), true); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_AUTOCLAIM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_AUTOCLAIM_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java b/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java index 798914d3..78ba49c9 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java @@ -1,48 +1,48 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.zcore.CommandVisibility; -import com.massivecraft.factions.zcore.MCommand; -import com.massivecraft.factions.zcore.util.TL; - -import java.util.ArrayList; - -public class CmdAutoHelp extends MCommand { - - public CmdAutoHelp() { - super(SavageFactions.plugin); - this.aliases.add("?"); - this.aliases.add("h"); - this.aliases.add("help"); - - this.setHelpShort(""); - - this.optionalArgs.put("page", "1"); - } - - @Override - public void perform() { - - if (this.commandChain.size() == 0) { - return; - } - MCommand pcmd = this.commandChain.get(this.commandChain.size() - 1); - - ArrayList lines = new ArrayList<>(); - - lines.addAll(pcmd.helpLong); - - for (MCommand scmd : pcmd.subCommands) { - if (scmd.visibility == CommandVisibility.VISIBLE || (scmd.visibility == CommandVisibility.SECRET && scmd.validSenderPermissions(sender, false))) { - lines.add(scmd.getUseageTemplate(this.commandChain, true)); - } - } - - sendMessage(p.txt.getPage(lines, this.argAsInt(0, 1), TL.COMMAND_AUTOHELP_HELPFOR.toString() + pcmd.aliases.get(0) + "\"")); - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_HELP_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.zcore.CommandVisibility; +import com.massivecraft.factions.zcore.MCommand; +import com.massivecraft.factions.zcore.util.TL; + +import java.util.ArrayList; + +public class CmdAutoHelp extends MCommand { + + public CmdAutoHelp() { + super(SavageFactions.plugin); + this.aliases.add("?"); + this.aliases.add("h"); + this.aliases.add("help"); + + this.setHelpShort(""); + + this.optionalArgs.put("page", "1"); + } + + @Override + public void perform() { + + if (this.commandChain.size() == 0) { + return; + } + MCommand pcmd = this.commandChain.get(this.commandChain.size() - 1); + + ArrayList lines = new ArrayList<>(); + + lines.addAll(pcmd.helpLong); + + for (MCommand scmd : pcmd.subCommands) { + if (scmd.visibility == CommandVisibility.VISIBLE || (scmd.visibility == CommandVisibility.SECRET && scmd.validSenderPermissions(sender, false))) { + lines.add(scmd.getUseageTemplate(this.commandChain, true)); + } + } + + sendMessage(p.txt.getPage(lines, this.argAsInt(0, 1), TL.COMMAND_AUTOHELP_HELPFOR.toString() + pcmd.aliases.get(0) + "\"")); + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_HELP_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBan.java b/src/main/java/com/massivecraft/factions/cmd/CmdBan.java index 64551254..2bbe9f33 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBan.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBan.java @@ -15,87 +15,87 @@ import java.util.logging.Level; public class CmdBan extends FCommand { - public CmdBan() { - super(); - this.aliases.add("ban"); + public CmdBan() { + super(); + this.aliases.add("ban"); - this.requiredArgs.add("target"); + this.requiredArgs.add("target"); - this.permission = Permission.BAN.node; - this.disableOnLock = true; + this.permission = Permission.BAN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { + @Override + public void perform() { - // Adds bypass to admins and clean permission check - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.BAN); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "ban"); - return; - } - } + // Adds bypass to admins and clean permission check + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.BAN); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "ban"); + return; + } + } - // Good on permission checks. Now lets just ban the player. - FPlayer target = argAsFPlayer(0); - if (target == null) { - return; // the above method sends a message if fails to find someone. - } + // Good on permission checks. Now lets just ban the player. + FPlayer target = argAsFPlayer(0); + if (target == null) { + return; // the above method sends a message if fails to find someone. + } - if (fme == target) { - // You may not ban yourself - fme.msg(TL.COMMAND_BAN_SELF); - return; - } else if (target.getFaction() == myFaction && target.getRole().value >= fme.getRole().value) { - // You may not ban someone that has same or higher faction rank - fme.msg(TL.COMMAND_BAN_INSUFFICIENTRANK, target.getName()); - return; - } + if (fme == target) { + // You may not ban yourself + fme.msg(TL.COMMAND_BAN_SELF); + return; + } else if (target.getFaction() == myFaction && target.getRole().value >= fme.getRole().value) { + // You may not ban someone that has same or higher faction rank + fme.msg(TL.COMMAND_BAN_INSUFFICIENTRANK, target.getName()); + return; + } - for (BanInfo banInfo : myFaction.getBannedPlayers()) { - if (banInfo.getBanned().equals(target.getId())) { - msg(TL.COMMAND_BAN_ALREADYBANNED); - return; - } - } + for (BanInfo banInfo : myFaction.getBannedPlayers()) { + if (banInfo.getBanned().equals(target.getId())) { + msg(TL.COMMAND_BAN_ALREADYBANNED); + return; + } + } - // Ban the user. - myFaction.ban(target, fme); - myFaction.deinvite(target); // can't hurt + // Ban the user. + myFaction.ban(target, fme); + myFaction.deinvite(target); // can't hurt - // If in same Faction, lets make sure to kick them and throw an event. - if (target.getFaction() == myFaction) { + // If in same Faction, lets make sure to kick them and throw an event. + if (target.getFaction() == myFaction) { - FPlayerLeaveEvent event = new FPlayerLeaveEvent(target, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.BANNED); - Bukkit.getServer().getPluginManager().callEvent(event); + FPlayerLeaveEvent event = new FPlayerLeaveEvent(target, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.BANNED); + Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - // if someone cancels a ban, we'll get people complaining here. So lets log it. - SavageFactions.plugin.log(Level.WARNING, "Attempted to ban {0} but someone cancelled the kick event. This isn't good.", target.getName()); - return; - } + if (event.isCancelled()) { + // if someone cancels a ban, we'll get people complaining here. So lets log it. + SavageFactions.plugin.log(Level.WARNING, "Attempted to ban {0} but someone cancelled the kick event. This isn't good.", target.getName()); + return; + } - // Didn't get cancelled so remove them and reset their invite. - myFaction.removeFPlayer(target); - target.resetFactionData(); - } + // Didn't get cancelled so remove them and reset their invite. + myFaction.removeFPlayer(target); + target.resetFactionData(); + } - // Lets inform the people! - target.msg(TL.COMMAND_BAN_TARGET, myFaction.getTag(target.getFaction())); - myFaction.msg(TL.COMMAND_BAN_BANNED, fme.getName(), target.getName()); - } + // Lets inform the people! + target.msg(TL.COMMAND_BAN_TARGET, myFaction.getTag(target.getFaction())); + myFaction.msg(TL.COMMAND_BAN_BANNED, fme.getName(), target.getName()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BAN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BAN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java b/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java index 42d8c7e5..87154386 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java @@ -13,60 +13,60 @@ import java.util.List; public class CmdBanlist extends FCommand { - public CmdBanlist() { - super(); - this.aliases.add("banlist"); - this.aliases.add("bans"); - this.aliases.add("banl"); + public CmdBanlist() { + super(); + this.aliases.add("banlist"); + this.aliases.add("bans"); + this.aliases.add("banl"); - this.optionalArgs.put("faction", "faction"); + this.optionalArgs.put("faction", "faction"); - this.permission = Permission.BAN.node; - this.disableOnLock = true; + this.permission = Permission.BAN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction target = myFaction; - if (!args.isEmpty()) { - target = argAsFaction(0); - } + @Override + public void perform() { + Faction target = myFaction; + if (!args.isEmpty()) { + target = argAsFaction(0); + } - if (target == Factions.getInstance().getWilderness()) { - sender.sendMessage(TL.COMMAND_BANLIST_NOFACTION.toString()); - return; - } + if (target == Factions.getInstance().getWilderness()) { + sender.sendMessage(TL.COMMAND_BANLIST_NOFACTION.toString()); + return; + } - if (target == null) { - sender.sendMessage(TL.COMMAND_BANLIST_INVALID.format(argAsString(0))); - return; - } + if (target == null) { + sender.sendMessage(TL.COMMAND_BANLIST_INVALID.format(argAsString(0))); + return; + } - List lines = new ArrayList<>(); - lines.add(TL.COMMAND_BANLIST_HEADER.format(target.getBannedPlayers().size(), target.getTag(myFaction))); - int i = 1; + List lines = new ArrayList<>(); + lines.add(TL.COMMAND_BANLIST_HEADER.format(target.getBannedPlayers().size(), target.getTag(myFaction))); + int i = 1; - for (BanInfo info : target.getBannedPlayers()) { - FPlayer banned = FPlayers.getInstance().getById(info.getBanned()); - FPlayer banner = FPlayers.getInstance().getById(info.getBanner()); - String timestamp = TL.sdf.format(info.getTime()); + for (BanInfo info : target.getBannedPlayers()) { + FPlayer banned = FPlayers.getInstance().getById(info.getBanned()); + FPlayer banner = FPlayers.getInstance().getById(info.getBanner()); + String timestamp = TL.sdf.format(info.getTime()); - lines.add(TL.COMMAND_BANLIST_ENTRY.format(i, banned.getName(), banner.getName(), timestamp)); - i++; - } + lines.add(TL.COMMAND_BANLIST_ENTRY.format(i, banned.getName(), banner.getName(), timestamp)); + i++; + } - for (String s : lines) { - fme.sendMessage(s); - } - } + for (String s : lines) { + fme.sendMessage(s); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BANLIST_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BANLIST_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java b/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java index 7f8e6fa6..46960073 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java @@ -13,123 +13,123 @@ import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; public class CmdBanner extends FCommand { - public CmdBanner() { - super(); + public CmdBanner() { + super(); - this.aliases.add("banner"); - this.aliases.add("warbanner"); + this.aliases.add("banner"); + this.aliases.add("warbanner"); - this.permission = Permission.BANNER.node; - this.disableOnLock = false; + this.permission = Permission.BANNER.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { - msg(TL.COMMAND_BANNER_DISABLED); - return; - } - if (!fme.hasMoney(SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000))) { - msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); - return; - } - takeMoney(fme, SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000)); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { + msg(TL.COMMAND_BANNER_DISABLED); + return; + } + if (!fme.hasMoney(SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000))) { + msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); + return; + } + takeMoney(fme, SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000)); - //ItemStack warBanner = SavageFactions.plugin.createItem(Material.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); - //BannerMeta bannerMeta = (BannerMeta) warBanner.getItemMeta(); - ItemStack warBanner = fme.getFaction().getBanner(); - if (warBanner != null) { - ItemMeta warmeta = warBanner.getItemMeta(); - warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); - warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); - warBanner.setItemMeta(warmeta); + //ItemStack warBanner = SavageFactions.plugin.createItem(Material.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); + //BannerMeta bannerMeta = (BannerMeta) warBanner.getItemMeta(); + ItemStack warBanner = fme.getFaction().getBanner(); + if (warBanner != null) { + ItemMeta warmeta = warBanner.getItemMeta(); + warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); + warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); + warBanner.setItemMeta(warmeta); - } else { + } else { - warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); - } - fme.msg(TL.COMMAND_BANNER_SUCCESS); - warBanner.setAmount(1); - me.getInventory().addItem(warBanner); - } + warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); + } + fme.msg(TL.COMMAND_BANNER_SUCCESS); + warBanner.setAmount(1); + me.getInventory().addItem(warBanner); + } - public boolean hasMoney(FPlayer fme, int amt) { - Economy econ = SavageFactions.plugin.getEcon(); - if (econ.getBalance(fme.getPlayer()) >= amt) { - return true; - } else { - fme.msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); - return false; - } - } + public boolean hasMoney(FPlayer fme, int amt) { + Economy econ = SavageFactions.plugin.getEcon(); + if (econ.getBalance(fme.getPlayer()) >= amt) { + return true; + } else { + fme.msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); + return false; + } + } - public void takeMoney(FPlayer fme, int amt) { - if (hasMoney(fme, amt)) { - Economy econ = SavageFactions.plugin.getEcon(); - econ.withdrawPlayer(fme.getPlayer(), amt); - fme.sendMessage(TL.COMMAND_BANNER_MONEYTAKE.toString().replace("{amount}", amt + "")); - } - } + public void takeMoney(FPlayer fme, int amt) { + if (hasMoney(fme, amt)) { + Economy econ = SavageFactions.plugin.getEcon(); + econ.withdrawPlayer(fme.getPlayer(), amt); + fme.sendMessage(TL.COMMAND_BANNER_MONEYTAKE.toString().replace("{amount}", amt + "")); + } + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - public void removeFromInventory(Inventory inventory, ItemStack item) { - int amt = item.getAmount(); - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - if (items[i].getAmount() > amt) { - items[i].setAmount(items[i].getAmount() - amt); - break; - } else if (items[i].getAmount() == amt) { - items[i] = null; - break; - } else { - amt -= items[i].getAmount(); - items[i] = null; - } - } - } - inventory.setContents(items); - } + public void removeFromInventory(Inventory inventory, ItemStack item) { + int amt = item.getAmount(); + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + if (items[i].getAmount() > amt) { + items[i].setAmount(items[i].getAmount() - amt); + break; + } else if (items[i].getAmount() == amt) { + items[i] = null; + break; + } else { + amt -= items[i].getAmount(); + items[i] = null; + } + } + } + inventory.setContents(items); + } - public int getEmptySlots(Player p) { - PlayerInventory inventory = p.getInventory(); - ItemStack[] cont = inventory.getContents(); - int i = 0; - for (ItemStack item : cont) - if (item != null && item.getType() != Material.AIR) { - i++; - } - return 36 - i; - } + public int getEmptySlots(Player p) { + PlayerInventory inventory = p.getInventory(); + ItemStack[] cont = inventory.getContents(); + int i = 0; + for (ItemStack item : cont) + if (item != null && item.getType() != Material.AIR) { + i++; + } + return 36 - i; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BANNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BANNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java b/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java index fcbe859f..514a5c67 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java @@ -6,47 +6,47 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdBoom extends FCommand { - public CmdBoom() { - super(); - this.aliases.add("noboom"); - this.aliases.add("explosions"); - this.aliases.add("toggleexplosions"); + public CmdBoom() { + super(); + this.aliases.add("noboom"); + this.aliases.add("explosions"); + this.aliases.add("toggleexplosions"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.NO_BOOM.node; - this.disableOnLock = true; + this.permission = Permission.NO_BOOM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!myFaction.isPeaceful()) { - fme.msg(TL.COMMAND_BOOM_PEACEFULONLY); - return; - } + @Override + public void perform() { + if (!myFaction.isPeaceful()) { + fme.msg(TL.COMMAND_BOOM_PEACEFULONLY); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostNoBoom, TL.COMMAND_BOOM_TOTOGGLE, TL.COMMAND_BOOM_FORTOGGLE)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostNoBoom, TL.COMMAND_BOOM_TOTOGGLE, TL.COMMAND_BOOM_FORTOGGLE)) { + return; + } - myFaction.setPeacefulExplosionsEnabled(this.argAsBool(0, !myFaction.getPeacefulExplosionsEnabled())); + myFaction.setPeacefulExplosionsEnabled(this.argAsBool(0, !myFaction.getPeacefulExplosionsEnabled())); - String enabled = myFaction.noExplosionsInTerritory() ? TL.GENERIC_DISABLED.toString() : TL.GENERIC_ENABLED.toString(); + String enabled = myFaction.noExplosionsInTerritory() ? TL.GENERIC_DISABLED.toString() : TL.GENERIC_ENABLED.toString(); - // Inform - myFaction.msg(TL.COMMAND_BOOM_ENABLED, fme.describeTo(myFaction), enabled); - } + // Inform + myFaction.msg(TL.COMMAND_BOOM_ENABLED, fme.describeTo(myFaction), enabled); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BOOM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BOOM_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java b/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java index 3dd55678..410d1865 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java @@ -6,39 +6,39 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdBypass extends FCommand { - public CmdBypass() { - super(); - this.aliases.add("bypass"); + public CmdBypass() { + super(); + this.aliases.add("bypass"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.BYPASS.node; - this.disableOnLock = false; + this.permission = Permission.BYPASS.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - fme.setIsAdminBypassing(this.argAsBool(0, !fme.isAdminBypassing())); + @Override + public void perform() { + fme.setIsAdminBypassing(this.argAsBool(0, !fme.isAdminBypassing())); - // TODO: Move this to a transient field in the model?? - if (fme.isAdminBypassing()) { - fme.msg(TL.COMMAND_BYPASS_ENABLE.toString()); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_ENABLELOG.toString()); - } else { - fme.msg(TL.COMMAND_BYPASS_DISABLE.toString()); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_DISABLELOG.toString()); - } - } + // TODO: Move this to a transient field in the model?? + if (fme.isAdminBypassing()) { + fme.msg(TL.COMMAND_BYPASS_ENABLE.toString()); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_ENABLELOG.toString()); + } else { + fme.msg(TL.COMMAND_BYPASS_DISABLE.toString()); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_DISABLELOG.toString()); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BYPASS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BYPASS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdChat.java b/src/main/java/com/massivecraft/factions/cmd/CmdChat.java index 983868c0..ffda5965 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdChat.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdChat.java @@ -8,80 +8,80 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdChat extends FCommand { - public CmdChat() { - super(); - this.aliases.add("c"); - this.aliases.add("chat"); + public CmdChat() { + super(); + this.aliases.add("c"); + this.aliases.add("chat"); - //this.requiredArgs.add(""); - this.optionalArgs.put("mode", "next"); + //this.requiredArgs.add(""); + this.optionalArgs.put("mode", "next"); - this.permission = Permission.CHAT.node; - this.disableOnLock = false; + this.permission = Permission.CHAT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!Conf.factionOnlyChat) { - msg(TL.COMMAND_CHAT_DISABLED.toString()); - return; - } + @Override + public void perform() { + if (!Conf.factionOnlyChat) { + msg(TL.COMMAND_CHAT_DISABLED.toString()); + return; + } - String modeString = this.argAsString(0); - ChatMode modeTarget = fme.getChatMode().getNext(); + String modeString = this.argAsString(0); + ChatMode modeTarget = fme.getChatMode().getNext(); - if (modeString != null) { - modeString = modeString.toLowerCase(); - // Only allow Mods and higher rank to switch to this channel. - if (modeString.startsWith("m")) { - if (!fme.getRole().isAtLeast(Role.MODERATOR)) { - msg(TL.COMMAND_CHAT_MOD_ONLY); - return; - } else modeTarget = ChatMode.MOD; - } else if (modeString.startsWith("p")) { - modeTarget = ChatMode.PUBLIC; - } else if (modeString.startsWith("a")) { - modeTarget = ChatMode.ALLIANCE; - } else if (modeString.startsWith("f")) { - modeTarget = ChatMode.FACTION; - } else if (modeString.startsWith("t")) { - modeTarget = ChatMode.TRUCE; - } else { - msg(TL.COMMAND_CHAT_INVALIDMODE); - return; - } - } + if (modeString != null) { + modeString = modeString.toLowerCase(); + // Only allow Mods and higher rank to switch to this channel. + if (modeString.startsWith("m")) { + if (!fme.getRole().isAtLeast(Role.MODERATOR)) { + msg(TL.COMMAND_CHAT_MOD_ONLY); + return; + } else modeTarget = ChatMode.MOD; + } else if (modeString.startsWith("p")) { + modeTarget = ChatMode.PUBLIC; + } else if (modeString.startsWith("a")) { + modeTarget = ChatMode.ALLIANCE; + } else if (modeString.startsWith("f")) { + modeTarget = ChatMode.FACTION; + } else if (modeString.startsWith("t")) { + modeTarget = ChatMode.TRUCE; + } else { + msg(TL.COMMAND_CHAT_INVALIDMODE); + return; + } + } - fme.setChatMode(modeTarget); + fme.setChatMode(modeTarget); - switch (fme.getChatMode()) { - case MOD: - msg(TL.COMMAND_CHAT_MODE_MOD); - break; - case PUBLIC: - msg(TL.COMMAND_CHAT_MODE_PUBLIC); - break; - case ALLIANCE: - msg(TL.COMMAND_CHAT_MODE_ALLIANCE); - break; - case TRUCE: - msg(TL.COMMAND_CHAT_MODE_TRUCE); - break; - default: - msg(TL.COMMAND_CHAT_MODE_FACTION); - break; - } - } + switch (fme.getChatMode()) { + case MOD: + msg(TL.COMMAND_CHAT_MODE_MOD); + break; + case PUBLIC: + msg(TL.COMMAND_CHAT_MODE_PUBLIC); + break; + case ALLIANCE: + msg(TL.COMMAND_CHAT_MODE_ALLIANCE); + break; + case TRUCE: + msg(TL.COMMAND_CHAT_MODE_TRUCE); + break; + default: + msg(TL.COMMAND_CHAT_MODE_FACTION); + break; + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CHAT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CHAT_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java b/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java index f6cd198f..d8d1b4e3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java @@ -6,37 +6,37 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdChatSpy extends FCommand { - public CmdChatSpy() { - super(); - this.aliases.add("chatspy"); + public CmdChatSpy() { + super(); + this.aliases.add("chatspy"); - this.optionalArgs.put("on/off", "flip"); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.CHATSPY.node; - this.disableOnLock = false; + this.permission = Permission.CHATSPY.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - fme.setSpyingChat(this.argAsBool(0, !fme.isSpyingChat())); + @Override + public void perform() { + fme.setSpyingChat(this.argAsBool(0, !fme.isSpyingChat())); - if (fme.isSpyingChat()) { - fme.msg(TL.COMMAND_CHATSPY_ENABLE); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_ENABLELOG.toString()); - } else { - fme.msg(TL.COMMAND_CHATSPY_DISABLE); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_DISABLELOG.toString()); - } - } + if (fme.isSpyingChat()) { + fme.msg(TL.COMMAND_CHATSPY_ENABLE); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_ENABLELOG.toString()); + } else { + fme.msg(TL.COMMAND_CHATSPY_DISABLE); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_DISABLELOG.toString()); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CHATSPY_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CHATSPY_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java b/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java index 01021f8d..fe153b0a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java @@ -6,66 +6,66 @@ import com.massivecraft.factions.util.WarmUpUtil; import com.massivecraft.factions.zcore.util.TL; public class CmdCheckpoint extends FCommand { - public CmdCheckpoint() { - super(); - this.aliases.add("checkp"); - this.aliases.add("checkpoint"); - this.aliases.add("cpoint"); + public CmdCheckpoint() { + super(); + this.aliases.add("checkp"); + this.aliases.add("checkpoint"); + this.aliases.add("cpoint"); - this.optionalArgs.put("set", ""); + this.optionalArgs.put("set", ""); - this.permission = Permission.CHECKPOINT.node; - this.disableOnLock = false; + this.permission = Permission.CHECKPOINT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("checkpoints.Enabled")) { - fme.msg(TL.COMMAND_CHECKPOINT_DISABLED); - return; - } - if (args.size() == 1) { - FLocation myLocation = new FLocation(fme.getPlayer().getLocation()); - Faction myLocFaction = Board.getInstance().getFactionAt(myLocation); - if (myLocFaction == Factions.getInstance().getWilderness() || myLocFaction == fme.getFaction()) { - fme.getFaction().setCheckpoint(fme.getPlayer().getLocation()); - fme.msg(TL.COMMAND_CHECKPOINT_SET); - return; - } else { - fme.msg(TL.COMMAND_CHECKPOINT_INVALIDLOCATION); - return; - } - } - if (fme.getFaction().getCheckpoint() == null) { - fme.msg(TL.COMMAND_CHECKPOINT_NOT_SET); - return; - } - FLocation checkLocation = new FLocation(fme.getFaction().getCheckpoint()); - Faction checkfaction = Board.getInstance().getFactionAt(checkLocation); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("checkpoints.Enabled")) { + fme.msg(TL.COMMAND_CHECKPOINT_DISABLED); + return; + } + if (args.size() == 1) { + FLocation myLocation = new FLocation(fme.getPlayer().getLocation()); + Faction myLocFaction = Board.getInstance().getFactionAt(myLocation); + if (myLocFaction == Factions.getInstance().getWilderness() || myLocFaction == fme.getFaction()) { + fme.getFaction().setCheckpoint(fme.getPlayer().getLocation()); + fme.msg(TL.COMMAND_CHECKPOINT_SET); + return; + } else { + fme.msg(TL.COMMAND_CHECKPOINT_INVALIDLOCATION); + return; + } + } + if (fme.getFaction().getCheckpoint() == null) { + fme.msg(TL.COMMAND_CHECKPOINT_NOT_SET); + return; + } + FLocation checkLocation = new FLocation(fme.getFaction().getCheckpoint()); + Faction checkfaction = Board.getInstance().getFactionAt(checkLocation); - if (checkfaction.getId().equals(Factions.getInstance().getWilderness().getId()) || checkfaction.getId().equals(fme.getFaction().getId())) { - fme.msg(TL.COMMAND_CHECKPOINT_GO); - this.doWarmUp(WarmUpUtil.Warmup.CHECKPOINT, TL.WARMUPS_NOTIFY_TELEPORT, "Checkpoint", new Runnable() { - @Override - public void run() { - fme.getPlayer().teleport(fme.getFaction().getCheckpoint()); - } - }, this.p.getConfig().getLong("warmups.f-checkpoint", 0)); - } else { - fme.msg(TL.COMMAND_CHECKPOINT_CLAIMED); - } + if (checkfaction.getId().equals(Factions.getInstance().getWilderness().getId()) || checkfaction.getId().equals(fme.getFaction().getId())) { + fme.msg(TL.COMMAND_CHECKPOINT_GO); + this.doWarmUp(WarmUpUtil.Warmup.CHECKPOINT, TL.WARMUPS_NOTIFY_TELEPORT, "Checkpoint", new Runnable() { + @Override + public void run() { + fme.getPlayer().teleport(fme.getFaction().getCheckpoint()); + } + }, this.p.getConfig().getLong("warmups.f-checkpoint", 0)); + } else { + fme.msg(TL.COMMAND_CHECKPOINT_CLAIMED); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CHECKPOINT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CHECKPOINT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdChest.java b/src/main/java/com/massivecraft/factions/cmd/CmdChest.java index f007b99b..8fcb0d7a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdChest.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdChest.java @@ -9,47 +9,47 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdChest extends FCommand { - public CmdChest() { - this.aliases.add("chest"); - this.aliases.add("pv"); + public CmdChest() { + this.aliases.add("chest"); + this.aliases.add("pv"); - //this.requiredArgs.add(""); + //this.requiredArgs.add(""); - this.permission = Permission.CHEST.node; - this.disableOnLock = false; + this.permission = Permission.CHEST.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { + @Override + public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fchest.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - // This permission check is way too explicit but it's clean - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.CHEST); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "access chest"); - return; - } - } + if (!SavageFactions.plugin.getConfig().getBoolean("fchest.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + // This permission check is way too explicit but it's clean + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.CHEST); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "access chest"); + return; + } + } - me.openInventory(fme.getFaction().getChestInventory()); + me.openInventory(fme.getFaction().getChestInventory()); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_VAULT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_VAULT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java index f0e4077d..9fa20093 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java @@ -14,82 +14,82 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdClaim extends FCommand { - public CmdClaim() { - super(); - this.aliases.add("claim"); + public CmdClaim() { + super(); + this.aliases.add("claim"); - //this.requiredArgs.add(""); - this.optionalArgs.put("radius", "1"); - this.optionalArgs.put("faction", "your"); + //this.requiredArgs.add(""); + this.optionalArgs.put("radius", "1"); + this.optionalArgs.put("faction", "your"); - this.permission = Permission.CLAIM.node; - this.disableOnLock = true; + this.permission = Permission.CLAIM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // Read and validate input - int radius = this.argAsInt(0, 1); // Default to 1 - final Faction forFaction = this.argAsFaction(1, myFaction); // Default to own + @Override + public void perform() { + // Read and validate input + int radius = this.argAsInt(0, 1); // Default to 1 + final Faction forFaction = this.argAsFaction(1, myFaction); // Default to own - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "change faction territory"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "change faction territory"); + return; + } + } - if (forFaction.isWilderness()) { - CmdUnclaim cmdUnclaim = SavageFactions.plugin.cmdBase.cmdUnclaim; - cmdUnclaim.execute(sender, args.size() > 1 ? args.subList(0, 1) : args); - return; - } + if (forFaction.isWilderness()) { + CmdUnclaim cmdUnclaim = SavageFactions.plugin.cmdBase.cmdUnclaim; + cmdUnclaim.execute(sender, args.size() > 1 ? args.subList(0, 1) : args); + return; + } - if (radius < 1) { - msg(TL.COMMAND_CLAIM_INVALIDRADIUS); - return; - } + if (radius < 1) { + msg(TL.COMMAND_CLAIM_INVALIDRADIUS); + return; + } - if (radius < 2) { - // single chunk - fme.attemptClaim(forFaction, me.getLocation(), true); - } else { - // radius claim - if (!Permission.CLAIM_RADIUS.has(sender, false)) { - msg(TL.COMMAND_CLAIM_DENIED); - return; - } + if (radius < 2) { + // single chunk + fme.attemptClaim(forFaction, me.getLocation(), true); + } else { + // radius claim + if (!Permission.CLAIM_RADIUS.has(sender, false)) { + msg(TL.COMMAND_CLAIM_DENIED); + return; + } - new SpiralTask(new FLocation(me), radius) { - private final int limit = Conf.radiusClaimFailureLimit - 1; - private int failCount = 0; + new SpiralTask(new FLocation(me), radius) { + private final int limit = Conf.radiusClaimFailureLimit - 1; + private int failCount = 0; - @Override - public boolean work() { - boolean success = fme.attemptClaim(forFaction, this.currentLocation(), true); - if (success) { - failCount = 0; - } else if (failCount++ >= limit) { - this.stop(); - return false; - } + @Override + public boolean work() { + boolean success = fme.attemptClaim(forFaction, this.currentLocation(), true); + if (success) { + failCount = 0; + } else if (failCount++ >= limit) { + this.stop(); + return false; + } - return true; - } - }; - } - } + return true; + } + }; + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CLAIM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CLAIM_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java b/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java index feee8c76..2b2bf2b3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java @@ -6,35 +6,35 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdClaimAt extends FCommand { - public CmdClaimAt() { - super(); - this.aliases.add("claimat"); + public CmdClaimAt() { + super(); + this.aliases.add("claimat"); - this.requiredArgs.add("world"); - this.requiredArgs.add("x"); - this.requiredArgs.add("z"); + this.requiredArgs.add("world"); + this.requiredArgs.add("x"); + this.requiredArgs.add("z"); - this.permission = Permission.CLAIMAT.node; - this.disableOnLock = true; + this.permission = Permission.CLAIMAT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - int x = argAsInt(1); - int z = argAsInt(2); - FLocation location = new FLocation(argAsString(0), x, z); - fme.attemptClaim(myFaction, location, true); - } + @Override + public void perform() { + int x = argAsInt(1); + int z = argAsInt(2); + FLocation location = new FLocation(argAsString(0), x, z); + fme.attemptClaim(myFaction, location, true); + } - @Override - public TL getUsageTranslation() { - return null; - } + @Override + public TL getUsageTranslation() { + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java b/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java index e3507db5..fad5124f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java @@ -9,70 +9,70 @@ import org.bukkit.block.BlockFace; public class CmdClaimLine extends FCommand { - public static final BlockFace[] axis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST}; + public static final BlockFace[] axis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST}; - public CmdClaimLine() { + public CmdClaimLine() { - // Aliases - this.aliases.add("claimline"); - this.aliases.add("cl"); + // Aliases + this.aliases.add("claimline"); + this.aliases.add("cl"); - // Args - this.optionalArgs.put("amount", "1"); - this.optionalArgs.put("direction", "facing"); - this.optionalArgs.put("faction", "you"); + // Args + this.optionalArgs.put("amount", "1"); + this.optionalArgs.put("direction", "facing"); + this.optionalArgs.put("faction", "you"); - this.permission = Permission.CLAIM_LINE.node; - this.disableOnLock = true; + this.permission = Permission.CLAIM_LINE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // Args - Integer amount = this.argAsInt(0, 1); // Default to 1 + @Override + public void perform() { + // Args + Integer amount = this.argAsInt(0, 1); // Default to 1 - if (amount > Conf.lineClaimLimit) { - fme.msg(TL.COMMAND_CLAIMLINE_ABOVEMAX, Conf.lineClaimLimit); - return; - } + if (amount > Conf.lineClaimLimit) { + fme.msg(TL.COMMAND_CLAIMLINE_ABOVEMAX, Conf.lineClaimLimit); + return; + } - String direction = this.argAsString(1); - BlockFace blockFace; + String direction = this.argAsString(1); + BlockFace blockFace; - if (direction == null) { - blockFace = axis[Math.round(me.getLocation().getYaw() / 90f) & 0x3]; - } else if (direction.equalsIgnoreCase("north")) { - blockFace = BlockFace.NORTH; - } else if (direction.equalsIgnoreCase("east")) { - blockFace = BlockFace.EAST; - } else if (direction.equalsIgnoreCase("south")) { - blockFace = BlockFace.SOUTH; - } else if (direction.equalsIgnoreCase("west")) { - blockFace = BlockFace.WEST; - } else { - fme.msg(TL.COMMAND_CLAIMLINE_NOTVALID, direction); - return; - } + if (direction == null) { + blockFace = axis[Math.round(me.getLocation().getYaw() / 90f) & 0x3]; + } else if (direction.equalsIgnoreCase("north")) { + blockFace = BlockFace.NORTH; + } else if (direction.equalsIgnoreCase("east")) { + blockFace = BlockFace.EAST; + } else if (direction.equalsIgnoreCase("south")) { + blockFace = BlockFace.SOUTH; + } else if (direction.equalsIgnoreCase("west")) { + blockFace = BlockFace.WEST; + } else { + fme.msg(TL.COMMAND_CLAIMLINE_NOTVALID, direction); + return; + } - final Faction forFaction = this.argAsFaction(2, myFaction); - Location location = me.getLocation(); + final Faction forFaction = this.argAsFaction(2, myFaction); + Location location = me.getLocation(); - // TODO: make this a task like claiming a radius? - for (int i = 0; i < amount; i++) { - fme.attemptClaim(forFaction, location, true); - location = location.add(blockFace.getModX() * 16, 0, blockFace.getModZ() * 16); - } - } + // TODO: make this a task like claiming a radius? + for (int i = 0; i < amount; i++) { + fme.attemptClaim(forFaction, location, true); + location = location.add(blockFace.getModX() * 16, 0, blockFace.getModZ() * 16); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CLAIMLINE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CLAIMLINE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java b/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java index f1aaefca..926df953 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java @@ -10,82 +10,82 @@ import mkremins.fanciful.FancyMessage; import org.bukkit.ChatColor; public class CmdColeader extends FCommand { - public CmdColeader() { - super(); - this.aliases.add("co"); - this.aliases.add("setcoleader"); - this.aliases.add("coleader"); - this.aliases.add("setco"); + public CmdColeader() { + super(); + this.aliases.add("co"); + this.aliases.add("setcoleader"); + this.aliases.add("coleader"); + this.aliases.add("setco"); - this.optionalArgs.put("player name", "name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.COLEADER.node; - this.disableOnLock = true; + this.permission = Permission.COLEADER.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = true; - } + senderMustBePlayer = false; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = true; + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (you == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_COLEADER_CANDIDATES.toString()).color(ChatColor.GOLD); - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); - } - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (you == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_COLEADER_CANDIDATES.toString()).color(ChatColor.GOLD); + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); + } + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); + } - sendFancyMessage(msg); - return; - } + sendFancyMessage(msg); + return; + } - boolean permAny = Permission.COLEADER_ANY.has(sender, false); - Faction targetFaction = you.getFaction(); + boolean permAny = Permission.COLEADER_ANY.has(sender, false); + Faction targetFaction = you.getFaction(); - if (targetFaction != myFaction && !permAny) { - msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); - return; - } + if (targetFaction != myFaction && !permAny) { + msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); + return; + } - if (fme != null && fme.getRole() != Role.LEADER && !permAny) { - msg(TL.COMMAND_COLEADER_NOTADMIN); - return; - } + if (fme != null && fme.getRole() != Role.LEADER && !permAny) { + msg(TL.COMMAND_COLEADER_NOTADMIN); + return; + } - if (you == fme && !permAny) { - msg(TL.COMMAND_COLEADER_SELF); - return; - } + if (you == fme && !permAny) { + msg(TL.COMMAND_COLEADER_SELF); + return; + } - if (you.getRole() == Role.LEADER) { - msg(TL.COMMAND_COLEADER_TARGETISADMIN); - return; - } + if (you.getRole() == Role.LEADER) { + msg(TL.COMMAND_COLEADER_TARGETISADMIN); + return; + } - if (you.getRole() == Role.COLEADER) { - // Revoke - you.setRole(Role.MODERATOR); - targetFaction.msg(TL.COMMAND_COLEADER_REVOKED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_COLEADER_REVOKES, you.describeTo(fme, true)); - } else { - // Give - you.setRole(Role.COLEADER); - targetFaction.msg(TL.COMMAND_COLEADER_PROMOTED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_COLEADER_PROMOTES, you.describeTo(fme, true)); - } - } + if (you.getRole() == Role.COLEADER) { + // Revoke + you.setRole(Role.MODERATOR); + targetFaction.msg(TL.COMMAND_COLEADER_REVOKED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_COLEADER_REVOKES, you.describeTo(fme, true)); + } else { + // Give + you.setRole(Role.COLEADER); + targetFaction.msg(TL.COMMAND_COLEADER_PROMOTED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_COLEADER_PROMOTES, you.describeTo(fme, true)); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_COLEADER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_COLEADER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java b/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java index 6717b53e..3d65283e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java @@ -16,234 +16,234 @@ import java.util.Set; public class CmdConfig extends FCommand { - private static HashMap properFieldNames = new HashMap<>(); + private static HashMap properFieldNames = new HashMap<>(); - public CmdConfig() { - super(); - this.aliases.add("config"); + public CmdConfig() { + super(); + this.aliases.add("config"); - this.requiredArgs.add("setting"); - this.requiredArgs.add("value"); - this.errorOnToManyArgs = false; + this.requiredArgs.add("setting"); + this.requiredArgs.add("value"); + this.errorOnToManyArgs = false; - this.permission = Permission.CONFIG.node; - this.disableOnLock = true; + this.permission = Permission.CONFIG.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // store a lookup map of lowercase field names paired with proper capitalization field names - // that way, if the person using this command messes up the capitalization, we can fix that - if (properFieldNames.isEmpty()) { - Field[] fields = Conf.class.getDeclaredFields(); - for (Field field : fields) { - properFieldNames.put(field.getName().toLowerCase(), field.getName()); - } - } + @Override + public void perform() { + // store a lookup map of lowercase field names paired with proper capitalization field names + // that way, if the person using this command messes up the capitalization, we can fix that + if (properFieldNames.isEmpty()) { + Field[] fields = Conf.class.getDeclaredFields(); + for (Field field : fields) { + properFieldNames.put(field.getName().toLowerCase(), field.getName()); + } + } - String field = this.argAsString(0).toLowerCase(); - if (field.startsWith("\"") && field.endsWith("\"")) { - field = field.substring(1, field.length() - 1); - } - String fieldName = properFieldNames.get(field); + String field = this.argAsString(0).toLowerCase(); + if (field.startsWith("\"") && field.endsWith("\"")) { + field = field.substring(1, field.length() - 1); + } + String fieldName = properFieldNames.get(field); - if (fieldName == null || fieldName.isEmpty()) { - msg(TL.COMMAND_CONFIG_NOEXIST, field); - return; - } + if (fieldName == null || fieldName.isEmpty()) { + msg(TL.COMMAND_CONFIG_NOEXIST, field); + return; + } - String success; + String success; - StringBuilder value = new StringBuilder(args.get(1)); - for (int i = 2; i < args.size(); i++) { - value.append(' ').append(args.get(i)); - } + StringBuilder value = new StringBuilder(args.get(1)); + for (int i = 2; i < args.size(); i++) { + value.append(' ').append(args.get(i)); + } - try { - Field target = Conf.class.getField(fieldName); + try { + Field target = Conf.class.getField(fieldName); - // boolean - if (target.getType() == boolean.class) { - boolean targetValue = this.strAsBool(value.toString()); - target.setBoolean(null, targetValue); + // boolean + if (target.getType() == boolean.class) { + boolean targetValue = this.strAsBool(value.toString()); + target.setBoolean(null, targetValue); - if (targetValue) { - success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_TRUE.toString(); - } else { - success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_FALSE.toString(); - } - } + if (targetValue) { + success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_TRUE.toString(); + } else { + success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_FALSE.toString(); + } + } - // int - else if (target.getType() == int.class) { - try { - int intVal = Integer.parseInt(value.toString()); - target.setInt(null, intVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + intVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_INTREQUIRED.format(fieldName)); - return; - } - } + // int + else if (target.getType() == int.class) { + try { + int intVal = Integer.parseInt(value.toString()); + target.setInt(null, intVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + intVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_INTREQUIRED.format(fieldName)); + return; + } + } - // long - else if (target.getType() == long.class) { - try { - long longVal = Long.parseLong(value.toString()); - target.setLong(null, longVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + longVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_LONGREQUIRED.format(fieldName)); - return; - } - } + // long + else if (target.getType() == long.class) { + try { + long longVal = Long.parseLong(value.toString()); + target.setLong(null, longVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + longVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_LONGREQUIRED.format(fieldName)); + return; + } + } - // double - else if (target.getType() == double.class) { - try { - double doubleVal = Double.parseDouble(value.toString()); - target.setDouble(null, doubleVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + doubleVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_DOUBLEREQUIRED.format(fieldName)); - return; - } - } + // double + else if (target.getType() == double.class) { + try { + double doubleVal = Double.parseDouble(value.toString()); + target.setDouble(null, doubleVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + doubleVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_DOUBLEREQUIRED.format(fieldName)); + return; + } + } - // float - else if (target.getType() == float.class) { - try { - float floatVal = Float.parseFloat(value.toString()); - target.setFloat(null, floatVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + floatVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_FLOATREQUIRED.format(fieldName)); - return; - } - } + // float + else if (target.getType() == float.class) { + try { + float floatVal = Float.parseFloat(value.toString()); + target.setFloat(null, floatVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + floatVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_FLOATREQUIRED.format(fieldName)); + return; + } + } - // String - else if (target.getType() == String.class) { - target.set(null, value.toString()); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + value + "\"."; - } + // String + else if (target.getType() == String.class) { + target.set(null, value.toString()); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + value + "\"."; + } - // ChatColor - else if (target.getType() == ChatColor.class) { - ChatColor newColor = null; - try { - newColor = ChatColor.valueOf(value.toString().toUpperCase()); - } catch (IllegalArgumentException ex) { + // ChatColor + else if (target.getType() == ChatColor.class) { + ChatColor newColor = null; + try { + newColor = ChatColor.valueOf(value.toString().toUpperCase()); + } catch (IllegalArgumentException ex) { - } - if (newColor == null) { - sendMessage(TL.COMMAND_CONFIG_INVALID_COLOUR.format(fieldName, value.toString().toUpperCase())); - return; - } - target.set(null, newColor); - success = "\"" + fieldName + TL.COMMAND_CONFIG_COLOURSET.toString() + value.toString().toUpperCase() + "\"."; - } + } + if (newColor == null) { + sendMessage(TL.COMMAND_CONFIG_INVALID_COLOUR.format(fieldName, value.toString().toUpperCase())); + return; + } + target.set(null, newColor); + success = "\"" + fieldName + TL.COMMAND_CONFIG_COLOURSET.toString() + value.toString().toUpperCase() + "\"."; + } - // Set or other parameterized collection - else if (target.getGenericType() instanceof ParameterizedType) { - ParameterizedType targSet = (ParameterizedType) target.getGenericType(); - Type innerType = targSet.getActualTypeArguments()[0]; + // Set or other parameterized collection + else if (target.getGenericType() instanceof ParameterizedType) { + ParameterizedType targSet = (ParameterizedType) target.getGenericType(); + Type innerType = targSet.getActualTypeArguments()[0]; - // not a Set, somehow, and that should be the only collection we're using in Conf.java - if (targSet.getRawType() != Set.class) { - sendMessage(TL.COMMAND_CONFIG_INVALID_COLLECTION.format(fieldName)); - return; - } + // not a Set, somehow, and that should be the only collection we're using in Conf.java + if (targSet.getRawType() != Set.class) { + sendMessage(TL.COMMAND_CONFIG_INVALID_COLLECTION.format(fieldName)); + return; + } - // Set - else if (innerType == Material.class) { - Material newMat = null; - try { - newMat = Material.valueOf(value.toString().toUpperCase()); - } catch (IllegalArgumentException ex) { + // Set + else if (innerType == Material.class) { + Material newMat = null; + try { + newMat = Material.valueOf(value.toString().toUpperCase()); + } catch (IllegalArgumentException ex) { - } - if (newMat == null) { - sendMessage(TL.COMMAND_CONFIG_INVALID_MATERIAL.format(fieldName, value.toString().toUpperCase())); - return; - } + } + if (newMat == null) { + sendMessage(TL.COMMAND_CONFIG_INVALID_MATERIAL.format(fieldName, value.toString().toUpperCase())); + return; + } - @SuppressWarnings("unchecked") Set matSet = (Set) target.get(null); + @SuppressWarnings("unchecked") Set matSet = (Set) target.get(null); - // Material already present, so remove it - if (matSet.contains(newMat)) { - matSet.remove(newMat); - target.set(null, matSet); - success = TL.COMMAND_CONFIG_MATERIAL_REMOVED.format(fieldName, value.toString().toUpperCase()); - } - // Material not present yet, add it - else { - matSet.add(newMat); - target.set(null, matSet); - success = TL.COMMAND_CONFIG_MATERIAL_ADDED.format(fieldName, value.toString().toUpperCase()); - } - } + // Material already present, so remove it + if (matSet.contains(newMat)) { + matSet.remove(newMat); + target.set(null, matSet); + success = TL.COMMAND_CONFIG_MATERIAL_REMOVED.format(fieldName, value.toString().toUpperCase()); + } + // Material not present yet, add it + else { + matSet.add(newMat); + target.set(null, matSet); + success = TL.COMMAND_CONFIG_MATERIAL_ADDED.format(fieldName, value.toString().toUpperCase()); + } + } - // Set - else if (innerType == String.class) { - @SuppressWarnings("unchecked") Set stringSet = (Set) target.get(null); + // Set + else if (innerType == String.class) { + @SuppressWarnings("unchecked") Set stringSet = (Set) target.get(null); - // String already present, so remove it - if (stringSet.contains(value.toString())) { - stringSet.remove(value.toString()); - target.set(null, stringSet); - success = TL.COMMAND_CONFIG_SET_REMOVED.format(fieldName, value.toString()); - } - // String not present yet, add it - else { - stringSet.add(value.toString()); - target.set(null, stringSet); - success = TL.COMMAND_CONFIG_SET_ADDED.format(fieldName, value.toString()); - } - } + // String already present, so remove it + if (stringSet.contains(value.toString())) { + stringSet.remove(value.toString()); + target.set(null, stringSet); + success = TL.COMMAND_CONFIG_SET_REMOVED.format(fieldName, value.toString()); + } + // String not present yet, add it + else { + stringSet.add(value.toString()); + target.set(null, stringSet); + success = TL.COMMAND_CONFIG_SET_ADDED.format(fieldName, value.toString()); + } + } - // Set of unknown type - else { - sendMessage(TL.COMMAND_CONFIG_INVALID_TYPESET.format(fieldName)); - return; - } - } + // Set of unknown type + else { + sendMessage(TL.COMMAND_CONFIG_INVALID_TYPESET.format(fieldName)); + return; + } + } - // unknown type - else { - sendMessage(TL.COMMAND_CONFIG_ERROR_TYPE.format(fieldName, target.getClass().getName())); - return; - } - } catch (NoSuchFieldException ex) { - sendMessage(TL.COMMAND_CONFIG_ERROR_MATCHING.format(fieldName)); - return; - } catch (IllegalAccessException ex) { - sendMessage(TL.COMMAND_CONFIG_ERROR_SETTING.format(fieldName, value.toString())); - return; - } + // unknown type + else { + sendMessage(TL.COMMAND_CONFIG_ERROR_TYPE.format(fieldName, target.getClass().getName())); + return; + } + } catch (NoSuchFieldException ex) { + sendMessage(TL.COMMAND_CONFIG_ERROR_MATCHING.format(fieldName)); + return; + } catch (IllegalAccessException ex) { + sendMessage(TL.COMMAND_CONFIG_ERROR_SETTING.format(fieldName, value.toString())); + return; + } - if (!success.isEmpty()) { - if (sender instanceof Player) { - sendMessage(success); - SavageFactions.plugin.log(success + TL.COMMAND_CONFIG_LOG.format((Player) sender)); - } else // using SavageFactions.plugin.log() instead of sendMessage if run from server console so that "[Factions v#.#.#]" is prepended in server log - { - SavageFactions.plugin.log(success); - } - } - // save change to disk - Conf.save(); - } + if (!success.isEmpty()) { + if (sender instanceof Player) { + sendMessage(success); + SavageFactions.plugin.log(success + TL.COMMAND_CONFIG_LOG.format((Player) sender)); + } else // using SavageFactions.plugin.log() instead of sendMessage if run from server console so that "[Factions v#.#.#]" is prepended in server log + { + SavageFactions.plugin.log(success); + } + } + // save change to disk + Conf.save(); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CONFIG_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CONFIG_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java b/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java index bc923ec6..caf90c96 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java @@ -9,39 +9,39 @@ import org.bukkit.command.ConsoleCommandSender; public class CmdConvert extends FCommand { - public CmdConvert() { - this.aliases.add("convert"); + public CmdConvert() { + this.aliases.add("convert"); - this.permission = Permission.CONVERT.node; + this.permission = Permission.CONVERT.node; - this.requiredArgs.add("[MYSQL|JSON]"); - } + this.requiredArgs.add("[MYSQL|JSON]"); + } - @Override - public void perform() { - if (!(this.sender instanceof ConsoleCommandSender)) { - this.sender.sendMessage(TL.GENERIC_CONSOLEONLY.toString()); - } - Backend nb = Backend.valueOf(this.argAsString(0).toUpperCase()); - if (nb == Conf.backEnd) { - this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_RUNNING.toString()); - return; - } - switch (nb) { - case JSON: - FactionsJSON.convertTo(); - break; - default: - this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_INVALID.toString()); - return; + @Override + public void perform() { + if (!(this.sender instanceof ConsoleCommandSender)) { + this.sender.sendMessage(TL.GENERIC_CONSOLEONLY.toString()); + } + Backend nb = Backend.valueOf(this.argAsString(0).toUpperCase()); + if (nb == Conf.backEnd) { + this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_RUNNING.toString()); + return; + } + switch (nb) { + case JSON: + FactionsJSON.convertTo(); + break; + default: + this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_INVALID.toString()); + return; - } - Conf.backEnd = nb; - } + } + Conf.backEnd = nb; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CONVERT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CONVERT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java b/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java index e6b3bad3..506ad1b0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java @@ -7,36 +7,36 @@ import org.bukkit.Location; public class CmdCoords extends FCommand { - public CmdCoords() { - super(); - this.aliases.add("coords"); - this.aliases.add("coord"); + public CmdCoords() { + super(); + this.aliases.add("coords"); + this.aliases.add("coord"); - this.permission = Permission.COORD.node; - this.disableOnLock = true; + this.permission = Permission.COORD.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Location location = fme.getPlayer().getLocation(); - String message = TL.COMMAND_COORDS_MESSAGE.toString().replace("{player}", fme.getPlayer().getDisplayName()).replace("{x}", (int) location.getX() + "") - .replace("{y}", (int) location.getY() + "").replace("{z}", (int) location.getZ() + "").replace("{world}", location.getWorld().getName()); - for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { - fPlayer.sendMessage(message); - } - } + @Override + public void perform() { + Location location = fme.getPlayer().getLocation(); + String message = TL.COMMAND_COORDS_MESSAGE.toString().replace("{player}", fme.getPlayer().getDisplayName()).replace("{x}", (int) location.getX() + "") + .replace("{y}", (int) location.getY() + "").replace("{z}", (int) location.getZ() + "").replace("{world}", location.getWorld().getName()); + for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { + fPlayer.sendMessage(message); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_COORDS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_COORDS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java index ad7455b1..48140931 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java @@ -14,105 +14,105 @@ import java.util.ArrayList; public class CmdCreate extends FCommand { - public CmdCreate() { - super(); - this.aliases.add("create"); + public CmdCreate() { + super(); + this.aliases.add("create"); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); - this.permission = Permission.CREATE.node; - this.disableOnLock = true; + this.permission = Permission.CREATE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - String tag = this.argAsString(0); + @Override + public void perform() { + String tag = this.argAsString(0); - if (fme.hasFaction()) { - msg(TL.COMMAND_CREATE_MUSTLEAVE); - return; - } + if (fme.hasFaction()) { + msg(TL.COMMAND_CREATE_MUSTLEAVE); + return; + } - if (Factions.getInstance().isTagTaken(tag)) { - msg(TL.COMMAND_CREATE_INUSE); - return; - } + if (Factions.getInstance().isTagTaken(tag)) { + msg(TL.COMMAND_CREATE_INUSE); + return; + } - ArrayList tagValidationErrors = MiscUtil.validateTag(tag); - if (tagValidationErrors.size() > 0) { - sendMessage(tagValidationErrors); - return; - } + ArrayList tagValidationErrors = MiscUtil.validateTag(tag); + if (tagValidationErrors.size() > 0) { + sendMessage(tagValidationErrors); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (!canAffordCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (!canAffordCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE.toString())) { + return; + } - // trigger the faction creation event (cancellable) - FactionCreateEvent createEvent = new FactionCreateEvent(me, tag); - Bukkit.getServer().getPluginManager().callEvent(createEvent); - if (createEvent.isCancelled()) { - return; - } + // trigger the faction creation event (cancellable) + FactionCreateEvent createEvent = new FactionCreateEvent(me, tag); + Bukkit.getServer().getPluginManager().callEvent(createEvent); + if (createEvent.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (!payForCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE, TL.COMMAND_CREATE_FORCREATE)) { - return; - } + // then make 'em pay (if applicable) + if (!payForCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE, TL.COMMAND_CREATE_FORCREATE)) { + return; + } - Faction faction = Factions.getInstance().createFaction(); + Faction faction = Factions.getInstance().createFaction(); - // TODO: Why would this even happen??? Auto increment clash?? - if (faction == null) { - msg(TL.COMMAND_CREATE_ERROR); - return; - } + // TODO: Why would this even happen??? Auto increment clash?? + if (faction == null) { + msg(TL.COMMAND_CREATE_ERROR); + return; + } - // finish setting up the Faction - faction.setTag(tag); + // finish setting up the Faction + faction.setTag(tag); - // trigger the faction join event for the creator - FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE); - Bukkit.getServer().getPluginManager().callEvent(joinEvent); - // join event cannot be cancelled or you'll have an empty faction + // trigger the faction join event for the creator + FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE); + Bukkit.getServer().getPluginManager().callEvent(joinEvent); + // join event cannot be cancelled or you'll have an empty faction - // finish setting up the FPlayer - fme.setFaction(faction); - // We should consider adding the role just AFTER joining the faction. - // That way we don't have to mess up deleting more stuff. - // And prevent the user from being returned to NORMAL after deleting his old faction. - fme.setRole(Role.LEADER); - if (SavageFactions.plugin.getConfig().getBoolean("faction-creation-broadcast", true)) { - for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { - follower.msg(TL.COMMAND_CREATE_CREATED, fme.describeTo(follower, true), faction.getTag(follower)); - } - } - msg(TL.COMMAND_CREATE_YOUSHOULD, p.cmdBase.cmdDescription.getUseageTemplate()); + // finish setting up the FPlayer + fme.setFaction(faction); + // We should consider adding the role just AFTER joining the faction. + // That way we don't have to mess up deleting more stuff. + // And prevent the user from being returned to NORMAL after deleting his old faction. + fme.setRole(Role.LEADER); + if (SavageFactions.plugin.getConfig().getBoolean("faction-creation-broadcast", true)) { + for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { + follower.msg(TL.COMMAND_CREATE_CREATED, fme.describeTo(follower, true), faction.getTag(follower)); + } + } + msg(TL.COMMAND_CREATE_YOUSHOULD, p.cmdBase.cmdDescription.getUseageTemplate()); - if (Conf.logFactionCreate) { - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CREATE_CREATEDLOG.toString() + tag); - } - if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - this.fme.msg(TL.COMMAND_PAYPALSET_CREATED); - } - if (Conf.useCustomDefaultPermissions) { - faction.setDefaultPerms(); - if (Conf.usePermissionHints) - this.fme.msg(TL.COMMAND_HINT_PERMISSION); - } - } + if (Conf.logFactionCreate) { + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CREATE_CREATEDLOG.toString() + tag); + } + if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + this.fme.msg(TL.COMMAND_PAYPALSET_CREATED); + } + if (Conf.useCustomDefaultPermissions) { + faction.setDefaultPerms(); + if (Conf.usePermissionHints) + this.fme.msg(TL.COMMAND_HINT_PERMISSION); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CREATE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CREATE_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java b/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java index 62c2b72e..51948c2c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java @@ -13,62 +13,62 @@ import org.bukkit.ChatColor; public class CmdDeinvite extends FCommand { - public CmdDeinvite() { - super(); - this.aliases.add("deinvite"); - this.aliases.add("deinv"); + public CmdDeinvite() { + super(); + this.aliases.add("deinvite"); + this.aliases.add("deinv"); - this.optionalArgs.put("player name", "name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.DEINVITE.node; - this.disableOnLock = true; + this.permission = Permission.DEINVITE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.INVITE); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); - return; - } - } - if (you == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_DEINVITE_CANDEINVITE.toString()).color(ChatColor.GOLD); - for (String id : myFaction.getInvites()) { - FPlayer fp = FPlayers.getInstance().getById(id); - String name = fp != null ? fp.getName() : id; - msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_DEINVITE_CLICKTODEINVITE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); - } - sendFancyMessage(msg); - return; - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.INVITE); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); + return; + } + } + if (you == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_DEINVITE_CANDEINVITE.toString()).color(ChatColor.GOLD); + for (String id : myFaction.getInvites()) { + FPlayer fp = FPlayers.getInstance().getById(id); + String name = fp != null ? fp.getName() : id; + msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_DEINVITE_CLICKTODEINVITE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); + } + sendFancyMessage(msg); + return; + } - if (you.getFaction() == myFaction) { - msg(TL.COMMAND_DEINVITE_ALREADYMEMBER, you.getName(), myFaction.getTag()); - msg(TL.COMMAND_DEINVITE_MIGHTWANT, p.cmdBase.cmdKick.getUseageTemplate(false)); - return; - } + if (you.getFaction() == myFaction) { + msg(TL.COMMAND_DEINVITE_ALREADYMEMBER, you.getName(), myFaction.getTag()); + msg(TL.COMMAND_DEINVITE_MIGHTWANT, p.cmdBase.cmdKick.getUseageTemplate(false)); + return; + } - myFaction.deinvite(you); + myFaction.deinvite(you); - you.msg(TL.COMMAND_DEINVITE_REVOKED, fme.describeTo(you), myFaction.describeTo(you)); + you.msg(TL.COMMAND_DEINVITE_REVOKED, fme.describeTo(you), myFaction.describeTo(you)); - myFaction.msg(TL.COMMAND_DEINVITE_REVOKES, fme.describeTo(myFaction), you.describeTo(myFaction)); - } + myFaction.msg(TL.COMMAND_DEINVITE_REVOKES, fme.describeTo(myFaction), you.describeTo(myFaction)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DEINVITE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DEINVITE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java b/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java index 6f592b3f..1249266f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java @@ -7,39 +7,39 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdDelFWarp extends FCommand { - public CmdDelFWarp() { - super(); - this.aliases.add("delwarp"); - this.aliases.add("dw"); - this.aliases.add("deletewarp"); - this.requiredArgs.add("warp name"); - this.senderMustBeMember = true; - this.senderMustBeModerator = true; - this.senderMustBePlayer = true; - this.permission = Permission.SETWARP.node; + public CmdDelFWarp() { + super(); + this.aliases.add("delwarp"); + this.aliases.add("dw"); + this.aliases.add("deletewarp"); + this.requiredArgs.add("warp name"); + this.senderMustBeMember = true; + this.senderMustBeModerator = true; + this.senderMustBePlayer = true; + this.permission = Permission.SETWARP.node; - } + } - @Override - public void perform() { - String warp = argAsString(0); - if (myFaction.isWarp(warp)) { - if (!transact(fme)) { - return; - } - myFaction.removeWarp(warp); - fme.msg(TL.COMMAND_DELFWARP_DELETED, warp); - } else { - fme.msg(TL.COMMAND_DELFWARP_INVALID, warp); - } - } + @Override + public void perform() { + String warp = argAsString(0); + if (myFaction.isWarp(warp)) { + if (!transact(fme)) { + return; + } + myFaction.removeWarp(warp); + fme.msg(TL.COMMAND_DELFWARP_DELETED, warp); + } else { + fme.msg(TL.COMMAND_DELFWARP_INVALID, warp); + } + } - private boolean transact(FPlayer player) { - return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.delwarp", 5), TL.COMMAND_DELFWARP_TODELETE.toString(), TL.COMMAND_DELFWARP_FORDELETE.toString()); - } + private boolean transact(FPlayer player) { + return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.delwarp", 5), TL.COMMAND_DELFWARP_TODELETE.toString(), TL.COMMAND_DELFWARP_FORDELETE.toString()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DELFWARP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DELFWARP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java b/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java index 2890d2f5..0378de1c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java @@ -2,8 +2,8 @@ package com.massivecraft.factions.cmd; public class CmdDemote extends FPromoteCommand { - public CmdDemote() { - aliases.add("demote"); - this.relative = -1; - } + public CmdDemote() { + aliases.add("demote"); + this.relative = -1; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java b/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java index a0e6d00a..fe272298 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java @@ -9,53 +9,53 @@ import com.massivecraft.factions.zcore.util.TextUtil; public class CmdDescription extends FCommand { - public CmdDescription() { - super(); - this.aliases.add("desc"); - this.aliases.add("description"); + public CmdDescription() { + super(); + this.aliases.add("desc"); + this.aliases.add("description"); - this.requiredArgs.add("desc"); - this.errorOnToManyArgs = false; - //this.optionalArgs + this.requiredArgs.add("desc"); + this.errorOnToManyArgs = false; + //this.optionalArgs - this.permission = Permission.DESCRIPTION.node; - this.disableOnLock = true; + this.permission = Permission.DESCRIPTION.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostDesc, TL.COMMAND_DESCRIPTION_TOCHANGE, TL.COMMAND_DESCRIPTION_FORCHANGE)) { - return; - } + @Override + public void perform() { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostDesc, TL.COMMAND_DESCRIPTION_TOCHANGE, TL.COMMAND_DESCRIPTION_FORCHANGE)) { + return; + } - // since "&" color tags seem to work even through plain old FPlayer.sendMessage() for some reason, we need to break those up - // And replace all the % because it messes with string formatting and this is easy way around that. - myFaction.setDescription(TextUtil.implode(args, " ").replaceAll("%", "").replaceAll("(&([a-f0-9klmnor]))", "& $2")); + // since "&" color tags seem to work even through plain old FPlayer.sendMessage() for some reason, we need to break those up + // And replace all the % because it messes with string formatting and this is easy way around that. + myFaction.setDescription(TextUtil.implode(args, " ").replaceAll("%", "").replaceAll("(&([a-f0-9klmnor]))", "& $2")); - if (!Conf.broadcastDescriptionChanges) { - fme.msg(TL.COMMAND_DESCRIPTION_CHANGED, myFaction.describeTo(fme)); - fme.sendMessage(myFaction.getDescription()); - return; - } + if (!Conf.broadcastDescriptionChanges) { + fme.msg(TL.COMMAND_DESCRIPTION_CHANGED, myFaction.describeTo(fme)); + fme.sendMessage(myFaction.getDescription()); + return; + } - // Broadcast the description to everyone - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg(TL.COMMAND_DESCRIPTION_CHANGES, myFaction.describeTo(fplayer)); - fplayer.sendMessage(myFaction.getDescription()); // players can inject "&" or "`" or "" or whatever in their description; &k is particularly interesting looking - } - } + // Broadcast the description to everyone + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg(TL.COMMAND_DESCRIPTION_CHANGES, myFaction.describeTo(fplayer)); + fplayer.sendMessage(myFaction.getDescription()); // players can inject "&" or "`" or "" or whatever in their description; &k is particularly interesting looking + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DESCRIPTION_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DESCRIPTION_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java b/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java index 2ad00c4d..2f806816 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java @@ -16,99 +16,99 @@ import java.util.HashMap; public class CmdDisband extends FCommand { - private static HashMap disbandMap = new HashMap<>(); + private static HashMap disbandMap = new HashMap<>(); - public CmdDisband() { - super(); - this.aliases.add("disband"); + public CmdDisband() { + super(); + this.aliases.add("disband"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction tag", "yours"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction tag", "yours"); - this.permission = Permission.DISBAND.node; - this.disableOnLock = true; + this.permission = Permission.DISBAND.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - // The faction, default to your own.. but null if console sender. - Faction faction = this.argAsFaction(0, fme == null ? null : myFaction); - if (faction == null) { - return; - } + @Override + public void perform() { + // The faction, default to your own.. but null if console sender. + Faction faction = this.argAsFaction(0, fme == null ? null : myFaction); + if (faction == null) { + return; + } - boolean isMyFaction = fme != null && faction == myFaction; + boolean isMyFaction = fme != null && faction == myFaction; - if (isMyFaction) { - if (!assertMinRole(Role.LEADER)) { - return; - } - } else { - if (!Permission.DISBAND_ANY.has(sender, true)) { - return; - } - } + if (isMyFaction) { + if (!assertMinRole(Role.LEADER)) { + return; + } + } else { + if (!Permission.DISBAND_ANY.has(sender, true)) { + return; + } + } - if (!fme.isAdminBypassing()) { - Access access = faction.getAccess(fme, PermissableAction.DISBAND); - if (fme.getRole() != Role.LEADER && faction.getFPlayerLeader() != fme && access != Access.ALLOW) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "disband " + faction.getTag()); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = faction.getAccess(fme, PermissableAction.DISBAND); + if (fme.getRole() != Role.LEADER && faction.getFPlayerLeader() != fme && access != Access.ALLOW) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "disband " + faction.getTag()); + return; + } + } - if (!faction.isNormal()) { - msg(TL.COMMAND_DISBAND_IMMUTABLE.toString()); - return; - } - if (faction.isPermanent()) { - msg(TL.COMMAND_DISBAND_MARKEDPERMANENT.toString()); - return; - } + if (!faction.isNormal()) { + msg(TL.COMMAND_DISBAND_IMMUTABLE.toString()); + return; + } + if (faction.isPermanent()) { + msg(TL.COMMAND_DISBAND_MARKEDPERMANENT.toString()); + return; + } - // check for tnt before disbanding. + // check for tnt before disbanding. - if (!disbandMap.containsKey(me.getUniqueId().toString()) && faction.getTnt() > 0) { - msg(TL.COMMAND_DISBAND_CONFIRM.toString().replace("{tnt}", faction.getTnt() + "")); - disbandMap.put(me.getUniqueId().toString(), faction.getId()); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - disbandMap.remove(me.getUniqueId().toString()); - } - }, 200L); - } else if (faction.getId().equals(disbandMap.get(me.getUniqueId().toString())) || faction.getTnt() == 0) { - if (SavageFactions.plugin.getConfig().getBoolean("faction-disband-broadcast", true)) { - for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { - String amountString = senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(follower); - UtilFly.checkFly(this.fme, Board.getInstance().getFactionAt(new FLocation(follower))); - if (follower.getFaction() == faction) { - follower.msg(TL.COMMAND_DISBAND_BROADCAST_YOURS, amountString); - } else { - follower.msg(TL.COMMAND_DISBAND_BROADCAST_NOTYOURS, amountString, faction.getTag(follower)); - } - } - faction.disband(me, PlayerDisbandReason.COMMAND); - } else { - faction.disband(me, PlayerDisbandReason.COMMAND); - me.sendMessage(String.valueOf(TL.COMMAND_DISBAND_PLAYER)); - } - } - } + if (!disbandMap.containsKey(me.getUniqueId().toString()) && faction.getTnt() > 0) { + msg(TL.COMMAND_DISBAND_CONFIRM.toString().replace("{tnt}", faction.getTnt() + "")); + disbandMap.put(me.getUniqueId().toString(), faction.getId()); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + disbandMap.remove(me.getUniqueId().toString()); + } + }, 200L); + } else if (faction.getId().equals(disbandMap.get(me.getUniqueId().toString())) || faction.getTnt() == 0) { + if (SavageFactions.plugin.getConfig().getBoolean("faction-disband-broadcast", true)) { + for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { + String amountString = senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(follower); + UtilFly.checkFly(this.fme, Board.getInstance().getFactionAt(new FLocation(follower))); + if (follower.getFaction() == faction) { + follower.msg(TL.COMMAND_DISBAND_BROADCAST_YOURS, amountString); + } else { + follower.msg(TL.COMMAND_DISBAND_BROADCAST_NOTYOURS, amountString, faction.getTag(follower)); + } + } + faction.disband(me, PlayerDisbandReason.COMMAND); + } else { + faction.disband(me, PlayerDisbandReason.COMMAND); + me.sendMessage(String.valueOf(TL.COMMAND_DISBAND_PLAYER)); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DISBAND_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DISBAND_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java b/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java index 21a4bac4..de8c13cc 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java @@ -16,78 +16,78 @@ import java.util.UUID; public class CmdFWarp extends FCommand { - public CmdFWarp() { - super(); - this.aliases.add("warp"); - this.aliases.add("warps"); - this.optionalArgs.put("warpname", "warpname"); - this.optionalArgs.put("password", "password"); + public CmdFWarp() { + super(); + this.aliases.add("warp"); + this.aliases.add("warps"); + this.optionalArgs.put("warpname", "warpname"); + this.optionalArgs.put("password", "password"); - this.permission = Permission.WARP.node; - this.senderMustBeMember = true; - this.senderMustBeModerator = false; - } + this.permission = Permission.WARP.node; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; + } - @Override - public void perform() { - //TODO: check if in combat. - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.WARP); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use warps"); - return; - } - } + @Override + public void perform() { + //TODO: check if in combat. + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.WARP); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use warps"); + return; + } + } - if (args.size() == 0) { - WarpGUI warpGUI = new WarpGUI(fme); - warpGUI.build(); + if (args.size() == 0) { + WarpGUI warpGUI = new WarpGUI(fme); + warpGUI.build(); - me.openInventory(warpGUI.getInventory()); - } else if (args.size() > 2) { - fme.msg(TL.COMMAND_FWARP_COMMANDFORMAT); - } else { - final String warpName = argAsString(0); - final String passwordAttempt = argAsString(1); + me.openInventory(warpGUI.getInventory()); + } else if (args.size() > 2) { + fme.msg(TL.COMMAND_FWARP_COMMANDFORMAT); + } else { + final String warpName = argAsString(0); + final String passwordAttempt = argAsString(1); - if (myFaction.isWarp(argAsString(0))) { + if (myFaction.isWarp(argAsString(0))) { - // Check if requires password and if so, check if valid. CASE SENSITIVE - if (myFaction.hasWarpPassword(warpName) && !myFaction.isWarpPassword(warpName, passwordAttempt)) { - fme.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); - return; - } + // Check if requires password and if so, check if valid. CASE SENSITIVE + if (myFaction.hasWarpPassword(warpName) && !myFaction.isWarpPassword(warpName, passwordAttempt)) { + fme.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); + return; + } - // Check transaction AFTER password check. - if (!transact(fme)) { - return; - } - final FPlayer fPlayer = fme; - final UUID uuid = fme.getPlayer().getUniqueId(); - this.doWarmUp(WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warpName, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(uuid); - if (player != null) { - player.teleport(fPlayer.getFaction().getWarp(warpName).getLocation()); - fPlayer.msg(TL.COMMAND_FWARP_WARPED, warpName); - } - } - }, this.p.getConfig().getLong("warmups.f-warp", 0)); - } else { - fme.msg(TL.COMMAND_FWARP_INVALID_WARP, warpName); - } - } - } + // Check transaction AFTER password check. + if (!transact(fme)) { + return; + } + final FPlayer fPlayer = fme; + final UUID uuid = fme.getPlayer().getUniqueId(); + this.doWarmUp(WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warpName, new Runnable() { + @Override + public void run() { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + player.teleport(fPlayer.getFaction().getWarp(warpName).getLocation()); + fPlayer.msg(TL.COMMAND_FWARP_WARPED, warpName); + } + } + }, this.p.getConfig().getLong("warmups.f-warp", 0)); + } else { + fme.msg(TL.COMMAND_FWARP_INVALID_WARP, warpName); + } + } + } - private boolean transact(FPlayer player) { - return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5), TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); - } + private boolean transact(FPlayer player) { + return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5), TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_FWARP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_FWARP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdFly.java b/src/main/java/com/massivecraft/factions/cmd/CmdFly.java index b9f737b6..d5072e82 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdFly.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdFly.java @@ -22,230 +22,230 @@ import java.util.concurrent.ConcurrentHashMap; public class CmdFly extends FCommand { - public static ConcurrentHashMap flyMap = new ConcurrentHashMap(); - public static int id = -1; - public static int flyid = -1; + public static ConcurrentHashMap flyMap = new ConcurrentHashMap(); + public static int id = -1; + public static int flyid = -1; - public CmdFly() { - super(); - this.aliases.add("fly"); + public CmdFly() { + super(); + this.aliases.add("fly"); - this.optionalArgs.put("on/off", "flip"); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.FLY.node; - this.senderMustBeMember = true; - this.senderMustBeModerator = false; - } + this.permission = Permission.FLY.node; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; + } - public static void startParticles() { - // Just a secondary check. - if (!SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { - return; - } + public static void startParticles() { + // Just a secondary check. + if (!SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { + return; + } - id = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - for (String name : flyMap.keySet()) { - Player player = Bukkit.getPlayer(name); - if (player == null) { - continue; - } - if (!player.isFlying()) { - continue; - } - if (!SavageFactions.plugin.mc17) { - if (player.getGameMode() == GameMode.SPECTATOR) { - continue; - } - } + id = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + for (String name : flyMap.keySet()) { + Player player = Bukkit.getPlayer(name); + if (player == null) { + continue; + } + if (!player.isFlying()) { + continue; + } + if (!SavageFactions.plugin.mc17) { + if (player.getGameMode() == GameMode.SPECTATOR) { + continue; + } + } - if (FPlayers.getInstance().getByPlayer(player).isVanished()) { - // Actually, vanished players (such as admins) should not display particles to prevent others from knowing their vanished assistance for moderation. - // But we can keep it as a config. - if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enable-While-Vanished")) { - return; - } - continue; - } - if (SavageFactions.plugin.useNonPacketParticles) { - // 1.9+ based servers will use the built in particleAPI instead of packet based. - // any particle amount higher than 0 made them go everywhere, and the offset at 0 was not working. - // So setting the amount to 0 spawns 1 in the precise location - player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation().add(0, -0.35, 0), 0); - } else { - ParticleEffect.CLOUD.display((float) 0, (float) 0, (float) 0, (float) 0, 3, player.getLocation().add(0, -0.35, 0), 16); - } + if (FPlayers.getInstance().getByPlayer(player).isVanished()) { + // Actually, vanished players (such as admins) should not display particles to prevent others from knowing their vanished assistance for moderation. + // But we can keep it as a config. + if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enable-While-Vanished")) { + return; + } + continue; + } + if (SavageFactions.plugin.useNonPacketParticles) { + // 1.9+ based servers will use the built in particleAPI instead of packet based. + // any particle amount higher than 0 made them go everywhere, and the offset at 0 was not working. + // So setting the amount to 0 spawns 1 in the precise location + player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation().add(0, -0.35, 0), 0); + } else { + ParticleEffect.CLOUD.display((float) 0, (float) 0, (float) 0, (float) 0, 3, player.getLocation().add(0, -0.35, 0), 16); + } - } - if (flyMap.keySet().size() == 0) { - Bukkit.getScheduler().cancelTask(id); - id = -1; - } - } - }, 10L, 3L); - } + } + if (flyMap.keySet().size() == 0) { + Bukkit.getScheduler().cancelTask(id); + id = -1; + } + } + }, 10L, 3L); + } - public static void startFlyCheck() { - flyid = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() throws ConcurrentModificationException { //threw the exception for now, until I recode fly :( Cringe. - checkTaskState(); - if (flyMap.keySet().size() != 0) { - for (String name : flyMap.keySet()) { - if (name == null) { - continue; - } - Player player = Bukkit.getPlayer(name); - if (player == null) { - continue; - } - if (!player.isFlying()) { - continue; - } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer == null) { - continue; - } - if (player.getGameMode() == GameMode.CREATIVE) { - continue; - } - if (!SavageFactions.plugin.mc17 && player.getGameMode() == GameMode.SPECTATOR) { - continue; - } - Faction myFaction = fPlayer.getFaction(); - if (myFaction.isWilderness()) { - fPlayer.setFlying(false); - flyMap.remove(name); - continue; - } - if (fPlayer.checkIfNearbyEnemies()) { - continue; - } - FLocation myFloc = new FLocation(player.getLocation()); - Faction toFac = Board.getInstance().getFactionAt(myFloc); - if (Board.getInstance().getFactionAt(myFloc) != myFaction) { - if (!checkBypassPerms(fPlayer, player, toFac)) { - fPlayer.setFlying(false); - flyMap.remove(name); - continue; - } - } + public static void startFlyCheck() { + flyid = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() throws ConcurrentModificationException { //threw the exception for now, until I recode fly :( Cringe. + checkTaskState(); + if (flyMap.keySet().size() != 0) { + for (String name : flyMap.keySet()) { + if (name == null) { + continue; + } + Player player = Bukkit.getPlayer(name); + if (player == null) { + continue; + } + if (!player.isFlying()) { + continue; + } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer == null) { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE) { + continue; + } + if (!SavageFactions.plugin.mc17 && player.getGameMode() == GameMode.SPECTATOR) { + continue; + } + Faction myFaction = fPlayer.getFaction(); + if (myFaction.isWilderness()) { + fPlayer.setFlying(false); + flyMap.remove(name); + continue; + } + if (fPlayer.checkIfNearbyEnemies()) { + continue; + } + FLocation myFloc = new FLocation(player.getLocation()); + Faction toFac = Board.getInstance().getFactionAt(myFloc); + if (Board.getInstance().getFactionAt(myFloc) != myFaction) { + if (!checkBypassPerms(fPlayer, player, toFac)) { + fPlayer.setFlying(false); + flyMap.remove(name); + continue; + } + } - } - } + } + } - } - }, 20L, 20L); - } + } + }, 20L, 20L); + } - private static boolean checkBypassPerms(FPlayer fme, Player me, Faction toFac) { - if (toFac != fme.getFaction()) { - if (!me.hasPermission("factions.fly.wilderness") && toFac.isWilderness() || !me.hasPermission("factions.fly.safezone") && toFac.isSafeZone() || !me.hasPermission("factions.fly.warzone") && toFac.isWarZone()) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - Access access = toFac.getAccess(fme, PermissableAction.FLY); - if ((!(me.hasPermission("factions.fly.enemy") || access == Access.ALLOW)) && toFac.getRelationTo(fme.getFaction()) == Relation.ENEMY) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - if (!(me.hasPermission("factions.fly.ally") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.ALLY) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - if (!(me.hasPermission("factions.fly.truce") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.TRUCE) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } + private static boolean checkBypassPerms(FPlayer fme, Player me, Faction toFac) { + if (toFac != fme.getFaction()) { + if (!me.hasPermission("factions.fly.wilderness") && toFac.isWilderness() || !me.hasPermission("factions.fly.safezone") && toFac.isSafeZone() || !me.hasPermission("factions.fly.warzone") && toFac.isWarZone()) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + Access access = toFac.getAccess(fme, PermissableAction.FLY); + if ((!(me.hasPermission("factions.fly.enemy") || access == Access.ALLOW)) && toFac.getRelationTo(fme.getFaction()) == Relation.ENEMY) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + if (!(me.hasPermission("factions.fly.ally") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.ALLY) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + if (!(me.hasPermission("factions.fly.truce") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.TRUCE) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } - if (!(me.hasPermission("factions.fly.neutral") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.NEUTRAL && !isSystemFaction(toFac)) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - return me.hasPermission("factions.fly") && access != Access.DENY; - } - return true; - } + if (!(me.hasPermission("factions.fly.neutral") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.NEUTRAL && !isSystemFaction(toFac)) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + return me.hasPermission("factions.fly") && access != Access.DENY; + } + return true; + } - public static Boolean isSystemFaction(Faction faction) { - return faction.isSafeZone() || - faction.isWarZone() || - faction.isWilderness(); - } + public static Boolean isSystemFaction(Faction faction) { + return faction.isSafeZone() || + faction.isWarZone() || + faction.isWilderness(); + } - public static void checkTaskState() { - if (flyMap.keySet().size() == 0) { - Bukkit.getScheduler().cancelTask(flyid); - flyid = -1; - } - } + public static void checkTaskState() { + if (flyMap.keySet().size() == 0) { + Bukkit.getScheduler().cancelTask(flyid); + flyid = -1; + } + } - public boolean isInFlightChecker(Player player) { - return flyMap.containsKey(player.getName()); - } + public boolean isInFlightChecker(Player player) { + return flyMap.containsKey(player.getName()); + } - @Override - public void perform() { - // Disabled by default. - if (!SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { - fme.msg(TL.COMMAND_FLY_DISABLED); - return; - } + @Override + public void perform() { + // Disabled by default. + if (!SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { + fme.msg(TL.COMMAND_FLY_DISABLED); + return; + } - FLocation myfloc = new FLocation(me.getLocation()); - Faction toFac = Board.getInstance().getFactionAt(myfloc); - if (!checkBypassPerms(fme, me, toFac)) return; - List entities = this.me.getNearbyEntities(16.0D, 256.0D, 16.0D); + FLocation myfloc = new FLocation(me.getLocation()); + Faction toFac = Board.getInstance().getFactionAt(myfloc); + if (!checkBypassPerms(fme, me, toFac)) return; + List entities = this.me.getNearbyEntities(16.0D, 256.0D, 16.0D); - for (int i = 0; i <= entities.size() - 1; ++i) { - if (entities.get(i) instanceof Player) { - Player eplayer = (Player) entities.get(i); - FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); - if (efplayer.getRelationTo(this.fme) == Relation.ENEMY && !efplayer.isStealthEnabled()) { - this.fme.msg(TL.COMMAND_FLY_CHECK_ENEMY); - return; - } - } - } + for (int i = 0; i <= entities.size() - 1; ++i) { + if (entities.get(i) instanceof Player) { + Player eplayer = (Player) entities.get(i); + FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); + if (efplayer.getRelationTo(this.fme) == Relation.ENEMY && !efplayer.isStealthEnabled()) { + this.fme.msg(TL.COMMAND_FLY_CHECK_ENEMY); + return; + } + } + } - if (args.size() == 0) { - toggleFlight(!fme.isFlying(), me); - } else if (args.size() == 1) { - toggleFlight(argAsBool(0), me); - } - } + if (args.size() == 0) { + toggleFlight(!fme.isFlying(), me); + } else if (args.size() == 1) { + toggleFlight(argAsBool(0), me); + } + } - private void toggleFlight(final boolean toggle, final Player player) { - if (!toggle) { - fme.setFlying(false); - flyMap.remove(player.getName()); - return; - } + private void toggleFlight(final boolean toggle, final Player player) { + if (!toggle) { + fme.setFlying(false); + flyMap.remove(player.getName()); + return; + } - if (fme.canFlyAtLocation()) + if (fme.canFlyAtLocation()) - this.doWarmUp(WarmUpUtil.Warmup.FLIGHT, TL.WARMUPS_NOTIFY_FLIGHT, "Fly", new Runnable() { - @Override - public void run() { - fme.setFlying(true); - flyMap.put(player.getName(), true); - if (id == -1) { - if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { - startParticles(); - } - } - if (flyid == -1) { - startFlyCheck(); - } - } - }, this.p.getConfig().getLong("warmups.f-fly", 0)); - } + this.doWarmUp(WarmUpUtil.Warmup.FLIGHT, TL.WARMUPS_NOTIFY_FLIGHT, "Fly", new Runnable() { + @Override + public void run() { + fme.setFlying(true); + flyMap.put(player.getName(), true); + if (id == -1) { + if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { + startParticles(); + } + } + if (flyid == -1) { + startFlyCheck(); + } + } + }, this.p.getConfig().getLong("warmups.f-fly", 0)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_FLY_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_FLY_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java b/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java index b01ceb6e..09d8e105 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java @@ -7,48 +7,48 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdFocus - extends FCommand { - public CmdFocus() { - aliases.add("focus"); + extends FCommand { + public CmdFocus() { + aliases.add("focus"); - requiredArgs.add("player"); + requiredArgs.add("player"); - permission = Permission.FOCUS.node; + permission = Permission.FOCUS.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { - fme.msg(TL.GENERIC_DISABLED); - return; - } - FPlayer target = argAsFPlayer(0); - if (target == null) { - return; - } - if (target.getFaction().getId().equalsIgnoreCase(myFaction.getId())) { - fme.msg(TL.COMMAND_FOCUS_SAMEFACTION); - return; - } - if ((myFaction.getFocused() != null) && (myFaction.getFocused().equalsIgnoreCase(target.getName()))) { - myFaction.setFocused(null); - myFaction.msg(TL.COMMAND_FOCUS_NO_LONGER, target.getName()); - FTeamWrapper.updatePrefixes(target.getFaction()); - return; - } - myFaction.msg(TL.COMMAND_FOCUS_FOCUSING, target.getName()); - myFaction.setFocused(target.getName()); - FTeamWrapper.updatePrefixes(target.getFaction()); - } + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { + fme.msg(TL.GENERIC_DISABLED); + return; + } + FPlayer target = argAsFPlayer(0); + if (target == null) { + return; + } + if (target.getFaction().getId().equalsIgnoreCase(myFaction.getId())) { + fme.msg(TL.COMMAND_FOCUS_SAMEFACTION); + return; + } + if ((myFaction.getFocused() != null) && (myFaction.getFocused().equalsIgnoreCase(target.getName()))) { + myFaction.setFocused(null); + myFaction.msg(TL.COMMAND_FOCUS_NO_LONGER, target.getName()); + FTeamWrapper.updatePrefixes(target.getFaction()); + return; + } + myFaction.msg(TL.COMMAND_FOCUS_FOCUSING, target.getName()); + myFaction.setFocused(target.getName()); + FTeamWrapper.updatePrefixes(target.getFaction()); + } - public TL getUsageTranslation() { - return TL.COMMAND_FOCUS_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_FOCUS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java b/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java index a2029688..a1a73848 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java @@ -9,70 +9,70 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; public class CmdGetVault extends FCommand { - public CmdGetVault() { - super(); + public CmdGetVault() { + super(); - this.aliases.add("getvault"); + this.aliases.add("getvault"); - this.permission = Permission.GETVAULT.node; - this.disableOnLock = true; + this.permission = Permission.GETVAULT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - Location vaultLocation = fme.getFaction().getVault(); - ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + Location vaultLocation = fme.getFaction().getVault(); + ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); - //check if vault is set - if (vaultLocation != null) { - fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); - return; - } + //check if vault is set + if (vaultLocation != null) { + fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); + return; + } - //has enough money? - int amount = SavageFactions.plugin.getConfig().getInt("fvault.Price"); - if (!fme.hasMoney(amount)) { - return; - } + //has enough money? + int amount = SavageFactions.plugin.getConfig().getInt("fvault.Price"); + if (!fme.hasMoney(amount)) { + return; + } - //success :) - fme.takeMoney(amount); - me.getInventory().addItem(vault); - fme.msg(TL.COMMAND_GETVAULT_RECEIVE); + //success :) + fme.takeMoney(amount); + me.getInventory().addItem(vault); + fme.msg(TL.COMMAND_GETVAULT_RECEIVE); - } + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_GETVAULT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_GETVAULT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java b/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java index e46084f5..5b7bd34b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java @@ -13,207 +13,207 @@ import java.util.List; public class CmdHelp extends FCommand { - public ArrayList> helpPages; + public ArrayList> helpPages; - public CmdHelp() { - super(); - this.aliases.add("help"); - this.aliases.add("h"); - this.aliases.add("?"); + public CmdHelp() { + super(); + this.aliases.add("help"); + this.aliases.add("h"); + this.aliases.add("?"); - //this.requiredArgs.add(""); - this.optionalArgs.put("page", "1"); + //this.requiredArgs.add(""); + this.optionalArgs.put("page", "1"); - this.permission = Permission.HELP.node; - this.disableOnLock = false; + this.permission = Permission.HELP.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - //----------------------------------------------// - // Build the help pages - //----------------------------------------------// + //----------------------------------------------// + // Build the help pages + //----------------------------------------------// - @Override - public void perform() { - if (SavageFactions.plugin.getConfig().getBoolean("use-old-help", true)) { - if (helpPages == null) { - updateHelp(); - } + @Override + public void perform() { + if (SavageFactions.plugin.getConfig().getBoolean("use-old-help", true)) { + if (helpPages == null) { + updateHelp(); + } - int page = this.argAsInt(0, 1); - sendMessage(p.txt.titleize("Factions Help (" + page + "/" + helpPages.size() + ")")); + int page = this.argAsInt(0, 1); + sendMessage(p.txt.titleize("Factions Help (" + page + "/" + helpPages.size() + ")")); - page -= 1; + page -= 1; - if (page < 0 || page >= helpPages.size()) { - msg(TL.COMMAND_HELP_404.format(String.valueOf(page))); - return; - } - sendMessage(helpPages.get(page)); - return; - } - ConfigurationSection help = SavageFactions.plugin.getConfig().getConfigurationSection("help"); - if (help == null) { - help = SavageFactions.plugin.getConfig().createSection("help"); // create new help section - List error = new ArrayList<>(); - error.add("&cUpdate help messages in config.yml!"); - error.add("&cSet use-old-help for legacy help messages"); - help.set("'1'", error); // add default error messages - } - String pageArg = this.argAsString(0, "1"); - List page = help.getStringList(pageArg); - if (page == null || page.isEmpty()) { - msg(TL.COMMAND_HELP_404.format(pageArg)); - return; - } - for (String helpLine : page) { - sendMessage(SavageFactions.plugin.txt.parse(helpLine)); - } - } + if (page < 0 || page >= helpPages.size()) { + msg(TL.COMMAND_HELP_404.format(String.valueOf(page))); + return; + } + sendMessage(helpPages.get(page)); + return; + } + ConfigurationSection help = SavageFactions.plugin.getConfig().getConfigurationSection("help"); + if (help == null) { + help = SavageFactions.plugin.getConfig().createSection("help"); // create new help section + List error = new ArrayList<>(); + error.add("&cUpdate help messages in config.yml!"); + error.add("&cSet use-old-help for legacy help messages"); + help.set("'1'", error); // add default error messages + } + String pageArg = this.argAsString(0, "1"); + List page = help.getStringList(pageArg); + if (page == null || page.isEmpty()) { + msg(TL.COMMAND_HELP_404.format(pageArg)); + return; + } + for (String helpLine : page) { + sendMessage(SavageFactions.plugin.txt.parse(helpLine)); + } + } - public void updateHelp() { - helpPages = new ArrayList<>(); - ArrayList pageLines; + public void updateHelp() { + helpPages = new ArrayList<>(); + ArrayList pageLines; - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdHelp.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdList.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdShow.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPower.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdJoin.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdLeave.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdChat.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdToggleAllianceChat.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdHome.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_NEXTCREATE.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdHelp.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdList.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdShow.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPower.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdJoin.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdLeave.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdChat.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdToggleAllianceChat.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdHome.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_NEXTCREATE.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdCreate.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdDescription.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdTag.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_INVITATIONS.toString())); - pageLines.add(p.cmdBase.cmdOpen.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdInvite.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdDeinvite.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_HOME.toString())); - pageLines.add(p.cmdBase.cmdSethome.getUseageTemplate(true)); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdCreate.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdDescription.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdTag.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_INVITATIONS.toString())); + pageLines.add(p.cmdBase.cmdOpen.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdInvite.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdDeinvite.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_HOME.toString())); + pageLines.add(p.cmdBase.cmdSethome.getUseageTemplate(true)); + helpPages.add(pageLines); - if (Econ.isSetup() && Conf.econEnabled && Conf.bankEnabled) { - pageLines = new ArrayList<>(); - pageLines.add(""); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_3.toString())); - pageLines.add(""); - pageLines.add(p.cmdBase.cmdMoney.getUseageTemplate(true)); - pageLines.add(""); - pageLines.add(""); - pageLines.add(""); - helpPages.add(pageLines); - } + if (Econ.isSetup() && Conf.econEnabled && Conf.bankEnabled) { + pageLines = new ArrayList<>(); + pageLines.add(""); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_3.toString())); + pageLines.add(""); + pageLines.add(p.cmdBase.cmdMoney.getUseageTemplate(true)); + pageLines.add(""); + pageLines.add(""); + pageLines.add(""); + helpPages.add(pageLines); + } - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdClaim.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdAutoClaim.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdUnclaim.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdUnclaimall.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdKick.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdMod.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdAdmin.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdTitle.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdSB.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdSeeChunk.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdStatus.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PLAYERTITLES.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdClaim.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdAutoClaim.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdUnclaim.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdUnclaimall.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdKick.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdMod.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdAdmin.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdTitle.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdSB.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdSeeChunk.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdStatus.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PLAYERTITLES.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdMap.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdBoom.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdOwner.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdOwnerList.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_3.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdMap.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdBoom.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdOwner.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdOwnerList.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_3.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdDisband.getUseageTemplate(true)); - pageLines.add(""); - pageLines.add(p.cmdBase.cmdRelationAlly.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdRelationNeutral.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdRelationEnemy.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_3.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_4.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdDisband.getUseageTemplate(true)); + pageLines.add(""); + pageLines.add(p.cmdBase.cmdRelationAlly.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdRelationNeutral.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdRelationEnemy.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_3.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_4.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_5.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_6.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_7.toString())); - pageLines.add(TL.COMMAND_HELP_RELATIONS_8.toString()); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_9.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_10.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_11.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_12.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_13.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_5.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_6.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_7.toString())); + pageLines.add(TL.COMMAND_HELP_RELATIONS_8.toString()); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_9.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_10.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_11.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_12.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_13.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_3.toString())); - pageLines.add(TL.COMMAND_HELP_PERMISSIONS_4.toString()); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_5.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_6.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_7.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_8.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_9.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_3.toString())); + pageLines.add(TL.COMMAND_HELP_PERMISSIONS_4.toString()); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_5.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_6.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_7.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_8.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_9.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(TL.COMMAND_HELP_MOAR_1.toString()); - pageLines.add(p.cmdBase.cmdBypass.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_3.toString())); - pageLines.add(p.cmdBase.cmdSafeunclaimall.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdWarunclaimall.getUseageTemplate(true)); - //TODO:TL - pageLines.add(p.txt.parse("Note: " + p.cmdBase.cmdUnclaim.getUseageTemplate(false) + SavageFactions.plugin.txt.parse("") + " works on safe/war zones as well.")); - pageLines.add(p.cmdBase.cmdPeaceful.getUseageTemplate(true)); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(TL.COMMAND_HELP_MOAR_1.toString()); + pageLines.add(p.cmdBase.cmdBypass.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_3.toString())); + pageLines.add(p.cmdBase.cmdSafeunclaimall.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdWarunclaimall.getUseageTemplate(true)); + //TODO:TL + pageLines.add(p.txt.parse("Note: " + p.cmdBase.cmdUnclaim.getUseageTemplate(false) + SavageFactions.plugin.txt.parse("") + " works on safe/war zones as well.")); + pageLines.add(p.cmdBase.cmdPeaceful.getUseageTemplate(true)); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_2.toString())); - pageLines.add(p.cmdBase.cmdChatSpy.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPermanent.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPermanentPower.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPowerBoost.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdConfig.getUseageTemplate(true)); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_2.toString())); + pageLines.add(p.cmdBase.cmdChatSpy.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPermanent.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPermanentPower.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPowerBoost.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdConfig.getUseageTemplate(true)); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_3.toString())); - pageLines.add(p.cmdBase.cmdLock.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdReload.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdSaveAll.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdVersion.getUseageTemplate(true)); - helpPages.add(pageLines); - } + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_3.toString())); + pageLines.add(p.cmdBase.cmdLock.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdReload.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdSaveAll.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdVersion.getUseageTemplate(true)); + helpPages.add(pageLines); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_HELP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_HELP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdHome.java b/src/main/java/com/massivecraft/factions/cmd/CmdHome.java index 1ec5fed7..e680f552 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdHome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdHome.java @@ -20,130 +20,130 @@ import java.util.List; public class CmdHome extends FCommand { - public CmdHome() { - super(); - this.aliases.add("home"); + public CmdHome() { + super(); + this.aliases.add("home"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.HOME.node; - this.disableOnLock = false; + this.permission = Permission.HOME.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // TODO: Hide this command on help also. - if (!Conf.homesEnabled) { - fme.msg(TL.COMMAND_HOME_DISABLED); - return; - } + @Override + public void perform() { + // TODO: Hide this command on help also. + if (!Conf.homesEnabled) { + fme.msg(TL.COMMAND_HOME_DISABLED); + return; + } - if (!Conf.homesTeleportCommandEnabled) { - fme.msg(TL.COMMAND_HOME_TELEPORTDISABLED); - return; - } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.HOME); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "teleport home"); - return; - } - } + if (!Conf.homesTeleportCommandEnabled) { + fme.msg(TL.COMMAND_HOME_TELEPORTDISABLED); + return; + } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.HOME); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "teleport home"); + return; + } + } - if (!myFaction.hasHome()) { - fme.msg(TL.COMMAND_HOME_NOHOME.toString() + (fme.getRole().value < Role.MODERATOR.value ? TL.GENERIC_ASKYOURLEADER.toString() : TL.GENERIC_YOUSHOULD.toString())); - fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate()); - return; - } + if (!myFaction.hasHome()) { + fme.msg(TL.COMMAND_HOME_NOHOME.toString() + (fme.getRole().value < Role.MODERATOR.value ? TL.GENERIC_ASKYOURLEADER.toString() : TL.GENERIC_YOUSHOULD.toString())); + fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate()); + return; + } - if (!Conf.homesTeleportAllowedFromEnemyTerritory && fme.isInEnemyTerritory()) { - fme.msg(TL.COMMAND_HOME_INENEMY); - return; - } + if (!Conf.homesTeleportAllowedFromEnemyTerritory && fme.isInEnemyTerritory()) { + fme.msg(TL.COMMAND_HOME_INENEMY); + return; + } - if (!Conf.homesTeleportAllowedFromDifferentWorld && me.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) { - fme.msg(TL.COMMAND_HOME_WRONGWORLD); - return; - } + if (!Conf.homesTeleportAllowedFromDifferentWorld && me.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) { + fme.msg(TL.COMMAND_HOME_WRONGWORLD); + return; + } - Faction faction = Board.getInstance().getFactionAt(new FLocation(me.getLocation())); - final Location loc = me.getLocation().clone(); + Faction faction = Board.getInstance().getFactionAt(new FLocation(me.getLocation())); + final Location loc = me.getLocation().clone(); - // if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby - if (Conf.homesTeleportAllowedEnemyDistance > 0 && - !faction.isSafeZone() && - (!fme.isInOwnTerritory() || (fme.isInOwnTerritory() && !Conf.homesTeleportIgnoreEnemiesIfInOwnTerritory))) { - World w = loc.getWorld(); - double x = loc.getX(); - double y = loc.getY(); - double z = loc.getZ(); + // if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby + if (Conf.homesTeleportAllowedEnemyDistance > 0 && + !faction.isSafeZone() && + (!fme.isInOwnTerritory() || (fme.isInOwnTerritory() && !Conf.homesTeleportIgnoreEnemiesIfInOwnTerritory))) { + World w = loc.getWorld(); + double x = loc.getX(); + double y = loc.getY(); + double z = loc.getZ(); - for (Player p : me.getServer().getOnlinePlayers()) { - if (p == null || !p.isOnline() || p.isDead() || p == me || p.getWorld() != w) { - continue; - } + for (Player p : me.getServer().getOnlinePlayers()) { + if (p == null || !p.isOnline() || p.isDead() || p == me || p.getWorld() != w) { + continue; + } - FPlayer fp = FPlayers.getInstance().getByPlayer(p); - if (fme.getRelationTo(fp) != Relation.ENEMY || fp.isVanished()) { - continue; - } + FPlayer fp = FPlayers.getInstance().getByPlayer(p); + if (fme.getRelationTo(fp) != Relation.ENEMY || fp.isVanished()) { + continue; + } - Location l = p.getLocation(); - double dx = Math.abs(x - l.getX()); - double dy = Math.abs(y - l.getY()); - double dz = Math.abs(z - l.getZ()); - double max = Conf.homesTeleportAllowedEnemyDistance; + Location l = p.getLocation(); + double dx = Math.abs(x - l.getX()); + double dy = Math.abs(y - l.getY()); + double dz = Math.abs(z - l.getZ()); + double max = Conf.homesTeleportAllowedEnemyDistance; - // box-shaped distance check - if (dx > max || dy > max || dz > max) { - continue; - } + // box-shaped distance check + if (dx > max || dy > max || dz > max) { + continue; + } - fme.msg(TL.COMMAND_HOME_ENEMYNEAR, String.valueOf(Conf.homesTeleportAllowedEnemyDistance)); - return; - } - } + fme.msg(TL.COMMAND_HOME_ENEMYNEAR, String.valueOf(Conf.homesTeleportAllowedEnemyDistance)); + return; + } + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostHome, TL.COMMAND_HOME_TOTELEPORT.toString(), TL.COMMAND_HOME_FORTELEPORT.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostHome, TL.COMMAND_HOME_TOTELEPORT.toString(), TL.COMMAND_HOME_FORTELEPORT.toString())) { + return; + } - // if Essentials teleport handling is enabled and available, pass the teleport off to it (for delay and cooldown) - if (Essentials.handleTeleport(me, myFaction.getHome())) { - return; - } + // if Essentials teleport handling is enabled and available, pass the teleport off to it (for delay and cooldown) + if (Essentials.handleTeleport(me, myFaction.getHome())) { + return; + } - this.doWarmUp(WarmUpUtil.Warmup.HOME, TL.WARMUPS_NOTIFY_TELEPORT, "Home", new Runnable() { - @Override - public void run() { - // Create a smoke effect - if (Conf.homesTeleportCommandSmokeEffectEnabled) { - List smokeLocations = new ArrayList<>(); - smokeLocations.add(loc); - smokeLocations.add(loc.add(0, 1, 0)); - smokeLocations.add(CmdHome.this.myFaction.getHome()); - smokeLocations.add(CmdHome.this.myFaction.getHome().clone().add(0, 1, 0)); - SmokeUtil.spawnCloudRandom(smokeLocations, Conf.homesTeleportCommandSmokeEffectThickness); - } + this.doWarmUp(WarmUpUtil.Warmup.HOME, TL.WARMUPS_NOTIFY_TELEPORT, "Home", new Runnable() { + @Override + public void run() { + // Create a smoke effect + if (Conf.homesTeleportCommandSmokeEffectEnabled) { + List smokeLocations = new ArrayList<>(); + smokeLocations.add(loc); + smokeLocations.add(loc.add(0, 1, 0)); + smokeLocations.add(CmdHome.this.myFaction.getHome()); + smokeLocations.add(CmdHome.this.myFaction.getHome().clone().add(0, 1, 0)); + SmokeUtil.spawnCloudRandom(smokeLocations, Conf.homesTeleportCommandSmokeEffectThickness); + } - CmdHome.this.me.teleport(CmdHome.this.myFaction.getHome()); - } - }, this.p.getConfig().getLong("warmups.f-home", 0)); - } + CmdHome.this.me.teleport(CmdHome.this.myFaction.getHome()); + } + }, this.p.getConfig().getLong("warmups.f-home", 0)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_HOME_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_HOME_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java b/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java index 5e465e4a..4660844f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java @@ -4,37 +4,37 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdInspect extends FCommand { - public CmdInspect() { - super(); - this.aliases.add("inspect"); - this.aliases.add("ins"); + public CmdInspect() { + super(); + this.aliases.add("inspect"); + this.aliases.add("ins"); - this.permission = Permission.INSPECT.node; - this.disableOnLock = true; + this.permission = Permission.INSPECT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (fme.isInspectMode()) { - fme.setInspectMode(false); - msg(TL.COMMAND_INSPECT_DISABLED_MSG); - } else { - fme.setInspectMode(true); - msg(TL.COMMAND_INSPECT_ENABLED); - } + @Override + public void perform() { + if (fme.isInspectMode()) { + fme.setInspectMode(false); + msg(TL.COMMAND_INSPECT_DISABLED_MSG); + } else { + fme.setInspectMode(true); + msg(TL.COMMAND_INSPECT_ENABLED); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_INSPECT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_INSPECT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java b/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java index a177d8f7..00a9197e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java @@ -12,83 +12,83 @@ import org.bukkit.ChatColor; public class CmdInvite extends FCommand { - public CmdInvite() { - super(); - this.aliases.add("invite"); - this.aliases.add("inv"); + public CmdInvite() { + super(); + this.aliases.add("invite"); + this.aliases.add("inv"); - this.requiredArgs.add("player name"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("player name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.INVITE.node; - this.disableOnLock = true; + this.permission = Permission.INVITE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer target = this.argAsBestFPlayerMatch(0); - if (target == null) { - return; - } + @Override + public void perform() { + FPlayer target = this.argAsBestFPlayerMatch(0); + if (target == null) { + return; + } - if (target.getFaction() == myFaction) { - msg(TL.COMMAND_INVITE_ALREADYMEMBER, target.getName(), myFaction.getTag()); - msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdKick.getUseageTemplate(false)); - return; - } + if (target.getFaction() == myFaction) { + msg(TL.COMMAND_INVITE_ALREADYMEMBER, target.getName(), myFaction.getTag()); + msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdKick.getUseageTemplate(false)); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostInvite, TL.COMMAND_INVITE_TOINVITE.toString(), TL.COMMAND_INVITE_FORINVITE.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostInvite, TL.COMMAND_INVITE_TOINVITE.toString(), TL.COMMAND_INVITE_FORINVITE.toString())) { + return; + } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.INVITE); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.INVITE); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); + return; + } + } - if (myFaction.isInvited(target)) { - fme.msg(TL.COMMAND_INVITE_ALREADYINVITED, target.getName()); - return; - } - if (myFaction.isBanned(target)) { - fme.msg(TL.COMMAND_INVITE_BANNED, target.getName()); - return; - } + if (myFaction.isInvited(target)) { + fme.msg(TL.COMMAND_INVITE_ALREADYINVITED, target.getName()); + return; + } + if (myFaction.isBanned(target)) { + fme.msg(TL.COMMAND_INVITE_BANNED, target.getName()); + return; + } - myFaction.invite(target); - // Send the invitation to the target player when online, otherwise just ignore - if (target.isOnline()) { - // Tooltips, colors, and commands only apply to the string immediately before it. - FancyMessage message = new FancyMessage(fme.describeTo(target, true)) - .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) - .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) - .then(TL.COMMAND_INVITE_INVITEDYOU.toString()) - .color(ChatColor.YELLOW) - .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) - .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) - .then(myFaction.describeTo(target)).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) - .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()); + myFaction.invite(target); + // Send the invitation to the target player when online, otherwise just ignore + if (target.isOnline()) { + // Tooltips, colors, and commands only apply to the string immediately before it. + FancyMessage message = new FancyMessage(fme.describeTo(target, true)) + .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) + .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) + .then(TL.COMMAND_INVITE_INVITEDYOU.toString()) + .color(ChatColor.YELLOW) + .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) + .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) + .then(myFaction.describeTo(target)).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) + .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()); - message.send(target.getPlayer()); - } + message.send(target.getPlayer()); + } - myFaction.msg(TL.COMMAND_INVITE_INVITED, fme.describeTo(myFaction, true), target.describeTo(myFaction)); - } + myFaction.msg(TL.COMMAND_INVITE_INVITED, fme.describeTo(myFaction, true), target.describeTo(myFaction)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_INVITE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_INVITE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java b/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java index f34a2bf2..3688b2b4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java @@ -8,120 +8,120 @@ import org.bukkit.Bukkit; public class CmdJoin extends FCommand { - public CmdJoin() { - super(); - this.aliases.add("join"); + public CmdJoin() { + super(); + this.aliases.add("join"); - this.requiredArgs.add("faction name"); - this.optionalArgs.put("player", "you"); + this.requiredArgs.add("faction name"); + this.optionalArgs.put("player", "you"); - this.permission = Permission.JOIN.node; - this.disableOnLock = true; + this.permission = Permission.JOIN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction faction = this.argAsFaction(0); - if (faction == null) { - return; - } + @Override + public void perform() { + Faction faction = this.argAsFaction(0); + if (faction == null) { + return; + } - FPlayer fplayer = this.argAsBestFPlayerMatch(1, fme, false); - boolean samePlayer = fplayer == fme; + FPlayer fplayer = this.argAsBestFPlayerMatch(1, fme, false); + boolean samePlayer = fplayer == fme; - if (!samePlayer && !Permission.JOIN_OTHERS.has(sender, false)) { - msg(TL.COMMAND_JOIN_CANNOTFORCE); - return; - } + if (!samePlayer && !Permission.JOIN_OTHERS.has(sender, false)) { + msg(TL.COMMAND_JOIN_CANNOTFORCE); + return; + } - if (!faction.isNormal()) { - msg(TL.COMMAND_JOIN_SYSTEMFACTION); - return; - } + if (!faction.isNormal()) { + msg(TL.COMMAND_JOIN_SYSTEMFACTION); + return; + } - if (faction == fplayer.getFaction()) { - //TODO:TL - msg(TL.COMMAND_JOIN_ALREADYMEMBER, fplayer.describeTo(fme, true), (samePlayer ? "are" : "is"), faction.getTag(fme)); - return; - } + if (faction == fplayer.getFaction()) { + //TODO:TL + msg(TL.COMMAND_JOIN_ALREADYMEMBER, fplayer.describeTo(fme, true), (samePlayer ? "are" : "is"), faction.getTag(fme)); + return; + } - if (Conf.factionMemberLimit > 0 && faction.getFPlayers().size() >= Conf.factionMemberLimit) { - msg(TL.COMMAND_JOIN_ATLIMIT, faction.getTag(fme), Conf.factionMemberLimit, fplayer.describeTo(fme, false)); - return; - } + if (Conf.factionMemberLimit > 0 && faction.getFPlayers().size() >= Conf.factionMemberLimit) { + msg(TL.COMMAND_JOIN_ATLIMIT, faction.getTag(fme), Conf.factionMemberLimit, fplayer.describeTo(fme, false)); + return; + } - if (fplayer.hasFaction()) { - //TODO:TL - msg(TL.COMMAND_JOIN_INOTHERFACTION, fplayer.describeTo(fme, true), (samePlayer ? "your" : "their")); - return; - } + if (fplayer.hasFaction()) { + //TODO:TL + msg(TL.COMMAND_JOIN_INOTHERFACTION, fplayer.describeTo(fme, true), (samePlayer ? "your" : "their")); + return; + } - if (!Conf.canLeaveWithNegativePower && fplayer.getPower() < 0) { - msg(TL.COMMAND_JOIN_NEGATIVEPOWER, fplayer.describeTo(fme, true)); - return; - } + if (!Conf.canLeaveWithNegativePower && fplayer.getPower() < 0) { + msg(TL.COMMAND_JOIN_NEGATIVEPOWER, fplayer.describeTo(fme, true)); + return; + } - if (!(faction.getOpen() || faction.isInvited(fplayer) || fme.isAdminBypassing() || Permission.JOIN_ANY.has(sender, false))) { - msg(TL.COMMAND_JOIN_REQUIRESINVITATION); - if (samePlayer) { - faction.msg(TL.COMMAND_JOIN_ATTEMPTEDJOIN, fplayer.describeTo(faction, true)); - } - return; - } + if (!(faction.getOpen() || faction.isInvited(fplayer) || fme.isAdminBypassing() || Permission.JOIN_ANY.has(sender, false))) { + msg(TL.COMMAND_JOIN_REQUIRESINVITATION); + if (samePlayer) { + faction.msg(TL.COMMAND_JOIN_ATTEMPTEDJOIN, fplayer.describeTo(faction, true)); + } + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (samePlayer && !canAffordCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (samePlayer && !canAffordCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString())) { + return; + } - // Check for ban - if (!fme.isAdminBypassing() && faction.isBanned(fme)) { - fme.msg(TL.COMMAND_JOIN_BANNED, faction.getTag(fme)); - return; - } + // Check for ban + if (!fme.isAdminBypassing() && faction.isBanned(fme)) { + fme.msg(TL.COMMAND_JOIN_BANNED, faction.getTag(fme)); + return; + } - // trigger the join event (cancellable) - FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND); - Bukkit.getServer().getPluginManager().callEvent(joinEvent); - if (joinEvent.isCancelled()) { - return; - } + // trigger the join event (cancellable) + FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND); + Bukkit.getServer().getPluginManager().callEvent(joinEvent); + if (joinEvent.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (samePlayer && !payForCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString(), TL.COMMAND_JOIN_FORJOIN.toString())) { - return; - } + // then make 'em pay (if applicable) + if (samePlayer && !payForCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString(), TL.COMMAND_JOIN_FORJOIN.toString())) { + return; + } - fme.msg(TL.COMMAND_JOIN_SUCCESS, fplayer.describeTo(fme, true), faction.getTag(fme)); + fme.msg(TL.COMMAND_JOIN_SUCCESS, fplayer.describeTo(fme, true), faction.getTag(fme)); - if (!samePlayer) { - fplayer.msg(TL.COMMAND_JOIN_MOVED, fme.describeTo(fplayer, true), faction.getTag(fplayer)); - } - faction.msg(TL.COMMAND_JOIN_JOINED, fplayer.describeTo(faction, true)); + if (!samePlayer) { + fplayer.msg(TL.COMMAND_JOIN_MOVED, fme.describeTo(fplayer, true), faction.getTag(fplayer)); + } + faction.msg(TL.COMMAND_JOIN_JOINED, fplayer.describeTo(faction, true)); - fplayer.resetFactionData(); - fplayer.setFaction(faction); - faction.deinvite(fplayer); - fme.setRole(faction.getDefaultRole()); + fplayer.resetFactionData(); + fplayer.setFaction(faction); + faction.deinvite(fplayer); + fme.setRole(faction.getDefaultRole()); - if (Conf.logFactionJoin) { - if (samePlayer) { - SavageFactions.plugin.log(TL.COMMAND_JOIN_JOINEDLOG.toString(), fplayer.getName(), faction.getTag()); - } else { - SavageFactions.plugin.log(TL.COMMAND_JOIN_MOVEDLOG.toString(), fme.getName(), fplayer.getName(), faction.getTag()); - } - } - } + if (Conf.logFactionJoin) { + if (samePlayer) { + SavageFactions.plugin.log(TL.COMMAND_JOIN_JOINEDLOG.toString(), fplayer.getName(), faction.getTag()); + } else { + SavageFactions.plugin.log(TL.COMMAND_JOIN_MOVEDLOG.toString(), fme.getName(), fplayer.getName(), faction.getTag()); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_JOIN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_JOIN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdKick.java b/src/main/java/com/massivecraft/factions/cmd/CmdKick.java index dcdb74ff..0cb144bb 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdKick.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdKick.java @@ -16,125 +16,125 @@ import org.bukkit.ChatColor; public class CmdKick extends FCommand { - public CmdKick() { - super(); - this.aliases.add("kick"); + public CmdKick() { + super(); + this.aliases.add("kick"); - this.optionalArgs.put("player name", "player name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "player name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.KICK.node; - this.disableOnLock = false; + this.permission = Permission.KICK.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer toKick = this.argIsSet(0) ? this.argAsBestFPlayerMatch(0) : null; - if (toKick == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_KICK_CANDIDATES.toString()).color(ChatColor.GOLD); - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); - } - if (fme.getRole().isAtLeast(Role.COLEADER)) { - // For both coleader and admin, add mods. - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.GRAY).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); - } - if (fme.getRole() == Role.LEADER) { - // Only add coleader to this for the leader. - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.COLEADER)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.RED).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); - } - } - } + @Override + public void perform() { + FPlayer toKick = this.argIsSet(0) ? this.argAsBestFPlayerMatch(0) : null; + if (toKick == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_KICK_CANDIDATES.toString()).color(ChatColor.GOLD); + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); + } + if (fme.getRole().isAtLeast(Role.COLEADER)) { + // For both coleader and admin, add mods. + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.GRAY).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); + } + if (fme.getRole() == Role.LEADER) { + // Only add coleader to this for the leader. + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.COLEADER)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.RED).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); + } + } + } - sendFancyMessage(msg); - return; - } + sendFancyMessage(msg); + return; + } - if (fme == toKick) { - msg(TL.COMMAND_KICK_SELF); - msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdLeave.getUseageTemplate(false)); - return; - } + if (fme == toKick) { + msg(TL.COMMAND_KICK_SELF); + msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdLeave.getUseageTemplate(false)); + return; + } - Faction toKickFaction = toKick.getFaction(); + Faction toKickFaction = toKick.getFaction(); - if (toKickFaction.isWilderness()) { - sender.sendMessage(TL.COMMAND_KICK_NONE.toString()); - return; - } + if (toKickFaction.isWilderness()) { + sender.sendMessage(TL.COMMAND_KICK_NONE.toString()); + return; + } - // This permission check has been cleaned to be more understandable and logical - // Unless is admin, - // - Check for the kick permission. - // - Make sure the player is in the faction. - // - Make sure the kicked player has lower rank than the kicker. - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.KICK); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_NOPERMISSION, "kick"); - return; - } - if (toKickFaction != myFaction) { - msg(TL.COMMAND_KICK_NOTMEMBER, toKick.describeTo(fme, true), myFaction.describeTo(fme)); - return; - } - if (toKick.getRole().value >= fme.getRole().value) { - msg(TL.COMMAND_KICK_INSUFFICIENTRANK); - return; - } - if (!Conf.canLeaveWithNegativePower && toKick.getPower() < 0) { - msg(TL.COMMAND_KICK_NEGATIVEPOWER); - return; - } - } + // This permission check has been cleaned to be more understandable and logical + // Unless is admin, + // - Check for the kick permission. + // - Make sure the player is in the faction. + // - Make sure the kicked player has lower rank than the kicker. + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.KICK); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_NOPERMISSION, "kick"); + return; + } + if (toKickFaction != myFaction) { + msg(TL.COMMAND_KICK_NOTMEMBER, toKick.describeTo(fme, true), myFaction.describeTo(fme)); + return; + } + if (toKick.getRole().value >= fme.getRole().value) { + msg(TL.COMMAND_KICK_INSUFFICIENTRANK); + return; + } + if (!Conf.canLeaveWithNegativePower && toKick.getPower() < 0) { + msg(TL.COMMAND_KICK_NEGATIVEPOWER); + return; + } + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (!canAffordCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (!canAffordCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString())) { + return; + } - // trigger the leave event (cancellable) [reason:kicked] - FPlayerLeaveEvent event = new FPlayerLeaveEvent(toKick, toKick.getFaction(), FPlayerLeaveEvent.PlayerLeaveReason.KICKED); - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } + // trigger the leave event (cancellable) [reason:kicked] + FPlayerLeaveEvent event = new FPlayerLeaveEvent(toKick, toKick.getFaction(), FPlayerLeaveEvent.PlayerLeaveReason.KICKED); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (!payForCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString(), TL.COMMAND_KICK_FORKICK.toString())) { - return; - } + // then make 'em pay (if applicable) + if (!payForCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString(), TL.COMMAND_KICK_FORKICK.toString())) { + return; + } - toKickFaction.msg(TL.COMMAND_KICK_FACTION, fme.describeTo(toKickFaction, true), toKick.describeTo(toKickFaction, true)); + toKickFaction.msg(TL.COMMAND_KICK_FACTION, fme.describeTo(toKickFaction, true), toKick.describeTo(toKickFaction, true)); - toKick.msg(TL.COMMAND_KICK_KICKED, fme.describeTo(toKick, true), toKickFaction.describeTo(toKick)); - if (toKickFaction != myFaction) { - fme.msg(TL.COMMAND_KICK_KICKS, toKick.describeTo(fme), toKickFaction.describeTo(fme)); - } - if (Conf.logFactionKick) { - SavageFactions.plugin.log((senderIsConsole ? "A console command" : fme.getName()) + " kicked " + toKick.getName() + " from the faction: " + toKickFaction.getTag()); - } - if (toKick.getRole() == Role.LEADER) { - toKickFaction.promoteNewLeader(); - } - toKickFaction.deinvite(toKick); - toKick.resetFactionData(); - } + toKick.msg(TL.COMMAND_KICK_KICKED, fme.describeTo(toKick, true), toKickFaction.describeTo(toKick)); + if (toKickFaction != myFaction) { + fme.msg(TL.COMMAND_KICK_KICKS, toKick.describeTo(fme), toKickFaction.describeTo(fme)); + } + if (Conf.logFactionKick) { + SavageFactions.plugin.log((senderIsConsole ? "A console command" : fme.getName()) + " kicked " + toKick.getName() + " from the faction: " + toKickFaction.getTag()); + } + if (toKick.getRole() == Role.LEADER) { + toKickFaction.promoteNewLeader(); + } + toKickFaction.deinvite(toKick); + toKick.resetFactionData(); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_KICK_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_KICK_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java b/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java index 0ee95a2b..4c3ec562 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java @@ -4,32 +4,32 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdKillHolograms extends FCommand { - public CmdKillHolograms() { - super(); + public CmdKillHolograms() { + super(); - this.aliases.add("killholos"); + this.aliases.add("killholos"); - this.requiredArgs.add("radius"); + this.requiredArgs.add("radius"); - this.permission = Permission.KILLHOLOS.node; - this.disableOnLock = true; + this.permission = Permission.KILLHOLOS.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - me.sendMessage("Killing Invisible Armor Stands.."); - me.chat("/minecraft:kill @e[type=ArmorStand,r=" + argAsInt(0) + "]"); + @Override + public void perform() { + me.sendMessage("Killing Invisible Armor Stands.."); + me.chat("/minecraft:kill @e[type=ArmorStand,r=" + argAsInt(0) + "]"); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_KILLHOLOGRAMS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_KILLHOLOGRAMS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java b/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java index b28f4ab6..8d9c5634 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java @@ -5,32 +5,32 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLeave extends FCommand { - public CmdLeave() { - super(); - this.aliases.add("leave"); + public CmdLeave() { + super(); + this.aliases.add("leave"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.LEAVE.node; - this.disableOnLock = true; + this.permission = Permission.LEAVE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - fme.leave(true); - } + @Override + public void perform() { + fme.leave(true); + } - @Override - public TL getUsageTranslation() { - return TL.LEAVE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.LEAVE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdList.java b/src/main/java/com/massivecraft/factions/cmd/CmdList.java index 7c6793e1..46f75b2b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdList.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdList.java @@ -13,119 +13,119 @@ import java.util.*; public class CmdList extends FCommand { - private String[] defaults = new String[3]; + private String[] defaults = new String[3]; - public CmdList() { - super(); - this.aliases.add("list"); - this.aliases.add("ls"); + public CmdList() { + super(); + this.aliases.add("list"); + this.aliases.add("ls"); - // default values in case user has old config - defaults[0] = "&e&m----------&r&e[ &2Faction List &9{pagenumber}&e/&9{pagecount} &e]&m----------"; - defaults[1] = "Factionless {factionless} online"; - defaults[2] = "
    {faction} {online} / {members} online, Land / Power / Maxpower: {chunks}/{power}/{maxPower}"; + // default values in case user has old config + defaults[0] = "&e&m----------&r&e[ &2Faction List &9{pagenumber}&e/&9{pagecount} &e]&m----------"; + defaults[1] = "Factionless {factionless} online"; + defaults[2] = "{faction} {online} / {members} online, Land / Power / Maxpower: {chunks}/{power}/{maxPower}"; - //this.requiredArgs.add(""); - this.optionalArgs.put("page", "1"); + //this.requiredArgs.add(""); + this.optionalArgs.put("page", "1"); - this.permission = Permission.LIST.node; - this.disableOnLock = false; + this.permission = Permission.LIST.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostList, "to list the factions", "for listing the factions")) - return; + @Override + public void perform() { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostList, "to list the factions", "for listing the factions")) + return; - ArrayList factionList = Factions.getInstance().getAllFactions(); - factionList.remove(Factions.getInstance().getWilderness()); - factionList.remove(Factions.getInstance().getSafeZone()); - factionList.remove(Factions.getInstance().getWarZone()); + ArrayList factionList = Factions.getInstance().getAllFactions(); + factionList.remove(Factions.getInstance().getWilderness()); + factionList.remove(Factions.getInstance().getSafeZone()); + factionList.remove(Factions.getInstance().getWarZone()); - // remove exempt factions - if (fme != null && fme.getPlayer() != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt")) { - List exemptFactions = SavageFactions.plugin.getConfig().getStringList("show-exempt"); - Iterator factionIterator = factionList.iterator(); + // remove exempt factions + if (fme != null && fme.getPlayer() != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt")) { + List exemptFactions = SavageFactions.plugin.getConfig().getStringList("show-exempt"); + Iterator factionIterator = factionList.iterator(); - while (factionIterator.hasNext()) { - Faction next = factionIterator.next(); - if (exemptFactions.contains(next.getTag())) - factionIterator.remove(); - } - } + while (factionIterator.hasNext()) { + Faction next = factionIterator.next(); + if (exemptFactions.contains(next.getTag())) + factionIterator.remove(); + } + } - // Sort by total followers first - Collections.sort(factionList, new Comparator() { - @Override - public int compare(Faction f1, Faction f2) { - int f1Size = f1.getFPlayers().size(); - int f2Size = f2.getFPlayers().size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - } - }); + // Sort by total followers first + Collections.sort(factionList, new Comparator() { + @Override + public int compare(Faction f1, Faction f2) { + int f1Size = f1.getFPlayers().size(); + int f2Size = f2.getFPlayers().size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + } + }); - // Then sort by how many members are online now - Collections.sort(factionList, new Comparator() { - @Override - public int compare(Faction f1, Faction f2) { - int f1Size = f1.getFPlayersWhereOnline(true).size(); - int f2Size = f2.getFPlayersWhereOnline(true).size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - } - }); + // Then sort by how many members are online now + Collections.sort(factionList, new Comparator() { + @Override + public int compare(Faction f1, Faction f2) { + int f1Size = f1.getFPlayersWhereOnline(true).size(); + int f2Size = f2.getFPlayersWhereOnline(true).size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + } + }); - ArrayList lines = new ArrayList<>(); + ArrayList lines = new ArrayList<>(); - factionList.add(0, Factions.getInstance().getWilderness()); + factionList.add(0, Factions.getInstance().getWilderness()); - final int pageheight = 9; - int pagenumber = this.argAsInt(0, 1); - int pagecount = (factionList.size() / pageheight) + 1; - if (pagenumber > pagecount) { - pagenumber = pagecount; - } else if (pagenumber < 1) { - pagenumber = 1; - } - int start = (pagenumber - 1) * pageheight; - int end = start + pageheight; - if (end > factionList.size()) { - end = factionList.size(); - } + final int pageheight = 9; + int pagenumber = this.argAsInt(0, 1); + int pagecount = (factionList.size() / pageheight) + 1; + if (pagenumber > pagecount) { + pagenumber = pagecount; + } else if (pagenumber < 1) { + pagenumber = 1; + } + int start = (pagenumber - 1) * pageheight; + int end = start + pageheight; + if (end > factionList.size()) { + end = factionList.size(); + } - String header = p.getConfig().getString("list.header", defaults[0]); - header = header.replace("{pagenumber}", String.valueOf(pagenumber)).replace("{pagecount}", String.valueOf(pagecount)); - lines.add(p.txt.parse(header)); + String header = p.getConfig().getString("list.header", defaults[0]); + header = header.replace("{pagenumber}", String.valueOf(pagenumber)).replace("{pagecount}", String.valueOf(pagecount)); + lines.add(p.txt.parse(header)); - for (Faction faction : factionList.subList(start, end)) { - if (faction.isWilderness()) { - lines.add(p.txt.parse(TagUtil.parsePlain(faction, p.getConfig().getString("list.factionless", defaults[1])))); - continue; - } - lines.add(p.txt.parse(TagUtil.parsePlain(faction, fme, p.getConfig().getString("list.entry", defaults[2])))); - } - sendMessage(lines); - } + for (Faction faction : factionList.subList(start, end)) { + if (faction.isWilderness()) { + lines.add(p.txt.parse(TagUtil.parsePlain(faction, p.getConfig().getString("list.factionless", defaults[1])))); + continue; + } + lines.add(p.txt.parse(TagUtil.parsePlain(faction, fme, p.getConfig().getString("list.entry", defaults[2])))); + } + sendMessage(lines); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LIST_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LIST_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLock.java b/src/main/java/com/massivecraft/factions/cmd/CmdLock.java index 37c1bdac..e8872473 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLock.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLock.java @@ -5,40 +5,40 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLock extends FCommand { - // TODO: This solution needs refactoring. + // TODO: This solution needs refactoring. /* factions.lock: description: use the /f lock [on/off] command to temporarily lock the data files from being overwritten default: op */ - public CmdLock() { - super(); - this.aliases.add("lock"); + public CmdLock() { + super(); + this.aliases.add("lock"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.LOCK.node; - this.disableOnLock = false; + this.permission = Permission.LOCK.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - p.setLocked(this.argAsBool(0, !p.getLocked())); - msg(p.getLocked() ? TL.COMMAND_LOCK_LOCKED : TL.COMMAND_LOCK_UNLOCKED); - } + @Override + public void perform() { + p.setLocked(this.argAsBool(0, !p.getLocked())); + msg(p.getLocked() ? TL.COMMAND_LOCK_LOCKED : TL.COMMAND_LOCK_UNLOCKED); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LOCK_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LOCK_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java b/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java index b310cbd0..ca0917cb 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java @@ -5,27 +5,27 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLogins extends FCommand { - public CmdLogins() { - super(); - this.aliases.add("login"); - this.aliases.add("logins"); - this.aliases.add("logout"); - this.aliases.add("logouts"); - this.senderMustBePlayer = true; + public CmdLogins() { + super(); + this.aliases.add("login"); + this.aliases.add("logins"); + this.aliases.add("logout"); + this.aliases.add("logouts"); + this.senderMustBePlayer = true; - this.senderMustBeMember = true; - this.permission = Permission.MONITOR_LOGINS.node; - } + this.senderMustBeMember = true; + this.permission = Permission.MONITOR_LOGINS.node; + } - @Override - public void perform() { - boolean monitor = fme.isMonitoringJoins(); - fme.msg(TL.COMMAND_LOGINS_TOGGLE, String.valueOf(!monitor)); - fme.setMonitorJoins(!monitor); - } + @Override + public void perform() { + boolean monitor = fme.isMonitoringJoins(); + fme.msg(TL.COMMAND_LOGINS_TOGGLE, String.valueOf(!monitor)); + fme.setMonitorJoins(!monitor); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LOGINS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LOGINS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java index 9d40fbe6..ac02a91f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java @@ -6,38 +6,38 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLowPower extends FCommand { - public CmdLowPower() { - super(); - this.aliases.add("lowpower"); + public CmdLowPower() { + super(); + this.aliases.add("lowpower"); - this.disableOnLock = false; + this.disableOnLock = false; - senderMustBePlayer = true; + senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double maxPower = Conf.powerPlayerMax; - String format = TL.COMMAND_LOWPOWER_FORMAT.toString(); - msg(TL.COMMAND_LOWPOWER_HEADER.toString().replace("{maxpower}", (int) maxPower + "")); - for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { - if (fPlayer.getPower() < maxPower) { - sendMessage(format.replace("{player}", fPlayer.getName()).replace("{player_power}", (int) fPlayer.getPower() + "").replace("{maxpower}", (int) maxPower + "")); - } - } - } + @Override + public void perform() { + double maxPower = Conf.powerPlayerMax; + String format = TL.COMMAND_LOWPOWER_FORMAT.toString(); + msg(TL.COMMAND_LOWPOWER_HEADER.toString().replace("{maxpower}", (int) maxPower + "")); + for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { + if (fPlayer.getPower() < maxPower) { + sendMessage(format.replace("{player}", fPlayer.getName()).replace("{player_power}", (int) fPlayer.getPower() + "").replace("{maxpower}", (int) maxPower + "")); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LOWPOWER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LOWPOWER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMap.java b/src/main/java/com/massivecraft/factions/cmd/CmdMap.java index 14ec1fce..ccbaffbd 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMap.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMap.java @@ -9,62 +9,62 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMap extends FCommand { - public CmdMap() { - super(); - this.aliases.add("map"); + public CmdMap() { + super(); + this.aliases.add("map"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "once"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "once"); - this.permission = Permission.MAP.node; - this.disableOnLock = false; + this.permission = Permission.MAP.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (this.argIsSet(0)) { - if (this.argAsBool(0, !fme.isMapAutoUpdating())) { - // Turn on + @Override + public void perform() { + if (this.argIsSet(0)) { + if (this.argAsBool(0, !fme.isMapAutoUpdating())) { + // Turn on - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostMap, "to show the map", "for showing the map")) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostMap, "to show the map", "for showing the map")) { + return; + } - fme.setMapAutoUpdating(true); - msg(TL.COMMAND_MAP_UPDATE_ENABLED); + fme.setMapAutoUpdating(true); + msg(TL.COMMAND_MAP_UPDATE_ENABLED); - // And show the map once - showMap(); - } else { - // Turn off - fme.setMapAutoUpdating(false); - msg(TL.COMMAND_MAP_UPDATE_DISABLED); - } - } else { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostMap, TL.COMMAND_MAP_TOSHOW, TL.COMMAND_MAP_FORSHOW)) { - return; - } + // And show the map once + showMap(); + } else { + // Turn off + fme.setMapAutoUpdating(false); + msg(TL.COMMAND_MAP_UPDATE_DISABLED); + } + } else { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostMap, TL.COMMAND_MAP_TOSHOW, TL.COMMAND_MAP_FORSHOW)) { + return; + } - showMap(); - } - } + showMap(); + } + } - public void showMap() { - sendFancyMessage(Board.getInstance().getMap(fme, new FLocation(fme), fme.getPlayer().getLocation().getYaw())); - } + public void showMap() { + sendFancyMessage(Board.getInstance().getMap(fme, new FLocation(fme), fme.getPlayer().getLocation().getYaw())); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MAP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MAP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java b/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java index eac2f9b2..5588f828 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java @@ -5,36 +5,36 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMapHeight extends FCommand { - public CmdMapHeight() { - super(); + public CmdMapHeight() { + super(); - this.aliases.add("mapheight"); - this.aliases.add("mh"); + this.aliases.add("mapheight"); + this.aliases.add("mh"); - this.optionalArgs.put("height", "height"); + this.optionalArgs.put("height", "height"); - this.permission = Permission.MAPHEIGHT.node; + this.permission = Permission.MAPHEIGHT.node; - this.senderMustBePlayer = true; - } + this.senderMustBePlayer = true; + } - @Override - public void perform() { - if (args.size() == 0) { - fme.sendMessage(TL.COMMAND_MAPHEIGHT_CURRENT.format(fme.getMapHeight())); - return; - } + @Override + public void perform() { + if (args.size() == 0) { + fme.sendMessage(TL.COMMAND_MAPHEIGHT_CURRENT.format(fme.getMapHeight())); + return; + } - int height = argAsInt(0); + int height = argAsInt(0); - fme.setMapHeight(height); - fme.sendMessage(TL.COMMAND_MAPHEIGHT_SET.format(fme.getMapHeight())); - } + fme.setMapHeight(height); + fme.sendMessage(TL.COMMAND_MAPHEIGHT_SET.format(fme.getMapHeight())); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MAPHEIGHT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MAPHEIGHT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMod.java b/src/main/java/com/massivecraft/factions/cmd/CmdMod.java index 978d4428..56ab092b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMod.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMod.java @@ -11,79 +11,79 @@ import org.bukkit.ChatColor; public class CmdMod extends FCommand { - public CmdMod() { - super(); - this.aliases.add("mod"); - this.aliases.add("setmod"); - this.aliases.add("officer"); - this.aliases.add("setofficer"); + public CmdMod() { + super(); + this.aliases.add("mod"); + this.aliases.add("setmod"); + this.aliases.add("officer"); + this.aliases.add("setofficer"); - this.optionalArgs.put("player name", "name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.MOD.node; - this.disableOnLock = true; + this.permission = Permission.MOD.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (you == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_MOD_CANDIDATES.toString()).color(ChatColor.GOLD); - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " mod " + s); - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (you == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_MOD_CANDIDATES.toString()).color(ChatColor.GOLD); + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " mod " + s); + } - sendFancyMessage(msg); - return; - } + sendFancyMessage(msg); + return; + } - boolean permAny = Permission.MOD_ANY.has(sender, false); - Faction targetFaction = you.getFaction(); - if (targetFaction != myFaction && !permAny) { - msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); - return; - } + boolean permAny = Permission.MOD_ANY.has(sender, false); + Faction targetFaction = you.getFaction(); + if (targetFaction != myFaction && !permAny) { + msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); + return; + } - if (fme != null && fme.getRole() != Role.LEADER && !permAny) { - msg(TL.COMMAND_MOD_NOTADMIN); - return; - } + if (fme != null && fme.getRole() != Role.LEADER && !permAny) { + msg(TL.COMMAND_MOD_NOTADMIN); + return; + } - if (you == fme && !permAny) { - msg(TL.COMMAND_MOD_SELF); - return; - } + if (you == fme && !permAny) { + msg(TL.COMMAND_MOD_SELF); + return; + } - if (you.getRole() == Role.LEADER) { - msg(TL.COMMAND_MOD_TARGETISADMIN); - return; - } + if (you.getRole() == Role.LEADER) { + msg(TL.COMMAND_MOD_TARGETISADMIN); + return; + } - if (you.getRole() == Role.MODERATOR) { - // Revoke - you.setRole(Role.NORMAL); - targetFaction.msg(TL.COMMAND_MOD_REVOKED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_MOD_REVOKES, you.describeTo(fme, true)); - } else { - // Give - you.setRole(Role.MODERATOR); - targetFaction.msg(TL.COMMAND_MOD_PROMOTED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_MOD_PROMOTES, you.describeTo(fme, true)); - } - } + if (you.getRole() == Role.MODERATOR) { + // Revoke + you.setRole(Role.NORMAL); + targetFaction.msg(TL.COMMAND_MOD_REVOKED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_MOD_REVOKES, you.describeTo(fme, true)); + } else { + // Give + you.setRole(Role.MODERATOR); + targetFaction.msg(TL.COMMAND_MOD_PROMOTED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_MOD_PROMOTES, you.describeTo(fme, true)); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MOD_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MOD_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java index 361e632f..1720bd91 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java @@ -6,45 +6,45 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdModifyPower extends FCommand { - public CmdModifyPower() { - super(); + public CmdModifyPower() { + super(); - this.aliases.add("pm"); - this.aliases.add("mp"); - this.aliases.add("modifypower"); - this.aliases.add("modpower"); + this.aliases.add("pm"); + this.aliases.add("mp"); + this.aliases.add("modifypower"); + this.aliases.add("modpower"); - this.requiredArgs.add("name"); - this.requiredArgs.add("power"); + this.requiredArgs.add("name"); + this.requiredArgs.add("power"); - this.permission = Permission.MODIFY_POWER.node; // admin only perm. + this.permission = Permission.MODIFY_POWER.node; // admin only perm. - // Let's not require anything and let console modify this as well. - this.senderMustBeAdmin = false; - this.senderMustBePlayer = false; - this.senderMustBeMember = false; - senderMustBeColeader = false; - this.senderMustBeModerator = false; - } + // Let's not require anything and let console modify this as well. + this.senderMustBeAdmin = false; + this.senderMustBePlayer = false; + this.senderMustBeMember = false; + senderMustBeColeader = false; + this.senderMustBeModerator = false; + } - @Override - public void perform() { - // /f modify # - FPlayer player = argAsBestFPlayerMatch(0); - Double number = argAsDouble(1); // returns null if not a Double. + @Override + public void perform() { + // /f modify # + FPlayer player = argAsBestFPlayerMatch(0); + Double number = argAsDouble(1); // returns null if not a Double. - if (player == null || number == null) { - sender.sendMessage(getHelpShort()); - return; - } + if (player == null || number == null) { + sender.sendMessage(getHelpShort()); + return; + } - player.alterPower(number); - int newPower = player.getPowerRounded(); // int so we don't have super long doubles. - msg(TL.COMMAND_MODIFYPOWER_ADDED, number, player.getName(), newPower); - } + player.alterPower(number); + int newPower = player.getPowerRounded(); // int so we don't have super long doubles. + msg(TL.COMMAND_MODIFYPOWER_ADDED, number, player.getName(), newPower); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MODIFYPOWER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MODIFYPOWER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java index b1cd4e19..dbce6182 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java @@ -5,48 +5,48 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMoney extends FCommand { - public CmdMoneyBalance cmdMoneyBalance = new CmdMoneyBalance(); - public CmdMoneyDeposit cmdMoneyDeposit = new CmdMoneyDeposit(); - public CmdMoneyWithdraw cmdMoneyWithdraw = new CmdMoneyWithdraw(); - public CmdMoneyTransferFf cmdMoneyTransferFf = new CmdMoneyTransferFf(); - public CmdMoneyTransferFp cmdMoneyTransferFp = new CmdMoneyTransferFp(); - public CmdMoneyTransferPf cmdMoneyTransferPf = new CmdMoneyTransferPf(); + public CmdMoneyBalance cmdMoneyBalance = new CmdMoneyBalance(); + public CmdMoneyDeposit cmdMoneyDeposit = new CmdMoneyDeposit(); + public CmdMoneyWithdraw cmdMoneyWithdraw = new CmdMoneyWithdraw(); + public CmdMoneyTransferFf cmdMoneyTransferFf = new CmdMoneyTransferFf(); + public CmdMoneyTransferFp cmdMoneyTransferFp = new CmdMoneyTransferFp(); + public CmdMoneyTransferPf cmdMoneyTransferPf = new CmdMoneyTransferPf(); - public CmdMoney() { - super(); - this.aliases.add("money"); + public CmdMoney() { + super(); + this.aliases.add("money"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("","") + //this.requiredArgs.add(""); + //this.optionalArgs.put("","") - this.isMoneyCommand = true; + this.isMoneyCommand = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - this.helpLong.add(p.txt.parseTags(TL.COMMAND_MONEY_LONG.toString())); + this.helpLong.add(p.txt.parseTags(TL.COMMAND_MONEY_LONG.toString())); - this.addSubCommand(this.cmdMoneyBalance); - this.addSubCommand(this.cmdMoneyDeposit); - this.addSubCommand(this.cmdMoneyWithdraw); - this.addSubCommand(this.cmdMoneyTransferFf); - this.addSubCommand(this.cmdMoneyTransferFp); - this.addSubCommand(this.cmdMoneyTransferPf); + this.addSubCommand(this.cmdMoneyBalance); + this.addSubCommand(this.cmdMoneyDeposit); + this.addSubCommand(this.cmdMoneyWithdraw); + this.addSubCommand(this.cmdMoneyTransferFf); + this.addSubCommand(this.cmdMoneyTransferFp); + this.addSubCommand(this.cmdMoneyTransferPf); - } + } - @Override - public void perform() { - this.commandChain.add(this); - SavageFactions.plugin.cmdAutoHelp.execute(this.sender, this.args, this.commandChain); - } + @Override + public void perform() { + this.commandChain.add(this); + SavageFactions.plugin.cmdAutoHelp.execute(this.sender, this.args, this.commandChain); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEY_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEY_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java index bce68b8a..83699a5e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java @@ -7,46 +7,46 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMoneyBalance extends FCommand { - public CmdMoneyBalance() { - super(); - this.aliases.add("b"); - this.aliases.add("balance"); + public CmdMoneyBalance() { + super(); + this.aliases.add("b"); + this.aliases.add("balance"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction", "yours"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction", "yours"); - this.permission = Permission.MONEY_BALANCE.node; - this.setHelpShort(TL.COMMAND_MONEYBALANCE_SHORT.toString()); + this.permission = Permission.MONEY_BALANCE.node; + this.setHelpShort(TL.COMMAND_MONEYBALANCE_SHORT.toString()); - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction faction = myFaction; - if (this.argIsSet(0)) { - faction = this.argAsFaction(0); - } + @Override + public void perform() { + Faction faction = myFaction; + if (this.argIsSet(0)) { + faction = this.argAsFaction(0); + } - if (faction == null) { - return; - } - if (faction != myFaction && !Permission.MONEY_BALANCE_ANY.has(sender, true)) { - return; - } + if (faction == null) { + return; + } + if (faction != myFaction && !Permission.MONEY_BALANCE_ANY.has(sender, true)) { + return; + } - if (fme != null) { - Econ.sendBalanceInfo(fme, faction); - } - } + if (fme != null) { + Econ.sendBalanceInfo(fme, faction); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYBALANCE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYBALANCE_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java index cdf79595..331161b6 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java @@ -11,41 +11,41 @@ import org.bukkit.ChatColor; public class CmdMoneyDeposit extends FCommand { - public CmdMoneyDeposit() { - super(); - this.aliases.add("d"); - this.aliases.add("deposit"); + public CmdMoneyDeposit() { + super(); + this.aliases.add("d"); + this.aliases.add("deposit"); - this.requiredArgs.add("amount"); - this.optionalArgs.put("faction", "yours"); + this.requiredArgs.add("amount"); + this.optionalArgs.put("faction", "yours"); - this.permission = Permission.MONEY_DEPOSIT.node; + this.permission = Permission.MONEY_DEPOSIT.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator faction = this.argAsFaction(1, myFaction); - if (faction == null) { - return; - } - boolean success = Econ.transferMoney(fme, fme, faction, amount); + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator faction = this.argAsFaction(1, myFaction); + if (faction == null) { + return; + } + boolean success = Econ.transferMoney(fme, fme, faction, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYDEPOSIT_DEPOSITED.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYDEPOSIT_DEPOSITED.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYDEPOSIT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYDEPOSIT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java index 75d5884d..27274da4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java @@ -12,47 +12,47 @@ import org.bukkit.entity.Player; public class CmdMoneyTransferFf extends FCommand { - public CmdMoneyTransferFf() { - this.aliases.add("ff"); + public CmdMoneyTransferFf() { + this.aliases.add("ff"); - this.requiredArgs.add("amount"); - this.requiredArgs.add("faction"); - this.requiredArgs.add("faction"); + this.requiredArgs.add("amount"); + this.requiredArgs.add("faction"); + this.requiredArgs.add("faction"); - //this.optionalArgs.put("", ""); + //this.optionalArgs.put("", ""); - this.permission = Permission.MONEY_F2F.node; + this.permission = Permission.MONEY_F2F.node; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator from = this.argAsFaction(1); - if (from == null) { - return; - } - EconomyParticipator to = this.argAsFaction(2); - if (to == null) { - return; - } + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator from = this.argAsFaction(1); + if (from == null) { + return; + } + EconomyParticipator to = this.argAsFaction(2); + if (to == null) { + return; + } - boolean success = Econ.transferMoney(fme, from, to, amount); + boolean success = Econ.transferMoney(fme, from, to, amount); - if (success && Conf.logMoneyTransactions) { - String name = sender instanceof Player ? fme.getName() : sender.getName(); - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFF_TRANSFER.toString(), name, Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + String name = sender instanceof Player ? fme.getName() : sender.getName(); + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFF_TRANSFER.toString(), name, Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYTRANSFERFF_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYTRANSFERFF_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java index 17eb50bb..e743ea9e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java @@ -11,46 +11,46 @@ import org.bukkit.ChatColor; public class CmdMoneyTransferFp extends FCommand { - public CmdMoneyTransferFp() { - this.aliases.add("fp"); + public CmdMoneyTransferFp() { + this.aliases.add("fp"); - this.requiredArgs.add("amount"); - this.requiredArgs.add("faction"); - this.requiredArgs.add("player"); + this.requiredArgs.add("amount"); + this.requiredArgs.add("faction"); + this.requiredArgs.add("player"); - //this.optionalArgs.put("", ""); + //this.optionalArgs.put("", ""); - this.permission = Permission.MONEY_F2P.node; + this.permission = Permission.MONEY_F2P.node; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator from = this.argAsFaction(1); - if (from == null) { - return; - } - EconomyParticipator to = this.argAsBestFPlayerMatch(2); - if (to == null) { - return; - } + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator from = this.argAsFaction(1); + if (from == null) { + return; + } + EconomyParticipator to = this.argAsBestFPlayerMatch(2); + if (to == null) { + return; + } - boolean success = Econ.transferMoney(fme, from, to, amount); + boolean success = Econ.transferMoney(fme, from, to, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFP_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFP_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYTRANSFERFP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYTRANSFERFP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java index 474cb70e..f245e4d5 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java @@ -11,46 +11,46 @@ import org.bukkit.ChatColor; public class CmdMoneyTransferPf extends FCommand { - public CmdMoneyTransferPf() { - this.aliases.add("pf"); + public CmdMoneyTransferPf() { + this.aliases.add("pf"); - this.requiredArgs.add("amount"); - this.requiredArgs.add("player"); - this.requiredArgs.add("faction"); + this.requiredArgs.add("amount"); + this.requiredArgs.add("player"); + this.requiredArgs.add("faction"); - //this.optionalArgs.put("", ""); + //this.optionalArgs.put("", ""); - this.permission = Permission.MONEY_P2F.node; + this.permission = Permission.MONEY_P2F.node; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator from = this.argAsBestFPlayerMatch(1); - if (from == null) { - return; - } - EconomyParticipator to = this.argAsFaction(2); - if (to == null) { - return; - } + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator from = this.argAsBestFPlayerMatch(1); + if (from == null) { + return; + } + EconomyParticipator to = this.argAsFaction(2); + if (to == null) { + return; + } - boolean success = Econ.transferMoney(fme, from, to, amount); + boolean success = Econ.transferMoney(fme, from, to, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERPF_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERPF_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYTRANSFERPF_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYTRANSFERPF_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java index 32f4e07e..e08791d7 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java @@ -13,47 +13,47 @@ import org.bukkit.ChatColor; public class CmdMoneyWithdraw extends FCommand { - public CmdMoneyWithdraw() { - this.aliases.add("w"); - this.aliases.add("withdraw"); + public CmdMoneyWithdraw() { + this.aliases.add("w"); + this.aliases.add("withdraw"); - this.requiredArgs.add("amount"); - this.optionalArgs.put("faction", "yours"); + this.requiredArgs.add("amount"); + this.optionalArgs.put("faction", "yours"); - this.permission = Permission.MONEY_WITHDRAW.node; + this.permission = Permission.MONEY_WITHDRAW.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { + @Override + public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator faction = this.argAsFaction(1, myFaction); - if (faction == null) { - return; - } + double amount = this.argAsDouble(0, 0d); + EconomyParticipator faction = this.argAsFaction(1, myFaction); + if (faction == null) { + return; + } - Access access = myFaction.getAccess(fme, PermissableAction.WITHDRAW); - if (access == Access.DENY) { - fme.msg(TL.GENERIC_NOPERMISSION, "withdraw"); - return; - } + Access access = myFaction.getAccess(fme, PermissableAction.WITHDRAW); + if (access == Access.DENY) { + fme.msg(TL.GENERIC_NOPERMISSION, "withdraw"); + return; + } - boolean success = Econ.transferMoney(fme, faction, fme, amount); + boolean success = Econ.transferMoney(fme, faction, fme, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYWITHDRAW_WITHDRAW.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYWITHDRAW_WITHDRAW.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYWITHDRAW_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYWITHDRAW_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdNear.java b/src/main/java/com/massivecraft/factions/cmd/CmdNear.java index 0a6208c8..eeae4895 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdNear.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdNear.java @@ -8,47 +8,47 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; public class CmdNear extends FCommand { - public CmdNear() { - super(); + public CmdNear() { + super(); - this.aliases.add("near"); - this.aliases.add("nearby"); + this.aliases.add("near"); + this.aliases.add("nearby"); - this.disableOnLock = true; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fnear.Enabled")) { - fme.msg(TL.COMMAND_NEAR_DISABLED_MSG); - return; - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fnear.Enabled")) { + fme.msg(TL.COMMAND_NEAR_DISABLED_MSG); + return; + } - double range = SavageFactions.plugin.getConfig().getInt("fnear.Radius"); - String format = TL.COMMAND_NEAR_FORMAT.toString(); - fme.msg(TL.COMMAND_NEAR_USE_MSG); - for (Entity e : me.getNearbyEntities(range, 255, range)) { - if (e instanceof Player) { - Player player = (((Player) e).getPlayer()); - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fme.getFaction() == fplayer.getFaction()) { - double distance = me.getLocation().distance(player.getLocation()); - fme.sendMessage(format.replace("{playername}", player.getDisplayName()).replace("{distance}", (int) distance + "")); - } - } + double range = SavageFactions.plugin.getConfig().getInt("fnear.Radius"); + String format = TL.COMMAND_NEAR_FORMAT.toString(); + fme.msg(TL.COMMAND_NEAR_USE_MSG); + for (Entity e : me.getNearbyEntities(range, 255, range)) { + if (e instanceof Player) { + Player player = (((Player) e).getPlayer()); + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fme.getFaction() == fplayer.getFaction()) { + double distance = me.getLocation().distance(player.getLocation()); + fme.sendMessage(format.replace("{playername}", player.getDisplayName()).replace("{distance}", (int) distance + "")); + } + } - } - } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_NEAR_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_NEAR_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java b/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java index 0d3dabe3..ba0c8f6b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java @@ -8,48 +8,48 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdOpen extends FCommand { - public CmdOpen() { - super(); - this.aliases.add("open"); + public CmdOpen() { + super(); + this.aliases.add("open"); - //this.requiredArgs.add(""); - this.optionalArgs.put("yes/no", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("yes/no", "flip"); - this.permission = Permission.OPEN.node; - this.disableOnLock = false; + this.permission = Permission.OPEN.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostOpen, TL.COMMAND_OPEN_TOOPEN, TL.COMMAND_OPEN_FOROPEN)) { - return; - } + @Override + public void perform() { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostOpen, TL.COMMAND_OPEN_TOOPEN, TL.COMMAND_OPEN_FOROPEN)) { + return; + } - myFaction.setOpen(this.argAsBool(0, !myFaction.getOpen())); + myFaction.setOpen(this.argAsBool(0, !myFaction.getOpen())); - String open = myFaction.getOpen() ? TL.COMMAND_OPEN_OPEN.toString() : TL.COMMAND_OPEN_CLOSED.toString(); + String open = myFaction.getOpen() ? TL.COMMAND_OPEN_OPEN.toString() : TL.COMMAND_OPEN_CLOSED.toString(); - // Inform - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (fplayer.getFactionId().equals(myFaction.getId())) { - fplayer.msg(TL.COMMAND_OPEN_CHANGES, fme.getName(), open); - continue; - } - fplayer.msg(TL.COMMAND_OPEN_CHANGED, myFaction.getTag(fplayer.getFaction()), open); - } - } + // Inform + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.getFactionId().equals(myFaction.getId())) { + fplayer.msg(TL.COMMAND_OPEN_CHANGES, fme.getName(), open); + continue; + } + fplayer.msg(TL.COMMAND_OPEN_CHANGED, myFaction.getTag(fplayer.getFaction()), open); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_OPEN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_OPEN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java b/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java index 9811f02c..beb69334 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java @@ -8,100 +8,100 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdOwner extends FCommand { - public CmdOwner() { - super(); - this.aliases.add("owner"); + public CmdOwner() { + super(); + this.aliases.add("owner"); - //this.requiredArgs.add(""); - this.optionalArgs.put("player name", "you"); + //this.requiredArgs.add(""); + this.optionalArgs.put("player name", "you"); - this.permission = Permission.OWNER.node; - this.disableOnLock = true; + this.permission = Permission.OWNER.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - // TODO: Fix colors! + // TODO: Fix colors! - @Override - public void perform() { - boolean hasBypass = fme.isAdminBypassing(); + @Override + public void perform() { + boolean hasBypass = fme.isAdminBypassing(); - if (!hasBypass && !assertHasFaction()) { - return; - } + if (!hasBypass && !assertHasFaction()) { + return; + } - if (!Conf.ownedAreasEnabled) { - fme.msg(TL.COMMAND_OWNER_DISABLED); - return; - } + if (!Conf.ownedAreasEnabled) { + fme.msg(TL.COMMAND_OWNER_DISABLED); + return; + } - if (!hasBypass && Conf.ownedAreasLimitPerFaction > 0 && myFaction.getCountOfClaimsWithOwners() >= Conf.ownedAreasLimitPerFaction) { - fme.msg(TL.COMMAND_OWNER_LIMIT, Conf.ownedAreasLimitPerFaction); - return; - } + if (!hasBypass && Conf.ownedAreasLimitPerFaction > 0 && myFaction.getCountOfClaimsWithOwners() >= Conf.ownedAreasLimitPerFaction) { + fme.msg(TL.COMMAND_OWNER_LIMIT, Conf.ownedAreasLimitPerFaction); + return; + } - if (!hasBypass && !assertMinRole(Conf.ownedAreasModeratorsCanSet ? Role.MODERATOR : Role.LEADER)) { - return; - } + if (!hasBypass && !assertMinRole(Conf.ownedAreasModeratorsCanSet ? Role.MODERATOR : Role.LEADER)) { + return; + } - FLocation flocation = new FLocation(fme); + FLocation flocation = new FLocation(fme); - Faction factionHere = Board.getInstance().getFactionAt(flocation); - if (factionHere != myFaction) { - if (!factionHere.isNormal()) { - fme.msg(TL.COMMAND_OWNER_NOTCLAIMED); - return; - } + Faction factionHere = Board.getInstance().getFactionAt(flocation); + if (factionHere != myFaction) { + if (!factionHere.isNormal()) { + fme.msg(TL.COMMAND_OWNER_NOTCLAIMED); + return; + } - if (!hasBypass) { - fme.msg(TL.COMMAND_OWNER_WRONGFACTION); - return; - } - } + if (!hasBypass) { + fme.msg(TL.COMMAND_OWNER_WRONGFACTION); + return; + } + } - FPlayer target = this.argAsBestFPlayerMatch(0, fme); - if (target == null) { - return; - } + FPlayer target = this.argAsBestFPlayerMatch(0, fme); + if (target == null) { + return; + } - String playerName = target.getName(); + String playerName = target.getName(); - if (target.getFaction() != myFaction) { - fme.msg(TL.COMMAND_OWNER_NOTMEMBER, playerName); - return; - } + if (target.getFaction() != myFaction) { + fme.msg(TL.COMMAND_OWNER_NOTMEMBER, playerName); + return; + } - // if no player name was passed, and this claim does already have owners set, clear them - if (args.isEmpty() && myFaction.doesLocationHaveOwnersSet(flocation)) { - myFaction.clearClaimOwnership(flocation); - fme.msg(TL.COMMAND_OWNER_CLEARED); - return; - } + // if no player name was passed, and this claim does already have owners set, clear them + if (args.isEmpty() && myFaction.doesLocationHaveOwnersSet(flocation)) { + myFaction.clearClaimOwnership(flocation); + fme.msg(TL.COMMAND_OWNER_CLEARED); + return; + } - if (myFaction.isPlayerInOwnerList(target, flocation)) { - myFaction.removePlayerAsOwner(target, flocation); - fme.msg(TL.COMMAND_OWNER_REMOVED, playerName); - return; - } + if (myFaction.isPlayerInOwnerList(target, flocation)) { + myFaction.removePlayerAsOwner(target, flocation); + fme.msg(TL.COMMAND_OWNER_REMOVED, playerName); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostOwner, TL.COMMAND_OWNER_TOSET, TL.COMMAND_OWNER_FORSET)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostOwner, TL.COMMAND_OWNER_TOSET, TL.COMMAND_OWNER_FORSET)) { + return; + } - myFaction.setPlayerAsOwner(target, flocation); + myFaction.setPlayerAsOwner(target, flocation); - fme.msg(TL.COMMAND_OWNER_ADDED, playerName); - } + fme.msg(TL.COMMAND_OWNER_ADDED, playerName); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_OWNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_OWNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java b/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java index ee49571e..4d0f77d1 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java @@ -9,64 +9,64 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdOwnerList extends FCommand { - public CmdOwnerList() { - super(); - this.aliases.add("ownerlist"); + public CmdOwnerList() { + super(); + this.aliases.add("ownerlist"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.OWNERLIST.node; - this.disableOnLock = false; + this.permission = Permission.OWNERLIST.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - boolean hasBypass = fme.isAdminBypassing(); + @Override + public void perform() { + boolean hasBypass = fme.isAdminBypassing(); - if (!hasBypass && !assertHasFaction()) { - return; - } + if (!hasBypass && !assertHasFaction()) { + return; + } - if (!Conf.ownedAreasEnabled) { - fme.msg(TL.COMMAND_OWNERLIST_DISABLED); - return; - } + if (!Conf.ownedAreasEnabled) { + fme.msg(TL.COMMAND_OWNERLIST_DISABLED); + return; + } - FLocation flocation = new FLocation(fme); + FLocation flocation = new FLocation(fme); - if (Board.getInstance().getFactionAt(flocation) != myFaction) { - if (!hasBypass) { - fme.msg(TL.COMMAND_OWNERLIST_WRONGFACTION); - return; - } - //TODO: This code won't ever be called. - myFaction = Board.getInstance().getFactionAt(flocation); - if (!myFaction.isNormal()) { - fme.msg(TL.COMMAND_OWNERLIST_NOTCLAIMED); - return; - } - } + if (Board.getInstance().getFactionAt(flocation) != myFaction) { + if (!hasBypass) { + fme.msg(TL.COMMAND_OWNERLIST_WRONGFACTION); + return; + } + //TODO: This code won't ever be called. + myFaction = Board.getInstance().getFactionAt(flocation); + if (!myFaction.isNormal()) { + fme.msg(TL.COMMAND_OWNERLIST_NOTCLAIMED); + return; + } + } - String owners = myFaction.getOwnerListString(flocation); + String owners = myFaction.getOwnerListString(flocation); - if (owners == null || owners.isEmpty()) { - fme.msg(TL.COMMAND_OWNERLIST_NONE); - return; - } + if (owners == null || owners.isEmpty()) { + fme.msg(TL.COMMAND_OWNERLIST_NONE); + return; + } - fme.msg(TL.COMMAND_OWNERLIST_OWNERS, owners); - } + fme.msg(TL.COMMAND_OWNERLIST_OWNERS, owners); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_OWNERLIST_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_OWNERLIST_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java index ade8d076..29a789fe 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java @@ -6,44 +6,44 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdPaypalSee extends FCommand { - public CmdPaypalSee() { - aliases.add("seepaypal"); - aliases.add("getpaypal"); - requiredArgs.add("faction"); - permission = Permission.ADMIN.node; - disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + public CmdPaypalSee() { + aliases.add("seepaypal"); + aliases.add("getpaypal"); + requiredArgs.add("faction"); + permission = Permission.ADMIN.node; + disableOnLock = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - fme.msg(TL.GENERIC_DISABLED); - } else { - Faction faction = argAsFaction(0); + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + fme.msg(TL.GENERIC_DISABLED); + } else { + Faction faction = argAsFaction(0); - if (faction != null) { - if (!faction.isWilderness() && !faction.isSafeZone() && !faction.isWarZone()) { - if (faction.getPaypal() != null) { - fme.msg(TL.COMMAND_PAYPALSEE_FACTION_PAYPAL.toString(), faction.getTag(), faction.getPaypal()); - } else { - fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOTSET.toString(), faction.getTag(), faction.getPaypal()); - } + if (faction != null) { + if (!faction.isWilderness() && !faction.isSafeZone() && !faction.isWarZone()) { + if (faction.getPaypal() != null) { + fme.msg(TL.COMMAND_PAYPALSEE_FACTION_PAYPAL.toString(), faction.getTag(), faction.getPaypal()); + } else { + fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOTSET.toString(), faction.getTag(), faction.getPaypal()); + } - } else { - fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOFACTION.toString(), me.getName()); - } - } - } - } + } else { + fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOFACTION.toString(), me.getName()); + } + } + } + } - public TL getUsageTranslation() { - return TL.COMMAND_PAYPALSEE_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_PAYPALSEE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java index 35456fbd..02b1b3a4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java @@ -6,34 +6,34 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdPaypalSet extends FCommand { - public CmdPaypalSet() { - this.aliases.add("setpaypal"); - this.aliases.add("paypal"); - this.requiredArgs.add("email"); - this.permission = Permission.PAYPALSET.node; - this.disableOnLock = false; - this.senderMustBePlayer = true; - this.senderMustBeMember = false; - this.senderMustBeModerator = false; - this.senderMustBeColeader = true; - this.senderMustBeAdmin = false; + public CmdPaypalSet() { + this.aliases.add("setpaypal"); + this.aliases.add("paypal"); + this.requiredArgs.add("email"); + this.permission = Permission.PAYPALSET.node; + this.disableOnLock = false; + this.senderMustBePlayer = true; + this.senderMustBeMember = false; + this.senderMustBeModerator = false; + this.senderMustBeColeader = true; + this.senderMustBeAdmin = false; - } + } - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - fme.msg(TL.GENERIC_DISABLED); - } else { - String paypal = argAsString(0); - if (paypal != null) { - myFaction.paypalSet(paypal); - fme.msg(TL.COMMAND_PAYPALSET_SUCCESSFUL, paypal); - } - } - } + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + fme.msg(TL.GENERIC_DISABLED); + } else { + String paypal = argAsString(0); + if (paypal != null) { + myFaction.paypalSet(paypal); + fme.msg(TL.COMMAND_PAYPALSET_SUCCESSFUL, paypal); + } + } + } - public TL getUsageTranslation() { - return TL.COMMAND_PAYPALSET_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_PAYPALSET_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java b/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java index 02f6bb29..58151f98 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java @@ -8,55 +8,55 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdPeaceful extends FCommand { - public CmdPeaceful() { - super(); - this.aliases.add("peaceful"); + public CmdPeaceful() { + super(); + this.aliases.add("peaceful"); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); - this.permission = Permission.SET_PEACEFUL.node; - this.disableOnLock = true; + this.permission = Permission.SET_PEACEFUL.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - Faction faction = this.argAsFaction(0); - if (faction == null) { - return; - } + @Override + public void perform() { + Faction faction = this.argAsFaction(0); + if (faction == null) { + return; + } - String change; - if (faction.isPeaceful()) { - change = TL.COMMAND_PEACEFUL_REVOKE.toString(); - faction.setPeaceful(false); - } else { - change = TL.COMMAND_PEACEFUL_GRANT.toString(); - faction.setPeaceful(true); - } + String change; + if (faction.isPeaceful()) { + change = TL.COMMAND_PEACEFUL_REVOKE.toString(); + faction.setPeaceful(false); + } else { + change = TL.COMMAND_PEACEFUL_GRANT.toString(); + faction.setPeaceful(true); + } - // Inform all players - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); - if (fplayer.getFaction() == faction) { - fplayer.msg(TL.COMMAND_PEACEFUL_YOURS, blame, change); - } else { - fplayer.msg(TL.COMMAND_PEACEFUL_OTHER, blame, change, faction.getTag(fplayer)); - } - } + // Inform all players + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); + if (fplayer.getFaction() == faction) { + fplayer.msg(TL.COMMAND_PEACEFUL_YOURS, blame, change); + } else { + fplayer.msg(TL.COMMAND_PEACEFUL_OTHER, blame, change, faction.getTag(fplayer)); + } + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PEACEFUL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PEACEFUL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java b/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java index 6c942012..6c3f6541 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java @@ -16,111 +16,111 @@ import java.util.Set; public class CmdPerm extends FCommand { - public CmdPerm() { - super(); - this.aliases.add("perm"); - this.aliases.add("perms"); - this.aliases.add("permission"); - this.aliases.add("permissions"); + public CmdPerm() { + super(); + this.aliases.add("perm"); + this.aliases.add("perms"); + this.aliases.add("permission"); + this.aliases.add("permissions"); - this.optionalArgs.put("relation", "relation"); - this.optionalArgs.put("action", "action"); - this.optionalArgs.put("access", "access"); + this.optionalArgs.put("relation", "relation"); + this.optionalArgs.put("action", "action"); + this.optionalArgs.put("access", "access"); - this.disableOnLock = true; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = true; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = true; - } + } - @Override - public void perform() { - if (args.size() == 0) { - PermissableRelationGUI gui = new PermissableRelationGUI(fme); - gui.build(); + @Override + public void perform() { + if (args.size() == 0) { + PermissableRelationGUI gui = new PermissableRelationGUI(fme); + gui.build(); - me.openInventory(gui.getInventory()); - return; - } else if (args.size() == 1 && getPermissable(argAsString(0)) != null) { - PermissableActionGUI gui = new PermissableActionGUI(fme, getPermissable(argAsString(0))); - gui.build(); + me.openInventory(gui.getInventory()); + return; + } else if (args.size() == 1 && getPermissable(argAsString(0)) != null) { + PermissableActionGUI gui = new PermissableActionGUI(fme, getPermissable(argAsString(0))); + gui.build(); - me.openInventory(gui.getInventory()); - return; - } + me.openInventory(gui.getInventory()); + return; + } - // If not opening GUI, then setting the permission manually. - if (args.size() != 3) { - fme.msg(TL.COMMAND_PERM_DESCRIPTION); - return; - } + // If not opening GUI, then setting the permission manually. + if (args.size() != 3) { + fme.msg(TL.COMMAND_PERM_DESCRIPTION); + return; + } - Set permissables = new HashSet<>(); - Set permissableActions = new HashSet<>(); + Set permissables = new HashSet<>(); + Set permissableActions = new HashSet<>(); - boolean allRelations = argAsString(0).equalsIgnoreCase("all"); - boolean allActions = argAsString(1).equalsIgnoreCase("all"); + boolean allRelations = argAsString(0).equalsIgnoreCase("all"); + boolean allActions = argAsString(1).equalsIgnoreCase("all"); - if (allRelations) { - permissables.addAll(myFaction.getPermissions().keySet()); - } else { - Permissable permissable = getPermissable(argAsString(0)); + if (allRelations) { + permissables.addAll(myFaction.getPermissions().keySet()); + } else { + Permissable permissable = getPermissable(argAsString(0)); - if (permissable == null) { - fme.msg(TL.COMMAND_PERM_INVALID_RELATION); - return; - } + if (permissable == null) { + fme.msg(TL.COMMAND_PERM_INVALID_RELATION); + return; + } - permissables.add(permissable); - } + permissables.add(permissable); + } - if (allActions) { - permissableActions.addAll(Arrays.asList(PermissableAction.values())); - } else { - PermissableAction permissableAction = PermissableAction.fromString(argAsString(1)); - if (permissableAction == null) { - fme.msg(TL.COMMAND_PERM_INVALID_ACTION); - return; - } + if (allActions) { + permissableActions.addAll(Arrays.asList(PermissableAction.values())); + } else { + PermissableAction permissableAction = PermissableAction.fromString(argAsString(1)); + if (permissableAction == null) { + fme.msg(TL.COMMAND_PERM_INVALID_ACTION); + return; + } - permissableActions.add(permissableAction); - } + permissableActions.add(permissableAction); + } - Access access = Access.fromString(argAsString(2)); + Access access = Access.fromString(argAsString(2)); - if (access == null) { - fme.msg(TL.COMMAND_PERM_INVALID_ACCESS); - return; - } + if (access == null) { + fme.msg(TL.COMMAND_PERM_INVALID_ACCESS); + return; + } - for (Permissable permissable : permissables) { - for (PermissableAction permissableAction : permissableActions) { - fme.getFaction().setPermission(permissable, permissableAction, access); - } - } + for (Permissable permissable : permissables) { + for (PermissableAction permissableAction : permissableActions) { + fme.getFaction().setPermission(permissable, permissableAction, access); + } + } - fme.msg(TL.COMMAND_PERM_SET, argAsString(1), access.name(), argAsString(0)); - SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), argAsString(1), access.name(), argAsString(0)) + " for faction " + fme.getTag()); - } + fme.msg(TL.COMMAND_PERM_SET, argAsString(1), access.name(), argAsString(0)); + SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), argAsString(1), access.name(), argAsString(0)) + " for faction " + fme.getTag()); + } - private Permissable getPermissable(String name) { - if (Role.fromString(name.toUpperCase()) != null) { - return Role.fromString(name.toUpperCase()); - } else if (Relation.fromString(name.toUpperCase()) != null) { - return Relation.fromString(name.toUpperCase()); - } else { - return null; - } - } + private Permissable getPermissable(String name) { + if (Role.fromString(name.toUpperCase()) != null) { + return Role.fromString(name.toUpperCase()); + } else if (Relation.fromString(name.toUpperCase()) != null) { + return Relation.fromString(name.toUpperCase()); + } else { + return null; + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PERM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PERM_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java b/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java index 369b8415..54e71cd0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java @@ -1,63 +1,63 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.FPlayers; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - - -public class CmdPermanent extends FCommand { - - public CmdPermanent() { - super(); - this.aliases.add("permanent"); - - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); - - this.permission = Permission.SET_PERMANENT.node; - this.disableOnLock = true; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - Faction faction = this.argAsFaction(0); - if (faction == null) { - return; - } - - String change; - if (faction.isPermanent()) { - change = TL.COMMAND_PERMANENT_REVOKE.toString(); - faction.setPermanent(false); - } else { - change = TL.COMMAND_PERMANENT_GRANT.toString(); - faction.setPermanent(true); - } - - SavageFactions.plugin.log((fme == null ? "A server admin" : fme.getName()) + " " + change + " the faction \"" + faction.getTag() + "\"."); - - // Inform all players - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); - if (fplayer.getFaction() == faction) { - fplayer.msg(TL.COMMAND_PERMANENT_YOURS, blame, change); - } else { - fplayer.msg(TL.COMMAND_PERMANENT_OTHER, blame, change, faction.getTag(fplayer)); - } - } - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PERMANENT_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + + +public class CmdPermanent extends FCommand { + + public CmdPermanent() { + super(); + this.aliases.add("permanent"); + + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); + + this.permission = Permission.SET_PERMANENT.node; + this.disableOnLock = true; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + Faction faction = this.argAsFaction(0); + if (faction == null) { + return; + } + + String change; + if (faction.isPermanent()) { + change = TL.COMMAND_PERMANENT_REVOKE.toString(); + faction.setPermanent(false); + } else { + change = TL.COMMAND_PERMANENT_GRANT.toString(); + faction.setPermanent(true); + } + + SavageFactions.plugin.log((fme == null ? "A server admin" : fme.getName()) + " " + change + " the faction \"" + faction.getTag() + "\"."); + + // Inform all players + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); + if (fplayer.getFaction() == faction) { + fplayer.msg(TL.COMMAND_PERMANENT_YOURS, blame, change); + } else { + fplayer.msg(TL.COMMAND_PERMANENT_OTHER, blame, change, faction.getTag(fplayer)); + } + } + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PERMANENT_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java index 5e0018d5..5e985ea1 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java @@ -1,59 +1,59 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - -public class CmdPermanentPower extends FCommand { - public CmdPermanentPower() { - super(); - this.aliases.add("permanentpower"); - - this.requiredArgs.add("faction"); - this.requiredArgs.add("power"); - - this.permission = Permission.SET_PERMANENTPOWER.node; - this.disableOnLock = true; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - Faction targetFaction = this.argAsFaction(0); - if (targetFaction == null) { - return; - } - - Integer targetPower = this.argAsInt(1); - - targetFaction.setPermanentPower(targetPower); - - String change = TL.COMMAND_PERMANENTPOWER_REVOKE.toString(); - if (targetFaction.hasPermanentPower()) { - change = TL.COMMAND_PERMANENTPOWER_GRANT.toString(); - } - - // Inform sender - msg(TL.COMMAND_PERMANENTPOWER_SUCCESS, change, targetFaction.describeTo(fme)); - - // Inform all other players - for (FPlayer fplayer : targetFaction.getFPlayersWhereOnline(true)) { - if (fplayer == fme) { - continue; - } - String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); - fplayer.msg(TL.COMMAND_PERMANENTPOWER_FACTION, blame, change); - } - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PERMANENTPOWER_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + +public class CmdPermanentPower extends FCommand { + public CmdPermanentPower() { + super(); + this.aliases.add("permanentpower"); + + this.requiredArgs.add("faction"); + this.requiredArgs.add("power"); + + this.permission = Permission.SET_PERMANENTPOWER.node; + this.disableOnLock = true; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + Faction targetFaction = this.argAsFaction(0); + if (targetFaction == null) { + return; + } + + Integer targetPower = this.argAsInt(1); + + targetFaction.setPermanentPower(targetPower); + + String change = TL.COMMAND_PERMANENTPOWER_REVOKE.toString(); + if (targetFaction.hasPermanentPower()) { + change = TL.COMMAND_PERMANENTPOWER_GRANT.toString(); + } + + // Inform sender + msg(TL.COMMAND_PERMANENTPOWER_SUCCESS, change, targetFaction.describeTo(fme)); + + // Inform all other players + for (FPlayer fplayer : targetFaction.getFPlayersWhereOnline(true)) { + if (fplayer == fme) { + continue; + } + String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); + fplayer.msg(TL.COMMAND_PERMANENTPOWER_FACTION, blame, change); + } + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PERMANENTPOWER_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdPower.java index 985d8770..755ddbe0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPower.java @@ -7,50 +7,50 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdPower extends FCommand { - public CmdPower() { - super(); - this.aliases.add("power"); - this.aliases.add("pow"); + public CmdPower() { + super(); + this.aliases.add("power"); + this.aliases.add("pow"); - //this.requiredArgs.add("faction tag"); - this.optionalArgs.put("player name", "you"); + //this.requiredArgs.add("faction tag"); + this.optionalArgs.put("player name", "you"); - this.permission = Permission.POWER.node; - this.disableOnLock = false; + this.permission = Permission.POWER.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - FPlayer target = this.argAsBestFPlayerMatch(0, fme); - if (target == null) { - return; - } + @Override + public void perform() { + FPlayer target = this.argAsBestFPlayerMatch(0, fme); + if (target == null) { + return; + } - if (target != fme && !Permission.POWER_ANY.has(sender, true)) { - return; - } + if (target != fme && !Permission.POWER_ANY.has(sender, true)) { + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostPower, TL.COMMAND_POWER_TOSHOW, TL.COMMAND_POWER_FORSHOW)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostPower, TL.COMMAND_POWER_TOSHOW, TL.COMMAND_POWER_FORSHOW)) { + return; + } - double powerBoost = target.getPowerBoost(); - String boost = (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_POWER_BONUS.toString() : TL.COMMAND_POWER_PENALTY.toString()) + powerBoost + ")"; - msg(TL.COMMAND_POWER_POWER, target.describeTo(fme, true), target.getPowerRounded(), target.getPowerMaxRounded(), boost); - } + double powerBoost = target.getPowerBoost(); + String boost = (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_POWER_BONUS.toString() : TL.COMMAND_POWER_PENALTY.toString()) + powerBoost + ")"; + msg(TL.COMMAND_POWER_POWER, target.describeTo(fme, true), target.getPowerRounded(), target.getPowerMaxRounded(), boost); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_POWER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_POWER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java b/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java index 53290afe..54a4d3b7 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java @@ -1,88 +1,88 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - -public class CmdPowerBoost extends FCommand { - - public CmdPowerBoost() { - super(); - this.aliases.add("powerboost"); - - this.requiredArgs.add("plugin|f|player|faction"); - this.requiredArgs.add("name"); - this.requiredArgs.add("# or reset"); - - this.permission = Permission.POWERBOOST.node; - this.disableOnLock = true; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - String type = this.argAsString(0).toLowerCase(); - boolean doPlayer = true; - if (type.equals("f") || type.equals("faction")) { - doPlayer = false; - } else if (!type.equals("plugin") && !type.equals("player")) { - msg(TL.COMMAND_POWERBOOST_HELP_1); - msg(TL.COMMAND_POWERBOOST_HELP_2); - return; - } - - Double targetPower = this.argAsDouble(2); - if (targetPower == null) { - if (this.argAsString(2).equalsIgnoreCase("reset")) { - targetPower = 0D; - } else { - msg(TL.COMMAND_POWERBOOST_INVALIDNUM); - return; - } - } - - String target; - - if (doPlayer) { - FPlayer targetPlayer = this.argAsBestFPlayerMatch(1); - if (targetPlayer == null) { - return; - } - - if (targetPower != 0) { - targetPower += targetPlayer.getPowerBoost(); - } - targetPlayer.setPowerBoost(targetPower); - target = TL.COMMAND_POWERBOOST_PLAYER.format(targetPlayer.getName()); - } else { - Faction targetFaction = this.argAsFaction(1); - if (targetFaction == null) { - return; - } - - if (targetPower != 0) { - targetPower += targetFaction.getPowerBoost(); - } - targetFaction.setPowerBoost(targetPower); - target = TL.COMMAND_POWERBOOST_FACTION.format(targetFaction.getTag()); - } - - int roundedPower = (int) Math.round(targetPower); - msg(TL.COMMAND_POWERBOOST_BOOST, target, roundedPower); - if (!senderIsConsole) { - SavageFactions.plugin.log(TL.COMMAND_POWERBOOST_BOOSTLOG.toString(), fme.getName(), target, roundedPower); - } - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_POWERBOOST_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + +public class CmdPowerBoost extends FCommand { + + public CmdPowerBoost() { + super(); + this.aliases.add("powerboost"); + + this.requiredArgs.add("plugin|f|player|faction"); + this.requiredArgs.add("name"); + this.requiredArgs.add("# or reset"); + + this.permission = Permission.POWERBOOST.node; + this.disableOnLock = true; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + String type = this.argAsString(0).toLowerCase(); + boolean doPlayer = true; + if (type.equals("f") || type.equals("faction")) { + doPlayer = false; + } else if (!type.equals("plugin") && !type.equals("player")) { + msg(TL.COMMAND_POWERBOOST_HELP_1); + msg(TL.COMMAND_POWERBOOST_HELP_2); + return; + } + + Double targetPower = this.argAsDouble(2); + if (targetPower == null) { + if (this.argAsString(2).equalsIgnoreCase("reset")) { + targetPower = 0D; + } else { + msg(TL.COMMAND_POWERBOOST_INVALIDNUM); + return; + } + } + + String target; + + if (doPlayer) { + FPlayer targetPlayer = this.argAsBestFPlayerMatch(1); + if (targetPlayer == null) { + return; + } + + if (targetPower != 0) { + targetPower += targetPlayer.getPowerBoost(); + } + targetPlayer.setPowerBoost(targetPower); + target = TL.COMMAND_POWERBOOST_PLAYER.format(targetPlayer.getName()); + } else { + Faction targetFaction = this.argAsFaction(1); + if (targetFaction == null) { + return; + } + + if (targetPower != 0) { + targetPower += targetFaction.getPowerBoost(); + } + targetFaction.setPowerBoost(targetPower); + target = TL.COMMAND_POWERBOOST_FACTION.format(targetFaction.getTag()); + } + + int roundedPower = (int) Math.round(targetPower); + msg(TL.COMMAND_POWERBOOST_BOOST, target, roundedPower); + if (!senderIsConsole) { + SavageFactions.plugin.log(TL.COMMAND_POWERBOOST_BOOSTLOG.toString(), fme.getName(), target, roundedPower); + } + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_POWERBOOST_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java b/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java index 699e740d..9bb67d32 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java @@ -2,9 +2,9 @@ package com.massivecraft.factions.cmd; public class CmdPromote extends FPromoteCommand { - public CmdPromote() { - aliases.add("promote"); - aliases.add("promo"); - this.relative = 1; - } + public CmdPromote() { + aliases.add("promote"); + aliases.add("promo"); + this.relative = 1; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java index 2520994f..c66d907c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationAlly extends FRelationCommand { - public CmdRelationAlly() { - aliases.add("ally"); - targetRelation = Relation.ALLY; - } + public CmdRelationAlly() { + aliases.add("ally"); + targetRelation = Relation.ALLY; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java index 720f0efe..0da925c3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationEnemy extends FRelationCommand { - public CmdRelationEnemy() { - aliases.add("enemy"); - targetRelation = Relation.ENEMY; - } + public CmdRelationEnemy() { + aliases.add("enemy"); + targetRelation = Relation.ENEMY; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java index 4dba5c03..104186e6 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationNeutral extends FRelationCommand { - public CmdRelationNeutral() { - aliases.add("neutral"); - targetRelation = Relation.NEUTRAL; - } + public CmdRelationNeutral() { + aliases.add("neutral"); + targetRelation = Relation.NEUTRAL; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java index 8136b22c..6cbe2a1e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationTruce extends FRelationCommand { - public CmdRelationTruce() { - aliases.add("truce"); - targetRelation = Relation.TRUCE; - } + public CmdRelationTruce() { + aliases.add("truce"); + targetRelation = Relation.TRUCE; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdReload.java b/src/main/java/com/massivecraft/factions/cmd/CmdReload.java index 7cf4b193..682fd9a3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdReload.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdReload.java @@ -8,41 +8,41 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdReload extends FCommand { - public CmdReload() { - super(); - this.aliases.add("reload"); + public CmdReload() { + super(); + this.aliases.add("reload"); - this.permission = Permission.RELOAD.node; - this.disableOnLock = false; + this.permission = Permission.RELOAD.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - long timeInitStart = System.currentTimeMillis(); - Conf.load(); - Conf.save(); - SavageFactions.plugin.reloadConfig(); - SavageFactions.plugin.changeItemIDSInConfig(); - SavageFactions.plugin.loadLang(); - int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); + @Override + public void perform() { + long timeInitStart = System.currentTimeMillis(); + Conf.load(); + Conf.save(); + SavageFactions.plugin.reloadConfig(); + SavageFactions.plugin.changeItemIDSInConfig(); + SavageFactions.plugin.loadLang(); + int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - SavageFactions.plugin.factionsFlight = true; - } - long timeReload = (System.currentTimeMillis() - timeInitStart); + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + SavageFactions.plugin.factionsFlight = true; + } + long timeReload = (System.currentTimeMillis() - timeInitStart); - msg(TL.COMMAND_RELOAD_TIME, timeReload); - } + msg(TL.COMMAND_RELOAD_TIME, timeReload); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_RELOAD_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_RELOAD_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRules.java b/src/main/java/com/massivecraft/factions/cmd/CmdRules.java index d0c75666..9f4df0d5 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRules.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRules.java @@ -8,84 +8,84 @@ import java.util.HashMap; import java.util.List; public class CmdRules extends FCommand { - public CmdRules() { - super(); - aliases.add("r"); - aliases.add("rule"); - aliases.add("rules"); + public CmdRules() { + super(); + aliases.add("r"); + aliases.add("rule"); + aliases.add("rules"); - this.optionalArgs.put("add/remove/set/clear", ""); - this.errorOnToManyArgs = false; + this.optionalArgs.put("add/remove/set/clear", ""); + this.errorOnToManyArgs = false; - permission = Permission.RULES.node; + permission = Permission.RULES.node; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("frules.Enabled")) { - fme.msg(TL.COMMAND_RULES_DISABLED_MSG); - return; - } - if (this.args.size() == 0) { - HashMap rules = fme.getFaction().getRulesMap(); - if (rules.size() == 0) { - List ruleList = SavageFactions.plugin.getConfig().getStringList("frules.default-rules"); - fme.sendMessage(SavageFactions.plugin.colorList(ruleList)); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("frules.Enabled")) { + fme.msg(TL.COMMAND_RULES_DISABLED_MSG); + return; + } + if (this.args.size() == 0) { + HashMap rules = fme.getFaction().getRulesMap(); + if (rules.size() == 0) { + List ruleList = SavageFactions.plugin.getConfig().getStringList("frules.default-rules"); + fme.sendMessage(SavageFactions.plugin.colorList(ruleList)); - } else { - for (int i = 0; i <= rules.size() - 1; i++) { - fme.sendMessage(SavageFactions.plugin.color(rules.get(i))); - } - } + } else { + for (int i = 0; i <= rules.size() - 1; i++) { + fme.sendMessage(SavageFactions.plugin.color(rules.get(i))); + } + } - } - if (this.args.size() == 1) { - if (args.get(0).equalsIgnoreCase("add")) { - fme.msg(TL.COMMAND_RULES_ADD_INVALIDARGS); - } - if (args.get(0).equalsIgnoreCase("set")) { - fme.msg(TL.COMMAND_RULES_SET_INVALIDARGS); - } - if (args.get(0).equalsIgnoreCase("remove")) { - fme.msg(TL.COMMAND_RULES_REMOVE_INVALIDARGS); - } - if (args.get(0).equalsIgnoreCase("clear")) { - fme.getFaction().clearRules(); - fme.msg(TL.COMMAND_RULES_CLEAR_SUCCESS); - } + } + if (this.args.size() == 1) { + if (args.get(0).equalsIgnoreCase("add")) { + fme.msg(TL.COMMAND_RULES_ADD_INVALIDARGS); + } + if (args.get(0).equalsIgnoreCase("set")) { + fme.msg(TL.COMMAND_RULES_SET_INVALIDARGS); + } + if (args.get(0).equalsIgnoreCase("remove")) { + fme.msg(TL.COMMAND_RULES_REMOVE_INVALIDARGS); + } + if (args.get(0).equalsIgnoreCase("clear")) { + fme.getFaction().clearRules(); + fme.msg(TL.COMMAND_RULES_CLEAR_SUCCESS); + } - } - if (this.args.size() >= 2) { - if (args.get(0).equalsIgnoreCase("add")) { - String message = ""; - StringBuilder string = new StringBuilder(message); - for (int i = 1; i <= args.size() - 1; i++) { - string.append(" " + args.get(i)); - } - fme.getFaction().addRule(string.toString()); - fme.msg(TL.COMMAND_RULES_ADD_SUCCESS); - } + } + if (this.args.size() >= 2) { + if (args.get(0).equalsIgnoreCase("add")) { + String message = ""; + StringBuilder string = new StringBuilder(message); + for (int i = 1; i <= args.size() - 1; i++) { + string.append(" " + args.get(i)); + } + fme.getFaction().addRule(string.toString()); + fme.msg(TL.COMMAND_RULES_ADD_SUCCESS); + } - if (this.args.size() == 2) { - if (args.get(0).equalsIgnoreCase("remove")) { - int index = argAsInt(1); - fme.getFaction().removeRule(index - 1); - fme.msg(TL.COMMAND_RULES_REMOVE_SUCCESS); - } - } + if (this.args.size() == 2) { + if (args.get(0).equalsIgnoreCase("remove")) { + int index = argAsInt(1); + fme.getFaction().removeRule(index - 1); + fme.msg(TL.COMMAND_RULES_REMOVE_SUCCESS); + } + } - } - } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_RULES_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_RULES_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSB.java b/src/main/java/com/massivecraft/factions/cmd/CmdSB.java index e0f18a3b..dedbfd9d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSB.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSB.java @@ -6,28 +6,28 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSB extends FCommand { - public CmdSB() { - this.aliases.add("sb"); - this.aliases.add("scoreboard"); - this.permission = Permission.SCOREBOARD.node; - this.senderMustBePlayer = true; - } + public CmdSB() { + this.aliases.add("sb"); + this.aliases.add("scoreboard"); + this.permission = Permission.SCOREBOARD.node; + this.senderMustBePlayer = true; + } - @Override - public void perform() { - boolean toggleTo = !fme.showScoreboard(); - FScoreboard board = FScoreboard.get(fme); - if (board == null) { - me.sendMessage(TL.COMMAND_TOGGLESB_DISABLED.toString()); - } else { - me.sendMessage(TL.TOGGLE_SB.toString().replace("{value}", String.valueOf(toggleTo))); - board.setSidebarVisibility(toggleTo); - } - fme.setShowScoreboard(toggleTo); - } + @Override + public void perform() { + boolean toggleTo = !fme.showScoreboard(); + FScoreboard board = FScoreboard.get(fme); + if (board == null) { + me.sendMessage(TL.COMMAND_TOGGLESB_DISABLED.toString()); + } else { + me.sendMessage(TL.TOGGLE_SB.toString().replace("{value}", String.valueOf(toggleTo))); + board.setSidebarVisibility(toggleTo); + } + fme.setShowScoreboard(toggleTo); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SCOREBOARD_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SCOREBOARD_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java index 520708f0..705b957c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java @@ -11,52 +11,52 @@ import org.bukkit.World; public class CmdSafeunclaimall extends FCommand { - public CmdSafeunclaimall() { - this.aliases.add("safeunclaimall"); - this.aliases.add("safedeclaimall"); + public CmdSafeunclaimall() { + this.aliases.add("safeunclaimall"); + this.aliases.add("safedeclaimall"); - //this.requiredArgs.add(""); - this.optionalArgs.put("world", "all"); + //this.requiredArgs.add(""); + this.optionalArgs.put("world", "all"); - this.permission = Permission.MANAGE_SAFE_ZONE.node; - this.disableOnLock = true; + this.permission = Permission.MANAGE_SAFE_ZONE.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - String worldName = argAsString(0); - World world = null; + @Override + public void perform() { + String worldName = argAsString(0); + World world = null; - if (worldName != null) { - world = Bukkit.getWorld(worldName); - } + if (worldName != null) { + world = Bukkit.getWorld(worldName); + } - String id = Factions.getInstance().getSafeZone().getId(); + String id = Factions.getInstance().getSafeZone().getId(); - if (world == null) { - Board.getInstance().unclaimAll(id); - } else { - Board.getInstance().unclaimAllInWorld(id, world); - } + if (world == null) { + Board.getInstance().unclaimAll(id); + } else { + Board.getInstance().unclaimAllInWorld(id, world); + } - msg(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMED); + msg(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMED); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG.format(sender.getName())); - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG.format(sender.getName())); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SAFEUNCLAIMALL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SAFEUNCLAIMALL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java b/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java index 98c23bb1..1d0e27b9 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java @@ -1,44 +1,44 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.Board; -import com.massivecraft.factions.Conf; -import com.massivecraft.factions.FPlayers; -import com.massivecraft.factions.Factions; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - -public class CmdSaveAll extends FCommand { - - public CmdSaveAll() { - super(); - this.aliases.add("saveall"); - this.aliases.add("save"); - - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); - - this.permission = Permission.SAVE.node; - this.disableOnLock = false; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - FPlayers.getInstance().forceSave(false); - Factions.getInstance().forceSave(false); - Board.getInstance().forceSave(false); - Conf.save(); - msg(TL.COMMAND_SAVEALL_SUCCESS); - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SAVEALL_DESCRIPTION; - } - +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + +public class CmdSaveAll extends FCommand { + + public CmdSaveAll() { + super(); + this.aliases.add("saveall"); + this.aliases.add("save"); + + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); + + this.permission = Permission.SAVE.node; + this.disableOnLock = false; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + FPlayers.getInstance().forceSave(false); + Factions.getInstance().forceSave(false); + Board.getInstance().forceSave(false); + Conf.save(); + msg(TL.COMMAND_SAVEALL_SUCCESS); + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SAVEALL_DESCRIPTION; + } + } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java b/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java index 72327d6e..a32d1f38 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java @@ -15,137 +15,137 @@ import java.util.Iterator; public class CmdSeeChunk extends FCommand { - //Used a hashmap cuz imma make a particle selection gui later, will store it where the boolean is rn. - public static HashMap seeChunkMap = new HashMap<>(); - Long interval = 10L; - private boolean useParticles; - private int length; - private ParticleEffect effect; - private int taskID = -1; + //Used a hashmap cuz imma make a particle selection gui later, will store it where the boolean is rn. + public static HashMap seeChunkMap = new HashMap<>(); + Long interval = 10L; + private boolean useParticles; + private int length; + private ParticleEffect effect; + private int taskID = -1; - //I remade it cause of people getting mad that I had the same seechunk as drtshock + //I remade it cause of people getting mad that I had the same seechunk as drtshock - public CmdSeeChunk() { - super(); - aliases.add("seechunk"); - aliases.add("sc"); + public CmdSeeChunk() { + super(); + aliases.add("seechunk"); + aliases.add("sc"); - permission = Permission.SEECHUNK.node; + permission = Permission.SEECHUNK.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - this.useParticles = p.getConfig().getBoolean("see-chunk.particles", true); - interval = SavageFactions.plugin.getConfig().getLong("see-chunk.interval", 10L); - if (effect == null) { - effect = ParticleEffect.REDSTONE; - } + this.useParticles = p.getConfig().getBoolean("see-chunk.particles", true); + interval = SavageFactions.plugin.getConfig().getLong("see-chunk.interval", 10L); + if (effect == null) { + effect = ParticleEffect.REDSTONE; + } - } + } - @Override - public void perform() { - if (seeChunkMap.containsKey(me.getName())) { - seeChunkMap.remove(me.getName()); - msg(TL.COMMAND_SEECHUNK_DISABLED); - } else { - seeChunkMap.put(me.getName(), true); - msg(TL.COMMAND_SEECHUNK_ENABLED); - manageTask(); - } - } + @Override + public void perform() { + if (seeChunkMap.containsKey(me.getName())) { + seeChunkMap.remove(me.getName()); + msg(TL.COMMAND_SEECHUNK_DISABLED); + } else { + seeChunkMap.put(me.getName(), true); + msg(TL.COMMAND_SEECHUNK_ENABLED); + manageTask(); + } + } - private void manageTask() { - if (taskID != -1) { - if (seeChunkMap.keySet().size() == 0) { - Bukkit.getScheduler().cancelTask(taskID); - taskID = -1; - } - } else { - startTask(); - } - } + private void manageTask() { + if (taskID != -1) { + if (seeChunkMap.keySet().size() == 0) { + Bukkit.getScheduler().cancelTask(taskID); + taskID = -1; + } + } else { + startTask(); + } + } - private void startTask() { - taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - Iterator itr = seeChunkMap.keySet().iterator(); - while (itr.hasNext()) { - Object nameObject = itr.next(); - String name = nameObject + ""; - Player player = Bukkit.getPlayer(name); - showBorders(player); - } - manageTask(); - } - }, 0, interval); - } + private void startTask() { + taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + Iterator itr = seeChunkMap.keySet().iterator(); + while (itr.hasNext()) { + Object nameObject = itr.next(); + String name = nameObject + ""; + Player player = Bukkit.getPlayer(name); + showBorders(player); + } + manageTask(); + } + }, 0, interval); + } - private void showBorders(Player me) { - World world = me.getWorld(); - FLocation flocation = new FLocation(me); - int chunkX = (int) flocation.getX(); - int chunkZ = (int) flocation.getZ(); + private void showBorders(Player me) { + World world = me.getWorld(); + FLocation flocation = new FLocation(me); + int chunkX = (int) flocation.getX(); + int chunkZ = (int) flocation.getZ(); - int blockX; - int blockZ; + int blockX; + int blockZ; - blockX = chunkX * 16; - blockZ = chunkZ * 16; - showPillar(me, world, blockX, blockZ); + blockX = chunkX * 16; + blockZ = chunkZ * 16; + showPillar(me, world, blockX, blockZ); - blockX = chunkX * 16 + 15; - blockZ = chunkZ * 16; - showPillar(me, world, blockX, blockZ); + blockX = chunkX * 16 + 15; + blockZ = chunkZ * 16; + showPillar(me, world, blockX, blockZ); - blockX = chunkX * 16; - blockZ = chunkZ * 16 + 15; - showPillar(me, world, blockX, blockZ); + blockX = chunkX * 16; + blockZ = chunkZ * 16 + 15; + showPillar(me, world, blockX, blockZ); - blockX = chunkX * 16 + 15; - blockZ = chunkZ * 16 + 15; - showPillar(me, world, blockX, blockZ); - } + blockX = chunkX * 16 + 15; + blockZ = chunkZ * 16 + 15; + showPillar(me, world, blockX, blockZ); + } - private void showPillar(Player player, World world, int blockX, int blockZ) { - for (int blockY = 0; blockY < player.getLocation().getBlockY() + 30; blockY++) { - Location loc = new Location(world, blockX, blockY, blockZ).add(0.5, 0, 0.5); - if (loc.getBlock().getType() != Material.AIR) { - continue; - } - if (useParticles) { - if (SavageFactions.plugin.useNonPacketParticles) { - // Dust options only exists in the 1.13 API, so we use an - // alternative method to achieve this in lower versions. - if (SavageFactions.plugin.mc113) { - player.spawnParticle(Particle.REDSTONE, loc, 0, new Particle.DustOptions(Color.RED, 1)); - } else { - player.getWorld().spawnParticle(Particle.REDSTONE, loc, 0, 255, 0, 0, 1); - } + private void showPillar(Player player, World world, int blockX, int blockZ) { + for (int blockY = 0; blockY < player.getLocation().getBlockY() + 30; blockY++) { + Location loc = new Location(world, blockX, blockY, blockZ).add(0.5, 0, 0.5); + if (loc.getBlock().getType() != Material.AIR) { + continue; + } + if (useParticles) { + if (SavageFactions.plugin.useNonPacketParticles) { + // Dust options only exists in the 1.13 API, so we use an + // alternative method to achieve this in lower versions. + if (SavageFactions.plugin.mc113) { + player.spawnParticle(Particle.REDSTONE, loc, 0, new Particle.DustOptions(Color.RED, 1)); + } else { + player.getWorld().spawnParticle(Particle.REDSTONE, loc, 0, 255, 0, 0, 1); + } - } else { - this.effect.display(0, 0, 0, 0, 1, loc, player); - } + } else { + this.effect.display(0, 0, 0, 0, 1, loc, player); + } - } else { - Material type = blockY % 5 == 0 ? SavageFactions.plugin.REDSTONE_LAMP_ON : SavageFactions.plugin.STAINED_GLASS; - VisualizeUtil.addLocation(player, loc, type); - } - } - } + } else { + Material type = blockY % 5 == 0 ? SavageFactions.plugin.REDSTONE_LAMP_ON : SavageFactions.plugin.STAINED_GLASS; + VisualizeUtil.addLocation(player, loc, type); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.GENERIC_PLACEHOLDER; - } + @Override + public TL getUsageTranslation() { + return TL.GENERIC_PLACEHOLDER; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java index 1558b54d..ed4e0249 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java @@ -5,35 +5,35 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSetBanner extends FCommand { - public CmdSetBanner() { - super(); - aliases.add("setbanner"); + public CmdSetBanner() { + super(); + aliases.add("setbanner"); - permission = Permission.BANNER.node; + permission = Permission.BANNER.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = true; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = true; - } + } - public void perform() { - if (!me.getItemInHand().getType().toString().contains("BANNER")) { - fme.msg(TL.COMMAND_SETBANNER_NOTBANNER); - return; - } + public void perform() { + if (!me.getItemInHand().getType().toString().contains("BANNER")) { + fme.msg(TL.COMMAND_SETBANNER_NOTBANNER); + return; + } - fme.getFaction().setBannerPattern(me.getItemInHand()); - fme.msg(TL.COMMAND_SETBANNER_SUCCESS); + fme.getFaction().setBannerPattern(me.getItemInHand()); + fme.msg(TL.COMMAND_SETBANNER_SUCCESS); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETBANNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETBANNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java index 9735f1c0..8bd5a49d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java @@ -6,43 +6,43 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSetDefaultRole extends FCommand { - public CmdSetDefaultRole() { - super(); + public CmdSetDefaultRole() { + super(); - this.aliases.add("defaultrole"); - this.aliases.add("defaultrank"); - this.aliases.add("default"); - this.aliases.add("def"); - this.requiredArgs.add("role"); + this.aliases.add("defaultrole"); + this.aliases.add("defaultrank"); + this.aliases.add("default"); + this.aliases.add("def"); + this.requiredArgs.add("role"); - this.senderMustBeAdmin = true; - this.senderMustBePlayer = true; - senderMustBeColeader = false; + this.senderMustBeAdmin = true; + this.senderMustBePlayer = true; + senderMustBeColeader = false; - this.permission = Permission.DEFAULTRANK.node; - } + this.permission = Permission.DEFAULTRANK.node; + } - @Override - public void perform() { - Role target = Role.fromString(argAsString(0).toUpperCase()); - if (target == null) { - msg(TL.COMMAND_SETDEFAULTROLE_INVALIDROLE, argAsString(0)); - return; - } + @Override + public void perform() { + Role target = Role.fromString(argAsString(0).toUpperCase()); + if (target == null) { + msg(TL.COMMAND_SETDEFAULTROLE_INVALIDROLE, argAsString(0)); + return; + } - if (target == Role.LEADER) { - msg(TL.COMMAND_SETDEFAULTROLE_NOTTHATROLE, argAsString(0)); - return; - } + if (target == Role.LEADER) { + msg(TL.COMMAND_SETDEFAULTROLE_NOTTHATROLE, argAsString(0)); + return; + } - myFaction.setDefaultRole(target); - msg(TL.COMMAND_SETDEFAULTROLE_SUCCESS, target.nicename); - } + myFaction.setDefaultRole(target); + msg(TL.COMMAND_SETDEFAULTROLE_SUCCESS, target.nicename); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETDEFAULTROLE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETDEFAULTROLE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java index 6914ac0b..f60d5770 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java @@ -12,72 +12,72 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSetFWarp extends FCommand { - public CmdSetFWarp() { - super(); + public CmdSetFWarp() { + super(); - this.aliases.add("setwarp"); - this.aliases.add("sw"); + this.aliases.add("setwarp"); + this.aliases.add("sw"); - this.requiredArgs.add("warp name"); - this.optionalArgs.put("password", "password"); + this.requiredArgs.add("warp name"); + this.optionalArgs.put("password", "password"); - this.senderMustBeMember = true; - this.senderMustBeModerator = false; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; - this.senderMustBePlayer = true; + this.senderMustBePlayer = true; - this.permission = Permission.SETWARP.node; - } + this.permission = Permission.SETWARP.node; + } - @Override - public void perform() { - if (!(fme.getRelationToLocation() == Relation.MEMBER)) { - fme.msg(TL.COMMAND_SETFWARP_NOTCLAIMED); - return; - } + @Override + public void perform() { + if (!(fme.getRelationToLocation() == Relation.MEMBER)) { + fme.msg(TL.COMMAND_SETFWARP_NOTCLAIMED); + return; + } - // This statement allows us to check if they've specifically denied it, or default to - // the old setting of allowing moderators to set warps. - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.SETWARP); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set warps"); - return; - } - } + // This statement allows us to check if they've specifically denied it, or default to + // the old setting of allowing moderators to set warps. + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.SETWARP); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set warps"); + return; + } + } - String warp = argAsString(0); + String warp = argAsString(0); - // Checks if warp with same name already exists and ignores maxWarp check if it does. - boolean warpExists = myFaction.isWarp(warp); + // Checks if warp with same name already exists and ignores maxWarp check if it does. + boolean warpExists = myFaction.isWarp(warp); - int maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); - boolean tooManyWarps = maxWarps <= myFaction.getWarps().size(); - if (tooManyWarps && !warpExists) { - fme.msg(TL.COMMAND_SETFWARP_LIMIT, maxWarps); - return; - } + int maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); + boolean tooManyWarps = maxWarps <= myFaction.getWarps().size(); + if (tooManyWarps && !warpExists) { + fme.msg(TL.COMMAND_SETFWARP_LIMIT, maxWarps); + return; + } - if (!transact(fme)) { - return; - } + if (!transact(fme)) { + return; + } - String password = argAsString(1); + String password = argAsString(1); - LazyLocation loc = new LazyLocation(fme.getPlayer().getLocation()); - myFaction.setWarp(warp, loc); - if (password != null) { - myFaction.setWarpPassword(warp, password); - } - fme.msg(TL.COMMAND_SETFWARP_SET, warp, password != null ? password : ""); - } + LazyLocation loc = new LazyLocation(fme.getPlayer().getLocation()); + myFaction.setWarp(warp, loc); + if (password != null) { + myFaction.setWarpPassword(warp, password); + } + fme.msg(TL.COMMAND_SETFWARP_SET, warp, password != null ? password : ""); + } - private boolean transact(FPlayer player) { - return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.setwarp", 5), TL.COMMAND_SETFWARP_TOSET.toString(), TL.COMMAND_SETFWARP_FORSET.toString()); - } + private boolean transact(FPlayer player) { + return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.setwarp", 5), TL.COMMAND_SETFWARP_TOSET.toString(), TL.COMMAND_SETFWARP_FORSET.toString()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETFWARP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETFWARP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java index 1f3a98f9..de49364e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java @@ -7,44 +7,44 @@ import org.bukkit.ChatColor; public class CmdSetMaxVaults extends FCommand { - public CmdSetMaxVaults() { - this.aliases.add("setmaxvaults"); - this.aliases.add("smv"); + public CmdSetMaxVaults() { + this.aliases.add("setmaxvaults"); + this.aliases.add("smv"); - this.requiredArgs.add("faction"); - this.requiredArgs.add("number"); + this.requiredArgs.add("faction"); + this.requiredArgs.add("number"); - this.permission = Permission.SETMAXVAULTS.node; - this.disableOnLock = false; + this.permission = Permission.SETMAXVAULTS.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - Faction targetFaction = argAsFaction(0); - int value = argAsInt(1, -1); - if (value < 0) { - sender.sendMessage(ChatColor.RED + "Number must be greater than 0."); - return; - } + @Override + public void perform() { + Faction targetFaction = argAsFaction(0); + int value = argAsInt(1, -1); + if (value < 0) { + sender.sendMessage(ChatColor.RED + "Number must be greater than 0."); + return; + } - if (targetFaction == null) { - sender.sendMessage(ChatColor.RED + "Couldn't find Faction: " + ChatColor.YELLOW + argAsString(0)); - return; - } + if (targetFaction == null) { + sender.sendMessage(ChatColor.RED + "Couldn't find Faction: " + ChatColor.YELLOW + argAsString(0)); + return; + } - targetFaction.setMaxVaults(value); - sender.sendMessage(TL.COMMAND_SETMAXVAULTS_SUCCESS.format(targetFaction.getTag(), value)); - } + targetFaction.setMaxVaults(value); + sender.sendMessage(TL.COMMAND_SETMAXVAULTS_SUCCESS.format(targetFaction.getTag(), value)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETMAXVAULTS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETMAXVAULTS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java b/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java index b9440e05..eaf2c94d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java @@ -12,68 +12,68 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSethome extends FCommand { - public CmdSethome() { - this.aliases.add("sethome"); + public CmdSethome() { + this.aliases.add("sethome"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction tag", "mine"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction tag", "mine"); - this.permission = Permission.SETHOME.node; - this.disableOnLock = true; + this.permission = Permission.SETHOME.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!Conf.homesEnabled) { - fme.msg(TL.COMMAND_SETHOME_DISABLED); - return; - } + @Override + public void perform() { + if (!Conf.homesEnabled) { + fme.msg(TL.COMMAND_SETHOME_DISABLED); + return; + } - Faction faction = this.argAsFaction(0, myFaction); - if (faction == null) { - return; - } + Faction faction = this.argAsFaction(0, myFaction); + if (faction == null) { + return; + } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.SETHOME); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.SETHOME_ANY.has(sender, true)) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set home"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.SETHOME); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.SETHOME_ANY.has(sender, true)) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set home"); + return; + } + } - // Can the player set the faction home HERE? - if (!Permission.BYPASS.has(me) && - Conf.homesMustBeInClaimedTerritory && - Board.getInstance().getFactionAt(new FLocation(me)) != faction) { - fme.msg(TL.COMMAND_SETHOME_NOTCLAIMED); - return; - } + // Can the player set the faction home HERE? + if (!Permission.BYPASS.has(me) && + Conf.homesMustBeInClaimedTerritory && + Board.getInstance().getFactionAt(new FLocation(me)) != faction) { + fme.msg(TL.COMMAND_SETHOME_NOTCLAIMED); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostSethome, TL.COMMAND_SETHOME_TOSET, TL.COMMAND_SETHOME_FORSET)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostSethome, TL.COMMAND_SETHOME_TOSET, TL.COMMAND_SETHOME_FORSET)) { + return; + } - faction.setHome(me.getLocation()); + faction.setHome(me.getLocation()); - faction.msg(TL.COMMAND_SETHOME_SET, fme.describeTo(myFaction, true)); - faction.sendMessage(p.cmdBase.cmdHome.getUseageTemplate()); - if (faction != myFaction) { - fme.msg(TL.COMMAND_SETHOME_SETOTHER, faction.getTag(fme)); - } - } + faction.msg(TL.COMMAND_SETHOME_SET, fme.describeTo(myFaction, true)); + faction.sendMessage(p.cmdBase.cmdHome.getUseageTemplate()); + if (faction != myFaction) { + fme.msg(TL.COMMAND_SETHOME_SETOTHER, faction.getTag(fme)); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETHOME_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETHOME_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java index 66ae2ee8..ee437b55 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java @@ -14,105 +14,105 @@ import java.util.List; public class CmdShow extends FCommand { - List defaults = new ArrayList<>(); + List defaults = new ArrayList<>(); - public CmdShow() { - this.aliases.add("show"); - this.aliases.add("who"); + public CmdShow() { + this.aliases.add("show"); + this.aliases.add("who"); - // add defaults to /f show in case config doesnt have it - defaults.add("{header}"); - defaults.add("Description: {description}"); - defaults.add("Joining: {joining} {peaceful}"); - defaults.add("Land / Power / Maxpower: {chunks} / {power} / {maxPower}"); - defaults.add("Founded: {create-date}"); - defaults.add("This faction is permanent, remaining even with no members."); - defaults.add("Land value: {land-value} {land-refund}"); - defaults.add("Balance: {faction-balance}"); - defaults.add("Allies({allies}/{max-allies}): {allies-list}"); - defaults.add("Online: ({online}/{members}): {online-list}"); - defaults.add("Offline: ({offline}/{members}): {offline-list}"); + // add defaults to /f show in case config doesnt have it + defaults.add("{header}"); + defaults.add("Description: {description}"); + defaults.add("Joining: {joining} {peaceful}"); + defaults.add("Land / Power / Maxpower: {chunks} / {power} / {maxPower}"); + defaults.add("Founded: {create-date}"); + defaults.add("This faction is permanent, remaining even with no members."); + defaults.add("Land value: {land-value} {land-refund}"); + defaults.add("Balance: {faction-balance}"); + defaults.add("Allies({allies}/{max-allies}): {allies-list}"); + defaults.add("Online: ({online}/{members}): {online-list}"); + defaults.add("Offline: ({offline}/{members}): {offline-list}"); - // this.requiredArgs.add(""); - this.optionalArgs.put("faction tag", "yours"); + // this.requiredArgs.add(""); + this.optionalArgs.put("faction tag", "yours"); - this.permission = Permission.SHOW.node; - this.disableOnLock = false; + this.permission = Permission.SHOW.node; + this.disableOnLock = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction faction = myFaction; - if (this.argIsSet(0)) - faction = this.argAsFaction(0); + @Override + public void perform() { + Faction faction = myFaction; + if (this.argIsSet(0)) + faction = this.argAsFaction(0); - if (faction == null) - return; + if (faction == null) + return; - if (fme != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt") - && SavageFactions.plugin.getConfig().getStringList("show-exempt").contains(faction.getTag())) { - msg(TL.COMMAND_SHOW_EXEMPT); - return; - } + if (fme != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt") + && SavageFactions.plugin.getConfig().getStringList("show-exempt").contains(faction.getTag())) { + msg(TL.COMMAND_SHOW_EXEMPT); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostShow, TL.COMMAND_SHOW_TOSHOW, TL.COMMAND_SHOW_FORSHOW)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostShow, TL.COMMAND_SHOW_TOSHOW, TL.COMMAND_SHOW_FORSHOW)) { + return; + } - List show = SavageFactions.plugin.getConfig().getStringList("show"); - if (show == null || show.isEmpty()) - show = defaults; + List show = SavageFactions.plugin.getConfig().getStringList("show"); + if (show == null || show.isEmpty()) + show = defaults; - if (!faction.isNormal()) { - String tag = faction.getTag(fme); - // send header and that's all - String header = show.get(0); - if (TagReplacer.HEADER.contains(header)) { - msg(p.txt.titleize(tag)); - } else { - msg(p.txt.parse(TagReplacer.FACTION.replace(header, tag))); - } - return; // we only show header for non-normal factions - } + if (!faction.isNormal()) { + String tag = faction.getTag(fme); + // send header and that's all + String header = show.get(0); + if (TagReplacer.HEADER.contains(header)) { + msg(p.txt.titleize(tag)); + } else { + msg(p.txt.parse(TagReplacer.FACTION.replace(header, tag))); + } + return; // we only show header for non-normal factions + } - for (String raw : show) { - String parsed = TagUtil.parsePlain(faction, fme, raw); // use relations - if (parsed == null) { - continue; // Due to minimal f show. - } + for (String raw : show) { + String parsed = TagUtil.parsePlain(faction, fme, raw); // use relations + if (parsed == null) { + continue; // Due to minimal f show. + } - if (fme != null) { - parsed = TagUtil.parsePlaceholders(fme.getPlayer(), parsed); - } + if (fme != null) { + parsed = TagUtil.parsePlaceholders(fme.getPlayer(), parsed); + } - if (TagUtil.hasFancy(parsed)) { - List fancy = TagUtil.parseFancy(faction, fme, parsed); - if (fancy != null) - sendFancyMessage(fancy); + if (TagUtil.hasFancy(parsed)) { + List fancy = TagUtil.parseFancy(faction, fme, parsed); + if (fancy != null) + sendFancyMessage(fancy); - continue; - } - if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { - if (parsed.contains("{ig}")) { - // replaces all variables with no home TL - parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); - } - if (parsed.contains("%")) { - parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. - } - msg(p.txt.parse(parsed)); - } - } - } + continue; + } + if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { + if (parsed.contains("{ig}")) { + // replaces all variables with no home TL + parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); + } + if (parsed.contains("%")) { + parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. + } + msg(p.txt.parse(parsed)); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SHOW_COMMANDDESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SHOW_COMMANDDESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java b/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java index 10c0492b..f51f662b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java @@ -8,51 +8,51 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdShowClaims extends FCommand { - public CmdShowClaims() { + public CmdShowClaims() { - this.aliases.add("showclaims"); - this.aliases.add("showclaim"); + this.aliases.add("showclaims"); + this.aliases.add("showclaim"); - permission = Permission.SHOWCLAIMS.node; + permission = Permission.SHOWCLAIMS.node; - this.senderMustBePlayer = true; - this.senderMustBeMember = true; - this.senderMustBeModerator = false; - this.senderMustBePlayer = true; + this.senderMustBePlayer = true; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; + this.senderMustBePlayer = true; - } + } - @Override - public void perform() { - sendMessage(TL.COMMAND_SHOWCLAIMS_HEADER.toString().replace("{faction}", fme.getFaction().describeTo(fme))); - ListMultimap chunkMap = ArrayListMultimap.create(); - String format = TL.COMMAND_SHOWCLAIMS_CHUNKSFORMAT.toString(); - for (FLocation fLocation : fme.getFaction().getAllClaims()) { - chunkMap.put(fLocation.getWorldName(), format.replace("{x}", fLocation.getX() + "").replace("{z}", fLocation.getZ() + "")); - } - for (String world : chunkMap.keySet()) { - String message = TL.COMMAND_SHOWCLAIMS_FORMAT.toString().replace("{world}", world); - sendMessage(message.replace("{chunks}", "")); // made {chunks} blank as I removed the placeholder and people wont update their config :shrug: - StringBuilder chunks = new StringBuilder(); - for (String chunkString : chunkMap.get(world)) { - chunks.append(chunkString + ", "); - if (chunks.toString().length() >= 2000) { - sendMessage(chunks.toString()); - chunks.setLength(0); - } - } + @Override + public void perform() { + sendMessage(TL.COMMAND_SHOWCLAIMS_HEADER.toString().replace("{faction}", fme.getFaction().describeTo(fme))); + ListMultimap chunkMap = ArrayListMultimap.create(); + String format = TL.COMMAND_SHOWCLAIMS_CHUNKSFORMAT.toString(); + for (FLocation fLocation : fme.getFaction().getAllClaims()) { + chunkMap.put(fLocation.getWorldName(), format.replace("{x}", fLocation.getX() + "").replace("{z}", fLocation.getZ() + "")); + } + for (String world : chunkMap.keySet()) { + String message = TL.COMMAND_SHOWCLAIMS_FORMAT.toString().replace("{world}", world); + sendMessage(message.replace("{chunks}", "")); // made {chunks} blank as I removed the placeholder and people wont update their config :shrug: + StringBuilder chunks = new StringBuilder(); + for (String chunkString : chunkMap.get(world)) { + chunks.append(chunkString + ", "); + if (chunks.toString().length() >= 2000) { + sendMessage(chunks.toString()); + chunks.setLength(0); + } + } - sendMessage(""); - } + sendMessage(""); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SHOWCLAIMS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SHOWCLAIMS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java b/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java index 4666ff03..79f48b91 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java @@ -10,32 +10,32 @@ import org.bukkit.ChatColor; public class CmdShowInvites extends FCommand { - public CmdShowInvites() { - super(); - aliases.add("showinvites"); - permission = Permission.SHOW_INVITES.node; + public CmdShowInvites() { + super(); + aliases.add("showinvites"); + permission = Permission.SHOW_INVITES.node; - senderMustBePlayer = true; - senderMustBeMember = true; + senderMustBePlayer = true; + senderMustBeMember = true; - } + } - @Override - public void perform() { - FancyMessage msg = new FancyMessage(TL.COMMAND_SHOWINVITES_PENDING.toString()).color(ChatColor.GOLD); - for (String id : myFaction.getInvites()) { - FPlayer fp = FPlayers.getInstance().getById(id); - String name = fp != null ? fp.getName() : id; - msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_SHOWINVITES_CLICKTOREVOKE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); - } + @Override + public void perform() { + FancyMessage msg = new FancyMessage(TL.COMMAND_SHOWINVITES_PENDING.toString()).color(ChatColor.GOLD); + for (String id : myFaction.getInvites()) { + FPlayer fp = FPlayers.getInstance().getById(id); + String name = fp != null ? fp.getName() : id; + msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_SHOWINVITES_CLICKTOREVOKE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); + } - sendFancyMessage(msg); - } + sendFancyMessage(msg); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SHOWINVITES_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SHOWINVITES_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java b/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java index 4dfec779..1df3b189 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java @@ -10,35 +10,35 @@ import java.util.ArrayList; public class CmdStatus extends FCommand { - public CmdStatus() { - super(); - this.aliases.add("status"); - this.aliases.add("s"); + public CmdStatus() { + super(); + this.aliases.add("status"); + this.aliases.add("s"); - this.permission = Permission.STATUS.node; + this.permission = Permission.STATUS.node; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - ArrayList ret = new ArrayList<>(); - for (FPlayer fp : myFaction.getFPlayers()) { - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; - String last = fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - String power = ChatColor.YELLOW + String.valueOf(fp.getPowerRounded()) + " / " + fp.getPowerMaxRounded() + ChatColor.RESET; - ret.add(String.format(TL.COMMAND_STATUS_FORMAT.toString(), ChatColor.GOLD + fp.getRole().getPrefix() + fp.getName() + ChatColor.RESET, power, last).trim()); - } - fme.sendMessage(ret); - } + @Override + public void perform() { + ArrayList ret = new ArrayList<>(); + for (FPlayer fp : myFaction.getFPlayers()) { + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + String last = fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + String power = ChatColor.YELLOW + String.valueOf(fp.getPowerRounded()) + " / " + fp.getPowerMaxRounded() + ChatColor.RESET; + ret.add(String.format(TL.COMMAND_STATUS_FORMAT.toString(), ChatColor.GOLD + fp.getRole().getPrefix() + fp.getName() + ChatColor.RESET, power, last).trim()); + } + fme.sendMessage(ret); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_STATUS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_STATUS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java b/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java index fe391273..cd1d9438 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java @@ -5,32 +5,32 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdStealth extends FCommand { - public CmdStealth() { - this.aliases.add("ninja"); - this.aliases.add("stealth"); - this.permission = Permission.STEALTH.node; + public CmdStealth() { + this.aliases.add("ninja"); + this.aliases.add("stealth"); + this.permission = Permission.STEALTH.node; - this.disableOnLock = true; + this.disableOnLock = true; - this.senderMustBePlayer = true; - this.senderMustBeMember = false; - this.senderMustBeModerator = false; - this.senderMustBeColeader = false; - this.senderMustBeAdmin = false; + this.senderMustBePlayer = true; + this.senderMustBeMember = false; + this.senderMustBeModerator = false; + this.senderMustBeColeader = false; + this.senderMustBeAdmin = false; - } + } - public void perform() { - Faction faction = fme.getFaction(); - if (faction != null && !faction.getId().equalsIgnoreCase("0") && !faction.getId().equalsIgnoreCase("none") && !faction.getId().equalsIgnoreCase("safezone") && !faction.getId().equalsIgnoreCase("warzone")) { - fme.setStealth(!fme.isStealthEnabled()); - fme.msg(fme.isStealthEnabled() ? TL.COMMAND_STEALTH_ENABLE : TL.COMMAND_STEALTH_DISABLE); - } else { - fme.msg(TL.COMMAND_STEALTH_MUSTBEMEMBER); - } - } + public void perform() { + Faction faction = fme.getFaction(); + if (faction != null && !faction.getId().equalsIgnoreCase("0") && !faction.getId().equalsIgnoreCase("none") && !faction.getId().equalsIgnoreCase("safezone") && !faction.getId().equalsIgnoreCase("warzone")) { + fme.setStealth(!fme.isStealthEnabled()); + fme.msg(fme.isStealthEnabled() ? TL.COMMAND_STEALTH_ENABLE : TL.COMMAND_STEALTH_DISABLE); + } else { + fme.msg(TL.COMMAND_STEALTH_MUSTBEMEMBER); + } + } - public TL getUsageTranslation() { - return TL.COMMAND_STEALTH_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_STEALTH_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java b/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java index 57b60fb9..f1aa9172 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java @@ -14,98 +14,98 @@ import org.bukkit.scheduler.BukkitRunnable; public class CmdStuck extends FCommand { - public CmdStuck() { - super(); + public CmdStuck() { + super(); - this.aliases.add("stuck"); - this.aliases.add("halp!"); // halp!c: + this.aliases.add("stuck"); + this.aliases.add("halp!"); // halp!c: - this.permission = Permission.STUCK.node; - this.disableOnLock = true; + this.permission = Permission.STUCK.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - final Player player = fme.getPlayer(); - final Location sentAt = player.getLocation(); - final FLocation chunk = fme.getLastStoodAt(); - final long delay = SavageFactions.plugin.getConfig().getLong("hcf.stuck.delay", 30); - final int radius = SavageFactions.plugin.getConfig().getInt("hcf.stuck.radius", 10); + @Override + public void perform() { + final Player player = fme.getPlayer(); + final Location sentAt = player.getLocation(); + final FLocation chunk = fme.getLastStoodAt(); + final long delay = SavageFactions.plugin.getConfig().getLong("hcf.stuck.delay", 30); + final int radius = SavageFactions.plugin.getConfig().getInt("hcf.stuck.radius", 10); - if (SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { - long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); - String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); - msg(TL.COMMAND_STUCK_EXISTS, time); - } else { + if (SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { + long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); + String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); + msg(TL.COMMAND_STUCK_EXISTS, time); + } else { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostStuck, TL.COMMAND_STUCK_TOSTUCK.format(fme.getName()), TL.COMMAND_STUCK_FORSTUCK.format(fme.getName()))) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostStuck, TL.COMMAND_STUCK_TOSTUCK.format(fme.getName()), TL.COMMAND_STUCK_FORSTUCK.format(fme.getName()))) { + return; + } - final int id = Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new BukkitRunnable() { + final int id = Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new BukkitRunnable() { - @Override - public void run() { - if (!SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { - return; - } + @Override + public void run() { + if (!SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { + return; + } - // check for world difference or radius exceeding - final World world = chunk.getWorld(); - if (world.getUID() != player.getWorld().getUID() || sentAt.distance(player.getLocation()) > radius) { - msg(TL.COMMAND_STUCK_OUTSIDE.format(radius)); - SavageFactions.plugin.getTimers().remove(player.getUniqueId()); - SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); - return; - } + // check for world difference or radius exceeding + final World world = chunk.getWorld(); + if (world.getUID() != player.getWorld().getUID() || sentAt.distance(player.getLocation()) > radius) { + msg(TL.COMMAND_STUCK_OUTSIDE.format(radius)); + SavageFactions.plugin.getTimers().remove(player.getUniqueId()); + SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); + return; + } - final Board board = Board.getInstance(); - // spiral task to find nearest wilderness chunk - new SpiralTask(new FLocation(me), radius * 2) { + final Board board = Board.getInstance(); + // spiral task to find nearest wilderness chunk + new SpiralTask(new FLocation(me), radius * 2) { - @Override - public boolean work() { - FLocation chunk = currentFLocation(); - Faction faction = board.getFactionAt(chunk); - int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); - if (faction.isWilderness() && !chunk.isOutsideWorldBorder(buffer)) { - int cx = FLocation.chunkToBlock((int) chunk.getX()); - int cz = FLocation.chunkToBlock((int) chunk.getZ()); - int y = world.getHighestBlockYAt(cx, cz); - Location tp = new Location(world, cx, y, cz); - msg(TL.COMMAND_STUCK_TELEPORT, tp.getBlockX(), tp.getBlockY(), tp.getBlockZ()); - SavageFactions.plugin.getTimers().remove(player.getUniqueId()); - SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); - if (!Essentials.handleTeleport(player, tp)) { - player.teleport(tp); - SavageFactions.plugin.debug("/f stuck used regular teleport, not essentials!"); - } - this.stop(); - return false; - } - return true; - } - }; - } - }, delay * 20).getTaskId(); + @Override + public boolean work() { + FLocation chunk = currentFLocation(); + Faction faction = board.getFactionAt(chunk); + int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); + if (faction.isWilderness() && !chunk.isOutsideWorldBorder(buffer)) { + int cx = FLocation.chunkToBlock((int) chunk.getX()); + int cz = FLocation.chunkToBlock((int) chunk.getZ()); + int y = world.getHighestBlockYAt(cx, cz); + Location tp = new Location(world, cx, y, cz); + msg(TL.COMMAND_STUCK_TELEPORT, tp.getBlockX(), tp.getBlockY(), tp.getBlockZ()); + SavageFactions.plugin.getTimers().remove(player.getUniqueId()); + SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); + if (!Essentials.handleTeleport(player, tp)) { + player.teleport(tp); + SavageFactions.plugin.debug("/f stuck used regular teleport, not essentials!"); + } + this.stop(); + return false; + } + return true; + } + }; + } + }, delay * 20).getTaskId(); - SavageFactions.plugin.getTimers().put(player.getUniqueId(), System.currentTimeMillis() + (delay * 1000)); - long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); - String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); - msg(TL.COMMAND_STUCK_START, time); - SavageFactions.plugin.getStuckMap().put(player.getUniqueId(), id); - } - } + SavageFactions.plugin.getTimers().put(player.getUniqueId(), System.currentTimeMillis() + (delay * 1000)); + long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); + String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); + msg(TL.COMMAND_STUCK_START, time); + SavageFactions.plugin.getStuckMap().put(player.getUniqueId(), id); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_STUCK_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_STUCK_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTag.java b/src/main/java/com/massivecraft/factions/cmd/CmdTag.java index bc65ef26..6eefe687 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTag.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTag.java @@ -12,79 +12,79 @@ import java.util.ArrayList; public class CmdTag extends FCommand { - public CmdTag() { - this.aliases.add("tag"); - this.aliases.add("rename"); + public CmdTag() { + this.aliases.add("tag"); + this.aliases.add("rename"); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); - this.permission = Permission.TAG.node; - this.disableOnLock = true; + this.permission = Permission.TAG.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - String tag = this.argAsString(0); + @Override + public void perform() { + String tag = this.argAsString(0); - // TODO does not first test cover selfcase? - if (Factions.getInstance().isTagTaken(tag) && !MiscUtil.getComparisonString(tag).equals(myFaction.getComparisonTag())) { - msg(TL.COMMAND_TAG_TAKEN); - return; - } + // TODO does not first test cover selfcase? + if (Factions.getInstance().isTagTaken(tag) && !MiscUtil.getComparisonString(tag).equals(myFaction.getComparisonTag())) { + msg(TL.COMMAND_TAG_TAKEN); + return; + } - ArrayList errors = MiscUtil.validateTag(tag); - if (errors.size() > 0) { - sendMessage(errors); - return; - } + ArrayList errors = MiscUtil.validateTag(tag); + if (errors.size() > 0) { + sendMessage(errors); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (!canAffordCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (!canAffordCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE.toString())) { + return; + } - // trigger the faction rename event (cancellable) - FactionRenameEvent renameEvent = new FactionRenameEvent(fme, tag); - Bukkit.getServer().getPluginManager().callEvent(renameEvent); - if (renameEvent.isCancelled()) { - return; - } + // trigger the faction rename event (cancellable) + FactionRenameEvent renameEvent = new FactionRenameEvent(fme, tag); + Bukkit.getServer().getPluginManager().callEvent(renameEvent); + if (renameEvent.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (!payForCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE, TL.COMMAND_TAG_FORCHANGE)) { - return; - } + // then make 'em pay (if applicable) + if (!payForCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE, TL.COMMAND_TAG_FORCHANGE)) { + return; + } - String oldtag = myFaction.getTag(); - myFaction.setTag(tag); + String oldtag = myFaction.getTag(); + myFaction.setTag(tag); - // Inform - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (fplayer.getFactionId().equals(myFaction.getId())) { - fplayer.msg(TL.COMMAND_TAG_FACTION, fme.describeTo(myFaction, true), myFaction.getTag(myFaction)); - continue; - } + // Inform + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.getFactionId().equals(myFaction.getId())) { + fplayer.msg(TL.COMMAND_TAG_FACTION, fme.describeTo(myFaction, true), myFaction.getTag(myFaction)); + continue; + } - // Broadcast the tag change (if applicable) - if (Conf.broadcastTagChanges) { - Faction faction = fplayer.getFaction(); - fplayer.msg(TL.COMMAND_TAG_CHANGED, fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); - } - } + // Broadcast the tag change (if applicable) + if (Conf.broadcastTagChanges) { + Faction faction = fplayer.getFaction(); + fplayer.msg(TL.COMMAND_TAG_CHANGED, fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); + } + } - FTeamWrapper.updatePrefixes(myFaction); - } + FTeamWrapper.updatePrefixes(myFaction); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TAG_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TAG_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java b/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java index 2d716dee..11461956 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java @@ -8,51 +8,51 @@ import com.massivecraft.factions.zcore.util.TextUtil; public class CmdTitle extends FCommand { - public CmdTitle() { - this.aliases.add("title"); + public CmdTitle() { + this.aliases.add("title"); - this.requiredArgs.add("player name"); - this.optionalArgs.put("title", ""); + this.requiredArgs.add("player name"); + this.optionalArgs.put("title", ""); - this.permission = Permission.TITLE.node; - this.disableOnLock = true; + this.permission = Permission.TITLE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (you == null) { - return; - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (you == null) { + return; + } - args.remove(0); - String title = TextUtil.implode(args, " "); + args.remove(0); + String title = TextUtil.implode(args, " "); - if (!canIAdministerYou(fme, you)) { - return; - } + if (!canIAdministerYou(fme, you)) { + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostTitle, TL.COMMAND_TITLE_TOCHANGE, TL.COMMAND_TITLE_FORCHANGE)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostTitle, TL.COMMAND_TITLE_TOCHANGE, TL.COMMAND_TITLE_FORCHANGE)) { + return; + } - you.setTitle(sender, title); + you.setTitle(sender, title); - // Inform - myFaction.msg(TL.COMMAND_TITLE_CHANGED, fme.describeTo(myFaction, true), you.describeTo(myFaction, true)); - } + // Inform + myFaction.msg(TL.COMMAND_TITLE_CHANGED, fme.describeTo(myFaction, true), you.describeTo(myFaction, true)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TITLE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TITLE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java b/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java index 6bb42301..77f0f55a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java @@ -12,172 +12,172 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; public class CmdTnt extends FCommand { - public CmdTnt() { - super(); - this.aliases.add("tnt"); + public CmdTnt() { + super(); + this.aliases.add("tnt"); - this.optionalArgs.put("add/take", ""); - this.optionalArgs.put("amount", "number"); + this.optionalArgs.put("add/take", ""); + this.optionalArgs.put("amount", "number"); - this.permission = Permission.TNT.node; - this.disableOnLock = true; + this.permission = Permission.TNT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("ftnt.Enabled")) { - fme.msg(TL.COMMAND_TNT_DISABLED_MSG); - return; - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("ftnt.Enabled")) { + fme.msg(TL.COMMAND_TNT_DISABLED_MSG); + return; + } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TNTBANK); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt bank"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TNTBANK); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt bank"); + return; + } + } - if (args.size() == 2) { - if (args.get(0).equalsIgnoreCase("add") || args.get(0).equalsIgnoreCase("a")) { - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - int amount = Integer.parseInt(args.get(1)); - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - Inventory inv = me.getInventory(); - int invTnt = 0; - for (int i = 0; i <= inv.getSize(); i++) { - if (inv.getItem(i) == null) { - continue; - } - if (inv.getItem(i).getType() == Material.TNT) { - invTnt += inv.getItem(i).getAmount(); - } - } - if (amount > invTnt) { - fme.msg(TL.COMMAND_TNT_DEPOSIT_NOTENOUGH); - return; - } - ItemStack tnt = new ItemStack(Material.TNT, amount); - if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { - msg(TL.COMMAND_TNT_EXCEEDLIMIT); - return; - } - removeFromInventory(me.getInventory(), tnt); - me.updateInventory(); + if (args.size() == 2) { + if (args.get(0).equalsIgnoreCase("add") || args.get(0).equalsIgnoreCase("a")) { + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + int amount = Integer.parseInt(args.get(1)); + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + Inventory inv = me.getInventory(); + int invTnt = 0; + for (int i = 0; i <= inv.getSize(); i++) { + if (inv.getItem(i) == null) { + continue; + } + if (inv.getItem(i).getType() == Material.TNT) { + invTnt += inv.getItem(i).getAmount(); + } + } + if (amount > invTnt) { + fme.msg(TL.COMMAND_TNT_DEPOSIT_NOTENOUGH); + return; + } + ItemStack tnt = new ItemStack(Material.TNT, amount); + if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { + msg(TL.COMMAND_TNT_EXCEEDLIMIT); + return; + } + removeFromInventory(me.getInventory(), tnt); + me.updateInventory(); - fme.getFaction().addTnt(amount); - fme.msg(TL.COMMAND_TNT_DEPOSIT_SUCCESS); - fme.sendMessage(SavageFactions.plugin.color(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + ""))); - return; + fme.getFaction().addTnt(amount); + fme.msg(TL.COMMAND_TNT_DEPOSIT_SUCCESS); + fme.sendMessage(SavageFactions.plugin.color(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + ""))); + return; - } - if (args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t")) { - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - int amount = Integer.parseInt(args.get(1)); - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - if (fme.getFaction().getTnt() < amount) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if ((remainderAmt == 0 && !hasAvaliableSlot(me, fullStacks))) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); - return; - } - if (!hasAvaliableSlot(me, fullStacks + 1)) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); - return; - } - ItemStack tnt64 = new ItemStack(Material.TNT, 64); - for (int i = 0; i <= fullStacks - 1; i++) { - me.getInventory().addItem(tnt64); - } - if (remainderAmt != 0) { - ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); - me.getInventory().addItem(tnt); - } - fme.getFaction().takeTnt(amount); - me.updateInventory(); - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_SUCCESS); - } - } else if (args.size() == 1) { - fme.msg(TL.GENERIC_ARGS_TOOFEW); - fme.msg(args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t") ? TL.COMMAND_TNT_TAKE_DESCRIPTION : TL.COMMAND_TNT_ADD_DESCRIPTION); - } - fme.sendMessage(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + "")); - } + } + if (args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t")) { + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + int amount = Integer.parseInt(args.get(1)); + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + if (fme.getFaction().getTnt() < amount) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if ((remainderAmt == 0 && !hasAvaliableSlot(me, fullStacks))) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); + return; + } + if (!hasAvaliableSlot(me, fullStacks + 1)) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); + return; + } + ItemStack tnt64 = new ItemStack(Material.TNT, 64); + for (int i = 0; i <= fullStacks - 1; i++) { + me.getInventory().addItem(tnt64); + } + if (remainderAmt != 0) { + ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); + me.getInventory().addItem(tnt); + } + fme.getFaction().takeTnt(amount); + me.updateInventory(); + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_SUCCESS); + } + } else if (args.size() == 1) { + fme.msg(TL.GENERIC_ARGS_TOOFEW); + fme.msg(args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t") ? TL.COMMAND_TNT_TAKE_DESCRIPTION : TL.COMMAND_TNT_ADD_DESCRIPTION); + } + fme.sendMessage(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + "")); + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - public boolean hasAvaliableSlot(Player player, int howmany) { - Integer check = 0; - for (ItemStack item : player.getInventory().getContents()) { - if (item == null) { - check++; - } - } - return check >= howmany; - } + public boolean hasAvaliableSlot(Player player, int howmany) { + Integer check = 0; + for (ItemStack item : player.getInventory().getContents()) { + if (item == null) { + check++; + } + } + return check >= howmany; + } - public void removeFromInventory(Inventory inventory, ItemStack item) { - int amt = item.getAmount(); - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - if (items[i].getAmount() > amt) { - items[i].setAmount(items[i].getAmount() - amt); - break; - } else if (items[i].getAmount() == amt) { - items[i] = null; - break; - } else { - amt -= items[i].getAmount(); - items[i] = null; - } - } - } - inventory.setContents(items); - } + public void removeFromInventory(Inventory inventory, ItemStack item) { + int amt = item.getAmount(); + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + if (items[i].getAmount() > amt) { + items[i].setAmount(items[i].getAmount() - amt); + break; + } else if (items[i].getAmount() == amt) { + items[i] = null; + break; + } else { + amt -= items[i].getAmount(); + items[i] = null; + } + } + } + inventory.setContents(items); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TNT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TNT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java b/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java index b6237e59..954b89e4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java @@ -16,240 +16,240 @@ import org.bukkit.inventory.PlayerInventory; public class CmdTntFill extends FCommand { - public CmdTntFill() { - super(); - this.aliases.add("tntfill"); + public CmdTntFill() { + super(); + this.aliases.add("tntfill"); - this.requiredArgs.add("radius"); - this.requiredArgs.add("amount"); + this.requiredArgs.add("radius"); + this.requiredArgs.add("amount"); - this.permission = Permission.TNTFILL.node; - this.disableOnLock = true; + this.permission = Permission.TNTFILL.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("Tntfill.enabled")) { - this.fme.msg(TL.GENERIC_DISABLED); - return; - } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TNTFILL); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt fill"); - return; - } - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("Tntfill.enabled")) { + this.fme.msg(TL.GENERIC_DISABLED); + return; + } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TNTFILL); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt fill"); + return; + } + } - msg(TL.COMMAND_TNTFILL_HEADER); - int radius = argAsInt(0, 16); - int amount = argAsInt(1, 16); - if (radius > SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius")) { - fme.msg(TL.COMMAND_TNTFILL_RADIUSMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius") + "")); - return; - } - if (amount > SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount")) { - fme.msg(TL.COMMAND_TNTFILL_AMOUNTMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount") + "")); - return; - } + msg(TL.COMMAND_TNTFILL_HEADER); + int radius = argAsInt(0, 16); + int amount = argAsInt(1, 16); + if (radius > SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius")) { + fme.msg(TL.COMMAND_TNTFILL_RADIUSMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius") + "")); + return; + } + if (amount > SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount")) { + fme.msg(TL.COMMAND_TNTFILL_AMOUNTMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount") + "")); + return; + } - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - boolean bankMode = fme.getRole().isAtLeast(Role.MODERATOR); - Location start = me.getLocation(); - int counter = 0; - for (double x = start.getX() - radius; x <= start.getX() + radius; x++) { - for (double y = start.getY() - radius; y <= start.getY() + radius; y++) { - for (double z = start.getZ() - radius; z <= start.getZ() + radius; z++) { - Location blockLoc = new Location(start.getWorld(), x, y, z); - if (blockLoc.getBlock().getState() instanceof Dispenser) { - Dispenser disp = (Dispenser) blockLoc.getBlock().getState(); - Inventory dispenser = disp.getInventory(); - if (canHold(dispenser, amount)) { - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { - if (!fme.getRole().isAtLeast(Role.MODERATOR)) { - fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); - sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); - me.updateInventory(); - return; - } else if (bankMode) { - //msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}",fme.getRole().nicename)); - bankMode = true; - removeFromBank(amount); - if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { - fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); - sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); - me.updateInventory(); - return; - } - } - } - ItemStack tnt64 = new ItemStack(Material.TNT, 64); - for (int i = 0; i <= fullStacks - 1; i++) { - dispenser.addItem(tnt64); - takeTnt(64); - } - if (remainderAmt != 0) { - ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); - dispenser.addItem(tnt); - takeTnt(remainderAmt); - } - //sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}",amount + "").replace("{x}",(int) x + "").replace("{y}",(int) y + "").replace("{z}",(int) z + "")); - counter++; - } + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + boolean bankMode = fme.getRole().isAtLeast(Role.MODERATOR); + Location start = me.getLocation(); + int counter = 0; + for (double x = start.getX() - radius; x <= start.getX() + radius; x++) { + for (double y = start.getY() - radius; y <= start.getY() + radius; y++) { + for (double z = start.getZ() - radius; z <= start.getZ() + radius; z++) { + Location blockLoc = new Location(start.getWorld(), x, y, z); + if (blockLoc.getBlock().getState() instanceof Dispenser) { + Dispenser disp = (Dispenser) blockLoc.getBlock().getState(); + Inventory dispenser = disp.getInventory(); + if (canHold(dispenser, amount)) { + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { + if (!fme.getRole().isAtLeast(Role.MODERATOR)) { + fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); + sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); + me.updateInventory(); + return; + } else if (bankMode) { + //msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}",fme.getRole().nicename)); + bankMode = true; + removeFromBank(amount); + if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { + fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); + sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); + me.updateInventory(); + return; + } + } + } + ItemStack tnt64 = new ItemStack(Material.TNT, 64); + for (int i = 0; i <= fullStacks - 1; i++) { + dispenser.addItem(tnt64); + takeTnt(64); + } + if (remainderAmt != 0) { + ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); + dispenser.addItem(tnt); + takeTnt(remainderAmt); + } + //sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}",amount + "").replace("{x}",(int) x + "").replace("{y}",(int) y + "").replace("{z}",(int) z + "")); + counter++; + } - } - } - } - } - if (bankMode) { - msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}", fme.getRole().nicename)); - } - sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); - me.updateInventory(); + } + } + } + } + if (bankMode) { + msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}", fme.getRole().nicename)); + } + sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); + me.updateInventory(); - } + } - private void removeFromBank(int amount) { - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - if (fme.getFaction().getTnt() < amount) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - if (getEmptySlots(me) + 1 <= fullStacks) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - ItemStack tnt64 = new ItemStack(Material.TNT, 64); - for (int i = 0; i <= fullStacks - 1; i++) { - me.getInventory().addItem(tnt64); - } - if (remainderAmt != 0) { - ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); - me.getInventory().addItem(tnt); - } - fme.getFaction().takeTnt(amount); - me.updateInventory(); - } + private void removeFromBank(int amount) { + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + if (fme.getFaction().getTnt() < amount) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + if (getEmptySlots(me) + 1 <= fullStacks) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + ItemStack tnt64 = new ItemStack(Material.TNT, 64); + for (int i = 0; i <= fullStacks - 1; i++) { + me.getInventory().addItem(tnt64); + } + if (remainderAmt != 0) { + ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); + me.getInventory().addItem(tnt); + } + fme.getFaction().takeTnt(amount); + me.updateInventory(); + } - public void takeTnt(int amount) { - Inventory inv = me.getInventory(); - int invTnt = 0; - for (int i = 0; i <= inv.getSize(); i++) { - if (inv.getItem(i) == null) { - continue; - } - if (inv.getItem(i).getType() == Material.TNT) { - invTnt += inv.getItem(i).getAmount(); - } - } - if (amount > invTnt) { - fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH); - return; - } - ItemStack tnt = new ItemStack(Material.TNT, amount); - if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { - msg(TL.COMMAND_TNT_EXCEEDLIMIT); - return; - } - removeFromInventory(me.getInventory(), tnt); - } + public void takeTnt(int amount) { + Inventory inv = me.getInventory(); + int invTnt = 0; + for (int i = 0; i <= inv.getSize(); i++) { + if (inv.getItem(i) == null) { + continue; + } + if (inv.getItem(i).getType() == Material.TNT) { + invTnt += inv.getItem(i).getAmount(); + } + } + if (amount > invTnt) { + fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH); + return; + } + ItemStack tnt = new ItemStack(Material.TNT, amount); + if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { + msg(TL.COMMAND_TNT_EXCEEDLIMIT); + return; + } + removeFromInventory(me.getInventory(), tnt); + } - public boolean canHold(Inventory inventory, int amount) { - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { - return false; - } - if (getEmptySlots(me) + 1 <= fullStacks) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return false; - } - return true; - } + public boolean canHold(Inventory inventory, int amount) { + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { + return false; + } + if (getEmptySlots(me) + 1 <= fullStacks) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return false; + } + return true; + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - public void removeFromInventory(Inventory inventory, ItemStack item) { - int amt = item.getAmount(); - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - if (items[i].getAmount() > amt) { - items[i].setAmount(items[i].getAmount() - amt); - break; - } else if (items[i].getAmount() == amt) { - items[i] = null; - break; - } else { - amt -= items[i].getAmount(); - items[i] = null; - } - } - } - inventory.setContents(items); - } + public void removeFromInventory(Inventory inventory, ItemStack item) { + int amt = item.getAmount(); + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + if (items[i].getAmount() > amt) { + items[i].setAmount(items[i].getAmount() - amt); + break; + } else if (items[i].getAmount() == amt) { + items[i] = null; + break; + } else { + amt -= items[i].getAmount(); + items[i] = null; + } + } + } + inventory.setContents(items); + } - public int getEmptySlots(Player p) { - PlayerInventory inventory = p.getInventory(); - ItemStack[] cont = inventory.getContents(); - int i = 0; - for (ItemStack item : cont) - if (item != null && item.getType() != Material.AIR) { - i++; - } - return 36 - i; - } + public int getEmptySlots(Player p) { + PlayerInventory inventory = p.getInventory(); + ItemStack[] cont = inventory.getContents(); + int i = 0; + for (ItemStack item : cont) + if (item != null && item.getType() != Material.AIR) { + i++; + } + return 36 - i; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TNTFILL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TNTFILL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java b/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java index 95664b6d..3f4d45ba 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java @@ -6,39 +6,39 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdToggleAllianceChat extends FCommand { - public CmdToggleAllianceChat() { - super(); - this.aliases.add("tac"); - this.aliases.add("togglealliancechat"); - this.aliases.add("ac"); + public CmdToggleAllianceChat() { + super(); + this.aliases.add("tac"); + this.aliases.add("togglealliancechat"); + this.aliases.add("ac"); - this.disableOnLock = false; + this.disableOnLock = false; - this.permission = Permission.TOGGLE_ALLIANCE_CHAT.node; - this.disableOnLock = false; + this.permission = Permission.TOGGLE_ALLIANCE_CHAT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION; + } - @Override - public void perform() { - if (!Conf.factionOnlyChat) { - msg(TL.COMMAND_CHAT_DISABLED.toString()); - return; - } + @Override + public void perform() { + if (!Conf.factionOnlyChat) { + msg(TL.COMMAND_CHAT_DISABLED.toString()); + return; + } - boolean ignoring = fme.isIgnoreAllianceChat(); + boolean ignoring = fme.isIgnoreAllianceChat(); - msg(ignoring ? TL.COMMAND_TOGGLEALLIANCECHAT_UNIGNORE : TL.COMMAND_TOGGLEALLIANCECHAT_IGNORE); - fme.setIgnoreAllianceChat(!ignoring); - } + msg(ignoring ? TL.COMMAND_TOGGLEALLIANCECHAT_UNIGNORE : TL.COMMAND_TOGGLEALLIANCECHAT_IGNORE); + fme.setIgnoreAllianceChat(!ignoring); + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTop.java b/src/main/java/com/massivecraft/factions/cmd/CmdTop.java index 48c9a9f5..5fd1180a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTop.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTop.java @@ -12,167 +12,167 @@ import java.util.ArrayList; public class CmdTop extends FCommand { - public CmdTop() { - super(); - this.aliases.add("top"); - this.aliases.add("t"); + public CmdTop() { + super(); + this.aliases.add("top"); + this.aliases.add("t"); - //this.requiredArgs.add(""); - this.requiredArgs.add("criteria"); - this.optionalArgs.put("page", "1"); + //this.requiredArgs.add(""); + this.requiredArgs.add("criteria"); + this.optionalArgs.put("page", "1"); - this.permission = Permission.TOP.node; - this.disableOnLock = false; + this.permission = Permission.TOP.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - // Can sort by: money, members, online, allies, enemies, power, land. - // Get all Factions and remove non player ones. - ArrayList factionList = Factions.getInstance().getAllFactions(); - factionList.remove(Factions.getInstance().getWilderness()); - factionList.remove(Factions.getInstance().getSafeZone()); - factionList.remove(Factions.getInstance().getWarZone()); + @Override + public void perform() { + // Can sort by: money, members, online, allies, enemies, power, land. + // Get all Factions and remove non player ones. + ArrayList factionList = Factions.getInstance().getAllFactions(); + factionList.remove(Factions.getInstance().getWilderness()); + factionList.remove(Factions.getInstance().getSafeZone()); + factionList.remove(Factions.getInstance().getWarZone()); - String criteria = argAsString(0); + String criteria = argAsString(0); - // TODO: Better way to sort? - if (criteria.equalsIgnoreCase("members")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getFPlayers().size(); - int f2Size = f2.getFPlayers().size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("start")) { - factionList.sort((f1, f2) -> { - long f1start = f1.getFoundedDate(); - long f2start = f2.getFoundedDate(); - // flip signs because a smaller date is farther in the past - if (f1start > f2start) { - return 1; - } else if (f1start < f2start) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("power")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getPowerRounded(); - int f2Size = f2.getPowerRounded(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("land")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getLandRounded(); - int f2Size = f2.getLandRounded(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("online")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getFPlayersWhereOnline(true).size(); - int f2Size = f2.getFPlayersWhereOnline(true).size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("money") || criteria.equalsIgnoreCase("balance") || criteria.equalsIgnoreCase("bal")) { - factionList.sort((f1, f2) -> { - double f1Size = Econ.getBalance(f1.getAccountId()); - // Lets get the balance of /all/ the players in the Faction. - for (FPlayer fp : f1.getFPlayers()) { - f1Size = f1Size + Econ.getBalance(fp.getAccountId()); - } - double f2Size = Econ.getBalance(f2.getAccountId()); - for (FPlayer fp : f2.getFPlayers()) { - f2Size = f2Size + Econ.getBalance(fp.getAccountId()); - } - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else { - msg(TL.COMMAND_TOP_INVALID, criteria); - } + // TODO: Better way to sort? + if (criteria.equalsIgnoreCase("members")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getFPlayers().size(); + int f2Size = f2.getFPlayers().size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("start")) { + factionList.sort((f1, f2) -> { + long f1start = f1.getFoundedDate(); + long f2start = f2.getFoundedDate(); + // flip signs because a smaller date is farther in the past + if (f1start > f2start) { + return 1; + } else if (f1start < f2start) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("power")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getPowerRounded(); + int f2Size = f2.getPowerRounded(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("land")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getLandRounded(); + int f2Size = f2.getLandRounded(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("online")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getFPlayersWhereOnline(true).size(); + int f2Size = f2.getFPlayersWhereOnline(true).size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("money") || criteria.equalsIgnoreCase("balance") || criteria.equalsIgnoreCase("bal")) { + factionList.sort((f1, f2) -> { + double f1Size = Econ.getBalance(f1.getAccountId()); + // Lets get the balance of /all/ the players in the Faction. + for (FPlayer fp : f1.getFPlayers()) { + f1Size = f1Size + Econ.getBalance(fp.getAccountId()); + } + double f2Size = Econ.getBalance(f2.getAccountId()); + for (FPlayer fp : f2.getFPlayers()) { + f2Size = f2Size + Econ.getBalance(fp.getAccountId()); + } + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else { + msg(TL.COMMAND_TOP_INVALID, criteria); + } - ArrayList lines = new ArrayList<>(); + ArrayList lines = new ArrayList<>(); - final int pageheight = 9; - int pagenumber = this.argAsInt(1, 1); - int pagecount = (factionList.size() / pageheight) + 1; - if (pagenumber > pagecount) { - pagenumber = pagecount; - } else if (pagenumber < 1) { - pagenumber = 1; - } - int start = (pagenumber - 1) * pageheight; - int end = start + pageheight; - if (end > factionList.size()) { - end = factionList.size(); - } + final int pageheight = 9; + int pagenumber = this.argAsInt(1, 1); + int pagecount = (factionList.size() / pageheight) + 1; + if (pagenumber > pagecount) { + pagenumber = pagecount; + } else if (pagenumber < 1) { + pagenumber = 1; + } + int start = (pagenumber - 1) * pageheight; + int end = start + pageheight; + if (end > factionList.size()) { + end = factionList.size(); + } - lines.add(TL.COMMAND_TOP_TOP.format(criteria.toUpperCase(), pagenumber, pagecount)); + lines.add(TL.COMMAND_TOP_TOP.format(criteria.toUpperCase(), pagenumber, pagecount)); - int rank = 1; - for (Faction faction : factionList.subList(start, end)) { - // Get the relation color if player is executing this. - String fac = sender instanceof Player ? faction.getRelationTo(fme).getColor() + faction.getTag() : faction.getTag(); - lines.add(TL.COMMAND_TOP_LINE.format(rank, fac, getValue(faction, criteria))); - rank++; - } + int rank = 1; + for (Faction faction : factionList.subList(start, end)) { + // Get the relation color if player is executing this. + String fac = sender instanceof Player ? faction.getRelationTo(fme).getColor() + faction.getTag() : faction.getTag(); + lines.add(TL.COMMAND_TOP_LINE.format(rank, fac, getValue(faction, criteria))); + rank++; + } - sendMessage(lines); - } + sendMessage(lines); + } - private String getValue(Faction faction, String criteria) { - if (criteria.equalsIgnoreCase("online")) { - return String.valueOf(faction.getFPlayersWhereOnline(true).size()); - } else if (criteria.equalsIgnoreCase("start")) { - return TL.sdf.format(faction.getFoundedDate()); - } else if (criteria.equalsIgnoreCase("members")) { - return String.valueOf(faction.getFPlayers().size()); - } else if (criteria.equalsIgnoreCase("land")) { - return String.valueOf(faction.getLandRounded()); - } else if (criteria.equalsIgnoreCase("power")) { - return String.valueOf(faction.getPowerRounded()); - } else { // Last one is balance, and it has 3 different things it could be. - double balance = Econ.getBalance(faction.getAccountId()); - for (FPlayer fp : faction.getFPlayers()) { - balance = Math.round(balance + Econ.getBalance(fp.getAccountId())); - } - return String.valueOf(balance); - } - } + private String getValue(Faction faction, String criteria) { + if (criteria.equalsIgnoreCase("online")) { + return String.valueOf(faction.getFPlayersWhereOnline(true).size()); + } else if (criteria.equalsIgnoreCase("start")) { + return TL.sdf.format(faction.getFoundedDate()); + } else if (criteria.equalsIgnoreCase("members")) { + return String.valueOf(faction.getFPlayers().size()); + } else if (criteria.equalsIgnoreCase("land")) { + return String.valueOf(faction.getLandRounded()); + } else if (criteria.equalsIgnoreCase("power")) { + return String.valueOf(faction.getPowerRounded()); + } else { // Last one is balance, and it has 3 different things it could be. + double balance = Econ.getBalance(faction.getAccountId()); + for (FPlayer fp : faction.getFPlayers()) { + balance = Math.round(balance + Econ.getBalance(fp.getAccountId())); + } + return String.valueOf(balance); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TOP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TOP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java b/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java index 4023e49f..55f81229 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java @@ -8,46 +8,46 @@ import com.massivecraft.factions.util.WarmUpUtil; import com.massivecraft.factions.zcore.util.TL; public class CmdTpBanner extends FCommand { - public CmdTpBanner() { - super(); + public CmdTpBanner() { + super(); - this.aliases.add("tpbanner"); + this.aliases.add("tpbanner"); - this.permission = Permission.TPBANNER.node; - this.disableOnLock = true; + this.permission = Permission.TPBANNER.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { - return; - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { + return; + } - final FactionsPlayerListener fpl = new FactionsPlayerListener(); + final FactionsPlayerListener fpl = new FactionsPlayerListener(); - if (FactionsBlockListener.bannerLocations.containsKey(fme.getTag())) { - fme.msg(TL.COMMAND_TPBANNER_SUCCESS); - this.doWarmUp(WarmUpUtil.Warmup.BANNER, TL.WARMUPS_NOTIFY_TELEPORT, "Banner", new Runnable() { - @Override - public void run() { - me.teleport(FactionsBlockListener.bannerLocations.get(fme.getTag())); - } - }, this.p.getConfig().getLong("warmups.f-banner", 0)); - } else { - fme.msg(TL.COMMAND_TPBANNER_NOTSET); - } + if (FactionsBlockListener.bannerLocations.containsKey(fme.getTag())) { + fme.msg(TL.COMMAND_TPBANNER_SUCCESS); + this.doWarmUp(WarmUpUtil.Warmup.BANNER, TL.WARMUPS_NOTIFY_TELEPORT, "Banner", new Runnable() { + @Override + public void run() { + me.teleport(FactionsBlockListener.bannerLocations.get(fme.getTag())); + } + }, this.p.getConfig().getLong("warmups.f-banner", 0)); + } else { + fme.msg(TL.COMMAND_TPBANNER_NOTSET); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TPBANNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TPBANNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java index 86ba4be7..26ac45db 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java @@ -9,51 +9,51 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdUnban extends FCommand { - public CmdUnban() { - super(); - this.aliases.add("unban"); + public CmdUnban() { + super(); + this.aliases.add("unban"); - this.requiredArgs.add("target"); + this.requiredArgs.add("target"); - this.permission = Permission.BAN.node; - this.disableOnLock = true; + this.permission = Permission.BAN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.BAN); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.BAN.has(sender, true)) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage bans"); - return; - } - } + @Override + public void perform() { + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.BAN); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.BAN.has(sender, true)) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage bans"); + return; + } + } - // Good on permission checks. Now lets just ban the player. - FPlayer target = argAsFPlayer(0); - if (target == null) { - return; // the above method sends a message if fails to find someone. - } + // Good on permission checks. Now lets just ban the player. + FPlayer target = argAsFPlayer(0); + if (target == null) { + return; // the above method sends a message if fails to find someone. + } - if (!myFaction.isBanned(target)) { - fme.msg(TL.COMMAND_UNBAN_NOTBANNED, target.getName()); - return; - } + if (!myFaction.isBanned(target)) { + fme.msg(TL.COMMAND_UNBAN_NOTBANNED, target.getName()); + return; + } - myFaction.unban(target); + myFaction.unban(target); - myFaction.msg(TL.COMMAND_UNBAN_UNBANNED, fme.getName(), target.getName()); - target.msg(TL.COMMAND_UNBAN_TARGET, myFaction.getTag(target)); - } + myFaction.msg(TL.COMMAND_UNBAN_UNBANNED, fme.getName(), target.getName()); + target.msg(TL.COMMAND_UNBAN_TARGET, myFaction.getTag(target)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UNBAN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UNBAN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java index 9fa2293e..3b9d0f4a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java @@ -13,172 +13,172 @@ import org.bukkit.Bukkit; public class CmdUnclaim extends FCommand { - public CmdUnclaim() { - this.aliases.add("unclaim"); - this.aliases.add("declaim"); + public CmdUnclaim() { + this.aliases.add("unclaim"); + this.aliases.add("declaim"); - this.optionalArgs.put("radius", "1"); + this.optionalArgs.put("radius", "1"); - this.permission = Permission.UNCLAIM.node; - this.disableOnLock = true; + this.permission = Permission.UNCLAIM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // Read and validate input - int radius = this.argAsInt(0, 1); // Default to 1 + @Override + public void perform() { + // Read and validate input + int radius = this.argAsInt(0, 1); // Default to 1 - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage faction territory"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage faction territory"); + return; + } + } - if (radius < 1) { - msg(TL.COMMAND_CLAIM_INVALIDRADIUS); - return; - } + if (radius < 1) { + msg(TL.COMMAND_CLAIM_INVALIDRADIUS); + return; + } - if (radius < 2) { - // single chunk - unClaim(new FLocation(me)); - } else { - // radius claim - if (!Permission.CLAIM_RADIUS.has(sender, false)) { - msg(TL.COMMAND_CLAIM_DENIED); - return; - } + if (radius < 2) { + // single chunk + unClaim(new FLocation(me)); + } else { + // radius claim + if (!Permission.CLAIM_RADIUS.has(sender, false)) { + msg(TL.COMMAND_CLAIM_DENIED); + return; + } - new SpiralTask(new FLocation(me), radius) { - private final int limit = Conf.radiusClaimFailureLimit - 1; - private int failCount = 0; + new SpiralTask(new FLocation(me), radius) { + private final int limit = Conf.radiusClaimFailureLimit - 1; + private int failCount = 0; - @Override - public boolean work() { - boolean success = unClaim(this.currentFLocation()); - if (success) { - failCount = 0; - } else if (failCount++ >= limit) { - this.stop(); - return false; - } + @Override + public boolean work() { + boolean success = unClaim(this.currentFLocation()); + if (success) { + failCount = 0; + } else if (failCount++ >= limit) { + this.stop(); + return false; + } - return true; - } - }; - } - } + return true; + } + }; + } + } - private boolean unClaim(FLocation target) { - Faction targetFaction = Board.getInstance().getFactionAt(target); - if (targetFaction.isSafeZone()) { - if (Permission.MANAGE_SAFE_ZONE.has(sender)) { - Board.getInstance().removeAt(target); - msg(TL.COMMAND_UNCLAIM_SAFEZONE_SUCCESS); + private boolean unClaim(FLocation target) { + Faction targetFaction = Board.getInstance().getFactionAt(target); + if (targetFaction.isSafeZone()) { + if (Permission.MANAGE_SAFE_ZONE.has(sender)) { + Board.getInstance().removeAt(target); + msg(TL.COMMAND_UNCLAIM_SAFEZONE_SUCCESS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } - return true; - } else { - msg(TL.COMMAND_UNCLAIM_SAFEZONE_NOPERM); - return false; - } - } else if (targetFaction.isWarZone()) { - if (Permission.MANAGE_WAR_ZONE.has(sender)) { - Board.getInstance().removeAt(target); - msg(TL.COMMAND_UNCLAIM_WARZONE_SUCCESS); + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } + return true; + } else { + msg(TL.COMMAND_UNCLAIM_SAFEZONE_NOPERM); + return false; + } + } else if (targetFaction.isWarZone()) { + if (Permission.MANAGE_WAR_ZONE.has(sender)) { + Board.getInstance().removeAt(target); + msg(TL.COMMAND_UNCLAIM_WARZONE_SUCCESS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } - return true; - } else { - msg(TL.COMMAND_UNCLAIM_WARZONE_NOPERM); - return false; - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } + return true; + } else { + msg(TL.COMMAND_UNCLAIM_WARZONE_NOPERM); + return false; + } + } - if (fme.isAdminBypassing()) { - LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); - Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); - if (unclaimEvent.isCancelled()) { - return false; - } + if (fme.isAdminBypassing()) { + LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); + Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); + if (unclaimEvent.isCancelled()) { + return false; + } - Board.getInstance().removeAt(target); + Board.getInstance().removeAt(target); - targetFaction.msg(TL.COMMAND_UNCLAIM_UNCLAIMED, fme.describeTo(targetFaction, true)); - msg(TL.COMMAND_UNCLAIM_UNCLAIMS); + targetFaction.msg(TL.COMMAND_UNCLAIM_UNCLAIMED, fme.describeTo(targetFaction, true)); + msg(TL.COMMAND_UNCLAIM_UNCLAIMS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } - return true; - } + return true; + } - if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) == Access.DENY) { - return false; - } + if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) == Access.DENY) { + return false; + } - if (!assertHasFaction()) { - return false; - } + if (!assertHasFaction()) { + return false; + } - if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) != Access.ALLOW && !assertMinRole(Role.MODERATOR)) { - return false; - } + if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) != Access.ALLOW && !assertMinRole(Role.MODERATOR)) { + return false; + } - if (myFaction != targetFaction) { - msg(TL.COMMAND_UNCLAIM_WRONGFACTION); - return false; - } + if (myFaction != targetFaction) { + msg(TL.COMMAND_UNCLAIM_WRONGFACTION); + return false; + } - LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); - Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); - if (unclaimEvent.isCancelled()) { - return false; - } + LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); + Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); + if (unclaimEvent.isCancelled()) { + return false; + } - if (Econ.shouldBeUsed()) { - double refund = Econ.calculateClaimRefund(myFaction.getLandRounded()); + if (Econ.shouldBeUsed()) { + double refund = Econ.calculateClaimRefund(myFaction.getLandRounded()); - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { - if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { - return false; - } - } else { - if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { - return false; - } - } - } + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { + if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { + return false; + } + } else { + if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { + return false; + } + } + } - Board.getInstance().removeAt(target); - myFaction.msg(TL.COMMAND_UNCLAIM_FACTIONUNCLAIMED, fme.describeTo(myFaction, true)); + Board.getInstance().removeAt(target); + myFaction.msg(TL.COMMAND_UNCLAIM_FACTIONUNCLAIMED, fme.describeTo(myFaction, true)); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } - return true; - } + return true; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UNCLAIM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UNCLAIM_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java index 5d8efb28..8eef33a2 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java @@ -11,55 +11,55 @@ import org.bukkit.Bukkit; public class CmdUnclaimall extends FCommand { - public CmdUnclaimall() { - this.aliases.add("unclaimall"); - this.aliases.add("declaimall"); + public CmdUnclaimall() { + this.aliases.add("unclaimall"); + this.aliases.add("declaimall"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.UNCLAIM_ALL.node; - this.disableOnLock = true; + this.permission = Permission.UNCLAIM_ALL.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (Econ.shouldBeUsed()) { - double refund = Econ.calculateTotalLandRefund(myFaction.getLandRounded()); - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { - if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { - return; - } - } else { - if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { - return; - } - } - } + @Override + public void perform() { + if (Econ.shouldBeUsed()) { + double refund = Econ.calculateTotalLandRefund(myFaction.getLandRounded()); + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { + if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { + return; + } + } else { + if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { + return; + } + } + } - LandUnclaimAllEvent unclaimAllEvent = new LandUnclaimAllEvent(myFaction, fme); - Bukkit.getServer().getPluginManager().callEvent(unclaimAllEvent); - if (unclaimAllEvent.isCancelled()) { - return; - } + LandUnclaimAllEvent unclaimAllEvent = new LandUnclaimAllEvent(myFaction, fme); + Bukkit.getServer().getPluginManager().callEvent(unclaimAllEvent); + if (unclaimAllEvent.isCancelled()) { + return; + } - Board.getInstance().unclaimAll(myFaction.getId()); - myFaction.msg(TL.COMMAND_UNCLAIMALL_UNCLAIMED, fme.describeTo(myFaction, true)); + Board.getInstance().unclaimAll(myFaction.getId()); + myFaction.msg(TL.COMMAND_UNCLAIMALL_UNCLAIMED, fme.describeTo(myFaction, true)); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIMALL_LOG.format(fme.getName(), myFaction.getTag())); - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIMALL_LOG.format(fme.getName(), myFaction.getTag())); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UNCLAIMALL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UNCLAIMALL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java b/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java index ee8ac071..726e7c59 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java @@ -6,37 +6,37 @@ import com.massivecraft.factions.zcore.fupgrades.FUpgradesGUI; import com.massivecraft.factions.zcore.util.TL; public class CmdUpgrades extends FCommand { - public CmdUpgrades() { - super(); - this.aliases.add("upgrades"); - this.aliases.add("upgrade"); + public CmdUpgrades() { + super(); + this.aliases.add("upgrades"); + this.aliases.add("upgrade"); - //this.requiredArgs.add(""); - this.optionalArgs.put("mobs/crops/exp", ""); + //this.requiredArgs.add(""); + this.optionalArgs.put("mobs/crops/exp", ""); - this.permission = Permission.UPGRADES.node; - this.disableOnLock = true; + this.permission = Permission.UPGRADES.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fupgrades.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - FUpgradesGUI fgui = new FUpgradesGUI(); - fgui.openMainMenu(fme); - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fupgrades.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + FUpgradesGUI fgui = new FUpgradesGUI(); + fgui.openMainMenu(fme); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UPGRADES_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UPGRADES_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdVault.java b/src/main/java/com/massivecraft/factions/cmd/CmdVault.java index 55fd8150..c4909596 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdVault.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdVault.java @@ -14,66 +14,66 @@ import org.bukkit.inventory.Inventory; public class CmdVault extends FCommand { - public CmdVault() { - this.aliases.add("vault"); + public CmdVault() { + this.aliases.add("vault"); - //this.requiredArgs.add(""); + //this.requiredArgs.add(""); - this.permission = Permission.VAULT.node; - this.disableOnLock = false; + this.permission = Permission.VAULT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { + @Override + public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - Access access = fme.getFaction().getAccess(fme, PermissableAction.VAULT); - if (access.equals(Access.DENY)) { - fme.msg(TL.GENERIC_NOPERMISSION, "vault"); - return; - } + if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + Access access = fme.getFaction().getAccess(fme, PermissableAction.VAULT); + if (access.equals(Access.DENY)) { + fme.msg(TL.GENERIC_NOPERMISSION, "vault"); + return; + } - if (fme.isInVault()) { - me.closeInventory(); - return; - } - fme.setInVault(true); - Location vaultLocation = fme.getFaction().getVault(); - if (vaultLocation == null) { - fme.msg(TL.COMMAND_VAULT_INVALID); - return; - } - FLocation vaultFLocation = new FLocation(vaultLocation); - if (Board.getInstance().getFactionAt(vaultFLocation) != fme.getFaction()) { - fme.getFaction().setVault(null); - fme.msg(TL.COMMAND_VAULT_INVALID); - return; - } - if (vaultLocation.getBlock().getType() != Material.CHEST) { - fme.getFaction().setVault(null); - fme.msg(TL.COMMAND_VAULT_INVALID); - return; - } - Chest chest = (Chest) vaultLocation.getBlock().getState(); - Inventory chestInv = chest.getBlockInventory(); - fme.msg(TL.COMMAND_VAULT_OPENING); - me.openInventory(chestInv); + if (fme.isInVault()) { + me.closeInventory(); + return; + } + fme.setInVault(true); + Location vaultLocation = fme.getFaction().getVault(); + if (vaultLocation == null) { + fme.msg(TL.COMMAND_VAULT_INVALID); + return; + } + FLocation vaultFLocation = new FLocation(vaultLocation); + if (Board.getInstance().getFactionAt(vaultFLocation) != fme.getFaction()) { + fme.getFaction().setVault(null); + fme.msg(TL.COMMAND_VAULT_INVALID); + return; + } + if (vaultLocation.getBlock().getType() != Material.CHEST) { + fme.getFaction().setVault(null); + fme.msg(TL.COMMAND_VAULT_INVALID); + return; + } + Chest chest = (Chest) vaultLocation.getBlock().getState(); + Inventory chestInv = chest.getBlockInventory(); + fme.msg(TL.COMMAND_VAULT_OPENING); + me.openInventory(chestInv); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_VAULT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_VAULT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java b/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java index e0772fdc..f10f4e36 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java @@ -7,30 +7,30 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdVersion extends FCommand { - public CmdVersion() { - this.aliases.add("version"); - this.aliases.add("ver"); + public CmdVersion() { + this.aliases.add("version"); + this.aliases.add("ver"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.VERSION.node; - this.disableOnLock = false; + this.permission = Permission.VERSION.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - msg(TL.COMMAND_VERSION_NAME); // Did this so people can differentiate between SavageFactions and FactionsUUID (( Requested Feature )) - msg(TL.COMMAND_VERSION_VERSION, SavageFactions.plugin.getDescription().getFullName()); - } + @Override + public void perform() { + msg(TL.COMMAND_VERSION_NAME); // Did this so people can differentiate between SavageFactions and FactionsUUID (( Requested Feature )) + msg(TL.COMMAND_VERSION_VERSION, SavageFactions.plugin.getDescription().getFullName()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_VERSION_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_VERSION_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java index f69b3390..6a206a1d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java @@ -11,51 +11,51 @@ import org.bukkit.World; public class CmdWarunclaimall extends FCommand { - public CmdWarunclaimall() { - this.aliases.add("warunclaimall"); - this.aliases.add("wardeclaimall"); + public CmdWarunclaimall() { + this.aliases.add("warunclaimall"); + this.aliases.add("wardeclaimall"); - //this.requiredArgs.add(""); - this.optionalArgs.put("world", "all"); + //this.requiredArgs.add(""); + this.optionalArgs.put("world", "all"); - this.permission = Permission.MANAGE_WAR_ZONE.node; - this.disableOnLock = true; + this.permission = Permission.MANAGE_WAR_ZONE.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - String worldName = argAsString(0); - World world = null; + @Override + public void perform() { + String worldName = argAsString(0); + World world = null; - if (worldName != null) { - world = Bukkit.getWorld(worldName); - } + if (worldName != null) { + world = Bukkit.getWorld(worldName); + } - String id = Factions.getInstance().getWarZone().getId(); + String id = Factions.getInstance().getWarZone().getId(); - if (world == null) { - Board.getInstance().unclaimAll(id); - } else { - Board.getInstance().unclaimAllInWorld(id, world); - } + if (world == null) { + Board.getInstance().unclaimAll(id); + } else { + Board.getInstance().unclaimAllInWorld(id, world); + } - fme.msg(TL.COMMAND_WARUNCLAIMALL_SUCCESS); + fme.msg(TL.COMMAND_WARUNCLAIMALL_SUCCESS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_WARUNCLAIMALL_LOG.format(fme.getName())); - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_WARUNCLAIMALL_LOG.format(fme.getName())); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_WARUNCLAIMALL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_WARUNCLAIMALL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java b/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java index 96cb84f5..e94b5b6f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java +++ b/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java @@ -10,249 +10,249 @@ import java.util.logging.Level; public class FCmdRoot extends FCommand { - public CmdAdmin cmdAdmin = new CmdAdmin(); - public CmdAutoClaim cmdAutoClaim = new CmdAutoClaim(); - public CmdBoom cmdBoom = new CmdBoom(); - public CmdBypass cmdBypass = new CmdBypass(); - public CmdChat cmdChat = new CmdChat(); - public CmdChatSpy cmdChatSpy = new CmdChatSpy(); - public CmdClaim cmdClaim = new CmdClaim(); - public CmdConfig cmdConfig = new CmdConfig(); - public CmdCreate cmdCreate = new CmdCreate(); - public CmdDeinvite cmdDeinvite = new CmdDeinvite(); - public CmdDescription cmdDescription = new CmdDescription(); - public CmdDisband cmdDisband = new CmdDisband(); - public CmdFocus cmdFocus = new CmdFocus(); - public CmdHelp cmdHelp = new CmdHelp(); - public CmdHome cmdHome = new CmdHome(); - public CmdInvite cmdInvite = new CmdInvite(); - public CmdJoin cmdJoin = new CmdJoin(); - public CmdKick cmdKick = new CmdKick(); - public CmdLeave cmdLeave = new CmdLeave(); - public CmdList cmdList = new CmdList(); - public CmdLock cmdLock = new CmdLock(); - public CmdMap cmdMap = new CmdMap(); - public CmdMod cmdMod = new CmdMod(); - public CmdMoney cmdMoney = new CmdMoney(); - public CmdOpen cmdOpen = new CmdOpen(); - public CmdOwner cmdOwner = new CmdOwner(); - public CmdOwnerList cmdOwnerList = new CmdOwnerList(); - public CmdPeaceful cmdPeaceful = new CmdPeaceful(); - public CmdPermanent cmdPermanent = new CmdPermanent(); - public CmdPermanentPower cmdPermanentPower = new CmdPermanentPower(); - public CmdPowerBoost cmdPowerBoost = new CmdPowerBoost(); - public CmdPower cmdPower = new CmdPower(); - public CmdRelationAlly cmdRelationAlly = new CmdRelationAlly(); - public CmdRelationEnemy cmdRelationEnemy = new CmdRelationEnemy(); - public CmdRelationNeutral cmdRelationNeutral = new CmdRelationNeutral(); - public CmdRelationTruce cmdRelationTruce = new CmdRelationTruce(); - public CmdReload cmdReload = new CmdReload(); - public CmdSafeunclaimall cmdSafeunclaimall = new CmdSafeunclaimall(); - public CmdSaveAll cmdSaveAll = new CmdSaveAll(); - public CmdSethome cmdSethome = new CmdSethome(); - public CmdShow cmdShow = new CmdShow(); - public CmdStatus cmdStatus = new CmdStatus(); - public CmdStealth cmdStealth = new CmdStealth(); - public CmdStuck cmdStuck = new CmdStuck(); - public CmdTag cmdTag = new CmdTag(); - public CmdTitle cmdTitle = new CmdTitle(); - public CmdToggleAllianceChat cmdToggleAllianceChat = new CmdToggleAllianceChat(); - public CmdUnclaim cmdUnclaim = new CmdUnclaim(); - public CmdUnclaimall cmdUnclaimall = new CmdUnclaimall(); - public CmdVersion cmdVersion = new CmdVersion(); - public CmdWarunclaimall cmdWarunclaimall = new CmdWarunclaimall(); - public CmdSB cmdSB = new CmdSB(); - public CmdShowInvites cmdShowInvites = new CmdShowInvites(); - public CmdAnnounce cmdAnnounce = new CmdAnnounce(); - public CmdPaypalSet cmdPaypalSet = new CmdPaypalSet(); - public CmdPaypalSee cmdPaypalSee = new CmdPaypalSee(); - public CmdSeeChunk cmdSeeChunk = new CmdSeeChunk(); - public CmdConvert cmdConvert = new CmdConvert(); - public CmdFWarp cmdFWarp = new CmdFWarp(); - public CmdSetFWarp cmdSetFWarp = new CmdSetFWarp(); - public CmdDelFWarp cmdDelFWarp = new CmdDelFWarp(); - public CmdModifyPower cmdModifyPower = new CmdModifyPower(); - public CmdLogins cmdLogins = new CmdLogins(); - public CmdClaimLine cmdClaimLine = new CmdClaimLine(); - public CmdTop cmdTop = new CmdTop(); - public CmdAHome cmdAHome = new CmdAHome(); - public CmdPerm cmdPerm = new CmdPerm(); - public CmdPromote cmdPromote = new CmdPromote(); - public CmdDemote cmdDemote = new CmdDemote(); - public CmdSetDefaultRole cmdSetDefaultRole = new CmdSetDefaultRole(); - public CmdMapHeight cmdMapHeight = new CmdMapHeight(); - public CmdClaimAt cmdClaimAt = new CmdClaimAt(); - public CmdBan cmdban = new CmdBan(); - public CmdUnban cmdUnban = new CmdUnban(); - public CmdBanlist cmdbanlist = new CmdBanlist(); - public CmdRules cmdRules = new CmdRules(); - public CmdCheckpoint cmdCheckpoint = new CmdCheckpoint(); - public CmdTnt cmdTnt = new CmdTnt(); - public CmdNear cmdNear = new CmdNear(); - public CmdUpgrades cmdUpgrades = new CmdUpgrades(); - public CmdVault cmdVault = new CmdVault(); - public CmdGetVault cmdGetVault = new CmdGetVault(); - public CmdFly cmdFly = new CmdFly(); - public CmdColeader cmdColeader = new CmdColeader(); - public CmdBanner cmdBanner = new CmdBanner(); - public CmdTpBanner cmdTpBanner = new CmdTpBanner(); - public CmdKillHolograms cmdKillHolograms = new CmdKillHolograms(); - public CmdInspect cmdInspect = new CmdInspect(); - public CmdCoords cmdCoords = new CmdCoords(); - public CmdShowClaims cmdShowClaims = new CmdShowClaims(); - public CmdLowPower cmdLowPower = new CmdLowPower(); - public CmdTntFill cmdTntFill = new CmdTntFill(); - public CmdChest cmdChest = new CmdChest(); - public CmdSetBanner cmdSetBanner = new CmdSetBanner(); + public CmdAdmin cmdAdmin = new CmdAdmin(); + public CmdAutoClaim cmdAutoClaim = new CmdAutoClaim(); + public CmdBoom cmdBoom = new CmdBoom(); + public CmdBypass cmdBypass = new CmdBypass(); + public CmdChat cmdChat = new CmdChat(); + public CmdChatSpy cmdChatSpy = new CmdChatSpy(); + public CmdClaim cmdClaim = new CmdClaim(); + public CmdConfig cmdConfig = new CmdConfig(); + public CmdCreate cmdCreate = new CmdCreate(); + public CmdDeinvite cmdDeinvite = new CmdDeinvite(); + public CmdDescription cmdDescription = new CmdDescription(); + public CmdDisband cmdDisband = new CmdDisband(); + public CmdFocus cmdFocus = new CmdFocus(); + public CmdHelp cmdHelp = new CmdHelp(); + public CmdHome cmdHome = new CmdHome(); + public CmdInvite cmdInvite = new CmdInvite(); + public CmdJoin cmdJoin = new CmdJoin(); + public CmdKick cmdKick = new CmdKick(); + public CmdLeave cmdLeave = new CmdLeave(); + public CmdList cmdList = new CmdList(); + public CmdLock cmdLock = new CmdLock(); + public CmdMap cmdMap = new CmdMap(); + public CmdMod cmdMod = new CmdMod(); + public CmdMoney cmdMoney = new CmdMoney(); + public CmdOpen cmdOpen = new CmdOpen(); + public CmdOwner cmdOwner = new CmdOwner(); + public CmdOwnerList cmdOwnerList = new CmdOwnerList(); + public CmdPeaceful cmdPeaceful = new CmdPeaceful(); + public CmdPermanent cmdPermanent = new CmdPermanent(); + public CmdPermanentPower cmdPermanentPower = new CmdPermanentPower(); + public CmdPowerBoost cmdPowerBoost = new CmdPowerBoost(); + public CmdPower cmdPower = new CmdPower(); + public CmdRelationAlly cmdRelationAlly = new CmdRelationAlly(); + public CmdRelationEnemy cmdRelationEnemy = new CmdRelationEnemy(); + public CmdRelationNeutral cmdRelationNeutral = new CmdRelationNeutral(); + public CmdRelationTruce cmdRelationTruce = new CmdRelationTruce(); + public CmdReload cmdReload = new CmdReload(); + public CmdSafeunclaimall cmdSafeunclaimall = new CmdSafeunclaimall(); + public CmdSaveAll cmdSaveAll = new CmdSaveAll(); + public CmdSethome cmdSethome = new CmdSethome(); + public CmdShow cmdShow = new CmdShow(); + public CmdStatus cmdStatus = new CmdStatus(); + public CmdStealth cmdStealth = new CmdStealth(); + public CmdStuck cmdStuck = new CmdStuck(); + public CmdTag cmdTag = new CmdTag(); + public CmdTitle cmdTitle = new CmdTitle(); + public CmdToggleAllianceChat cmdToggleAllianceChat = new CmdToggleAllianceChat(); + public CmdUnclaim cmdUnclaim = new CmdUnclaim(); + public CmdUnclaimall cmdUnclaimall = new CmdUnclaimall(); + public CmdVersion cmdVersion = new CmdVersion(); + public CmdWarunclaimall cmdWarunclaimall = new CmdWarunclaimall(); + public CmdSB cmdSB = new CmdSB(); + public CmdShowInvites cmdShowInvites = new CmdShowInvites(); + public CmdAnnounce cmdAnnounce = new CmdAnnounce(); + public CmdPaypalSet cmdPaypalSet = new CmdPaypalSet(); + public CmdPaypalSee cmdPaypalSee = new CmdPaypalSee(); + public CmdSeeChunk cmdSeeChunk = new CmdSeeChunk(); + public CmdConvert cmdConvert = new CmdConvert(); + public CmdFWarp cmdFWarp = new CmdFWarp(); + public CmdSetFWarp cmdSetFWarp = new CmdSetFWarp(); + public CmdDelFWarp cmdDelFWarp = new CmdDelFWarp(); + public CmdModifyPower cmdModifyPower = new CmdModifyPower(); + public CmdLogins cmdLogins = new CmdLogins(); + public CmdClaimLine cmdClaimLine = new CmdClaimLine(); + public CmdTop cmdTop = new CmdTop(); + public CmdAHome cmdAHome = new CmdAHome(); + public CmdPerm cmdPerm = new CmdPerm(); + public CmdPromote cmdPromote = new CmdPromote(); + public CmdDemote cmdDemote = new CmdDemote(); + public CmdSetDefaultRole cmdSetDefaultRole = new CmdSetDefaultRole(); + public CmdMapHeight cmdMapHeight = new CmdMapHeight(); + public CmdClaimAt cmdClaimAt = new CmdClaimAt(); + public CmdBan cmdban = new CmdBan(); + public CmdUnban cmdUnban = new CmdUnban(); + public CmdBanlist cmdbanlist = new CmdBanlist(); + public CmdRules cmdRules = new CmdRules(); + public CmdCheckpoint cmdCheckpoint = new CmdCheckpoint(); + public CmdTnt cmdTnt = new CmdTnt(); + public CmdNear cmdNear = new CmdNear(); + public CmdUpgrades cmdUpgrades = new CmdUpgrades(); + public CmdVault cmdVault = new CmdVault(); + public CmdGetVault cmdGetVault = new CmdGetVault(); + public CmdFly cmdFly = new CmdFly(); + public CmdColeader cmdColeader = new CmdColeader(); + public CmdBanner cmdBanner = new CmdBanner(); + public CmdTpBanner cmdTpBanner = new CmdTpBanner(); + public CmdKillHolograms cmdKillHolograms = new CmdKillHolograms(); + public CmdInspect cmdInspect = new CmdInspect(); + public CmdCoords cmdCoords = new CmdCoords(); + public CmdShowClaims cmdShowClaims = new CmdShowClaims(); + public CmdLowPower cmdLowPower = new CmdLowPower(); + public CmdTntFill cmdTntFill = new CmdTntFill(); + public CmdChest cmdChest = new CmdChest(); + public CmdSetBanner cmdSetBanner = new CmdSetBanner(); - public FCmdRoot() { - super(); - this.aliases.addAll(Conf.baseCommandAliases); - this.aliases.removeAll(Collections.singletonList(null)); // remove any nulls from extra commas - this.allowNoSlashAccess = Conf.allowNoSlashCommand; + public FCmdRoot() { + super(); + this.aliases.addAll(Conf.baseCommandAliases); + this.aliases.removeAll(Collections.singletonList(null)); // remove any nulls from extra commas + this.allowNoSlashAccess = Conf.allowNoSlashCommand; - //this.requiredArgs.add(""); - //this.optionalArgs.put("","") + //this.requiredArgs.add(""); + //this.optionalArgs.put("","") - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - this.disableOnLock = false; + this.disableOnLock = false; - this.setHelpShort("The faction base command"); - this.helpLong.add(p.txt.parseTags("This command contains all faction stuff.")); + this.setHelpShort("The faction base command"); + this.helpLong.add(p.txt.parseTags("This command contains all faction stuff.")); - //this.subCommands.add(plugin.cmdHelp); + //this.subCommands.add(plugin.cmdHelp); - this.addSubCommand(this.cmdAdmin); - this.addSubCommand(this.cmdAutoClaim); - this.addSubCommand(this.cmdBoom); - this.addSubCommand(this.cmdBypass); - this.addSubCommand(this.cmdChat); - this.addSubCommand(this.cmdToggleAllianceChat); - this.addSubCommand(this.cmdChatSpy); - this.addSubCommand(this.cmdClaim); - this.addSubCommand(this.cmdConfig); - this.addSubCommand(this.cmdCreate); - this.addSubCommand(this.cmdDeinvite); - this.addSubCommand(this.cmdDescription); - this.addSubCommand(this.cmdDisband); + this.addSubCommand(this.cmdAdmin); + this.addSubCommand(this.cmdAutoClaim); + this.addSubCommand(this.cmdBoom); + this.addSubCommand(this.cmdBypass); + this.addSubCommand(this.cmdChat); + this.addSubCommand(this.cmdToggleAllianceChat); + this.addSubCommand(this.cmdChatSpy); + this.addSubCommand(this.cmdClaim); + this.addSubCommand(this.cmdConfig); + this.addSubCommand(this.cmdCreate); + this.addSubCommand(this.cmdDeinvite); + this.addSubCommand(this.cmdDescription); + this.addSubCommand(this.cmdDisband); - this.addSubCommand(this.cmdHelp); - this.addSubCommand(this.cmdHome); - this.addSubCommand(this.cmdInvite); - this.addSubCommand(this.cmdJoin); - this.addSubCommand(this.cmdKick); - this.addSubCommand(this.cmdLeave); - this.addSubCommand(this.cmdList); - this.addSubCommand(this.cmdLock); - this.addSubCommand(this.cmdMap); - this.addSubCommand(this.cmdMod); - this.addSubCommand(this.cmdMoney); - this.addSubCommand(this.cmdOpen); - this.addSubCommand(this.cmdOwner); - this.addSubCommand(this.cmdOwnerList); - this.addSubCommand(this.cmdPeaceful); - this.addSubCommand(this.cmdPermanent); - this.addSubCommand(this.cmdPermanentPower); - this.addSubCommand(this.cmdPower); - this.addSubCommand(this.cmdPowerBoost); - this.addSubCommand(this.cmdRelationAlly); - this.addSubCommand(this.cmdRelationEnemy); - this.addSubCommand(this.cmdRelationNeutral); - this.addSubCommand(this.cmdRelationTruce); - this.addSubCommand(this.cmdReload); - this.addSubCommand(this.cmdSafeunclaimall); - this.addSubCommand(this.cmdSaveAll); - this.addSubCommand(this.cmdSethome); - this.addSubCommand(this.cmdShow); - this.addSubCommand(this.cmdStatus); - this.addSubCommand(this.cmdStealth); - this.addSubCommand(this.cmdStuck); - this.addSubCommand(this.cmdTag); - this.addSubCommand(this.cmdTitle); - this.addSubCommand(this.cmdUnclaim); - this.addSubCommand(this.cmdUnclaimall); - this.addSubCommand(this.cmdVersion); - this.addSubCommand(this.cmdWarunclaimall); - this.addSubCommand(this.cmdSB); - this.addSubCommand(this.cmdShowInvites); - this.addSubCommand(this.cmdAnnounce); - this.addSubCommand(this.cmdSeeChunk); - this.addSubCommand(this.cmdConvert); - this.addSubCommand(this.cmdFWarp); - this.addSubCommand(this.cmdSetFWarp); - this.addSubCommand(this.cmdDelFWarp); - this.addSubCommand(this.cmdModifyPower); - this.addSubCommand(this.cmdLogins); - this.addSubCommand(this.cmdClaimLine); - this.addSubCommand(this.cmdAHome); - this.addSubCommand(this.cmdPerm); - this.addSubCommand(this.cmdPromote); - this.addSubCommand(this.cmdDemote); - this.addSubCommand(this.cmdSetDefaultRole); - this.addSubCommand(this.cmdMapHeight); - this.addSubCommand(this.cmdClaimAt); - this.addSubCommand(this.cmdban); - this.addSubCommand(this.cmdUnban); - this.addSubCommand(this.cmdbanlist); - this.addSubCommand(this.cmdRules); - this.addSubCommand(this.cmdCheckpoint); - this.addSubCommand(this.cmdTnt); - this.addSubCommand(this.cmdNear); - this.addSubCommand(this.cmdUpgrades); - this.addSubCommand(this.cmdVault); - this.addSubCommand(this.cmdGetVault); - this.addSubCommand(this.cmdColeader); - this.addSubCommand(this.cmdBanner); - this.addSubCommand(this.cmdTpBanner); - this.addSubCommand(this.cmdKillHolograms); - this.addSubCommand(this.cmdCoords); - this.addSubCommand(this.cmdShowClaims); - this.addSubCommand(this.cmdLowPower); - this.addSubCommand(this.cmdTntFill); - this.addSubCommand(this.cmdChest); - this.addSubCommand(this.cmdSetBanner); + this.addSubCommand(this.cmdHelp); + this.addSubCommand(this.cmdHome); + this.addSubCommand(this.cmdInvite); + this.addSubCommand(this.cmdJoin); + this.addSubCommand(this.cmdKick); + this.addSubCommand(this.cmdLeave); + this.addSubCommand(this.cmdList); + this.addSubCommand(this.cmdLock); + this.addSubCommand(this.cmdMap); + this.addSubCommand(this.cmdMod); + this.addSubCommand(this.cmdMoney); + this.addSubCommand(this.cmdOpen); + this.addSubCommand(this.cmdOwner); + this.addSubCommand(this.cmdOwnerList); + this.addSubCommand(this.cmdPeaceful); + this.addSubCommand(this.cmdPermanent); + this.addSubCommand(this.cmdPermanentPower); + this.addSubCommand(this.cmdPower); + this.addSubCommand(this.cmdPowerBoost); + this.addSubCommand(this.cmdRelationAlly); + this.addSubCommand(this.cmdRelationEnemy); + this.addSubCommand(this.cmdRelationNeutral); + this.addSubCommand(this.cmdRelationTruce); + this.addSubCommand(this.cmdReload); + this.addSubCommand(this.cmdSafeunclaimall); + this.addSubCommand(this.cmdSaveAll); + this.addSubCommand(this.cmdSethome); + this.addSubCommand(this.cmdShow); + this.addSubCommand(this.cmdStatus); + this.addSubCommand(this.cmdStealth); + this.addSubCommand(this.cmdStuck); + this.addSubCommand(this.cmdTag); + this.addSubCommand(this.cmdTitle); + this.addSubCommand(this.cmdUnclaim); + this.addSubCommand(this.cmdUnclaimall); + this.addSubCommand(this.cmdVersion); + this.addSubCommand(this.cmdWarunclaimall); + this.addSubCommand(this.cmdSB); + this.addSubCommand(this.cmdShowInvites); + this.addSubCommand(this.cmdAnnounce); + this.addSubCommand(this.cmdSeeChunk); + this.addSubCommand(this.cmdConvert); + this.addSubCommand(this.cmdFWarp); + this.addSubCommand(this.cmdSetFWarp); + this.addSubCommand(this.cmdDelFWarp); + this.addSubCommand(this.cmdModifyPower); + this.addSubCommand(this.cmdLogins); + this.addSubCommand(this.cmdClaimLine); + this.addSubCommand(this.cmdAHome); + this.addSubCommand(this.cmdPerm); + this.addSubCommand(this.cmdPromote); + this.addSubCommand(this.cmdDemote); + this.addSubCommand(this.cmdSetDefaultRole); + this.addSubCommand(this.cmdMapHeight); + this.addSubCommand(this.cmdClaimAt); + this.addSubCommand(this.cmdban); + this.addSubCommand(this.cmdUnban); + this.addSubCommand(this.cmdbanlist); + this.addSubCommand(this.cmdRules); + this.addSubCommand(this.cmdCheckpoint); + this.addSubCommand(this.cmdTnt); + this.addSubCommand(this.cmdNear); + this.addSubCommand(this.cmdUpgrades); + this.addSubCommand(this.cmdVault); + this.addSubCommand(this.cmdGetVault); + this.addSubCommand(this.cmdColeader); + this.addSubCommand(this.cmdBanner); + this.addSubCommand(this.cmdTpBanner); + this.addSubCommand(this.cmdKillHolograms); + this.addSubCommand(this.cmdCoords); + this.addSubCommand(this.cmdShowClaims); + this.addSubCommand(this.cmdLowPower); + this.addSubCommand(this.cmdTntFill); + this.addSubCommand(this.cmdChest); + this.addSubCommand(this.cmdSetBanner); - if (Bukkit.getServer().getPluginManager().getPlugin("CoreProtect") != null) { - SavageFactions.plugin.log("Found CoreProtect, enabling Inspect"); - this.addSubCommand(this.cmdInspect); - } else { - SavageFactions.plugin.log("CoreProtect not found, disabling Inspect"); - } - if (SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { - addSubCommand(this.cmdFocus); - } + if (Bukkit.getServer().getPluginManager().getPlugin("CoreProtect") != null) { + SavageFactions.plugin.log("Found CoreProtect, enabling Inspect"); + this.addSubCommand(this.cmdInspect); + } else { + SavageFactions.plugin.log("CoreProtect not found, disabling Inspect"); + } + if (SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { + addSubCommand(this.cmdFocus); + } - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { - this.addSubCommand(this.cmdFly); - } - if (Bukkit.getServer().getPluginManager().getPlugin("FactionsTop") != null) { - SavageFactions.plugin.log(Level.INFO, "Found FactionsTop plugin. Disabling our own /f top command."); - } else { - SavageFactions.plugin.log(Level.INFO, "Enabling FactionsTop command, this is a very basic /f top please get a dedicated /f top resource if you want land calculation etc."); - this.addSubCommand(this.cmdTop); - } - if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - this.addSubCommand(this.cmdPaypalSet); - this.addSubCommand(this.cmdPaypalSee); - } + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { + this.addSubCommand(this.cmdFly); + } + if (Bukkit.getServer().getPluginManager().getPlugin("FactionsTop") != null) { + SavageFactions.plugin.log(Level.INFO, "Found FactionsTop plugin. Disabling our own /f top command."); + } else { + SavageFactions.plugin.log(Level.INFO, "Enabling FactionsTop command, this is a very basic /f top please get a dedicated /f top resource if you want land calculation etc."); + this.addSubCommand(this.cmdTop); + } + if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + this.addSubCommand(this.cmdPaypalSet); + this.addSubCommand(this.cmdPaypalSee); + } - } + } - @Override - public void perform() { - this.commandChain.add(this); - this.cmdHelp.execute(this.sender, this.args, this.commandChain); - } + @Override + public void perform() { + this.commandChain.add(this); + this.cmdHelp.execute(this.sender, this.args, this.commandChain); + } - @Override - public TL getUsageTranslation() { - return TL.GENERIC_PLACEHOLDER; - } + @Override + public TL getUsageTranslation() { + return TL.GENERIC_PLACEHOLDER; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/FCommand.java b/src/main/java/com/massivecraft/factions/cmd/FCommand.java index e8e9d635..03aab442 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FCommand.java @@ -15,330 +15,330 @@ import java.util.List; public abstract class FCommand extends MCommand { - public static final SimpleDateFormat sdf = new SimpleDateFormat(TL.DATE_FORMAT.toString()); - - public boolean disableOnLock; - - public FPlayer fme; - public Faction myFaction; - public boolean senderMustBeMember; - public boolean senderMustBeModerator; - public boolean senderMustBeAdmin; - public boolean senderMustBeColeader; - - - public boolean isMoneyCommand; - - public FCommand() { - super(SavageFactions.plugin); - - // Due to safety reasons it defaults to disable on lock. - disableOnLock = true; - - // The money commands must be disabled if money should not be used. - isMoneyCommand = false; - - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void setCommandSender(CommandSender sender) { - super.setCommandSender(sender); - if (sender instanceof Player) { - this.fme = FPlayers.getInstance().getByPlayer((Player) sender); - this.myFaction = this.fme.getFaction(); - } else { - this.fme = null; - this.myFaction = null; - } - } - - @Override - public void execute(CommandSender sender, List args, List> commandChain) { - setCommandSender(sender); - super.execute(sender, args, commandChain); - } - - @Override - public boolean isEnabled() { - if (p.getLocked() && this.disableOnLock) { - msg("Factions was locked by an admin. Please try again later."); - return false; - } - - if (this.isMoneyCommand && !Conf.econEnabled) { - msg("Faction economy features are disabled on this server."); - return false; - } - - if (this.isMoneyCommand && !Conf.bankEnabled) { - msg("The faction bank system is disabled on this server."); - return false; - } - - return true; - } - - @Override - public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { - boolean superValid = super.validSenderType(sender, informSenderIfNot); - if (!superValid) { - return false; - } - - if (!(this.senderMustBeMember || this.senderMustBeModerator || this.senderMustBeAdmin || this.senderMustBeColeader)) { - return true; - } - - if (!(sender instanceof Player)) { - return false; - } - - if (!fme.hasFaction()) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("You are not member of any faction.")); - } - return false; - } - - - if (this.senderMustBeModerator && !fme.getRole().isAtLeast(Role.MODERATOR)) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("Only faction moderators can %s.", this.getHelpShort())); - } - return false; - } - - if (this.senderMustBeColeader && !fme.getRole().isAtLeast(Role.COLEADER)) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("Only faction coleaders can %s.", this.getHelpShort())); - } - return false; - } - - if (this.senderMustBeAdmin && !fme.getRole().isAtLeast(Role.LEADER)) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("Only faction admins can %s.", this.getHelpShort())); - } - return false; - } - - - return true; - } - - // -------------------------------------------- // - // Assertions - // -------------------------------------------- // - - public boolean assertHasFaction() { - if (me == null) { - return true; - } - - if (!fme.hasFaction()) { - sendMessage("You are not member of any faction."); - return false; - } - return true; - } - - public boolean assertMinRole(Role role) { - if (me == null) { - return true; - } - - if (fme.getRole().value < role.value) { - msg("You must be " + role + " to " + this.getHelpShort() + "."); - return false; - } - return true; - } - - // -------------------------------------------- // - // Argument Readers - // -------------------------------------------- // - - // FPLAYER ====================== - public FPlayer strAsFPlayer(String name, FPlayer def, boolean msg) { - FPlayer ret = def; - - if (name != null) { - for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { - if (fplayer.getName().equalsIgnoreCase(name)) { - ret = fplayer; - break; - } - } - } - - if (msg && ret == null) { - this.msg("No player \"%s\" could be found.", name); - } - - return ret; - } - - public FPlayer argAsFPlayer(int idx, FPlayer def, boolean msg) { - return this.strAsFPlayer(this.argAsString(idx), def, msg); - } - - public FPlayer argAsFPlayer(int idx, FPlayer def) { - return this.argAsFPlayer(idx, def, true); - } - - public FPlayer argAsFPlayer(int idx) { - return this.argAsFPlayer(idx, null); - } - - // BEST FPLAYER MATCH ====================== - public FPlayer strAsBestFPlayerMatch(String name, FPlayer def, boolean msg) { - return strAsFPlayer(name, def, msg); - } - - public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def, boolean msg) { - return this.strAsBestFPlayerMatch(this.argAsString(idx), def, msg); - } - - public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def) { - return this.argAsBestFPlayerMatch(idx, def, true); - } - - public FPlayer argAsBestFPlayerMatch(int idx) { - return this.argAsBestFPlayerMatch(idx, null); - } - - // FACTION ====================== - public Faction strAsFaction(String name, Faction def, boolean msg) { - Faction ret = def; - - if (name != null) { - // First we try an exact match - Faction faction = Factions.getInstance().getByTag(name); // Checks for faction name match. - - // Now lets try for warzone / safezone. Helpful for custom warzone / safezone names. - // Do this after we check for an exact match in case they rename the warzone / safezone - // and a player created faction took one of the names. - if (faction == null) { - if (name.equalsIgnoreCase("warzone")) { - faction = Factions.getInstance().getWarZone(); - } else if (name.equalsIgnoreCase("safezone")) { - faction = Factions.getInstance().getSafeZone(); - } - } - - // Next we match faction tags - if (faction == null) { - faction = Factions.getInstance().getBestTagMatch(name); - } - - // Next we match player names - if (faction == null) { - FPlayer fplayer = strAsFPlayer(name, null, false); - if (fplayer != null) { - faction = fplayer.getFaction(); - } - } - - if (faction != null) { - ret = faction; - } - } - - if (msg && ret == null) { - this.msg("The faction or player \"%s\" could not be found.", name); - } - - return ret; - } - - public Faction argAsFaction(int idx, Faction def, boolean msg) { - return this.strAsFaction(this.argAsString(idx), def, msg); - } - - public Faction argAsFaction(int idx, Faction def) { - return this.argAsFaction(idx, def, true); - } - - public Faction argAsFaction(int idx) { - return this.argAsFaction(idx, null); - } - - // -------------------------------------------- // - // Commonly used logic - // -------------------------------------------- // - - public boolean canIAdministerYou(FPlayer i, FPlayer you) { - if (!i.getFaction().equals(you.getFaction())) { - i.sendMessage(p.txt.parse("%s is not in the same faction as you.", you.describeTo(i, true))); - return false; - } - - if (i.getRole().value > you.getRole().value || i.getRole().equals(Role.LEADER)) { - return true; - } - - if (you.getRole().equals(Role.LEADER)) { - i.sendMessage(p.txt.parse("Only the faction admin can do that.")); - - } else if ((you.getRole().equals(Role.COLEADER))) { - if (i == you) { - return true; - } else { - i.sendMessage(p.txt.parse("Coleaders can't control each other...")); - } - - } else if (i.getRole().equals(Role.MODERATOR)) { - if (i == you) { - return true; //Moderators can control themselves - } else { - i.sendMessage(p.txt.parse("Moderators can't control each other...")); - } - } else { - i.sendMessage(p.txt.parse("You must be a faction moderator to do that.")); - } - - return false; - } - - // if economy is enabled and they're not on the bypass list, make 'em pay; returns true unless person can't afford the cost - public boolean payForCommand(double cost, String toDoThis, String forDoingThis) { - if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { - return true; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { - return Econ.modifyMoney(myFaction, -cost, toDoThis, forDoingThis); - } else { - return Econ.modifyMoney(fme, -cost, toDoThis, forDoingThis); - } - } - - public boolean payForCommand(double cost, TL toDoThis, TL forDoingThis) { - return payForCommand(cost, toDoThis.toString(), forDoingThis.toString()); - } - - // like above, but just make sure they can pay; returns true unless person can't afford the cost - public boolean canAffordCommand(double cost, String toDoThis) { - if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { - return true; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { - return Econ.hasAtLeast(myFaction, cost, toDoThis); - } else { - return Econ.hasAtLeast(fme, cost, toDoThis); - } - } - - public void doWarmUp(WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { - this.doWarmUp(this.fme, warmup, translationKey, action, runnable, delay); - } - - public void doWarmUp(FPlayer player, WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { - WarmUpUtil.process(player, warmup, translationKey, action, runnable, delay); - } + public static final SimpleDateFormat sdf = new SimpleDateFormat(TL.DATE_FORMAT.toString()); + + public boolean disableOnLock; + + public FPlayer fme; + public Faction myFaction; + public boolean senderMustBeMember; + public boolean senderMustBeModerator; + public boolean senderMustBeAdmin; + public boolean senderMustBeColeader; + + + public boolean isMoneyCommand; + + public FCommand() { + super(SavageFactions.plugin); + + // Due to safety reasons it defaults to disable on lock. + disableOnLock = true; + + // The money commands must be disabled if money should not be used. + isMoneyCommand = false; + + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void setCommandSender(CommandSender sender) { + super.setCommandSender(sender); + if (sender instanceof Player) { + this.fme = FPlayers.getInstance().getByPlayer((Player) sender); + this.myFaction = this.fme.getFaction(); + } else { + this.fme = null; + this.myFaction = null; + } + } + + @Override + public void execute(CommandSender sender, List args, List> commandChain) { + setCommandSender(sender); + super.execute(sender, args, commandChain); + } + + @Override + public boolean isEnabled() { + if (p.getLocked() && this.disableOnLock) { + msg("Factions was locked by an admin. Please try again later."); + return false; + } + + if (this.isMoneyCommand && !Conf.econEnabled) { + msg("Faction economy features are disabled on this server."); + return false; + } + + if (this.isMoneyCommand && !Conf.bankEnabled) { + msg("The faction bank system is disabled on this server."); + return false; + } + + return true; + } + + @Override + public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { + boolean superValid = super.validSenderType(sender, informSenderIfNot); + if (!superValid) { + return false; + } + + if (!(this.senderMustBeMember || this.senderMustBeModerator || this.senderMustBeAdmin || this.senderMustBeColeader)) { + return true; + } + + if (!(sender instanceof Player)) { + return false; + } + + if (!fme.hasFaction()) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("You are not member of any faction.")); + } + return false; + } + + + if (this.senderMustBeModerator && !fme.getRole().isAtLeast(Role.MODERATOR)) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("Only faction moderators can %s.", this.getHelpShort())); + } + return false; + } + + if (this.senderMustBeColeader && !fme.getRole().isAtLeast(Role.COLEADER)) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("Only faction coleaders can %s.", this.getHelpShort())); + } + return false; + } + + if (this.senderMustBeAdmin && !fme.getRole().isAtLeast(Role.LEADER)) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("Only faction admins can %s.", this.getHelpShort())); + } + return false; + } + + + return true; + } + + // -------------------------------------------- // + // Assertions + // -------------------------------------------- // + + public boolean assertHasFaction() { + if (me == null) { + return true; + } + + if (!fme.hasFaction()) { + sendMessage("You are not member of any faction."); + return false; + } + return true; + } + + public boolean assertMinRole(Role role) { + if (me == null) { + return true; + } + + if (fme.getRole().value < role.value) { + msg("You must be " + role + " to " + this.getHelpShort() + "."); + return false; + } + return true; + } + + // -------------------------------------------- // + // Argument Readers + // -------------------------------------------- // + + // FPLAYER ====================== + public FPlayer strAsFPlayer(String name, FPlayer def, boolean msg) { + FPlayer ret = def; + + if (name != null) { + for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { + if (fplayer.getName().equalsIgnoreCase(name)) { + ret = fplayer; + break; + } + } + } + + if (msg && ret == null) { + this.msg("No player \"%s\" could be found.", name); + } + + return ret; + } + + public FPlayer argAsFPlayer(int idx, FPlayer def, boolean msg) { + return this.strAsFPlayer(this.argAsString(idx), def, msg); + } + + public FPlayer argAsFPlayer(int idx, FPlayer def) { + return this.argAsFPlayer(idx, def, true); + } + + public FPlayer argAsFPlayer(int idx) { + return this.argAsFPlayer(idx, null); + } + + // BEST FPLAYER MATCH ====================== + public FPlayer strAsBestFPlayerMatch(String name, FPlayer def, boolean msg) { + return strAsFPlayer(name, def, msg); + } + + public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def, boolean msg) { + return this.strAsBestFPlayerMatch(this.argAsString(idx), def, msg); + } + + public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def) { + return this.argAsBestFPlayerMatch(idx, def, true); + } + + public FPlayer argAsBestFPlayerMatch(int idx) { + return this.argAsBestFPlayerMatch(idx, null); + } + + // FACTION ====================== + public Faction strAsFaction(String name, Faction def, boolean msg) { + Faction ret = def; + + if (name != null) { + // First we try an exact match + Faction faction = Factions.getInstance().getByTag(name); // Checks for faction name match. + + // Now lets try for warzone / safezone. Helpful for custom warzone / safezone names. + // Do this after we check for an exact match in case they rename the warzone / safezone + // and a player created faction took one of the names. + if (faction == null) { + if (name.equalsIgnoreCase("warzone")) { + faction = Factions.getInstance().getWarZone(); + } else if (name.equalsIgnoreCase("safezone")) { + faction = Factions.getInstance().getSafeZone(); + } + } + + // Next we match faction tags + if (faction == null) { + faction = Factions.getInstance().getBestTagMatch(name); + } + + // Next we match player names + if (faction == null) { + FPlayer fplayer = strAsFPlayer(name, null, false); + if (fplayer != null) { + faction = fplayer.getFaction(); + } + } + + if (faction != null) { + ret = faction; + } + } + + if (msg && ret == null) { + this.msg("The faction or player \"%s\" could not be found.", name); + } + + return ret; + } + + public Faction argAsFaction(int idx, Faction def, boolean msg) { + return this.strAsFaction(this.argAsString(idx), def, msg); + } + + public Faction argAsFaction(int idx, Faction def) { + return this.argAsFaction(idx, def, true); + } + + public Faction argAsFaction(int idx) { + return this.argAsFaction(idx, null); + } + + // -------------------------------------------- // + // Commonly used logic + // -------------------------------------------- // + + public boolean canIAdministerYou(FPlayer i, FPlayer you) { + if (!i.getFaction().equals(you.getFaction())) { + i.sendMessage(p.txt.parse("%s is not in the same faction as you.", you.describeTo(i, true))); + return false; + } + + if (i.getRole().value > you.getRole().value || i.getRole().equals(Role.LEADER)) { + return true; + } + + if (you.getRole().equals(Role.LEADER)) { + i.sendMessage(p.txt.parse("Only the faction admin can do that.")); + + } else if ((you.getRole().equals(Role.COLEADER))) { + if (i == you) { + return true; + } else { + i.sendMessage(p.txt.parse("Coleaders can't control each other...")); + } + + } else if (i.getRole().equals(Role.MODERATOR)) { + if (i == you) { + return true; //Moderators can control themselves + } else { + i.sendMessage(p.txt.parse("Moderators can't control each other...")); + } + } else { + i.sendMessage(p.txt.parse("You must be a faction moderator to do that.")); + } + + return false; + } + + // if economy is enabled and they're not on the bypass list, make 'em pay; returns true unless person can't afford the cost + public boolean payForCommand(double cost, String toDoThis, String forDoingThis) { + if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { + return true; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { + return Econ.modifyMoney(myFaction, -cost, toDoThis, forDoingThis); + } else { + return Econ.modifyMoney(fme, -cost, toDoThis, forDoingThis); + } + } + + public boolean payForCommand(double cost, TL toDoThis, TL forDoingThis) { + return payForCommand(cost, toDoThis.toString(), forDoingThis.toString()); + } + + // like above, but just make sure they can pay; returns true unless person can't afford the cost + public boolean canAffordCommand(double cost, String toDoThis) { + if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { + return true; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { + return Econ.hasAtLeast(myFaction, cost, toDoThis); + } else { + return Econ.hasAtLeast(fme, cost, toDoThis); + } + } + + public void doWarmUp(WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { + this.doWarmUp(this.fme, warmup, translationKey, action, runnable, delay); + } + + public void doWarmUp(FPlayer player, WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { + WarmUpUtil.process(player, warmup, translationKey, action, runnable, delay); + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java b/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java index d36779ed..94366584 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java @@ -9,86 +9,86 @@ import com.massivecraft.factions.zcore.util.TL; public class FPromoteCommand extends FCommand { - public int relative = 0; + public int relative = 0; - public FPromoteCommand() { - super(); + public FPromoteCommand() { + super(); - this.requiredArgs.add("player"); + this.requiredArgs.add("player"); - this.permission = Permission.PROMOTE.node; - this.disableOnLock = true; + this.permission = Permission.PROMOTE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer target = this.argAsBestFPlayerMatch(0); - if (target == null) { - msg(TL.GENERIC_NOPLAYERFOUND, this.argAsString(0)); - return; - } + @Override + public void perform() { + FPlayer target = this.argAsBestFPlayerMatch(0); + if (target == null) { + msg(TL.GENERIC_NOPLAYERFOUND, this.argAsString(0)); + return; + } - if (!target.getFaction().equals(myFaction)) { - msg(TL.COMMAND_PROMOTE_WRONGFACTION, target.getName()); - return; - } + if (!target.getFaction().equals(myFaction)) { + msg(TL.COMMAND_PROMOTE_WRONGFACTION, target.getName()); + return; + } - Role current = target.getRole(); - Role promotion = Role.getRelative(current, +relative); + Role current = target.getRole(); + Role promotion = Role.getRelative(current, +relative); - // Now it ain't that messy - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.PROMOTE); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_NOPERMISSION, "manage ranks"); - return; - } - if (target == fme) { - fme.msg(TL.COMMAND_PROMOTE_NOTSELF); - return; - } - // Don't allow people to manage role of their same rank - if (fme.getRole() == current) { - fme.msg(TL.COMMAND_PROMOTE_NOT_SAME); - return; - } - // Don't allow people to promote people to their same or higher rank. - if (fme.getRole().value <= promotion.value) { - fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); - return; - } - } + // Now it ain't that messy + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.PROMOTE); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_NOPERMISSION, "manage ranks"); + return; + } + if (target == fme) { + fme.msg(TL.COMMAND_PROMOTE_NOTSELF); + return; + } + // Don't allow people to manage role of their same rank + if (fme.getRole() == current) { + fme.msg(TL.COMMAND_PROMOTE_NOT_SAME); + return; + } + // Don't allow people to promote people to their same or higher rank. + if (fme.getRole().value <= promotion.value) { + fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); + return; + } + } - if (promotion == null) { - fme.msg(TL.COMMAND_PROMOTE_NOTTHATPLAYER); - return; - } + if (promotion == null) { + fme.msg(TL.COMMAND_PROMOTE_NOTTHATPLAYER); + return; + } - // Don't allow people to promote people to their same or higher rnak. - if (fme.getRole().value <= promotion.value) { - fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); - return; - } + // Don't allow people to promote people to their same or higher rnak. + if (fme.getRole().value <= promotion.value) { + fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); + return; + } - String action = relative > 0 ? TL.COMMAND_PROMOTE_PROMOTED.toString() : TL.COMMAND_PROMOTE_DEMOTED.toString(); + String action = relative > 0 ? TL.COMMAND_PROMOTE_PROMOTED.toString() : TL.COMMAND_PROMOTE_DEMOTED.toString(); - // Success! - target.setRole(promotion); - if (target.isOnline()) { - target.msg(TL.COMMAND_PROMOTE_TARGET, action, promotion.nicename); - } + // Success! + target.setRole(promotion); + if (target.isOnline()) { + target.msg(TL.COMMAND_PROMOTE_TARGET, action, promotion.nicename); + } - fme.msg(TL.COMMAND_PROMOTE_SUCCESS, action, target.getName(), promotion.nicename); - } + fme.msg(TL.COMMAND_PROMOTE_SUCCESS, action, target.getName(), promotion.nicename); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PROMOTE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PROMOTE_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java b/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java index 9efbff03..07172c9f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java @@ -14,113 +14,113 @@ import org.bukkit.ChatColor; public abstract class FRelationCommand extends FCommand { - public Relation targetRelation; + public Relation targetRelation; - public FRelationCommand() { - super(); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("player name", "you"); + public FRelationCommand() { + super(); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("player name", "you"); - this.permission = Permission.RELATION.node; - this.disableOnLock = true; + this.permission = Permission.RELATION.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction them = this.argAsFaction(0); - if (them == null) { - return; - } + @Override + public void perform() { + Faction them = this.argAsFaction(0); + if (them == null) { + return; + } - if (!them.isNormal()) { - msg(TL.COMMAND_RELATIONS_ALLTHENOPE); - return; - } + if (!them.isNormal()) { + msg(TL.COMMAND_RELATIONS_ALLTHENOPE); + return; + } - if (them == myFaction) { - msg(TL.COMMAND_RELATIONS_MORENOPE); - return; - } + if (them == myFaction) { + msg(TL.COMMAND_RELATIONS_MORENOPE); + return; + } - if (myFaction.getRelationWish(them) == targetRelation) { - msg(TL.COMMAND_RELATIONS_ALREADYINRELATIONSHIP, them.getTag()); - return; - } + if (myFaction.getRelationWish(them) == targetRelation) { + msg(TL.COMMAND_RELATIONS_ALREADYINRELATIONSHIP, them.getTag()); + return; + } - if (hasMaxRelations(them, targetRelation)) { - // We message them down there with the count. - return; - } - Relation oldRelation = myFaction.getRelationTo(them, true); - FactionRelationWishEvent wishEvent = new FactionRelationWishEvent(fme, myFaction, them, oldRelation, targetRelation); - Bukkit.getPluginManager().callEvent(wishEvent); - if (wishEvent.isCancelled()) { - return; - } + if (hasMaxRelations(them, targetRelation)) { + // We message them down there with the count. + return; + } + Relation oldRelation = myFaction.getRelationTo(them, true); + FactionRelationWishEvent wishEvent = new FactionRelationWishEvent(fme, myFaction, them, oldRelation, targetRelation); + Bukkit.getPluginManager().callEvent(wishEvent); + if (wishEvent.isCancelled()) { + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(targetRelation.getRelationCost(), TL.COMMAND_RELATIONS_TOMARRY, TL.COMMAND_RELATIONS_FORMARRY)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(targetRelation.getRelationCost(), TL.COMMAND_RELATIONS_TOMARRY, TL.COMMAND_RELATIONS_FORMARRY)) { + return; + } - // try to set the new relation - myFaction.setRelationWish(them, targetRelation); - Relation currentRelation = myFaction.getRelationTo(them, true); - ChatColor currentRelationColor = currentRelation.getColor(); + // try to set the new relation + myFaction.setRelationWish(them, targetRelation); + Relation currentRelation = myFaction.getRelationTo(them, true); + ChatColor currentRelationColor = currentRelation.getColor(); - // if the relation change was successful - if (targetRelation.value == currentRelation.value) { - // trigger the faction relation event - FactionRelationEvent relationEvent = new FactionRelationEvent(myFaction, them, oldRelation, currentRelation); - Bukkit.getServer().getPluginManager().callEvent(relationEvent); + // if the relation change was successful + if (targetRelation.value == currentRelation.value) { + // trigger the faction relation event + FactionRelationEvent relationEvent = new FactionRelationEvent(myFaction, them, oldRelation, currentRelation); + Bukkit.getServer().getPluginManager().callEvent(relationEvent); - them.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + myFaction.getTag()); - myFaction.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + them.getTag()); - } else { - // inform the other faction of your request - them.msg(TL.COMMAND_RELATIONS_PROPOSAL_1, currentRelationColor + myFaction.getTag(), targetRelation.getColor() + targetRelation.getTranslation()); - them.msg(TL.COMMAND_RELATIONS_PROPOSAL_2, Conf.baseCommandAliases.get(0), targetRelation, myFaction.getTag()); - myFaction.msg(TL.COMMAND_RELATIONS_PROPOSAL_SENT, currentRelationColor + them.getTag(), "" + targetRelation.getColor() + targetRelation); - } + them.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + myFaction.getTag()); + myFaction.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + them.getTag()); + } else { + // inform the other faction of your request + them.msg(TL.COMMAND_RELATIONS_PROPOSAL_1, currentRelationColor + myFaction.getTag(), targetRelation.getColor() + targetRelation.getTranslation()); + them.msg(TL.COMMAND_RELATIONS_PROPOSAL_2, Conf.baseCommandAliases.get(0), targetRelation, myFaction.getTag()); + myFaction.msg(TL.COMMAND_RELATIONS_PROPOSAL_SENT, currentRelationColor + them.getTag(), "" + targetRelation.getColor() + targetRelation); + } - if (!targetRelation.isNeutral() && them.isPeaceful()) { - them.msg(TL.COMMAND_RELATIONS_PEACEFUL); - myFaction.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); - } + if (!targetRelation.isNeutral() && them.isPeaceful()) { + them.msg(TL.COMMAND_RELATIONS_PEACEFUL); + myFaction.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); + } - if (!targetRelation.isNeutral() && myFaction.isPeaceful()) { - them.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); - myFaction.msg(TL.COMMAND_RELATIONS_PEACEFUL); - } + if (!targetRelation.isNeutral() && myFaction.isPeaceful()) { + them.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); + myFaction.msg(TL.COMMAND_RELATIONS_PEACEFUL); + } - FTeamWrapper.updatePrefixes(myFaction); - FTeamWrapper.updatePrefixes(them); - } + FTeamWrapper.updatePrefixes(myFaction); + FTeamWrapper.updatePrefixes(them); + } - private boolean hasMaxRelations(Faction them, Relation targetRelation) { - int max = SavageFactions.plugin.getConfig().getInt("max-relations." + targetRelation.toString(), -1); - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", false)) { - if (max != -1) { - if (myFaction.getRelationCount(targetRelation) >= max) { - msg(TL.COMMAND_RELATIONS_EXCEEDS_ME, max, targetRelation.getPluralTranslation()); - return true; - } - if (them.getRelationCount(targetRelation) >= max) { - msg(TL.COMMAND_RELATIONS_EXCEEDS_THEY, max, targetRelation.getPluralTranslation()); - return true; - } - } - } - return false; - } + private boolean hasMaxRelations(Faction them, Relation targetRelation) { + int max = SavageFactions.plugin.getConfig().getInt("max-relations." + targetRelation.toString(), -1); + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", false)) { + if (max != -1) { + if (myFaction.getRelationCount(targetRelation) >= max) { + msg(TL.COMMAND_RELATIONS_EXCEEDS_ME, max, targetRelation.getPluralTranslation()); + return true; + } + if (them.getRelationCount(targetRelation) >= max) { + msg(TL.COMMAND_RELATIONS_EXCEEDS_THEY, max, targetRelation.getPluralTranslation()); + return true; + } + } + } + return false; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_RELATIONS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_RELATIONS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java b/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java index d22632c1..9e9f8c67 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java @@ -6,37 +6,37 @@ import org.bukkit.event.HandlerList; public class FPlayerEnteredFactionEvent extends FactionPlayerEvent { - private static final HandlerList handlers = new HandlerList(); - private FPlayer fPlayer; - private Faction factionTo; - private Faction factionFrom; + private static final HandlerList handlers = new HandlerList(); + private FPlayer fPlayer; + private Faction factionTo; + private Faction factionFrom; - public FPlayerEnteredFactionEvent(Faction factionTo, Faction factionFrom, FPlayer fPlayer) { - super(fPlayer.getFaction(), fPlayer); - this.factionFrom = factionFrom; - this.factionTo = factionTo; - this.fPlayer = fPlayer; - } + public FPlayerEnteredFactionEvent(Faction factionTo, Faction factionFrom, FPlayer fPlayer) { + super(fPlayer.getFaction(), fPlayer); + this.factionFrom = factionFrom; + this.factionTo = factionTo; + this.fPlayer = fPlayer; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } - @Override - public FPlayer getfPlayer() { - return fPlayer; - } + @Override + public FPlayer getfPlayer() { + return fPlayer; + } - public Faction getFactionTo() { - return factionTo; - } + public Faction getFactionTo() { + return factionTo; + } - public Faction getFactionFrom() { - return factionFrom; - } + public Faction getFactionFrom() { + return factionFrom; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java b/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java index fd9617da..1755bdff 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java @@ -9,34 +9,34 @@ import org.bukkit.event.Cancellable; */ public class FPlayerJoinEvent extends FactionPlayerEvent implements Cancellable { - PlayerJoinReason reason; - boolean cancelled = false; + PlayerJoinReason reason; + boolean cancelled = false; - public FPlayerJoinEvent(FPlayer fp, Faction f, PlayerJoinReason r) { - super(f, fp); - reason = r; - } + public FPlayerJoinEvent(FPlayer fp, Faction f, PlayerJoinReason r) { + super(f, fp); + reason = r; + } - /** - * Get the reason the player joined the faction. - * - * @return reason player joined the faction. - */ - public PlayerJoinReason getReason() { - return reason; - } + /** + * Get the reason the player joined the faction. + * + * @return reason player joined the faction. + */ + public PlayerJoinReason getReason() { + return reason; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - cancelled = c; - } + @Override + public void setCancelled(boolean c) { + cancelled = c; + } - public enum PlayerJoinReason { - CREATE, LEADER, COMMAND - } + public enum PlayerJoinReason { + CREATE, LEADER, COMMAND + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java b/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java index e9b764d9..0ecb80d1 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java @@ -6,35 +6,35 @@ import org.bukkit.event.Cancellable; public class FPlayerLeaveEvent extends FactionPlayerEvent implements Cancellable { - boolean cancelled = false; - private PlayerLeaveReason reason; + boolean cancelled = false; + private PlayerLeaveReason reason; - public FPlayerLeaveEvent(FPlayer p, Faction f, PlayerLeaveReason r) { - super(f, p); - reason = r; - } + public FPlayerLeaveEvent(FPlayer p, Faction f, PlayerLeaveReason r) { + super(f, p); + reason = r; + } - /** - * Get the reason the player left the faction. - * - * @return reason player left the faction. - */ - public PlayerLeaveReason getReason() { - return reason; - } + /** + * Get the reason the player left the faction. + * + * @return reason player left the faction. + */ + public PlayerLeaveReason getReason() { + return reason; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - // Don't let them cancel factions disbanding. - cancelled = reason != PlayerLeaveReason.DISBAND && reason != PlayerLeaveReason.RESET && c; - } + @Override + public void setCancelled(boolean c) { + // Don't let them cancel factions disbanding. + cancelled = reason != PlayerLeaveReason.DISBAND && reason != PlayerLeaveReason.RESET && c; + } - public enum PlayerLeaveReason { - KICKED, DISBAND, RESET, JOINOTHER, LEAVE, BANNED - } + public enum PlayerLeaveReason { + KICKED, DISBAND, RESET, JOINOTHER, LEAVE, BANNED + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java b/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java index f2f283c8..5a80a15a 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java @@ -4,25 +4,25 @@ import com.massivecraft.factions.FPlayer; import org.bukkit.event.HandlerList; public class FPlayerStoppedFlying extends FactionPlayerEvent { - private static final HandlerList handlers = new HandlerList(); - private FPlayer fPlayer; + private static final HandlerList handlers = new HandlerList(); + private FPlayer fPlayer; - public FPlayerStoppedFlying(FPlayer fPlayer) { - super(fPlayer.getFaction(), fPlayer); - this.fPlayer = fPlayer; - } + public FPlayerStoppedFlying(FPlayer fPlayer) { + super(fPlayer.getFaction(), fPlayer); + this.fPlayer = fPlayer; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - @Override - public FPlayer getfPlayer() { - return fPlayer; - } + @Override + public FPlayer getfPlayer() { + return fPlayer; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java b/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java index afdd1ab4..18791908 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java @@ -12,41 +12,41 @@ import org.bukkit.event.HandlerList; */ public class FactionCreateEvent extends Event implements Cancellable { - private static final HandlerList handlers = new HandlerList(); + private static final HandlerList handlers = new HandlerList(); - private String factionTag; - private Player sender; - private boolean cancelled; + private String factionTag; + private Player sender; + private boolean cancelled; - public FactionCreateEvent(Player sender, String tag) { - this.factionTag = tag; - this.sender = sender; - this.cancelled = false; - } + public FactionCreateEvent(Player sender, String tag) { + this.factionTag = tag; + this.sender = sender; + this.cancelled = false; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - public FPlayer getFPlayer() { - return FPlayers.getInstance().getByPlayer(sender); - } + public FPlayer getFPlayer() { + return FPlayers.getInstance().getByPlayer(sender); + } - public String getFactionTag() { - return factionTag; - } + public String getFactionTag() { + return factionTag; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java b/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java index 1d810c27..0555fa2a 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java @@ -11,42 +11,42 @@ import org.bukkit.event.Cancellable; */ public class FactionDisbandEvent extends FactionEvent implements Cancellable { - private final Player sender; - private final PlayerDisbandReason reason; - private boolean cancelled = false; + private final Player sender; + private final PlayerDisbandReason reason; + private boolean cancelled = false; - public FactionDisbandEvent(Player sender, String factionId, PlayerDisbandReason reason) { - super(Factions.getInstance().getFactionById(factionId)); - this.sender = sender; - this.reason = reason; - } + public FactionDisbandEvent(Player sender, String factionId, PlayerDisbandReason reason) { + super(Factions.getInstance().getFactionById(factionId)); + this.sender = sender; + this.reason = reason; + } - public FPlayer getFPlayer() { - return FPlayers.getInstance().getByPlayer(sender); - } + public FPlayer getFPlayer() { + return FPlayers.getInstance().getByPlayer(sender); + } - public Player getPlayer() { - return sender; - } + public Player getPlayer() { + return sender; + } - public PlayerDisbandReason getReason() { - return reason; - } + public PlayerDisbandReason getReason() { + return reason; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - cancelled = c; - } + @Override + public void setCancelled(boolean c) { + cancelled = c; + } - public enum PlayerDisbandReason { - COMMAND, - PLUGIN, - INACTIVITY, - LEAVE, - } + public enum PlayerDisbandReason { + COMMAND, + PLUGIN, + INACTIVITY, + LEAVE, + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionEvent.java b/src/main/java/com/massivecraft/factions/event/FactionEvent.java index 54595475..892f0ac0 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionEvent.java @@ -9,29 +9,29 @@ import org.bukkit.event.HandlerList; */ public class FactionEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private final Faction faction; + private static final HandlerList handlers = new HandlerList(); + private final Faction faction; - public FactionEvent(Faction faction) { - this.faction = faction; - } + public FactionEvent(Faction faction) { + this.faction = faction; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - /** - * Get the Faction involved in the event. - * - * @return faction involved in the event. - */ - public Faction getFaction() { - return this.faction; - } + /** + * Get the Faction involved in the event. + * + * @return faction involved in the event. + */ + public Faction getFaction() { + return this.faction; + } - @Override - public HandlerList getHandlers() { - return handlers; - } + @Override + public HandlerList getHandlers() { + return handlers; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java b/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java index ca0f86f4..3a76dcdd 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java @@ -8,14 +8,14 @@ import com.massivecraft.factions.Faction; */ public class FactionPlayerEvent extends FactionEvent { - protected final FPlayer fPlayer; + protected final FPlayer fPlayer; - public FactionPlayerEvent(Faction faction, FPlayer fPlayer) { - super(faction); - this.fPlayer = fPlayer; - } + public FactionPlayerEvent(Faction faction, FPlayer fPlayer) { + super(faction); + this.fPlayer = fPlayer; + } - public FPlayer getfPlayer() { - return this.fPlayer; - } + public FPlayer getfPlayer() { + return this.fPlayer; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java b/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java index 93b6cab2..761fd1a4 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java @@ -10,41 +10,41 @@ import org.bukkit.event.HandlerList; */ public class FactionRelationEvent extends Event { - private static final HandlerList handlers = new HandlerList(); + private static final HandlerList handlers = new HandlerList(); - private Faction fsender; - private Faction ftarget; - private Relation foldrel; - private Relation frel; + private Faction fsender; + private Faction ftarget; + private Relation foldrel; + private Relation frel; - public FactionRelationEvent(Faction sender, Faction target, Relation oldrel, Relation rel) { - fsender = sender; - ftarget = target; - foldrel = oldrel; - frel = rel; - } + public FactionRelationEvent(Faction sender, Faction target, Relation oldrel, Relation rel) { + fsender = sender; + ftarget = target; + foldrel = oldrel; + frel = rel; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } - public Relation getOldRelation() { - return foldrel; - } + public Relation getOldRelation() { + return foldrel; + } - public Relation getRelation() { - return frel; - } + public Relation getRelation() { + return frel; + } - public Faction getFaction() { - return fsender; - } + public Faction getFaction() { + return fsender; + } - public Faction getTargetFaction() { - return ftarget; - } + public Faction getTargetFaction() { + return ftarget; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java b/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java index 8590f7b4..dfdc6ef6 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java @@ -6,39 +6,39 @@ import com.massivecraft.factions.struct.Relation; import org.bukkit.event.Cancellable; public class FactionRelationWishEvent extends FactionPlayerEvent implements Cancellable { - private final Faction targetFaction; - private final Relation currentRelation; - private final Relation targetRelation; + private final Faction targetFaction; + private final Relation currentRelation; + private final Relation targetRelation; - private boolean cancelled; + private boolean cancelled; - public FactionRelationWishEvent(FPlayer caller, Faction sender, Faction targetFaction, Relation currentRelation, Relation targetRelation) { - super(sender, caller); + public FactionRelationWishEvent(FPlayer caller, Faction sender, Faction targetFaction, Relation currentRelation, Relation targetRelation) { + super(sender, caller); - this.targetFaction = targetFaction; - this.currentRelation = currentRelation; - this.targetRelation = targetRelation; - } + this.targetFaction = targetFaction; + this.currentRelation = currentRelation; + this.targetRelation = targetRelation; + } - public Faction getTargetFaction() { - return targetFaction; - } + public Faction getTargetFaction() { + return targetFaction; + } - public Relation getCurrentRelation() { - return currentRelation; - } + public Relation getCurrentRelation() { + return currentRelation; + } - public Relation getTargetRelation() { - return targetRelation; - } + public Relation getTargetRelation() { + return targetRelation; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java b/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java index 8dc8f022..cedeec77 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java @@ -6,52 +6,52 @@ import org.bukkit.event.Cancellable; public class FactionRenameEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled = false; - private String tag; + private boolean cancelled = false; + private String tag; - public FactionRenameEvent(FPlayer sender, String newTag) { - super(sender.getFaction(), sender); - tag = newTag; - } + public FactionRenameEvent(FPlayer sender, String newTag) { + super(sender.getFaction(), sender); + tag = newTag; + } - /** - * Get the player involved in the event. - * - * @return Player involved in the event. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the player involved in the event. + * + * @return Player involved in the event. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - /** - * Get the faction tag before it was renamed. - * - * @return old faction tag. - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getOldFactionTag() { - return getFaction().getTag(); - } + /** + * Get the faction tag before it was renamed. + * + * @return old faction tag. + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getOldFactionTag() { + return getFaction().getTag(); + } - /** - * Get the new faction tag. - * - * @return new faction tag as String. - */ - public String getFactionTag() { - return tag; - } + /** + * Get the new faction tag. + * + * @return new faction tag as String. + */ + public String getFactionTag() { + return tag; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java b/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java index 8bef95f0..223d6852 100644 --- a/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java +++ b/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java @@ -11,64 +11,64 @@ import org.bukkit.event.Cancellable; */ public class LandClaimEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled; - private FLocation location; + private boolean cancelled; + private FLocation location; - public LandClaimEvent(FLocation loc, Faction f, FPlayer p) { - super(f, p); - cancelled = false; - location = loc; - } + public LandClaimEvent(FLocation loc, Faction f, FPlayer p) { + super(f, p); + cancelled = false; + location = loc; + } - /** - * Get the FLocation involved in this event. - * - * @return the FLocation (also a chunk) involved in this event. - */ - public FLocation getLocation() { - return this.location; - } + /** + * Get the FLocation involved in this event. + * + * @return the FLocation (also a chunk) involved in this event. + */ + public FLocation getLocation() { + return this.location; + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in this event. - * - * @return player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in this event. + * + * @return player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java b/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java index 5b807bfd..47dfa00f 100644 --- a/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java +++ b/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java @@ -6,52 +6,52 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; public class LandUnclaimAllEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled; + private boolean cancelled; - public LandUnclaimAllEvent(Faction f, FPlayer p) { - super(f, p); - } + public LandUnclaimAllEvent(Faction f, FPlayer p) { + super(f, p); + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in the event. - * - * @return Player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in the event. + * + * @return Player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } } diff --git a/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java b/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java index 402f50e3..72ae23c3 100644 --- a/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java +++ b/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java @@ -11,59 +11,59 @@ import org.bukkit.event.Cancellable; */ public class LandUnclaimEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled; - private FLocation location; + private boolean cancelled; + private FLocation location; - public LandUnclaimEvent(FLocation loc, Faction f, FPlayer p) { - super(f, p); - cancelled = false; - location = loc; - } + public LandUnclaimEvent(FLocation loc, Faction f, FPlayer p) { + super(f, p); + cancelled = false; + location = loc; + } - public FLocation getLocation() { - return this.location; - } + public FLocation getLocation() { + return this.location; + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in the event. - * - * @return Player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in the event. + * + * @return Player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - cancelled = c; - } + @Override + public void setCancelled(boolean c) { + cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java b/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java index 45a5b19b..6304e39c 100644 --- a/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java +++ b/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java @@ -10,72 +10,72 @@ import org.bukkit.event.Cancellable; */ public class PowerLossEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled = false; - private String message; + private boolean cancelled = false; + private String message; - public PowerLossEvent(Faction f, FPlayer p) { - super(f, p); - } + public PowerLossEvent(Faction f, FPlayer p) { + super(f, p); + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in the event. - * - * @return Player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in the event. + * + * @return Player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - /** - * Get the power loss message. - * - * @return power loss message as String. - */ - public String getMessage() { - return message; - } + /** + * Get the power loss message. + * + * @return power loss message as String. + */ + public String getMessage() { + return message; + } - /** - * Set the power loss message. - * - * @param message of powerloss - */ - public void setMessage(String message) { - this.message = message; - } + /** + * Set the power loss message. + * + * @param message of powerloss + */ + public void setMessage(String message) { + this.message = message; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java b/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java index b9a7ec2c..e1782b8d 100644 --- a/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java +++ b/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java @@ -9,20 +9,20 @@ import org.bukkit.event.Cancellable; */ public class PowerRegenEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled = false; + private boolean cancelled = false; - public PowerRegenEvent(Faction f, FPlayer p) { - super(f, p); - } + public PowerRegenEvent(Faction f, FPlayer p) { + super(f, p); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java b/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java index 9ceeb827..2d8f4624 100644 --- a/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java +++ b/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java @@ -4,9 +4,9 @@ import com.massivecraft.factions.zcore.util.TL; public interface EconomyParticipator extends RelationParticipator { - String getAccountId(); + String getAccountId(); - void msg(String str, Object... args); + void msg(String str, Object... args); - void msg(TL translation, Object... args); + void msg(TL translation, Object... args); } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java b/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java index a536c43b..781bed18 100644 --- a/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java +++ b/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java @@ -5,13 +5,13 @@ import org.bukkit.ChatColor; public interface RelationParticipator { - String describeTo(RelationParticipator that); + String describeTo(RelationParticipator that); - String describeTo(RelationParticipator that, boolean ucfirst); + String describeTo(RelationParticipator that, boolean ucfirst); - Relation getRelationTo(RelationParticipator that); + Relation getRelationTo(RelationParticipator that); - Relation getRelationTo(RelationParticipator that, boolean ignorePeaceful); + Relation getRelationTo(RelationParticipator that, boolean ignorePeaceful); - ChatColor getColorTo(RelationParticipator to); + ChatColor getColorTo(RelationParticipator to); } diff --git a/src/main/java/com/massivecraft/factions/integration/Econ.java b/src/main/java/com/massivecraft/factions/integration/Econ.java index 064a150c..650a6b02 100644 --- a/src/main/java/com/massivecraft/factions/integration/Econ.java +++ b/src/main/java/com/massivecraft/factions/integration/Econ.java @@ -23,418 +23,418 @@ import java.util.logging.Level; public class Econ { - private static final DecimalFormat format = new DecimalFormat(TL.ECON_FORMAT.toString()); - private static Economy econ = null; + private static final DecimalFormat format = new DecimalFormat(TL.ECON_FORMAT.toString()); + private static Economy econ = null; - public static void setup() { - if (isSetup()) { - return; - } + public static void setup() { + if (isSetup()) { + return; + } - String integrationFail = "Economy integration is " + (Conf.econEnabled ? "enabled, but" : "disabled, and") + " the plugin \"Vault\" "; + String integrationFail = "Economy integration is " + (Conf.econEnabled ? "enabled, but" : "disabled, and") + " the plugin \"Vault\" "; - if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { - SavageFactions.plugin.log(integrationFail + "is not installed."); - return; - } + if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { + SavageFactions.plugin.log(integrationFail + "is not installed."); + return; + } - RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); - if (rsp == null) { - SavageFactions.plugin.log(integrationFail + "is not hooked into an economy plugin."); - return; - } - econ = rsp.getProvider(); + RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + SavageFactions.plugin.log(integrationFail + "is not hooked into an economy plugin."); + return; + } + econ = rsp.getProvider(); - SavageFactions.plugin.log("Economy integration through Vault plugin successful."); + SavageFactions.plugin.log("Economy integration through Vault plugin successful."); - if (!Conf.econEnabled) { - SavageFactions.plugin.log("NOTE: Economy is disabled. You can enable it with the command: f config econEnabled true"); - } + if (!Conf.econEnabled) { + SavageFactions.plugin.log("NOTE: Economy is disabled. You can enable it with the command: f config econEnabled true"); + } - SavageFactions.plugin.cmdBase.cmdHelp.updateHelp(); - } + SavageFactions.plugin.cmdBase.cmdHelp.updateHelp(); + } - public static boolean shouldBeUsed() { - return Conf.econEnabled && econ != null && econ.isEnabled(); - } + public static boolean shouldBeUsed() { + return Conf.econEnabled && econ != null && econ.isEnabled(); + } - public static boolean isSetup() { - return econ != null; - } + public static boolean isSetup() { + return econ != null; + } - public static void modifyUniverseMoney(double delta) { - if (!shouldBeUsed()) { - return; - } + public static void modifyUniverseMoney(double delta) { + if (!shouldBeUsed()) { + return; + } - if (Conf.econUniverseAccount == null) { - return; - } - if (Conf.econUniverseAccount.length() == 0) { - return; - } - if (!econ.hasAccount(Conf.econUniverseAccount)) { - return; - } + if (Conf.econUniverseAccount == null) { + return; + } + if (Conf.econUniverseAccount.length() == 0) { + return; + } + if (!econ.hasAccount(Conf.econUniverseAccount)) { + return; + } - modifyBalance(Conf.econUniverseAccount, delta); - } + modifyBalance(Conf.econUniverseAccount, delta); + } - public static void sendBalanceInfo(FPlayer to, EconomyParticipator about) { - if (!shouldBeUsed()) { - SavageFactions.plugin.log(Level.WARNING, "Vault does not appear to be hooked into an economy plugin."); - return; - } - to.msg("%s's balance is %s.", about.describeTo(to, true), Econ.moneyString(econ.getBalance(about.getAccountId()))); - } + public static void sendBalanceInfo(FPlayer to, EconomyParticipator about) { + if (!shouldBeUsed()) { + SavageFactions.plugin.log(Level.WARNING, "Vault does not appear to be hooked into an economy plugin."); + return; + } + to.msg("%s's balance is %s.", about.describeTo(to, true), Econ.moneyString(econ.getBalance(about.getAccountId()))); + } - public static boolean canIControllYou(EconomyParticipator i, EconomyParticipator you) { - Faction fI = RelationUtil.getFaction(i); - Faction fYou = RelationUtil.getFaction(you); + public static boolean canIControllYou(EconomyParticipator i, EconomyParticipator you) { + Faction fI = RelationUtil.getFaction(i); + Faction fYou = RelationUtil.getFaction(you); - // This is a system invoker. Accept it. - if (fI == null) { - return true; - } + // This is a system invoker. Accept it. + if (fI == null) { + return true; + } - // Bypassing players can do any kind of transaction - if (i instanceof FPlayer && ((FPlayer) i).isAdminBypassing()) { - return true; - } + // Bypassing players can do any kind of transaction + if (i instanceof FPlayer && ((FPlayer) i).isAdminBypassing()) { + return true; + } - // Players with the any withdraw can do. - if (i instanceof FPlayer && Permission.MONEY_WITHDRAW_ANY.has(((FPlayer) i).getPlayer())) { - return true; - } + // Players with the any withdraw can do. + if (i instanceof FPlayer && Permission.MONEY_WITHDRAW_ANY.has(((FPlayer) i).getPlayer())) { + return true; + } - // You can deposit to anywhere you feel like. It's your loss if you can't withdraw it again. - if (i == you) { - return true; - } + // You can deposit to anywhere you feel like. It's your loss if you can't withdraw it again. + if (i == you) { + return true; + } - // A faction can always transfer away the money of it's members and its own money... - // This will however probably never happen as a faction does not have free will. - // Ohh by the way... Yes it could. For daily rent to the faction. - if (i == fI && fI == fYou) { - return true; - } + // A faction can always transfer away the money of it's members and its own money... + // This will however probably never happen as a faction does not have free will. + // Ohh by the way... Yes it could. For daily rent to the faction. + if (i == fI && fI == fYou) { + return true; + } - // Factions can be controlled by members that are moderators... or any member if any member can withdraw. - if (you instanceof Faction && fI == fYou && (Conf.bankMembersCanWithdraw || ((FPlayer) i).getRole().value >= Role.MODERATOR.value)) { - return true; - } + // Factions can be controlled by members that are moderators... or any member if any member can withdraw. + if (you instanceof Faction && fI == fYou && (Conf.bankMembersCanWithdraw || ((FPlayer) i).getRole().value >= Role.MODERATOR.value)) { + return true; + } - // Otherwise you may not!;,,; - i.msg("%s lacks permission to control %s's money.", i.describeTo(i, true), you.describeTo(i)); - return false; - } + // Otherwise you may not!;,,; + i.msg("%s lacks permission to control %s's money.", i.describeTo(i, true), you.describeTo(i)); + return false; + } - public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { - return transferMoney(invoker, from, to, amount, true); - } + public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { + return transferMoney(invoker, from, to, amount, true); + } - public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount, boolean notify) { - if (!shouldBeUsed()) { - return false; - } + public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount, boolean notify) { + if (!shouldBeUsed()) { + return false; + } - // The amount must be positive. - // If the amount is negative we must flip and multiply amount with -1. - if (amount < 0) { - amount *= -1; - EconomyParticipator temp = from; - from = to; - to = temp; - } + // The amount must be positive. + // If the amount is negative we must flip and multiply amount with -1. + if (amount < 0) { + amount *= -1; + EconomyParticipator temp = from; + from = to; + to = temp; + } - // Check the rights - if (!canIControllYou(invoker, from)) { - return false; - } + // Check the rights + if (!canIControllYou(invoker, from)) { + return false; + } - OfflinePlayer fromAcc; - OfflinePlayer toAcc; + OfflinePlayer fromAcc; + OfflinePlayer toAcc; - if (isUUID(from.getAccountId())) { - fromAcc = Bukkit.getOfflinePlayer(UUID.fromString(from.getAccountId())); - if (fromAcc.getName() == null) { - return false; - } - } else { - fromAcc = Bukkit.getOfflinePlayer(from.getAccountId()); - } + if (isUUID(from.getAccountId())) { + fromAcc = Bukkit.getOfflinePlayer(UUID.fromString(from.getAccountId())); + if (fromAcc.getName() == null) { + return false; + } + } else { + fromAcc = Bukkit.getOfflinePlayer(from.getAccountId()); + } - if (isUUID(to.getAccountId())) { - toAcc = Bukkit.getOfflinePlayer(UUID.fromString(to.getAccountId())); - if (toAcc.getName() == null) { - return false; - } - } else { - toAcc = Bukkit.getOfflinePlayer(to.getAccountId()); - } + if (isUUID(to.getAccountId())) { + toAcc = Bukkit.getOfflinePlayer(UUID.fromString(to.getAccountId())); + if (toAcc.getName() == null) { + return false; + } + } else { + toAcc = Bukkit.getOfflinePlayer(to.getAccountId()); + } - // Is there enough money for the transaction to happen? - if (!econ.has(fromAcc, amount)) { - // There was not enough money to pay - if (invoker != null && notify) { - invoker.msg("%s can't afford to transfer %s to %s.", from.describeTo(invoker, true), moneyString(amount), to.describeTo(invoker)); - } + // Is there enough money for the transaction to happen? + if (!econ.has(fromAcc, amount)) { + // There was not enough money to pay + if (invoker != null && notify) { + invoker.msg("%s can't afford to transfer %s to %s.", from.describeTo(invoker, true), moneyString(amount), to.describeTo(invoker)); + } - return false; - } + return false; + } - // Transfer money - EconomyResponse erw = econ.withdrawPlayer(fromAcc, amount); + // Transfer money + EconomyResponse erw = econ.withdrawPlayer(fromAcc, amount); - if (erw.transactionSuccess()) { - EconomyResponse erd = econ.depositPlayer(toAcc, amount); - if (erd.transactionSuccess()) { - if (notify) { - sendTransferInfo(invoker, from, to, amount); - } - return true; - } else { - // transaction failed, refund account - econ.depositPlayer(fromAcc, amount); - } - } + if (erw.transactionSuccess()) { + EconomyResponse erd = econ.depositPlayer(toAcc, amount); + if (erd.transactionSuccess()) { + if (notify) { + sendTransferInfo(invoker, from, to, amount); + } + return true; + } else { + // transaction failed, refund account + econ.depositPlayer(fromAcc, amount); + } + } - // if we get here something with the transaction failed - if (notify) { - invoker.msg("Unable to transfer %s to %s from %s.", moneyString(amount), to.describeTo(invoker), from.describeTo(invoker, true)); - } + // if we get here something with the transaction failed + if (notify) { + invoker.msg("Unable to transfer %s to %s from %s.", moneyString(amount), to.describeTo(invoker), from.describeTo(invoker, true)); + } - return false; - } + return false; + } - public static Set getFplayers(EconomyParticipator ep) { - Set fplayers = new HashSet<>(); + public static Set getFplayers(EconomyParticipator ep) { + Set fplayers = new HashSet<>(); - if (ep != null) { - if (ep instanceof FPlayer) { - fplayers.add((FPlayer) ep); - } else if (ep instanceof Faction) { - fplayers.addAll(((Faction) ep).getFPlayers()); - } - } + if (ep != null) { + if (ep instanceof FPlayer) { + fplayers.add((FPlayer) ep); + } else if (ep instanceof Faction) { + fplayers.addAll(((Faction) ep).getFPlayers()); + } + } - return fplayers; - } + return fplayers; + } - public static void sendTransferInfo(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { - Set recipients = new HashSet<>(); - recipients.addAll(getFplayers(invoker)); - recipients.addAll(getFplayers(from)); - recipients.addAll(getFplayers(to)); + public static void sendTransferInfo(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { + Set recipients = new HashSet<>(); + recipients.addAll(getFplayers(invoker)); + recipients.addAll(getFplayers(from)); + recipients.addAll(getFplayers(to)); - if (invoker == null) { - for (FPlayer recipient : recipients) { - recipient.msg("%s was transferred from %s to %s.", moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); - } - } else if (invoker == from) { - for (FPlayer recipient : recipients) { - recipient.msg("%s gave %s to %s.", from.describeTo(recipient, true), moneyString(amount), to.describeTo(recipient)); - } - } else if (invoker == to) { - for (FPlayer recipient : recipients) { - recipient.msg("%s took %s from %s.", to.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient)); - } - } else { - for (FPlayer recipient : recipients) { - recipient.msg("%s transferred %s from %s to %s.", invoker.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); - } - } - } + if (invoker == null) { + for (FPlayer recipient : recipients) { + recipient.msg("%s was transferred from %s to %s.", moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); + } + } else if (invoker == from) { + for (FPlayer recipient : recipients) { + recipient.msg("%s gave %s to %s.", from.describeTo(recipient, true), moneyString(amount), to.describeTo(recipient)); + } + } else if (invoker == to) { + for (FPlayer recipient : recipients) { + recipient.msg("%s took %s from %s.", to.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient)); + } + } else { + for (FPlayer recipient : recipients) { + recipient.msg("%s transferred %s from %s to %s.", invoker.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); + } + } + } - public static boolean hasAtLeast(EconomyParticipator ep, double delta, String toDoThis) { - if (!shouldBeUsed()) { - return true; - } + public static boolean hasAtLeast(EconomyParticipator ep, double delta, String toDoThis) { + if (!shouldBeUsed()) { + return true; + } - // going the hard way round as econ.has refuses to work. - boolean affordable = false; - double currentBalance; + // going the hard way round as econ.has refuses to work. + boolean affordable = false; + double currentBalance; - if (isUUID(ep.getAccountId())) { - OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); - if (offline.getName() != null) { - currentBalance = econ.getBalance(Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId()))); - } else { - currentBalance = 0; - } - } else { - currentBalance = econ.getBalance(ep.getAccountId()); - } + if (isUUID(ep.getAccountId())) { + OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); + if (offline.getName() != null) { + currentBalance = econ.getBalance(Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId()))); + } else { + currentBalance = 0; + } + } else { + currentBalance = econ.getBalance(ep.getAccountId()); + } - if (currentBalance >= delta) { - affordable = true; - } + if (currentBalance >= delta) { + affordable = true; + } - if (!affordable) { - if (toDoThis != null && !toDoThis.isEmpty()) { - ep.msg("%s can't afford %s %s.", ep.describeTo(ep, true), moneyString(delta), toDoThis); - } - return false; - } - return true; - } + if (!affordable) { + if (toDoThis != null && !toDoThis.isEmpty()) { + ep.msg("%s can't afford %s %s.", ep.describeTo(ep, true), moneyString(delta), toDoThis); + } + return false; + } + return true; + } - public static boolean modifyMoney(EconomyParticipator ep, double delta, String toDoThis, String forDoingThis) { - if (!shouldBeUsed()) { - return false; - } + public static boolean modifyMoney(EconomyParticipator ep, double delta, String toDoThis, String forDoingThis) { + if (!shouldBeUsed()) { + return false; + } - OfflinePlayer acc; + OfflinePlayer acc; - if (isUUID(ep.getAccountId())) { - acc = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); - if (acc.getName() == null) { - return false; - } - } else { - acc = Bukkit.getOfflinePlayer(ep.getAccountId()); - } + if (isUUID(ep.getAccountId())) { + acc = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); + if (acc.getName() == null) { + return false; + } + } else { + acc = Bukkit.getOfflinePlayer(ep.getAccountId()); + } - String You = ep.describeTo(ep, true); + String You = ep.describeTo(ep, true); - if (delta == 0) { - // no money actually transferred? + if (delta == 0) { + // no money actually transferred? // ep.msg("%s didn't have to pay anything %s.", You, forDoingThis); // might be for gains, might be for losses - return true; - } + return true; + } - if (delta > 0) { - // The player should gain money - // The account might not have enough space - EconomyResponse er = econ.depositPlayer(acc, delta); - if (er.transactionSuccess()) { - modifyUniverseMoney(-delta); - if (forDoingThis != null && !forDoingThis.isEmpty()) { - ep.msg("%s gained %s %s.", You, moneyString(delta), forDoingThis); - } - return true; - } else { - // transfer to account failed - if (forDoingThis != null && !forDoingThis.isEmpty()) { - ep.msg("%s would have gained %s %s, but the deposit failed.", You, moneyString(delta), forDoingThis); - } - return false; - } - } else { - // The player should loose money - // The player might not have enough. + if (delta > 0) { + // The player should gain money + // The account might not have enough space + EconomyResponse er = econ.depositPlayer(acc, delta); + if (er.transactionSuccess()) { + modifyUniverseMoney(-delta); + if (forDoingThis != null && !forDoingThis.isEmpty()) { + ep.msg("%s gained %s %s.", You, moneyString(delta), forDoingThis); + } + return true; + } else { + // transfer to account failed + if (forDoingThis != null && !forDoingThis.isEmpty()) { + ep.msg("%s would have gained %s %s, but the deposit failed.", You, moneyString(delta), forDoingThis); + } + return false; + } + } else { + // The player should loose money + // The player might not have enough. - if (econ.has(acc, -delta) && econ.withdrawPlayer(acc, -delta).transactionSuccess()) { - // There is enough money to pay - modifyUniverseMoney(-delta); - if (forDoingThis != null && !forDoingThis.isEmpty()) { - ep.msg("%s lost %s %s.", You, moneyString(-delta), forDoingThis); - } - return true; - } else { - // There was not enough money to pay - if (toDoThis != null && !toDoThis.isEmpty()) { - ep.msg("%s can't afford %s %s.", You, moneyString(-delta), toDoThis); - } - return false; - } - } - } + if (econ.has(acc, -delta) && econ.withdrawPlayer(acc, -delta).transactionSuccess()) { + // There is enough money to pay + modifyUniverseMoney(-delta); + if (forDoingThis != null && !forDoingThis.isEmpty()) { + ep.msg("%s lost %s %s.", You, moneyString(-delta), forDoingThis); + } + return true; + } else { + // There was not enough money to pay + if (toDoThis != null && !toDoThis.isEmpty()) { + ep.msg("%s can't afford %s %s.", You, moneyString(-delta), toDoThis); + } + return false; + } + } + } - public static String moneyString(double amount) { - return format.format(amount); - } + public static String moneyString(double amount) { + return format.format(amount); + } - // calculate the cost for claiming land - public static double calculateClaimCost(int ownedLand, boolean takingFromAnotherFaction) { - if (!shouldBeUsed()) { - return 0d; - } + // calculate the cost for claiming land + public static double calculateClaimCost(int ownedLand, boolean takingFromAnotherFaction) { + if (!shouldBeUsed()) { + return 0d; + } - // basic claim cost, plus land inflation cost, minus the potential bonus given for claiming from another faction - return Conf.econCostClaimWilderness + (Conf.econCostClaimWilderness * Conf.econClaimAdditionalMultiplier * ownedLand) - (takingFromAnotherFaction ? Conf.econCostClaimFromFactionBonus : 0); - } + // basic claim cost, plus land inflation cost, minus the potential bonus given for claiming from another faction + return Conf.econCostClaimWilderness + (Conf.econCostClaimWilderness * Conf.econClaimAdditionalMultiplier * ownedLand) - (takingFromAnotherFaction ? Conf.econCostClaimFromFactionBonus : 0); + } - // calculate refund amount for unclaiming land - public static double calculateClaimRefund(int ownedLand) { - return calculateClaimCost(ownedLand - 1, false) * Conf.econClaimRefundMultiplier; - } + // calculate refund amount for unclaiming land + public static double calculateClaimRefund(int ownedLand) { + return calculateClaimCost(ownedLand - 1, false) * Conf.econClaimRefundMultiplier; + } - // calculate value of all owned land - public static double calculateTotalLandValue(int ownedLand) { - double amount = 0; - for (int x = 0; x < ownedLand; x++) { - amount += calculateClaimCost(x, false); - } - return amount; - } + // calculate value of all owned land + public static double calculateTotalLandValue(int ownedLand) { + double amount = 0; + for (int x = 0; x < ownedLand; x++) { + amount += calculateClaimCost(x, false); + } + return amount; + } - // -------------------------------------------- // - // Standard account management methods - // -------------------------------------------- // + // -------------------------------------------- // + // Standard account management methods + // -------------------------------------------- // - // calculate refund amount for all owned land - public static double calculateTotalLandRefund(int ownedLand) { - return calculateTotalLandValue(ownedLand) * Conf.econClaimRefundMultiplier; - } + // calculate refund amount for all owned land + public static double calculateTotalLandRefund(int ownedLand) { + return calculateTotalLandValue(ownedLand) * Conf.econClaimRefundMultiplier; + } - public static boolean hasAccount(String name) { - return econ.hasAccount(name); - } + public static boolean hasAccount(String name) { + return econ.hasAccount(name); + } - public static double getBalance(String account) { - return econ.getBalance(account); - } + public static double getBalance(String account) { + return econ.getBalance(account); + } - public static String getFriendlyBalance(UUID uuid) { - OfflinePlayer offline = Bukkit.getOfflinePlayer(uuid); - if (offline.getName() == null) { - return "0"; - } - return format.format(econ.getBalance(offline)); - } + public static String getFriendlyBalance(UUID uuid) { + OfflinePlayer offline = Bukkit.getOfflinePlayer(uuid); + if (offline.getName() == null) { + return "0"; + } + return format.format(econ.getBalance(offline)); + } - public static String getFriendlyBalance(FPlayer player) { - return getFriendlyBalance(UUID.fromString(player.getId())); - } + public static String getFriendlyBalance(FPlayer player) { + return getFriendlyBalance(UUID.fromString(player.getId())); + } - public static boolean setBalance(String account, double amount) { - double current = econ.getBalance(account); - if (current > amount) { - return econ.withdrawPlayer(account, current - amount).transactionSuccess(); - } else { - return econ.depositPlayer(account, amount - current).transactionSuccess(); - } - } + public static boolean setBalance(String account, double amount) { + double current = econ.getBalance(account); + if (current > amount) { + return econ.withdrawPlayer(account, current - amount).transactionSuccess(); + } else { + return econ.depositPlayer(account, amount - current).transactionSuccess(); + } + } - public static boolean modifyBalance(String account, double amount) { - if (amount < 0) { - return econ.withdrawPlayer(account, -amount).transactionSuccess(); - } else { - return econ.depositPlayer(account, amount).transactionSuccess(); - } - } + public static boolean modifyBalance(String account, double amount) { + if (amount < 0) { + return econ.withdrawPlayer(account, -amount).transactionSuccess(); + } else { + return econ.depositPlayer(account, amount).transactionSuccess(); + } + } - public static boolean deposit(String account, double amount) { - return econ.depositPlayer(account, amount).transactionSuccess(); - } + public static boolean deposit(String account, double amount) { + return econ.depositPlayer(account, amount).transactionSuccess(); + } - public static boolean withdraw(String account, double amount) { - return econ.withdrawPlayer(account, amount).transactionSuccess(); - } + public static boolean withdraw(String account, double amount) { + return econ.withdrawPlayer(account, amount).transactionSuccess(); + } - // --------------------------------------- - // Helpful Utilities - // --------------------------------------- + // --------------------------------------- + // Helpful Utilities + // --------------------------------------- - public static boolean isUUID(String uuid) { - try { - UUID.fromString(uuid); - } catch (IllegalArgumentException ex) { - return false; - } + public static boolean isUUID(String uuid) { + try { + UUID.fromString(uuid); + } catch (IllegalArgumentException ex) { + return false; + } - return true; - } + return true; + } } diff --git a/src/main/java/com/massivecraft/factions/integration/Essentials.java b/src/main/java/com/massivecraft/factions/integration/Essentials.java index 8b0f8222..5025515b 100644 --- a/src/main/java/com/massivecraft/factions/integration/Essentials.java +++ b/src/main/java/com/massivecraft/factions/integration/Essentials.java @@ -15,32 +15,32 @@ import java.math.BigDecimal; public class Essentials { - private static IEssentials essentials; + private static IEssentials essentials; - public static void setup() { - Plugin ess = Bukkit.getPluginManager().getPlugin("Essentials"); - if (ess != null) { - essentials = (IEssentials) ess; - } - } + public static void setup() { + Plugin ess = Bukkit.getPluginManager().getPlugin("Essentials"); + if (ess != null) { + essentials = (IEssentials) ess; + } + } - // return false if feature is disabled or Essentials isn't available - public static boolean handleTeleport(Player player, Location loc) { - if (!Conf.homesTeleportCommandEssentialsIntegration || essentials == null) { - return false; - } + // return false if feature is disabled or Essentials isn't available + public static boolean handleTeleport(Player player, Location loc) { + if (!Conf.homesTeleportCommandEssentialsIntegration || essentials == null) { + return false; + } - Teleport teleport = essentials.getUser(player).getTeleport(); - Trade trade = new Trade(new BigDecimal(Conf.econCostHome), essentials); - try { - teleport.teleport(loc, trade, TeleportCause.PLUGIN); - } catch (Exception e) { - player.sendMessage(ChatColor.RED.toString() + e.getMessage()); - } - return true; - } + Teleport teleport = essentials.getUser(player).getTeleport(); + Trade trade = new Trade(new BigDecimal(Conf.econCostHome), essentials); + try { + teleport.teleport(loc, trade, TeleportCause.PLUGIN); + } catch (Exception e) { + player.sendMessage(ChatColor.RED.toString() + e.getMessage()); + } + return true; + } - public static boolean isVanished(Player player) { - return essentials != null && essentials.getUser(player).isVanished(); - } + public static boolean isVanished(Player player) { + return essentials != null && essentials.getUser(player).isVanished(); + } } diff --git a/src/main/java/com/massivecraft/factions/integration/Worldguard.java b/src/main/java/com/massivecraft/factions/integration/Worldguard.java index 0e429077..bc80b247 100644 --- a/src/main/java/com/massivecraft/factions/integration/Worldguard.java +++ b/src/main/java/com/massivecraft/factions/integration/Worldguard.java @@ -30,110 +30,110 @@ import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; public class Worldguard { - private static WorldGuardPlugin wg; - private static boolean enabled = false; + private static WorldGuardPlugin wg; + private static boolean enabled = false; - public static void init(Plugin plugin) { - Plugin wgplug = plugin.getServer().getPluginManager().getPlugin("WorldGuard"); - if (wgplug == null || !(wgplug instanceof WorldGuardPlugin)) { - enabled = false; - wg = null; - SavageFactions.plugin.log("Could not hook to WorldGuard. WorldGuard checks are disabled."); - } else { - wg = (WorldGuardPlugin) wgplug; - enabled = true; - SavageFactions.plugin.log("Successfully hooked to WorldGuard."); - } - } + public static void init(Plugin plugin) { + Plugin wgplug = plugin.getServer().getPluginManager().getPlugin("WorldGuard"); + if (wgplug == null || !(wgplug instanceof WorldGuardPlugin)) { + enabled = false; + wg = null; + SavageFactions.plugin.log("Could not hook to WorldGuard. WorldGuard checks are disabled."); + } else { + wg = (WorldGuardPlugin) wgplug; + enabled = true; + SavageFactions.plugin.log("Successfully hooked to WorldGuard."); + } + } - public static boolean isEnabled() { - return enabled; - } + public static boolean isEnabled() { + return enabled; + } - // PVP Flag check - // Returns: - // True: PVP is allowed - // False: PVP is disallowed - @SuppressWarnings("deprecation") - public static boolean isPVP(Player player) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return true; - } + // PVP Flag check + // Returns: + // True: PVP is allowed + // False: PVP is disallowed + @SuppressWarnings("deprecation") + public static boolean isPVP(Player player) { + if (!enabled) { + // No WG hooks so we'll always bypass this check. + return true; + } - Location loc = player.getLocation(); - World world = loc.getWorld(); - Vector pt = toVector(loc); + Location loc = player.getLocation(); + World world = loc.getWorld(); + Vector pt = toVector(loc); - RegionManager regionManager = wg.getRegionManager(world); - ApplicableRegionSet set = regionManager.getApplicableRegions(pt); - return set.allows(DefaultFlag.PVP); - } + RegionManager regionManager = wg.getRegionManager(world); + ApplicableRegionSet set = regionManager.getApplicableRegions(pt); + return set.allows(DefaultFlag.PVP); + } - // Check if player can build at location by worldguards rules. - // Returns: - // True: Player can build in the region. - // False: Player can not build in the region. - public static boolean playerCanBuild(Player player, Location loc) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return false; - } + // Check if player can build at location by worldguards rules. + // Returns: + // True: Player can build in the region. + // False: Player can not build in the region. + public static boolean playerCanBuild(Player player, Location loc) { + if (!enabled) { + // No WG hooks so we'll always bypass this check. + return false; + } - World world = loc.getWorld(); - Vector pt = toVector(loc); + World world = loc.getWorld(); + Vector pt = toVector(loc); - return wg.getRegionManager(world).getApplicableRegions(pt).size() > 0 && wg.canBuild(player, loc); - } + return wg.getRegionManager(world).getApplicableRegions(pt).size() > 0 && wg.canBuild(player, loc); + } - // Check for Regions in chunk the chunk - // Returns: - // True: Regions found within chunk - // False: No regions found within chunk + // Check for Regions in chunk the chunk + // Returns: + // True: Regions found within chunk + // False: No regions found within chunk - public static boolean checkForRegionsInChunk(FLocation floc) { - Chunk chunk = floc.getWorld().getChunkAt((int) floc.getX(), (int) floc.getZ()); + public static boolean checkForRegionsInChunk(FLocation floc) { + Chunk chunk = floc.getWorld().getChunkAt((int) floc.getX(), (int) floc.getZ()); - return checkForRegionsInChunk(chunk); - } + return checkForRegionsInChunk(chunk); + } - public static boolean checkForRegionsInChunk(Location loc) { - Chunk chunk = loc.getWorld().getChunkAt(loc); + public static boolean checkForRegionsInChunk(Location loc) { + Chunk chunk = loc.getWorld().getChunkAt(loc); - return checkForRegionsInChunk(chunk); - } + return checkForRegionsInChunk(chunk); + } - public static boolean checkForRegionsInChunk(Chunk chunk) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return false; - } + public static boolean checkForRegionsInChunk(Chunk chunk) { + if (!enabled) { + // No WG hooks so we'll always bypass this check. + return false; + } - World world = chunk.getWorld(); - int minChunkX = chunk.getX() << 4; - int minChunkZ = chunk.getZ() << 4; - int maxChunkX = minChunkX + 15; - int maxChunkZ = minChunkZ + 15; + World world = chunk.getWorld(); + int minChunkX = chunk.getX() << 4; + int minChunkZ = chunk.getZ() << 4; + int maxChunkX = minChunkX + 15; + int maxChunkZ = minChunkZ + 15; - int worldHeight = world.getMaxHeight(); // Allow for heights other than default + int worldHeight = world.getMaxHeight(); // Allow for heights other than default - BlockVector minChunk = new BlockVector(minChunkX, 0, minChunkZ); - BlockVector maxChunk = new BlockVector(maxChunkX, worldHeight, maxChunkZ); + BlockVector minChunk = new BlockVector(minChunkX, 0, minChunkZ); + BlockVector maxChunk = new BlockVector(maxChunkX, worldHeight, maxChunkZ); - RegionManager regionManager = wg.getRegionManager(world); - ProtectedCuboidRegion region = new ProtectedCuboidRegion("wgfactionoverlapcheck", minChunk, maxChunk); - Map allregions = regionManager.getRegions(); - Collection allregionslist = new ArrayList<>(allregions.values()); - List overlaps; - boolean foundregions = false; + RegionManager regionManager = wg.getRegionManager(world); + ProtectedCuboidRegion region = new ProtectedCuboidRegion("wgfactionoverlapcheck", minChunk, maxChunk); + Map allregions = regionManager.getRegions(); + Collection allregionslist = new ArrayList<>(allregions.values()); + List overlaps; + boolean foundregions = false; - try { - overlaps = region.getIntersectingRegions(allregionslist); - foundregions = overlaps != null && !overlaps.isEmpty(); - } catch (Exception e) { - e.printStackTrace(); - } + try { + overlaps = region.getIntersectingRegions(allregionslist); + foundregions = overlaps != null && !overlaps.isEmpty(); + } catch (Exception e) { + e.printStackTrace(); + } - return foundregions; - } + return foundregions; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java b/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java index 7fb28c15..239b04e8 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java @@ -3,105 +3,105 @@ package com.massivecraft.factions.integration.dynmap; import com.massivecraft.factions.Conf; public class DynmapStyle { - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public String lineColor = null; - public Double lineOpacity = null; - public Integer lineWeight = null; - public String fillColor = null; - public Double fillOpacity = null; - // NOTE: We just return the string here. We do not return the resolved Dynmap MarkerIcon object. - // The reason is we use this class in the MConf. For serialization to work Dynmap would have to be loaded and we can't require that. - // Using dynmap is optional. - public String homeMarker = null; - public Boolean boost = null; + public String lineColor = null; + public Double lineOpacity = null; + public Integer lineWeight = null; + public String fillColor = null; + public Double fillOpacity = null; + // NOTE: We just return the string here. We do not return the resolved Dynmap MarkerIcon object. + // The reason is we use this class in the MConf. For serialization to work Dynmap would have to be loaded and we can't require that. + // Using dynmap is optional. + public String homeMarker = null; + public Boolean boost = null; - @SafeVarargs - public static T coalesce(T... items) { - for (T item : items) { - if (item != null) { - return item; - } - } - return null; - } + @SafeVarargs + public static T coalesce(T... items) { + for (T item : items) { + if (item != null) { + return item; + } + } + return null; + } - public static int getColor(String string) { - int ret = 0x00FF00; - try { - ret = Integer.parseInt(string.substring(1), 16); - } catch (NumberFormatException ignored) { - } - return ret; - } + public static int getColor(String string) { + int ret = 0x00FF00; + try { + ret = Integer.parseInt(string.substring(1), 16); + } catch (NumberFormatException ignored) { + } + return ret; + } - public int getLineColor() { - return getColor(coalesce(this.lineColor, Conf.dynmapDefaultStyle.lineColor, Conf.DYNMAP_STYLE_LINE_COLOR)); - } + public int getLineColor() { + return getColor(coalesce(this.lineColor, Conf.dynmapDefaultStyle.lineColor, Conf.DYNMAP_STYLE_LINE_COLOR)); + } - public DynmapStyle setStrokeColor(String strokeColor) { - this.lineColor = strokeColor; - return this; - } + public DynmapStyle setStrokeColor(String strokeColor) { + this.lineColor = strokeColor; + return this; + } - public double getLineOpacity() { - return coalesce(this.lineOpacity, Conf.dynmapDefaultStyle.lineOpacity, Conf.DYNMAP_STYLE_LINE_OPACITY); - } + public double getLineOpacity() { + return coalesce(this.lineOpacity, Conf.dynmapDefaultStyle.lineOpacity, Conf.DYNMAP_STYLE_LINE_OPACITY); + } - public DynmapStyle setLineOpacity(Double strokeOpacity) { - this.lineOpacity = strokeOpacity; - return this; - } + public DynmapStyle setLineOpacity(Double strokeOpacity) { + this.lineOpacity = strokeOpacity; + return this; + } - public int getLineWeight() { - return coalesce(this.lineWeight, Conf.dynmapDefaultStyle.lineWeight, Conf.DYNMAP_STYLE_LINE_WEIGHT); - } + public int getLineWeight() { + return coalesce(this.lineWeight, Conf.dynmapDefaultStyle.lineWeight, Conf.DYNMAP_STYLE_LINE_WEIGHT); + } - public DynmapStyle setLineWeight(Integer strokeWeight) { - this.lineWeight = strokeWeight; - return this; - } + public DynmapStyle setLineWeight(Integer strokeWeight) { + this.lineWeight = strokeWeight; + return this; + } - public int getFillColor() { - return getColor(coalesce(this.fillColor, Conf.dynmapDefaultStyle.fillColor, Conf.DYNMAP_STYLE_FILL_COLOR)); - } + public int getFillColor() { + return getColor(coalesce(this.fillColor, Conf.dynmapDefaultStyle.fillColor, Conf.DYNMAP_STYLE_FILL_COLOR)); + } - public DynmapStyle setFillColor(String fillColor) { - this.fillColor = fillColor; - return this; - } + public DynmapStyle setFillColor(String fillColor) { + this.fillColor = fillColor; + return this; + } - public double getFillOpacity() { - return coalesce(this.fillOpacity, Conf.dynmapDefaultStyle.fillOpacity, Conf.DYNMAP_STYLE_FILL_OPACITY); - } + public double getFillOpacity() { + return coalesce(this.fillOpacity, Conf.dynmapDefaultStyle.fillOpacity, Conf.DYNMAP_STYLE_FILL_OPACITY); + } - public DynmapStyle setFillOpacity(Double fillOpacity) { - this.fillOpacity = fillOpacity; - return this; - } + public DynmapStyle setFillOpacity(Double fillOpacity) { + this.fillOpacity = fillOpacity; + return this; + } - public String getHomeMarker() { - return coalesce(this.homeMarker, Conf.dynmapDefaultStyle.homeMarker, Conf.DYNMAP_STYLE_HOME_MARKER); - } + public String getHomeMarker() { + return coalesce(this.homeMarker, Conf.dynmapDefaultStyle.homeMarker, Conf.DYNMAP_STYLE_HOME_MARKER); + } - public DynmapStyle setHomeMarker(String homeMarker) { - this.homeMarker = homeMarker; - return this; - } + public DynmapStyle setHomeMarker(String homeMarker) { + this.homeMarker = homeMarker; + return this; + } - // -------------------------------------------- // - // UTIL - // -------------------------------------------- // + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // - public boolean getBoost() { - return coalesce(this.boost, Conf.dynmapDefaultStyle.boost, Conf.DYNMAP_STYLE_BOOST); - } + public boolean getBoost() { + return coalesce(this.boost, Conf.dynmapDefaultStyle.boost, Conf.DYNMAP_STYLE_BOOST); + } - public DynmapStyle setBoost(Boolean boost) { - this.boost = boost; - return this; - } + public DynmapStyle setBoost(Boolean boost) { + this.boost = boost; + return this; + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java b/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java index 6aad4390..0f15ff22 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java @@ -17,750 +17,750 @@ import java.util.Map.Entry; // This source code is a heavily modified version of mikeprimms plugin Dynmap-Factions. public class EngineDynmap { - // -------------------------------------------- // - // CONSTANTS - // -------------------------------------------- // - - public final static int BLOCKS_PER_CHUNK = 16; - - public final static String DYNMAP_INTEGRATION = "\u00A7dDynmap Integration: \u00A7e"; - - public final static String FACTIONS = "factions"; - public final static String FACTIONS_ = FACTIONS + "_"; - - public final static String FACTIONS_MARKERSET = FACTIONS_ + "markerset"; - - public final static String FACTIONS_HOME = FACTIONS_ + "home"; - public final static String FACTIONS_HOME_ = FACTIONS_HOME + "_"; - - public final static String FACTIONS_PLAYERSET = FACTIONS_ + "playerset"; - public final static String FACTIONS_PLAYERSET_ = FACTIONS_PLAYERSET + "_"; - - // -------------------------------------------- // - // INSTANCE & CONSTRUCT - // -------------------------------------------- // - - private static final EngineDynmap i = new EngineDynmap(); - public DynmapAPI dynmapApi; - public MarkerAPI markerApi; - public MarkerSet markerset; - - private EngineDynmap() { - } - - public static EngineDynmap getInstance() { - return i; - } - - public static String getHtmlPlayerString(Collection playersOfficersList) { - StringBuilder ret = new StringBuilder(); - for (FPlayer fplayer : playersOfficersList) { - if (ret.length() > 0) { - ret.append(", "); - } - ret.append(getHtmlPlayerName(fplayer)); - } - return ret.toString(); - } - - public static String getHtmlPlayerName(FPlayer fplayer) { - return fplayer != null ? escapeHtml(fplayer.getName()) : "none"; - } - - public static String escapeHtml(String string) { - StringBuilder out = new StringBuilder(Math.max(16, string.length())); - for (int i = 0; i < string.length(); i++) { - char c = string.charAt(i); - if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { - out.append("&#") - .append((int) c) - .append(';'); - } else { - out.append(c); - } - } - return out.toString(); - } - - // Thread Safe / Asynchronous: Yes - public static void info(String msg) { - System.out.println(DYNMAP_INTEGRATION + msg); - } - - // -------------------------------------------- // - // UPDATE: HOMES - // -------------------------------------------- // - - // Thread Safe / Asynchronous: Yes - public static void severe(String msg) { - System.out.println(DYNMAP_INTEGRATION + ChatColor.RED.toString() + msg); - } - - public void init() { - Plugin dynmap = Bukkit.getServer().getPluginManager().getPlugin("dynmap"); - - if (dynmap == null || !dynmap.isEnabled()) { - return; - } - - // Should we even use dynmap? - if (!Conf.dynmapUse) { - if (this.markerset != null) { - this.markerset.deleteMarkerSet(); - this.markerset = null; - } - return; - } - - // Shedule non thread safe sync at the end! - Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - - final Map homes = createHomes(); - final Map areas = createAreas(); - final Map> playerSets = createPlayersets(); - - if (!updateCore()) { - return; - } - - // createLayer() is thread safe but it makes use of fields set in updateCore() so we must have it after. - if (!updateLayer(createLayer())) { - return; - } - - updateHomes(homes); - updateAreas(areas); - updatePlayersets(playerSets); - } - }, 100L, 100L); - } - - // -------------------------------------------- // - // UPDATE: AREAS - // -------------------------------------------- // - - // Thread Safe / Asynchronous: No - public boolean updateCore() { - // Get DynmapAPI - this.dynmapApi = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap"); - if (this.dynmapApi == null) { - severe("Could not retrieve the DynmapAPI."); - return false; - } - - // Get MarkerAPI - this.markerApi = this.dynmapApi.getMarkerAPI(); - if (this.markerApi == null) { - severe("Could not retrieve the MarkerAPI."); - return false; - } - - return true; - } - - // Thread Safe / Asynchronous: Yes - public TempMarkerSet createLayer() { - TempMarkerSet ret = new TempMarkerSet(); - ret.label = Conf.dynmapLayerName; - ret.minimumZoom = Conf.dynmapLayerMinimumZoom; - ret.priority = Conf.dynmapLayerPriority; - ret.hideByDefault = !Conf.dynmapLayerVisible; - return ret; - } - - // Thread Safe / Asynchronous: No - public boolean updateLayer(TempMarkerSet temp) { - this.markerset = this.markerApi.getMarkerSet(FACTIONS_MARKERSET); - if (this.markerset == null) { - this.markerset = temp.create(this.markerApi, FACTIONS_MARKERSET); - if (this.markerset == null) { - severe("Could not create the Faction Markerset/Layer"); - return false; - } - } else { - temp.update(this.markerset); - } - return true; - } - - // Thread Safe / Asynchronous: Yes - public Map createHomes() { - Map ret = new HashMap<>(); - - // Loop current factions - for (Faction faction : Factions.getInstance().getAllFactions()) { - Location ps = faction.getHome(); - if (ps == null) { - continue; - } - - DynmapStyle style = getStyle(faction); - - String markerId = FACTIONS_HOME_ + faction.getId(); - - TempMarker temp = new TempMarker(); - temp.label = ChatColor.stripColor(faction.getTag()); - temp.world = ps.getWorld().toString(); - temp.x = ps.getX(); - temp.y = ps.getY(); - temp.z = ps.getZ(); - temp.iconName = style.getHomeMarker(); - temp.description = getDescription(faction); - - ret.put(markerId, temp); - } - - return ret; - } - - // Thread Safe / Asynchronous: No - // This method places out the faction home markers into the factions markerset. - public void updateHomes(Map homes) { - // Put all current faction markers in a map - Map markers = new HashMap<>(); - for (Marker marker : this.markerset.getMarkers()) { - markers.put(marker.getMarkerID(), marker); - } - - // Loop homes - for (Entry entry : homes.entrySet()) { - String markerId = entry.getKey(); - TempMarker temp = entry.getValue(); - - // Get Creative - // NOTE: I remove from the map created just in the beginning of this method. - // NOTE: That way what is left at the end will be outdated markers to remove. - Marker marker = markers.remove(markerId); - if (marker == null) { - marker = temp.create(this.markerApi, this.markerset, markerId); - if (marker == null) { - EngineDynmap.severe("Could not get/create the home marker " + markerId); - } - } else { - temp.update(this.markerApi, marker); - } - } - - // Delete Deprecated Markers - // Only old markers should now be left - for (Marker marker : markers.values()) { - marker.deleteMarker(); - } - } - - // -------------------------------------------- // - // UPDATE: PLAYERSET - // -------------------------------------------- // - - // Thread Safe: YES - public Map createAreas() { - Map>> worldFactionChunks = createWorldFactionChunks(); - return createAreas(worldFactionChunks); - } - - // Thread Safe: YES - public Map>> createWorldFactionChunks() { - // Create map "world name --> faction --> set of chunk coords" - Map>> worldFactionChunks = new HashMap<>(); - - // Note: The board is the world. The board id is the world name. - MemoryBoard board = (MemoryBoard) Board.getInstance(); - - for (Entry entry : board.flocationIds.entrySet()) { - String world = entry.getKey().getWorldName(); - Faction chunkOwner = Factions.getInstance().getFactionById(entry.getValue()); - - Map> factionChunks = worldFactionChunks.get(world); - if (factionChunks == null) { - factionChunks = new HashMap<>(); - worldFactionChunks.put(world, factionChunks); - } - - Set factionTerritory = factionChunks.get(chunkOwner); - if (factionTerritory == null) { - factionTerritory = new HashSet<>(); - factionChunks.put(chunkOwner, factionTerritory); - } - - factionTerritory.add(entry.getKey()); - } - - return worldFactionChunks; - } - - // Thread Safe: YES - public Map createAreas(Map>> worldFactionChunks) { - Map ret = new HashMap<>(); - - // For each world - for (Entry>> entry : worldFactionChunks.entrySet()) { - String world = entry.getKey(); - Map> factionChunks = entry.getValue(); - - // For each faction and its chunks in that world - for (Entry> entry1 : factionChunks.entrySet()) { - Faction faction = entry1.getKey(); - Set chunks = entry1.getValue(); - Map worldFactionMarkers = createAreas(world, faction, chunks); - ret.putAll(worldFactionMarkers); - } - } - - return ret; - } - - // Thread Safe: YES - // Handle specific faction on specific world - // "handle faction on world" - public Map createAreas(String world, Faction faction, Set chunks) { - Map ret = new HashMap<>(); - - // If the faction is visible ... - if (!isVisible(faction, world)) { - return ret; - } - - // ... and has any chunks ... - if (chunks.isEmpty()) { - return ret; - } - - // Index of polygon for given faction - int markerIndex = 0; - - // Create the info window - String description = getDescription(faction); - - // Fetch Style - DynmapStyle style = this.getStyle(faction); - - // Loop through chunks: set flags on chunk map - TileFlags allChunkFlags = new TileFlags(); - LinkedList allChunks = new LinkedList<>(); - for (FLocation chunk : chunks) { - allChunkFlags.setFlag((int) chunk.getX(), (int) chunk.getZ(), true); // Set flag for chunk - allChunks.addLast(chunk); - } - - // Loop through until we don't find more areas - while (allChunks != null) { - TileFlags ourChunkFlags = null; - LinkedList ourChunks = null; - LinkedList newChunks = null; - - int minimumX = Integer.MAX_VALUE; - int minimumZ = Integer.MAX_VALUE; - for (FLocation chunk : allChunks) { - int chunkX = (int) chunk.getX(); - int chunkZ = (int) chunk.getZ(); - - // If we need to start shape, and this block is not part of one yet - if (ourChunkFlags == null && allChunkFlags.getFlag(chunkX, chunkZ)) { - ourChunkFlags = new TileFlags(); // Create map for shape - ourChunks = new LinkedList<>(); - floodFillTarget(allChunkFlags, ourChunkFlags, chunkX, chunkZ); // Copy shape - ourChunks.add(chunk); // Add it to our chunk list - minimumX = chunkX; - minimumZ = chunkZ; - } - // If shape found, and we're in it, add to our node list - else if (ourChunkFlags != null && ourChunkFlags.getFlag(chunkX, chunkZ)) { - ourChunks.add(chunk); - if (chunkX < minimumX) { - minimumX = chunkX; - minimumZ = chunkZ; - } else if (chunkX == minimumX && chunkZ < minimumZ) { - minimumZ = chunkZ; - } - } - // Else, keep it in the list for the next polygon - else { - if (newChunks == null) { - newChunks = new LinkedList<>(); - } - newChunks.add(chunk); - } - } - - // Replace list (null if no more to process) - allChunks = newChunks; - - if (ourChunkFlags == null) { - continue; - } - - // Trace outline of blocks - start from minx, minz going to x+ - int initialX = minimumX; - int initialZ = minimumZ; - int currentX = minimumX; - int currentZ = minimumZ; - Direction direction = Direction.XPLUS; - ArrayList linelist = new ArrayList<>(); - linelist.add(new int[]{initialX, initialZ}); // Add start point - while ((currentX != initialX) || (currentZ != initialZ) || (direction != Direction.ZMINUS)) { - switch (direction) { - case XPLUS: // Segment in X+ direction - if (!ourChunkFlags.getFlag(currentX + 1, currentZ)) { // Right turn? - linelist.add(new int[]{currentX + 1, currentZ}); // Finish line - direction = Direction.ZPLUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ - 1)) { // Straight? - currentX++; - } else { // Left turn - linelist.add(new int[]{currentX + 1, currentZ}); // Finish line - direction = Direction.ZMINUS; - currentX++; - currentZ--; - } - break; - case ZPLUS: // Segment in Z+ direction - if (!ourChunkFlags.getFlag(currentX, currentZ + 1)) { // Right turn? - linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line - direction = Direction.XMINUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ + 1)) { // Straight? - currentZ++; - } else { // Left turn - linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line - direction = Direction.XPLUS; - currentX++; - currentZ++; - } - break; - case XMINUS: // Segment in X- direction - if (!ourChunkFlags.getFlag(currentX - 1, currentZ)) { // Right turn? - linelist.add(new int[]{currentX, currentZ + 1}); // Finish line - direction = Direction.ZMINUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ + 1)) { // Straight? - currentX--; - } else { // Left turn - linelist.add(new int[]{currentX, currentZ + 1}); // Finish line - direction = Direction.ZPLUS; - currentX--; - currentZ++; - } - break; - case ZMINUS: // Segment in Z- direction - if (!ourChunkFlags.getFlag(currentX, currentZ - 1)) { // Right turn? - linelist.add(new int[]{currentX, currentZ}); // Finish line - direction = Direction.XPLUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ - 1)) { // Straight? - currentZ--; - } else { // Left turn - linelist.add(new int[]{currentX, currentZ}); // Finish line - direction = Direction.XMINUS; - currentX--; - currentZ--; - } - break; - } - } - - int sz = linelist.size(); - double[] x = new double[sz]; - double[] z = new double[sz]; - for (int i = 0; i < sz; i++) { - int[] line = linelist.get(i); - x[i] = (double) line[0] * (double) BLOCKS_PER_CHUNK; - z[i] = (double) line[1] * (double) BLOCKS_PER_CHUNK; - } - - // Build information for specific area - String markerId = FACTIONS_ + world + "__" + faction.getId() + "__" + markerIndex; - - TempAreaMarker temp = new TempAreaMarker(); - temp.label = faction.getTag(); - temp.world = world; - temp.x = x; - temp.z = z; - temp.description = description; - - temp.lineColor = style.getLineColor(); - temp.lineOpacity = style.getLineOpacity(); - temp.lineWeight = style.getLineWeight(); - - temp.fillColor = style.getFillColor(); - temp.fillOpacity = style.getFillOpacity(); - - temp.boost = style.getBoost(); - - ret.put(markerId, temp); - - markerIndex++; - } - - return ret; - } - - // -------------------------------------------- // - // UTIL & SHARED - // -------------------------------------------- // - - // Thread Safe: NO - public void updateAreas(Map areas) { - // Map Current - Map markers = new HashMap<>(); - for (AreaMarker marker : this.markerset.getAreaMarkers()) { - markers.put(marker.getMarkerID(), marker); - } - - // Loop New - for (Entry entry : areas.entrySet()) { - String markerId = entry.getKey(); - TempAreaMarker temp = entry.getValue(); - - // Get Creative - // NOTE: I remove from the map created just in the beginning of this method. - // NOTE: That way what is left at the end will be outdated markers to remove. - AreaMarker marker = markers.remove(markerId); - if (marker == null) { - marker = temp.create(this.markerset, markerId); - if (marker == null) { - severe("Could not get/create the area marker " + markerId); - } - } else { - temp.update(marker); - } - } - - // Only old/outdated should now be left. Delete them. - for (AreaMarker marker : markers.values()) { - marker.deleteMarker(); - } - } - - // Thread Safe / Asynchronous: Yes - public String createPlayersetId(Faction faction) { - if (faction == null) { - return null; - } - if (faction.isWilderness()) { - return null; - } - String factionId = faction.getId(); - if (factionId == null) { - return null; - } - return FACTIONS_PLAYERSET_ + factionId; - } - - // Thread Safe / Asynchronous: Yes - public Set createPlayerset(Faction faction) { - if (faction == null) { - return null; - } - if (faction.isWilderness()) { - return null; - } - - Set ret = new HashSet<>(); - - for (FPlayer fplayer : faction.getFPlayers()) { - // NOTE: We add both UUID and name. This might be a good idea for future proofing. - ret.add(fplayer.getId()); - ret.add(fplayer.getName()); - } - - return ret; - } - - // Thread Safe / Asynchronous: Yes - public Map> createPlayersets() { - if (!Conf.dynmapVisibilityByFaction) { - return null; - } - - Map> ret = new HashMap<>(); - - for (Faction faction : Factions.getInstance().getAllFactions()) { - String playersetId = createPlayersetId(faction); - if (playersetId == null) { - continue; - } - Set playerIds = createPlayerset(faction); - if (playerIds == null) { - continue; - } - ret.put(playersetId, playerIds); - } - - return ret; - } - - // Thread Safe / Asynchronous: No - public void updatePlayersets(Map> playersets) { - if (playersets == null) { - return; - } - - // Remove - for (PlayerSet set : this.markerApi.getPlayerSets()) { - if (!set.getSetID().startsWith(FACTIONS_PLAYERSET_)) { - continue; - } - - // (Null means remove all) - if (playersets.containsKey(set.getSetID())) { - continue; - } - - set.deleteSet(); - } - - // Add / Update - for (Entry> entry : playersets.entrySet()) { - // Extract from Entry - String setId = entry.getKey(); - Set playerIds = entry.getValue(); - - // Get Creatively - PlayerSet set = this.markerApi.getPlayerSet(setId); - if (set == null) { - set = this.markerApi.createPlayerSet(setId, // id - true, // symmetric - playerIds, // players - false // persistent - ); - } - if (set == null) { - severe("Could not get/create the player set " + setId); - continue; - } - - // Set Content - set.setPlayers(playerIds); - } - } - - // Thread Safe / Asynchronous: Yes - private String getDescription(Faction faction) { - String ret = "
    " + Conf.dynmapDescription + "
    "; - - // Name - String name = faction.getTag(); - name = escapeHtml(ChatColor.stripColor(name)); - ret = ret.replace("%name%", name); - - // Description - String description = faction.getDescription(); - description = escapeHtml(ChatColor.stripColor(description)); - ret = ret.replace("%description%", description); - - // Money - - String money = "unavailable"; - if (Conf.bankEnabled && Conf.dynmapDescriptionMoney) - money = String.format("%.2f", Econ.getBalance(faction.getAccountId())); - ret = ret.replace("%money%", money); - - - // Players - Set playersList = faction.getFPlayers(); - String playersCount = String.valueOf(playersList.size()); - String players = getHtmlPlayerString(playersList); - - FPlayer playersLeaderObject = faction.getFPlayerAdmin(); - String playersLeader = getHtmlPlayerName(playersLeaderObject); - - ArrayList playersCoAdminsList = faction.getFPlayersWhereRole(Role.COLEADER); - String playersCoAdminsCount = String.valueOf(playersCoAdminsList.size()); - String playersCoAdmins = getHtmlPlayerString(playersCoAdminsList); - - ArrayList playersModeratorsList = faction.getFPlayersWhereRole(Role.MODERATOR); - String playersModeratorsCount = String.valueOf(playersModeratorsList.size()); - String playersModerators = getHtmlPlayerString(playersModeratorsList); - - - ArrayList playersNormalsList = faction.getFPlayersWhereRole(Role.NORMAL); - String playersNormalsCount = String.valueOf(playersNormalsList.size()); - String playersNormals = getHtmlPlayerString(playersNormalsList); - - ret = ret.replace("%players%", players); - ret = ret.replace("%players.count%", playersCount); - ret = ret.replace("%players.leader%", playersLeader); - ret = ret.replace("%players.admins%", playersCoAdmins); - ret = ret.replace("%players.admins.count%", playersCoAdminsCount); - ret = ret.replace("%players.moderators%", playersModerators); - ret = ret.replace("%players.moderators.count%", playersModeratorsCount); - ret = ret.replace("%players.normals%", playersNormals); - ret = ret.replace("%players.normals.count%", playersNormalsCount); - - return ret; - } - - // Thread Safe / Asynchronous: Yes - private boolean isVisible(Faction faction, String world) { - if (faction == null) { - return false; - } - final String factionId = faction.getId(); - if (factionId == null) { - return false; - } - final String factionName = faction.getTag(); - if (factionName == null) { - return false; - } - - Set visible = Conf.dynmapVisibleFactions; - Set hidden = Conf.dynmapHiddenFactions; - - if (!visible.isEmpty() && !visible.contains(factionId) && !visible.contains(factionName) && !visible.contains("world:" + world)) { - return false; - } - - return !hidden.contains(factionId) && !hidden.contains(factionName) && !hidden.contains("world:" + world); - } - - // Thread Safe / Asynchronous: Yes - public DynmapStyle getStyle(Faction faction) { - DynmapStyle ret; - - ret = Conf.dynmapFactionStyles.get(faction.getId()); - if (ret != null) { - return ret; - } - - ret = Conf.dynmapFactionStyles.get(faction.getTag()); - if (ret != null) { - return ret; - } - - return Conf.dynmapDefaultStyle; - } - - // Find all contiguous blocks, set in target and clear in source - private int floodFillTarget(TileFlags source, TileFlags destination, int x, int y) { - int cnt = 0; - ArrayDeque stack = new ArrayDeque<>(); - stack.push(new int[]{x, y}); - - while (!stack.isEmpty()) { - int[] nxt = stack.pop(); - x = nxt[0]; - y = nxt[1]; - if (source.getFlag(x, y)) { // Set in src - source.setFlag(x, y, false); // Clear source - destination.setFlag(x, y, true); // Set in destination - cnt++; - if (source.getFlag(x + 1, y)) { - stack.push(new int[]{x + 1, y}); - } - if (source.getFlag(x - 1, y)) { - stack.push(new int[]{x - 1, y}); - } - if (source.getFlag(x, y + 1)) { - stack.push(new int[]{x, y + 1}); - } - if (source.getFlag(x, y - 1)) { - stack.push(new int[]{x, y - 1}); - } - } - } - return cnt; - } - - enum Direction { - XPLUS, ZPLUS, XMINUS, ZMINUS - } + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + public final static int BLOCKS_PER_CHUNK = 16; + + public final static String DYNMAP_INTEGRATION = "\u00A7dDynmap Integration: \u00A7e"; + + public final static String FACTIONS = "factions"; + public final static String FACTIONS_ = FACTIONS + "_"; + + public final static String FACTIONS_MARKERSET = FACTIONS_ + "markerset"; + + public final static String FACTIONS_HOME = FACTIONS_ + "home"; + public final static String FACTIONS_HOME_ = FACTIONS_HOME + "_"; + + public final static String FACTIONS_PLAYERSET = FACTIONS_ + "playerset"; + public final static String FACTIONS_PLAYERSET_ = FACTIONS_PLAYERSET + "_"; + + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static final EngineDynmap i = new EngineDynmap(); + public DynmapAPI dynmapApi; + public MarkerAPI markerApi; + public MarkerSet markerset; + + private EngineDynmap() { + } + + public static EngineDynmap getInstance() { + return i; + } + + public static String getHtmlPlayerString(Collection playersOfficersList) { + StringBuilder ret = new StringBuilder(); + for (FPlayer fplayer : playersOfficersList) { + if (ret.length() > 0) { + ret.append(", "); + } + ret.append(getHtmlPlayerName(fplayer)); + } + return ret.toString(); + } + + public static String getHtmlPlayerName(FPlayer fplayer) { + return fplayer != null ? escapeHtml(fplayer.getName()) : "none"; + } + + public static String escapeHtml(String string) { + StringBuilder out = new StringBuilder(Math.max(16, string.length())); + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { + out.append("&#") + .append((int) c) + .append(';'); + } else { + out.append(c); + } + } + return out.toString(); + } + + // Thread Safe / Asynchronous: Yes + public static void info(String msg) { + System.out.println(DYNMAP_INTEGRATION + msg); + } + + // -------------------------------------------- // + // UPDATE: HOMES + // -------------------------------------------- // + + // Thread Safe / Asynchronous: Yes + public static void severe(String msg) { + System.out.println(DYNMAP_INTEGRATION + ChatColor.RED.toString() + msg); + } + + public void init() { + Plugin dynmap = Bukkit.getServer().getPluginManager().getPlugin("dynmap"); + + if (dynmap == null || !dynmap.isEnabled()) { + return; + } + + // Should we even use dynmap? + if (!Conf.dynmapUse) { + if (this.markerset != null) { + this.markerset.deleteMarkerSet(); + this.markerset = null; + } + return; + } + + // Shedule non thread safe sync at the end! + Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + + final Map homes = createHomes(); + final Map areas = createAreas(); + final Map> playerSets = createPlayersets(); + + if (!updateCore()) { + return; + } + + // createLayer() is thread safe but it makes use of fields set in updateCore() so we must have it after. + if (!updateLayer(createLayer())) { + return; + } + + updateHomes(homes); + updateAreas(areas); + updatePlayersets(playerSets); + } + }, 100L, 100L); + } + + // -------------------------------------------- // + // UPDATE: AREAS + // -------------------------------------------- // + + // Thread Safe / Asynchronous: No + public boolean updateCore() { + // Get DynmapAPI + this.dynmapApi = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap"); + if (this.dynmapApi == null) { + severe("Could not retrieve the DynmapAPI."); + return false; + } + + // Get MarkerAPI + this.markerApi = this.dynmapApi.getMarkerAPI(); + if (this.markerApi == null) { + severe("Could not retrieve the MarkerAPI."); + return false; + } + + return true; + } + + // Thread Safe / Asynchronous: Yes + public TempMarkerSet createLayer() { + TempMarkerSet ret = new TempMarkerSet(); + ret.label = Conf.dynmapLayerName; + ret.minimumZoom = Conf.dynmapLayerMinimumZoom; + ret.priority = Conf.dynmapLayerPriority; + ret.hideByDefault = !Conf.dynmapLayerVisible; + return ret; + } + + // Thread Safe / Asynchronous: No + public boolean updateLayer(TempMarkerSet temp) { + this.markerset = this.markerApi.getMarkerSet(FACTIONS_MARKERSET); + if (this.markerset == null) { + this.markerset = temp.create(this.markerApi, FACTIONS_MARKERSET); + if (this.markerset == null) { + severe("Could not create the Faction Markerset/Layer"); + return false; + } + } else { + temp.update(this.markerset); + } + return true; + } + + // Thread Safe / Asynchronous: Yes + public Map createHomes() { + Map ret = new HashMap<>(); + + // Loop current factions + for (Faction faction : Factions.getInstance().getAllFactions()) { + Location ps = faction.getHome(); + if (ps == null) { + continue; + } + + DynmapStyle style = getStyle(faction); + + String markerId = FACTIONS_HOME_ + faction.getId(); + + TempMarker temp = new TempMarker(); + temp.label = ChatColor.stripColor(faction.getTag()); + temp.world = ps.getWorld().toString(); + temp.x = ps.getX(); + temp.y = ps.getY(); + temp.z = ps.getZ(); + temp.iconName = style.getHomeMarker(); + temp.description = getDescription(faction); + + ret.put(markerId, temp); + } + + return ret; + } + + // Thread Safe / Asynchronous: No + // This method places out the faction home markers into the factions markerset. + public void updateHomes(Map homes) { + // Put all current faction markers in a map + Map markers = new HashMap<>(); + for (Marker marker : this.markerset.getMarkers()) { + markers.put(marker.getMarkerID(), marker); + } + + // Loop homes + for (Entry entry : homes.entrySet()) { + String markerId = entry.getKey(); + TempMarker temp = entry.getValue(); + + // Get Creative + // NOTE: I remove from the map created just in the beginning of this method. + // NOTE: That way what is left at the end will be outdated markers to remove. + Marker marker = markers.remove(markerId); + if (marker == null) { + marker = temp.create(this.markerApi, this.markerset, markerId); + if (marker == null) { + EngineDynmap.severe("Could not get/create the home marker " + markerId); + } + } else { + temp.update(this.markerApi, marker); + } + } + + // Delete Deprecated Markers + // Only old markers should now be left + for (Marker marker : markers.values()) { + marker.deleteMarker(); + } + } + + // -------------------------------------------- // + // UPDATE: PLAYERSET + // -------------------------------------------- // + + // Thread Safe: YES + public Map createAreas() { + Map>> worldFactionChunks = createWorldFactionChunks(); + return createAreas(worldFactionChunks); + } + + // Thread Safe: YES + public Map>> createWorldFactionChunks() { + // Create map "world name --> faction --> set of chunk coords" + Map>> worldFactionChunks = new HashMap<>(); + + // Note: The board is the world. The board id is the world name. + MemoryBoard board = (MemoryBoard) Board.getInstance(); + + for (Entry entry : board.flocationIds.entrySet()) { + String world = entry.getKey().getWorldName(); + Faction chunkOwner = Factions.getInstance().getFactionById(entry.getValue()); + + Map> factionChunks = worldFactionChunks.get(world); + if (factionChunks == null) { + factionChunks = new HashMap<>(); + worldFactionChunks.put(world, factionChunks); + } + + Set factionTerritory = factionChunks.get(chunkOwner); + if (factionTerritory == null) { + factionTerritory = new HashSet<>(); + factionChunks.put(chunkOwner, factionTerritory); + } + + factionTerritory.add(entry.getKey()); + } + + return worldFactionChunks; + } + + // Thread Safe: YES + public Map createAreas(Map>> worldFactionChunks) { + Map ret = new HashMap<>(); + + // For each world + for (Entry>> entry : worldFactionChunks.entrySet()) { + String world = entry.getKey(); + Map> factionChunks = entry.getValue(); + + // For each faction and its chunks in that world + for (Entry> entry1 : factionChunks.entrySet()) { + Faction faction = entry1.getKey(); + Set chunks = entry1.getValue(); + Map worldFactionMarkers = createAreas(world, faction, chunks); + ret.putAll(worldFactionMarkers); + } + } + + return ret; + } + + // Thread Safe: YES + // Handle specific faction on specific world + // "handle faction on world" + public Map createAreas(String world, Faction faction, Set chunks) { + Map ret = new HashMap<>(); + + // If the faction is visible ... + if (!isVisible(faction, world)) { + return ret; + } + + // ... and has any chunks ... + if (chunks.isEmpty()) { + return ret; + } + + // Index of polygon for given faction + int markerIndex = 0; + + // Create the info window + String description = getDescription(faction); + + // Fetch Style + DynmapStyle style = this.getStyle(faction); + + // Loop through chunks: set flags on chunk map + TileFlags allChunkFlags = new TileFlags(); + LinkedList allChunks = new LinkedList<>(); + for (FLocation chunk : chunks) { + allChunkFlags.setFlag((int) chunk.getX(), (int) chunk.getZ(), true); // Set flag for chunk + allChunks.addLast(chunk); + } + + // Loop through until we don't find more areas + while (allChunks != null) { + TileFlags ourChunkFlags = null; + LinkedList ourChunks = null; + LinkedList newChunks = null; + + int minimumX = Integer.MAX_VALUE; + int minimumZ = Integer.MAX_VALUE; + for (FLocation chunk : allChunks) { + int chunkX = (int) chunk.getX(); + int chunkZ = (int) chunk.getZ(); + + // If we need to start shape, and this block is not part of one yet + if (ourChunkFlags == null && allChunkFlags.getFlag(chunkX, chunkZ)) { + ourChunkFlags = new TileFlags(); // Create map for shape + ourChunks = new LinkedList<>(); + floodFillTarget(allChunkFlags, ourChunkFlags, chunkX, chunkZ); // Copy shape + ourChunks.add(chunk); // Add it to our chunk list + minimumX = chunkX; + minimumZ = chunkZ; + } + // If shape found, and we're in it, add to our node list + else if (ourChunkFlags != null && ourChunkFlags.getFlag(chunkX, chunkZ)) { + ourChunks.add(chunk); + if (chunkX < minimumX) { + minimumX = chunkX; + minimumZ = chunkZ; + } else if (chunkX == minimumX && chunkZ < minimumZ) { + minimumZ = chunkZ; + } + } + // Else, keep it in the list for the next polygon + else { + if (newChunks == null) { + newChunks = new LinkedList<>(); + } + newChunks.add(chunk); + } + } + + // Replace list (null if no more to process) + allChunks = newChunks; + + if (ourChunkFlags == null) { + continue; + } + + // Trace outline of blocks - start from minx, minz going to x+ + int initialX = minimumX; + int initialZ = minimumZ; + int currentX = minimumX; + int currentZ = minimumZ; + Direction direction = Direction.XPLUS; + ArrayList linelist = new ArrayList<>(); + linelist.add(new int[]{initialX, initialZ}); // Add start point + while ((currentX != initialX) || (currentZ != initialZ) || (direction != Direction.ZMINUS)) { + switch (direction) { + case XPLUS: // Segment in X+ direction + if (!ourChunkFlags.getFlag(currentX + 1, currentZ)) { // Right turn? + linelist.add(new int[]{currentX + 1, currentZ}); // Finish line + direction = Direction.ZPLUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ - 1)) { // Straight? + currentX++; + } else { // Left turn + linelist.add(new int[]{currentX + 1, currentZ}); // Finish line + direction = Direction.ZMINUS; + currentX++; + currentZ--; + } + break; + case ZPLUS: // Segment in Z+ direction + if (!ourChunkFlags.getFlag(currentX, currentZ + 1)) { // Right turn? + linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line + direction = Direction.XMINUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ + 1)) { // Straight? + currentZ++; + } else { // Left turn + linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line + direction = Direction.XPLUS; + currentX++; + currentZ++; + } + break; + case XMINUS: // Segment in X- direction + if (!ourChunkFlags.getFlag(currentX - 1, currentZ)) { // Right turn? + linelist.add(new int[]{currentX, currentZ + 1}); // Finish line + direction = Direction.ZMINUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ + 1)) { // Straight? + currentX--; + } else { // Left turn + linelist.add(new int[]{currentX, currentZ + 1}); // Finish line + direction = Direction.ZPLUS; + currentX--; + currentZ++; + } + break; + case ZMINUS: // Segment in Z- direction + if (!ourChunkFlags.getFlag(currentX, currentZ - 1)) { // Right turn? + linelist.add(new int[]{currentX, currentZ}); // Finish line + direction = Direction.XPLUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ - 1)) { // Straight? + currentZ--; + } else { // Left turn + linelist.add(new int[]{currentX, currentZ}); // Finish line + direction = Direction.XMINUS; + currentX--; + currentZ--; + } + break; + } + } + + int sz = linelist.size(); + double[] x = new double[sz]; + double[] z = new double[sz]; + for (int i = 0; i < sz; i++) { + int[] line = linelist.get(i); + x[i] = (double) line[0] * (double) BLOCKS_PER_CHUNK; + z[i] = (double) line[1] * (double) BLOCKS_PER_CHUNK; + } + + // Build information for specific area + String markerId = FACTIONS_ + world + "__" + faction.getId() + "__" + markerIndex; + + TempAreaMarker temp = new TempAreaMarker(); + temp.label = faction.getTag(); + temp.world = world; + temp.x = x; + temp.z = z; + temp.description = description; + + temp.lineColor = style.getLineColor(); + temp.lineOpacity = style.getLineOpacity(); + temp.lineWeight = style.getLineWeight(); + + temp.fillColor = style.getFillColor(); + temp.fillOpacity = style.getFillOpacity(); + + temp.boost = style.getBoost(); + + ret.put(markerId, temp); + + markerIndex++; + } + + return ret; + } + + // -------------------------------------------- // + // UTIL & SHARED + // -------------------------------------------- // + + // Thread Safe: NO + public void updateAreas(Map areas) { + // Map Current + Map markers = new HashMap<>(); + for (AreaMarker marker : this.markerset.getAreaMarkers()) { + markers.put(marker.getMarkerID(), marker); + } + + // Loop New + for (Entry entry : areas.entrySet()) { + String markerId = entry.getKey(); + TempAreaMarker temp = entry.getValue(); + + // Get Creative + // NOTE: I remove from the map created just in the beginning of this method. + // NOTE: That way what is left at the end will be outdated markers to remove. + AreaMarker marker = markers.remove(markerId); + if (marker == null) { + marker = temp.create(this.markerset, markerId); + if (marker == null) { + severe("Could not get/create the area marker " + markerId); + } + } else { + temp.update(marker); + } + } + + // Only old/outdated should now be left. Delete them. + for (AreaMarker marker : markers.values()) { + marker.deleteMarker(); + } + } + + // Thread Safe / Asynchronous: Yes + public String createPlayersetId(Faction faction) { + if (faction == null) { + return null; + } + if (faction.isWilderness()) { + return null; + } + String factionId = faction.getId(); + if (factionId == null) { + return null; + } + return FACTIONS_PLAYERSET_ + factionId; + } + + // Thread Safe / Asynchronous: Yes + public Set createPlayerset(Faction faction) { + if (faction == null) { + return null; + } + if (faction.isWilderness()) { + return null; + } + + Set ret = new HashSet<>(); + + for (FPlayer fplayer : faction.getFPlayers()) { + // NOTE: We add both UUID and name. This might be a good idea for future proofing. + ret.add(fplayer.getId()); + ret.add(fplayer.getName()); + } + + return ret; + } + + // Thread Safe / Asynchronous: Yes + public Map> createPlayersets() { + if (!Conf.dynmapVisibilityByFaction) { + return null; + } + + Map> ret = new HashMap<>(); + + for (Faction faction : Factions.getInstance().getAllFactions()) { + String playersetId = createPlayersetId(faction); + if (playersetId == null) { + continue; + } + Set playerIds = createPlayerset(faction); + if (playerIds == null) { + continue; + } + ret.put(playersetId, playerIds); + } + + return ret; + } + + // Thread Safe / Asynchronous: No + public void updatePlayersets(Map> playersets) { + if (playersets == null) { + return; + } + + // Remove + for (PlayerSet set : this.markerApi.getPlayerSets()) { + if (!set.getSetID().startsWith(FACTIONS_PLAYERSET_)) { + continue; + } + + // (Null means remove all) + if (playersets.containsKey(set.getSetID())) { + continue; + } + + set.deleteSet(); + } + + // Add / Update + for (Entry> entry : playersets.entrySet()) { + // Extract from Entry + String setId = entry.getKey(); + Set playerIds = entry.getValue(); + + // Get Creatively + PlayerSet set = this.markerApi.getPlayerSet(setId); + if (set == null) { + set = this.markerApi.createPlayerSet(setId, // id + true, // symmetric + playerIds, // players + false // persistent + ); + } + if (set == null) { + severe("Could not get/create the player set " + setId); + continue; + } + + // Set Content + set.setPlayers(playerIds); + } + } + + // Thread Safe / Asynchronous: Yes + private String getDescription(Faction faction) { + String ret = "
    " + Conf.dynmapDescription + "
    "; + + // Name + String name = faction.getTag(); + name = escapeHtml(ChatColor.stripColor(name)); + ret = ret.replace("%name%", name); + + // Description + String description = faction.getDescription(); + description = escapeHtml(ChatColor.stripColor(description)); + ret = ret.replace("%description%", description); + + // Money + + String money = "unavailable"; + if (Conf.bankEnabled && Conf.dynmapDescriptionMoney) + money = String.format("%.2f", Econ.getBalance(faction.getAccountId())); + ret = ret.replace("%money%", money); + + + // Players + Set playersList = faction.getFPlayers(); + String playersCount = String.valueOf(playersList.size()); + String players = getHtmlPlayerString(playersList); + + FPlayer playersLeaderObject = faction.getFPlayerAdmin(); + String playersLeader = getHtmlPlayerName(playersLeaderObject); + + ArrayList playersCoAdminsList = faction.getFPlayersWhereRole(Role.COLEADER); + String playersCoAdminsCount = String.valueOf(playersCoAdminsList.size()); + String playersCoAdmins = getHtmlPlayerString(playersCoAdminsList); + + ArrayList playersModeratorsList = faction.getFPlayersWhereRole(Role.MODERATOR); + String playersModeratorsCount = String.valueOf(playersModeratorsList.size()); + String playersModerators = getHtmlPlayerString(playersModeratorsList); + + + ArrayList playersNormalsList = faction.getFPlayersWhereRole(Role.NORMAL); + String playersNormalsCount = String.valueOf(playersNormalsList.size()); + String playersNormals = getHtmlPlayerString(playersNormalsList); + + ret = ret.replace("%players%", players); + ret = ret.replace("%players.count%", playersCount); + ret = ret.replace("%players.leader%", playersLeader); + ret = ret.replace("%players.admins%", playersCoAdmins); + ret = ret.replace("%players.admins.count%", playersCoAdminsCount); + ret = ret.replace("%players.moderators%", playersModerators); + ret = ret.replace("%players.moderators.count%", playersModeratorsCount); + ret = ret.replace("%players.normals%", playersNormals); + ret = ret.replace("%players.normals.count%", playersNormalsCount); + + return ret; + } + + // Thread Safe / Asynchronous: Yes + private boolean isVisible(Faction faction, String world) { + if (faction == null) { + return false; + } + final String factionId = faction.getId(); + if (factionId == null) { + return false; + } + final String factionName = faction.getTag(); + if (factionName == null) { + return false; + } + + Set visible = Conf.dynmapVisibleFactions; + Set hidden = Conf.dynmapHiddenFactions; + + if (!visible.isEmpty() && !visible.contains(factionId) && !visible.contains(factionName) && !visible.contains("world:" + world)) { + return false; + } + + return !hidden.contains(factionId) && !hidden.contains(factionName) && !hidden.contains("world:" + world); + } + + // Thread Safe / Asynchronous: Yes + public DynmapStyle getStyle(Faction faction) { + DynmapStyle ret; + + ret = Conf.dynmapFactionStyles.get(faction.getId()); + if (ret != null) { + return ret; + } + + ret = Conf.dynmapFactionStyles.get(faction.getTag()); + if (ret != null) { + return ret; + } + + return Conf.dynmapDefaultStyle; + } + + // Find all contiguous blocks, set in target and clear in source + private int floodFillTarget(TileFlags source, TileFlags destination, int x, int y) { + int cnt = 0; + ArrayDeque stack = new ArrayDeque<>(); + stack.push(new int[]{x, y}); + + while (!stack.isEmpty()) { + int[] nxt = stack.pop(); + x = nxt[0]; + y = nxt[1]; + if (source.getFlag(x, y)) { // Set in src + source.setFlag(x, y, false); // Clear source + destination.setFlag(x, y, true); // Set in destination + cnt++; + if (source.getFlag(x + 1, y)) { + stack.push(new int[]{x + 1, y}); + } + if (source.getFlag(x - 1, y)) { + stack.push(new int[]{x - 1, y}); + } + if (source.getFlag(x, y + 1)) { + stack.push(new int[]{x, y + 1}); + } + if (source.getFlag(x, y - 1)) { + stack.push(new int[]{x, y - 1}); + } + } + } + return cnt; + } + + enum Direction { + XPLUS, ZPLUS, XMINUS, ZMINUS + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java b/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java index ec346d53..33e695b4 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java @@ -4,113 +4,113 @@ import org.dynmap.markers.AreaMarker; import org.dynmap.markers.MarkerSet; public class TempAreaMarker { - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public String label; - public String world; - public double[] x; - public double[] z; - public String description; + public String label; + public String world; + public double[] x; + public double[] z; + public String description; - public int lineColor; - public double lineOpacity; - public int lineWeight; + public int lineColor; + public double lineOpacity; + public int lineWeight; - public int fillColor; - public double fillOpacity; + public int fillColor; + public double fillOpacity; - public boolean boost; + public boolean boost; - // -------------------------------------------- // - // CREATE - // -------------------------------------------- // + // -------------------------------------------- // + // CREATE + // -------------------------------------------- // - public static boolean equals(AreaMarker marker, double[] x, double[] z) { - int length = marker.getCornerCount(); + public static boolean equals(AreaMarker marker, double[] x, double[] z) { + int length = marker.getCornerCount(); - if (x.length != length) { - return false; - } - if (z.length != length) { - return false; - } + if (x.length != length) { + return false; + } + if (z.length != length) { + return false; + } - for (int i = 0; i < length; i++) { - if (marker.getCornerX(i) != x[i]) { - return false; - } - if (marker.getCornerZ(i) != z[i]) { - return false; - } - } + for (int i = 0; i < length; i++) { + if (marker.getCornerX(i) != x[i]) { + return false; + } + if (marker.getCornerZ(i) != z[i]) { + return false; + } + } - return true; - } + return true; + } - // -------------------------------------------- // - // UPDATE - // -------------------------------------------- // + // -------------------------------------------- // + // UPDATE + // -------------------------------------------- // - public AreaMarker create(MarkerSet markerset, String markerId) { - AreaMarker ret = markerset.createAreaMarker(markerId, this.label, false, this.world, this.x, this.z, false // not persistent - ); + public AreaMarker create(MarkerSet markerset, String markerId) { + AreaMarker ret = markerset.createAreaMarker(markerId, this.label, false, this.world, this.x, this.z, false // not persistent + ); - if (ret == null) { - return null; - } + if (ret == null) { + return null; + } - // Description - ret.setDescription(this.description); + // Description + ret.setDescription(this.description); - // Line Style - ret.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); + // Line Style + ret.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); - // Fill Style - ret.setFillStyle(this.fillOpacity, this.fillColor); + // Fill Style + ret.setFillStyle(this.fillOpacity, this.fillColor); - // Boost Flag - ret.setBoostFlag(this.boost); + // Boost Flag + ret.setBoostFlag(this.boost); - return ret; - } + return ret; + } - // -------------------------------------------- // - // UTIL - // -------------------------------------------- // + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // - public void update(AreaMarker marker) { - // Corner Locations - if (!equals(marker, this.x, this.z)) { - marker.setCornerLocations(this.x, this.z); - } + public void update(AreaMarker marker) { + // Corner Locations + if (!equals(marker, this.x, this.z)) { + marker.setCornerLocations(this.x, this.z); + } - // Label - if (!marker.getLabel().equals(this.label)) { - marker.setLabel(this.label); - } + // Label + if (!marker.getLabel().equals(this.label)) { + marker.setLabel(this.label); + } - // Description - if (!marker.getDescription().equals(this.description)) { - marker.setDescription(this.description); - } + // Description + if (!marker.getDescription().equals(this.description)) { + marker.setDescription(this.description); + } - // Line Style - if (marker.getLineWeight() != this.lineWeight || - marker.getLineOpacity() != this.lineOpacity || - marker.getLineColor() != this.lineColor) { - marker.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); - } + // Line Style + if (marker.getLineWeight() != this.lineWeight || + marker.getLineOpacity() != this.lineOpacity || + marker.getLineColor() != this.lineColor) { + marker.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); + } - // Fill Style - if ((marker.getFillOpacity() != this.fillOpacity) || (marker.getFillColor() != this.fillColor)) { - marker.setFillStyle(this.fillOpacity, this.fillColor); - } - // Boost Flag - if (marker.getBoostFlag() != this.boost) { - marker.setBoostFlag(this.boost); - } - } + // Fill Style + if ((marker.getFillOpacity() != this.fillOpacity) || (marker.getFillColor() != this.fillColor)) { + marker.setFillStyle(this.fillOpacity, this.fillColor); + } + // Boost Flag + if (marker.getBoostFlag() != this.boost) { + marker.setBoostFlag(this.boost); + } + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java index b8eefdbe..d977ae9f 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java @@ -7,68 +7,68 @@ import org.dynmap.markers.MarkerIcon; import org.dynmap.markers.MarkerSet; public class TempMarker { - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public String label; - public String world; - public double x; - public double y; - public double z; - public String iconName; - public String description; + public String label; + public String world; + public double x; + public double y; + public double z; + public String iconName; + public String description; - // -------------------------------------------- // - // CREATE - // -------------------------------------------- // + // -------------------------------------------- // + // CREATE + // -------------------------------------------- // - public static MarkerIcon getMarkerIcon(MarkerAPI markerApi, String name) { - MarkerIcon ret = markerApi.getMarkerIcon(name); - if (ret == null) { - ret = markerApi.getMarkerIcon(Conf.DYNMAP_STYLE_HOME_MARKER); - } - return ret; - } + public static MarkerIcon getMarkerIcon(MarkerAPI markerApi, String name) { + MarkerIcon ret = markerApi.getMarkerIcon(name); + if (ret == null) { + ret = markerApi.getMarkerIcon(Conf.DYNMAP_STYLE_HOME_MARKER); + } + return ret; + } - // -------------------------------------------- // - // UPDATE - // -------------------------------------------- // + // -------------------------------------------- // + // UPDATE + // -------------------------------------------- // - public Marker create(MarkerAPI markerApi, MarkerSet markerset, String markerId) { - Marker ret = markerset.createMarker(markerId, this.label, this.world, this.x, this.y, this.z, getMarkerIcon(markerApi, this.iconName), false // not persistent - ); + public Marker create(MarkerAPI markerApi, MarkerSet markerset, String markerId) { + Marker ret = markerset.createMarker(markerId, this.label, this.world, this.x, this.y, this.z, getMarkerIcon(markerApi, this.iconName), false // not persistent + ); - if (ret == null) { - return null; - } + if (ret == null) { + return null; + } - ret.setDescription(this.description); + ret.setDescription(this.description); - return ret; - } + return ret; + } - // -------------------------------------------- // - // UTIL - // -------------------------------------------- // + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // - public void update(MarkerAPI markerApi, Marker marker) { - if (!this.world.equals(marker.getWorld()) || this.x != marker.getX() || this.y != marker.getY() || this.z != marker.getZ()) { - marker.setLocation(this.world, this.x, this.y, this.z); - } + public void update(MarkerAPI markerApi, Marker marker) { + if (!this.world.equals(marker.getWorld()) || this.x != marker.getX() || this.y != marker.getY() || this.z != marker.getZ()) { + marker.setLocation(this.world, this.x, this.y, this.z); + } - if (!marker.getLabel().equals(this.label)) { - marker.setLabel(this.label); - } + if (!marker.getLabel().equals(this.label)) { + marker.setLabel(this.label); + } - MarkerIcon icon = getMarkerIcon(markerApi, this.iconName); - if (marker.getMarkerIcon() == null || marker.getMarkerIcon().equals(icon)) { - marker.setMarkerIcon(icon); - } + MarkerIcon icon = getMarkerIcon(markerApi, this.iconName); + if (marker.getMarkerIcon() == null || marker.getMarkerIcon().equals(icon)) { + marker.setMarkerIcon(icon); + } - if (!marker.getDescription().equals(this.description)) { - marker.setDescription(this.description); - } - } + if (!marker.getDescription().equals(this.description)) { + marker.setDescription(this.description); + } + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java index 553bbde6..828a2f58 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java @@ -5,51 +5,51 @@ import org.dynmap.markers.MarkerSet; public class TempMarkerSet { - public String label; - public int minimumZoom; - public int priority; - public boolean hideByDefault; + public String label; + public int minimumZoom; + public int priority; + public boolean hideByDefault; - public MarkerSet create(MarkerAPI markerApi, String id) { - MarkerSet ret = markerApi.createMarkerSet(id, this.label, null, false); // ("null, false" at the end means "all icons allowed, not perisistent") + public MarkerSet create(MarkerAPI markerApi, String id) { + MarkerSet ret = markerApi.createMarkerSet(id, this.label, null, false); // ("null, false" at the end means "all icons allowed, not perisistent") - if (ret == null) { - return null; - } + if (ret == null) { + return null; + } - // Minimum Zoom - if (this.minimumZoom > 0) { - ret.setMinZoom(this.minimumZoom); - } + // Minimum Zoom + if (this.minimumZoom > 0) { + ret.setMinZoom(this.minimumZoom); + } - // Priority - ret.setLayerPriority(this.priority); + // Priority + ret.setLayerPriority(this.priority); - // Hide by Default - ret.setHideByDefault(this.hideByDefault); + // Hide by Default + ret.setHideByDefault(this.hideByDefault); - return ret; - } + return ret; + } - public void update(MarkerSet markerset) { - // Name - if (!markerset.getMarkerSetLabel().equals(this.label)) { - markerset.setMarkerSetLabel(this.label); - } + public void update(MarkerSet markerset) { + // Name + if (!markerset.getMarkerSetLabel().equals(this.label)) { + markerset.setMarkerSetLabel(this.label); + } - if (this.minimumZoom > 0) { - if (markerset.getMinZoom() != this.minimumZoom) { - markerset.setMinZoom(this.minimumZoom); - } - } + if (this.minimumZoom > 0) { + if (markerset.getMinZoom() != this.minimumZoom) { + markerset.setMinZoom(this.minimumZoom); + } + } - if (markerset.getLayerPriority() != this.priority) { - markerset.setLayerPriority(this.priority); - } + if (markerset.getLayerPriority() != this.priority) { + markerset.setLayerPriority(this.priority); + } - if (markerset.getHideByDefault() != this.hideByDefault) { - markerset.setHideByDefault(this.hideByDefault); - } - } + if (markerset.getHideByDefault() != this.hideByDefault) { + markerset.setHideByDefault(this.hideByDefault); + } + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java index 0d2ef465..1d7709b2 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java @@ -33,490 +33,490 @@ import java.util.List; public class FactionsBlockListener implements Listener { - public static HashMap bannerLocations = new HashMap<>(); - private HashMap bannerCooldownMap = new HashMap<>(); + public static HashMap bannerLocations = new HashMap<>(); + private HashMap bannerCooldownMap = new HashMap<>(); - public static boolean playerCanBuildDestroyBlock(Player player, Location location, String action, boolean justCheck) { - String name = player.getName(); - - if (Conf.playersWhoBypassAllProtection.contains(name)) - return true; - - FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); - if (me.isAdminBypassing()) - return true; - - FLocation loc = new FLocation(location); - Faction otherFaction = Board.getInstance().getFactionAt(loc); - - if (otherFaction.isWilderness()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) - return true; // This is not faction territory. Use whatever you like here. - - if (!justCheck) - me.msg("You can't " + action + " in the wilderness."); - - return false; - } else if (otherFaction.isSafeZone()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.safeZoneDenyBuild || Permission.MANAGE_SAFE_ZONE.has(player)) - return true; - - if (!justCheck) - me.msg("You can't " + action + " in a safe zone."); - - return false; - } else if (otherFaction.isWarZone()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.warZoneDenyBuild || Permission.MANAGE_WAR_ZONE.has(player)) - return true; - - if (!justCheck) - me.msg("You can't " + action + " in a war zone."); - - return false; - } - - if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) - return true; - - Faction myFaction = me.getFaction(); - Relation rel = myFaction.getRelationTo(otherFaction); - boolean online = otherFaction.hasPlayersOnline(); - boolean pain = !justCheck && rel.confPainBuild(online); - boolean deny = rel.confDenyBuild(online); - - Access access = otherFaction.getAccess(me, PermissableAction.fromString(action)); - if (access == Access.ALLOW && ((rel == Relation.ALLY) || (rel == Relation.ENEMY) || (rel == Relation.NEUTRAL) || (rel == Relation.TRUCE))) - deny = false; - - // hurt the player for building/destroying in other territory? - if (pain) { - player.damage(Conf.actionDeniedPainAmount); - - if (!deny) { - me.msg("It is painful to try to " + action + " in the territory of " + otherFaction.getTag(myFaction)); - } - } - - - // cancel building/destroying in other territory? - if (deny) { - if (!justCheck) { - me.msg("You can't " + action + " in the territory of " + otherFaction.getTag(myFaction)); - } - - return false; - } - - // Also cancel and/or cause pain if player doesn't have ownership rights for this claim - if (Conf.ownedAreasEnabled && (Conf.ownedAreaDenyBuild || Conf.ownedAreaPainBuild) && !otherFaction.playerHasOwnershipRights(me, loc)) { - if (!pain && Conf.ownedAreaPainBuild && !justCheck) { - player.damage(Conf.actionDeniedPainAmount); - if (!Conf.ownedAreaDenyBuild) { - me.msg("It is painful to try to " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); - } - } - if (Conf.ownedAreaDenyBuild) { - if (!justCheck) { - me.msg("You can't " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); - return false; - } - } - } - - // Check the permission just after making sure the land isn't owned by someone else to avoid bypass. - - if (access != Access.ALLOW && me.getRole() != Role.LEADER) { - // TODO: Update this once new access values are added other than just allow / deny. - if (access == Access.DENY) { - if (!justCheck) - me.msg(TL.GENERIC_NOPERMISSION, action); - return false; - } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { - if (!justCheck) - me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); - return false; - } - } - return true; - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockPlace(BlockPlaceEvent event) { - if (!event.canBuild()) { - return; - } - - // special case for flint&steel, which should only be prevented by DenyUsage list - if (event.getBlockPlaced().getType() == Material.FIRE) { - return; - } - - if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "build", false)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockFromTo(BlockFromToEvent event) { - if (!Conf.handleExploitLiquidFlow) { - return; - } - if (event.getBlock().isLiquid()) { - if (event.getToBlock().isEmpty()) { - Faction from = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - Faction to = Board.getInstance().getFactionAt(new FLocation(event.getToBlock())); - if (from == to) { - // not concerned with inter-faction events - return; - } - // from faction != to faction - if (to.isNormal()) { - if (from.isNormal() && from.getRelationTo(to).isAlly()) { - return; - } - event.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockDamage(BlockDamageEvent event) { - if (event.getInstaBreak() && !playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockPistonExtend(BlockPistonExtendEvent event) { - if (!Conf.pistonProtectionThroughDenyBuild) { - return; - } - - Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - - // target end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air - Block targetBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1); - - // if potentially pushing into air/water/lava in another territory, we need to check it out - if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && !canPistonMoveBlock(pistonFaction, targetBlock.getLocation())) { - event.setCancelled(true); - } - - /* - * note that I originally was testing the territory of each affected block, but since I found that pistons can only push - * up to 12 blocks and the width of any territory is 16 blocks, it should be safe (and much more lightweight) to test - * only the final target block as done above - */ - } - - @EventHandler - public void onVaultPlace(BlockPlaceEvent e) { - if (e.getItemInHand().getType() == Material.CHEST) { - ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); - if (e.getItemInHand().isSimilar(vault)) { - FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - if (fme.getFaction().getVault() != null) { - fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); - e.setCancelled(true); - return; - } - FLocation flocation = new FLocation(e.getBlockPlaced().getLocation()); - if (Board.getInstance().getFactionAt(flocation) != fme.getFaction()) { - fme.msg(TL.COMMAND_GETVAULT_INVALIDLOCATION); - e.setCancelled(true); - return; - } - Block start = e.getBlockPlaced(); - int radius = 1; - for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { - for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { - for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { - Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); - if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { - continue; - } - - Material blockMaterial = blockLoc.getBlock().getType(); - - if (blockMaterial == Material.CHEST || (SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault") && blockMaterial == Material.HOPPER)) { - e.setCancelled(true); - fme.msg(TL.COMMAND_GETVAULT_CHESTNEAR); - return; - } - } - } - } - - fme.msg(TL.COMMAND_GETVAULT_SUCCESS); - fme.getFaction().setVault(e.getBlockPlaced().getLocation()); - - } - } - } - - @EventHandler - public void onHopperPlace(BlockPlaceEvent e) { - - if (e.getItemInHand().getType() != Material.HOPPER && !SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault")) { - return; - } - - Faction factionAt = Board.getInstance().getFactionAt(new FLocation(e.getBlockPlaced().getLocation())); - - if (factionAt.isWilderness() || factionAt.getVault() == null) { - return; - } - - - FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - - Block start = e.getBlockPlaced(); - int radius = 1; - for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { - for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { - for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { - Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); - if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { - continue; - } - - if (blockLoc.getBlock().getType() == Material.CHEST) { - if (factionAt.getVault().equals(blockLoc)) { - e.setCancelled(true); - fme.msg(TL.COMMAND_VAULT_NO_HOPPER); - return; - } - } - } - } - } - - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockPistonRetract(BlockPistonRetractEvent event) { - // if not a sticky piston, retraction should be fine - if (!event.isSticky() || !Conf.pistonProtectionThroughDenyBuild) { - return; - } - - Location targetLoc = event.getRetractLocation(); - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(targetLoc)); - - // Check if the piston is moving in a faction's territory. This disables pistons entirely in faction territory. - if (otherFaction.isNormal() && SavageFactions.plugin.getConfig().getBoolean("disable-pistons-in-territory", false)) { - event.setCancelled(true); - return; - } - - // if potentially retracted block is just air/water/lava, no worries - if (targetLoc.getBlock().isEmpty() || targetLoc.getBlock().isLiquid()) { - return; - } - - Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - - if (!canPistonMoveBlock(pistonFaction, targetLoc)) { - event.setCancelled(true); - } - } - - @EventHandler - public void onBannerPlace(BlockPlaceEvent e) { - if (SavageFactions.plugin.mc17) { - return; - } - - if (e.getItemInHand().getType() == SavageFactions.plugin.BANNER) { - ItemStack bannerInHand = e.getItemInHand(); - FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - ItemStack warBanner = fme.getFaction().getBanner(); - if (warBanner != null) { - ItemMeta warmeta = warBanner.getItemMeta(); - warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); - warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); - warBanner.setItemMeta(warmeta); - } else { - warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); - } - if (warBanner.isSimilar(bannerInHand)) { - - if (fme.getFaction().isWilderness()) { - fme.msg(TL.WARBANNER_NOFACTION); - e.setCancelled(true); - return; - } - int bannerTime = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Time") * 20; - - Location placedLoc = e.getBlockPlaced().getLocation(); - FLocation fplacedLoc = new FLocation(placedLoc); - if ((Board.getInstance().getFactionAt(fplacedLoc).isWarZone() && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Warzone")) - || (fme.getFaction().getRelationTo(Board.getInstance().getFactionAt(fplacedLoc)) == Relation.ENEMY) && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Enemy")) { - if (bannerCooldownMap.containsKey(fme.getTag())) { - fme.msg(TL.WARBANNER_COOLDOWN); - e.setCancelled(true); - return; - } - for (FPlayer fplayer : fme.getFaction().getFPlayers()) { - // if (fplayer == fme) { continue; } //Idk if I wanna not send the title to the player - fplayer.getPlayer().sendTitle(SavageFactions.plugin.color(fme.getTag() + " Placed A WarBanner!"), SavageFactions.plugin.color("&7use &c/f tpbanner&7 to tp to the banner!"), 10, 70, 20); - } - - bannerCooldownMap.put(fme.getTag(), true); - bannerLocations.put(fme.getTag(), e.getBlockPlaced().getLocation()); - final int bannerCooldown = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Place-Cooldown"); - final ArmorStand as = (ArmorStand) e.getBlockPlaced().getLocation().add(0.5, 1, 0.5).getWorld().spawnEntity(e.getBlockPlaced().getLocation().add(0.5, 1, 0.5), EntityType.ARMOR_STAND); //Spawn the ArmorStand - as.setVisible(false); //Makes the ArmorStand invisible - as.setGravity(false); //Make sure it doesn't fall - as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it - as.setCustomName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.BannerHolo").replace("{Faction}", fme.getTag()))); //Set this to the text you want - as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not - final ArmorStand armorStand = as; - final String tag = fme.getTag(); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - bannerCooldownMap.remove(tag); - } - }, Long.parseLong(bannerCooldown + "")); - final Block banner = e.getBlockPlaced(); - final Material bannerType = banner.getType(); - final Faction bannerFaction = fme.getFaction(); - banner.getWorld().strikeLightningEffect(banner.getLocation()); - // e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_LIGHTNING_IMPACT,2.0F,0.5F); - final int radius = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Effect-Radius"); - final List effects = SavageFactions.plugin.getConfig().getStringList("fbanners.Effects"); - final int affectorTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - - for (Entity e : banner.getLocation().getWorld().getNearbyEntities(banner.getLocation(), radius, 255, radius)) { - if (e instanceof Player) { - Player player = (Player) e; - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fplayer.getFaction() == bannerFaction) { - for (String effect : effects) { - String[] components = effect.split(":"); - player.addPotionEffect(new PotionEffect(PotionEffectType.getByName(components[0]), 100, Integer.parseInt(components[1]))); - } - ParticleEffect.LAVA.display(1, 1, 1, 1, 10, banner.getLocation(), 16); - ParticleEffect.FLAME.display(1, 1, 1, 1, 10, banner.getLocation(), 16); - - if (banner.getType() != bannerType) { - banner.setType(bannerType); - } - } - } - } - } - }, 0L, 20L); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - banner.setType(Material.AIR); - as.remove(); - banner.getWorld().strikeLightningEffect(banner.getLocation()); - Bukkit.getScheduler().cancelTask(affectorTask); - bannerLocations.remove(bannerFaction.getTag()); - } - }, Long.parseLong(bannerTime + "")); - } else { - fme.msg(TL.WARBANNER_INVALIDLOC); - e.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onFrostWalker(EntityBlockFormEvent event) { - if (event.getEntity() == null || event.getEntity().getType() != EntityType.PLAYER || event.getBlock() == null) { - return; - } - - Player player = (Player) event.getEntity(); - Location location = event.getBlock().getLocation(); - - // only notify every 10 seconds - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - boolean justCheck = fPlayer.getLastFrostwalkerMessage() + 10000 > System.currentTimeMillis(); - if (!justCheck) { - fPlayer.setLastFrostwalkerMessage(); - } - - // Check if they have build permissions here. If not, block this from happening. - if (!playerCanBuildDestroyBlock(player, location, "frostwalk", justCheck)) { - event.setCancelled(true); - } - } - - private boolean canPistonMoveBlock(Faction pistonFaction, Location target) { - - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(target)); - - if (pistonFaction == otherFaction) { - return true; - } - - if (otherFaction.isWilderness()) { - return !Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(target.getWorld().getName()); - - } else if (otherFaction.isSafeZone()) { - return !Conf.safeZoneDenyBuild; - - } else if (otherFaction.isWarZone()) { - return !Conf.warZoneDenyBuild; - - } - - Relation rel = pistonFaction.getRelationTo(otherFaction); - - return !rel.confDenyBuild(otherFaction.hasPlayersOnline()); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { - event.setCancelled(true); - return; - } - FPlayer fme = FPlayers.getInstance().getByPlayer(event.getPlayer()); - if (!fme.hasFaction()) { - return; - } - if (event.getBlock().getType() == SavageFactions.plugin.MOB_SPANWER) { - if (!fme.isAdminBypassing()) { - Access access = fme.getFaction().getAccess(fme, PermissableAction.SPAWNER); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "mine spawners"); - return; - } - } - } - } - - @EventHandler - public void onFarmLandDamage(EntityChangeBlockEvent event) { - if (event.getEntity() instanceof Player) { - Player player = (Player) event.getEntity(); - if (!playerCanBuildDestroyBlock(player, event.getBlock().getLocation(), PermissableAction.DESTROY.name(), true)) { - FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock().getLocation())); - Faction myFaction = me.getFaction(); - - me.msg("You can't jump on farmland in the territory of " + otherFaction.getTag(myFaction)); - event.setCancelled(true); - } - } - } + public static boolean playerCanBuildDestroyBlock(Player player, Location location, String action, boolean justCheck) { + String name = player.getName(); + + if (Conf.playersWhoBypassAllProtection.contains(name)) + return true; + + FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); + if (me.isAdminBypassing()) + return true; + + FLocation loc = new FLocation(location); + Faction otherFaction = Board.getInstance().getFactionAt(loc); + + if (otherFaction.isWilderness()) { + if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) + return true; + + if (!Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) + return true; // This is not faction territory. Use whatever you like here. + + if (!justCheck) + me.msg("You can't " + action + " in the wilderness."); + + return false; + } else if (otherFaction.isSafeZone()) { + if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) + return true; + + if (!Conf.safeZoneDenyBuild || Permission.MANAGE_SAFE_ZONE.has(player)) + return true; + + if (!justCheck) + me.msg("You can't " + action + " in a safe zone."); + + return false; + } else if (otherFaction.isWarZone()) { + if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) + return true; + + if (!Conf.warZoneDenyBuild || Permission.MANAGE_WAR_ZONE.has(player)) + return true; + + if (!justCheck) + me.msg("You can't " + action + " in a war zone."); + + return false; + } + + if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) + return true; + + Faction myFaction = me.getFaction(); + Relation rel = myFaction.getRelationTo(otherFaction); + boolean online = otherFaction.hasPlayersOnline(); + boolean pain = !justCheck && rel.confPainBuild(online); + boolean deny = rel.confDenyBuild(online); + + Access access = otherFaction.getAccess(me, PermissableAction.fromString(action)); + if (access == Access.ALLOW && ((rel == Relation.ALLY) || (rel == Relation.ENEMY) || (rel == Relation.NEUTRAL) || (rel == Relation.TRUCE))) + deny = false; + + // hurt the player for building/destroying in other territory? + if (pain) { + player.damage(Conf.actionDeniedPainAmount); + + if (!deny) { + me.msg("It is painful to try to " + action + " in the territory of " + otherFaction.getTag(myFaction)); + } + } + + + // cancel building/destroying in other territory? + if (deny) { + if (!justCheck) { + me.msg("You can't " + action + " in the territory of " + otherFaction.getTag(myFaction)); + } + + return false; + } + + // Also cancel and/or cause pain if player doesn't have ownership rights for this claim + if (Conf.ownedAreasEnabled && (Conf.ownedAreaDenyBuild || Conf.ownedAreaPainBuild) && !otherFaction.playerHasOwnershipRights(me, loc)) { + if (!pain && Conf.ownedAreaPainBuild && !justCheck) { + player.damage(Conf.actionDeniedPainAmount); + if (!Conf.ownedAreaDenyBuild) { + me.msg("It is painful to try to " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); + } + } + if (Conf.ownedAreaDenyBuild) { + if (!justCheck) { + me.msg("You can't " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); + return false; + } + } + } + + // Check the permission just after making sure the land isn't owned by someone else to avoid bypass. + + if (access != Access.ALLOW && me.getRole() != Role.LEADER) { + // TODO: Update this once new access values are added other than just allow / deny. + if (access == Access.DENY) { + if (!justCheck) + me.msg(TL.GENERIC_NOPERMISSION, action); + return false; + } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { + if (!justCheck) + me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); + return false; + } + } + return true; + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + if (!event.canBuild()) { + return; + } + + // special case for flint&steel, which should only be prevented by DenyUsage list + if (event.getBlockPlaced().getType() == Material.FIRE) { + return; + } + + if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "build", false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockFromTo(BlockFromToEvent event) { + if (!Conf.handleExploitLiquidFlow) { + return; + } + if (event.getBlock().isLiquid()) { + if (event.getToBlock().isEmpty()) { + Faction from = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); + Faction to = Board.getInstance().getFactionAt(new FLocation(event.getToBlock())); + if (from == to) { + // not concerned with inter-faction events + return; + } + // from faction != to faction + if (to.isNormal()) { + if (from.isNormal() && from.getRelationTo(to).isAlly()) { + return; + } + event.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockDamage(BlockDamageEvent event) { + if (event.getInstaBreak() && !playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPistonExtend(BlockPistonExtendEvent event) { + if (!Conf.pistonProtectionThroughDenyBuild) { + return; + } + + Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); + + // target end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air + Block targetBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1); + + // if potentially pushing into air/water/lava in another territory, we need to check it out + if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && !canPistonMoveBlock(pistonFaction, targetBlock.getLocation())) { + event.setCancelled(true); + } + + /* + * note that I originally was testing the territory of each affected block, but since I found that pistons can only push + * up to 12 blocks and the width of any territory is 16 blocks, it should be safe (and much more lightweight) to test + * only the final target block as done above + */ + } + + @EventHandler + public void onVaultPlace(BlockPlaceEvent e) { + if (e.getItemInHand().getType() == Material.CHEST) { + ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); + if (e.getItemInHand().isSimilar(vault)) { + FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); + if (fme.getFaction().getVault() != null) { + fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); + e.setCancelled(true); + return; + } + FLocation flocation = new FLocation(e.getBlockPlaced().getLocation()); + if (Board.getInstance().getFactionAt(flocation) != fme.getFaction()) { + fme.msg(TL.COMMAND_GETVAULT_INVALIDLOCATION); + e.setCancelled(true); + return; + } + Block start = e.getBlockPlaced(); + int radius = 1; + for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { + for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { + for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { + Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); + if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { + continue; + } + + Material blockMaterial = blockLoc.getBlock().getType(); + + if (blockMaterial == Material.CHEST || (SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault") && blockMaterial == Material.HOPPER)) { + e.setCancelled(true); + fme.msg(TL.COMMAND_GETVAULT_CHESTNEAR); + return; + } + } + } + } + + fme.msg(TL.COMMAND_GETVAULT_SUCCESS); + fme.getFaction().setVault(e.getBlockPlaced().getLocation()); + + } + } + } + + @EventHandler + public void onHopperPlace(BlockPlaceEvent e) { + + if (e.getItemInHand().getType() != Material.HOPPER && !SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault")) { + return; + } + + Faction factionAt = Board.getInstance().getFactionAt(new FLocation(e.getBlockPlaced().getLocation())); + + if (factionAt.isWilderness() || factionAt.getVault() == null) { + return; + } + + + FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); + + Block start = e.getBlockPlaced(); + int radius = 1; + for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { + for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { + for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { + Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); + if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { + continue; + } + + if (blockLoc.getBlock().getType() == Material.CHEST) { + if (factionAt.getVault().equals(blockLoc)) { + e.setCancelled(true); + fme.msg(TL.COMMAND_VAULT_NO_HOPPER); + return; + } + } + } + } + } + + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPistonRetract(BlockPistonRetractEvent event) { + // if not a sticky piston, retraction should be fine + if (!event.isSticky() || !Conf.pistonProtectionThroughDenyBuild) { + return; + } + + Location targetLoc = event.getRetractLocation(); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(targetLoc)); + + // Check if the piston is moving in a faction's territory. This disables pistons entirely in faction territory. + if (otherFaction.isNormal() && SavageFactions.plugin.getConfig().getBoolean("disable-pistons-in-territory", false)) { + event.setCancelled(true); + return; + } + + // if potentially retracted block is just air/water/lava, no worries + if (targetLoc.getBlock().isEmpty() || targetLoc.getBlock().isLiquid()) { + return; + } + + Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); + + if (!canPistonMoveBlock(pistonFaction, targetLoc)) { + event.setCancelled(true); + } + } + + @EventHandler + public void onBannerPlace(BlockPlaceEvent e) { + if (SavageFactions.plugin.mc17) { + return; + } + + if (e.getItemInHand().getType() == SavageFactions.plugin.BANNER) { + ItemStack bannerInHand = e.getItemInHand(); + FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); + ItemStack warBanner = fme.getFaction().getBanner(); + if (warBanner != null) { + ItemMeta warmeta = warBanner.getItemMeta(); + warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); + warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); + warBanner.setItemMeta(warmeta); + } else { + warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); + } + if (warBanner.isSimilar(bannerInHand)) { + + if (fme.getFaction().isWilderness()) { + fme.msg(TL.WARBANNER_NOFACTION); + e.setCancelled(true); + return; + } + int bannerTime = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Time") * 20; + + Location placedLoc = e.getBlockPlaced().getLocation(); + FLocation fplacedLoc = new FLocation(placedLoc); + if ((Board.getInstance().getFactionAt(fplacedLoc).isWarZone() && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Warzone")) + || (fme.getFaction().getRelationTo(Board.getInstance().getFactionAt(fplacedLoc)) == Relation.ENEMY) && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Enemy")) { + if (bannerCooldownMap.containsKey(fme.getTag())) { + fme.msg(TL.WARBANNER_COOLDOWN); + e.setCancelled(true); + return; + } + for (FPlayer fplayer : fme.getFaction().getFPlayers()) { + // if (fplayer == fme) { continue; } //Idk if I wanna not send the title to the player + fplayer.getPlayer().sendTitle(SavageFactions.plugin.color(fme.getTag() + " Placed A WarBanner!"), SavageFactions.plugin.color("&7use &c/f tpbanner&7 to tp to the banner!"), 10, 70, 20); + } + + bannerCooldownMap.put(fme.getTag(), true); + bannerLocations.put(fme.getTag(), e.getBlockPlaced().getLocation()); + final int bannerCooldown = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Place-Cooldown"); + final ArmorStand as = (ArmorStand) e.getBlockPlaced().getLocation().add(0.5, 1, 0.5).getWorld().spawnEntity(e.getBlockPlaced().getLocation().add(0.5, 1, 0.5), EntityType.ARMOR_STAND); //Spawn the ArmorStand + as.setVisible(false); //Makes the ArmorStand invisible + as.setGravity(false); //Make sure it doesn't fall + as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it + as.setCustomName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.BannerHolo").replace("{Faction}", fme.getTag()))); //Set this to the text you want + as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not + final ArmorStand armorStand = as; + final String tag = fme.getTag(); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + bannerCooldownMap.remove(tag); + } + }, Long.parseLong(bannerCooldown + "")); + final Block banner = e.getBlockPlaced(); + final Material bannerType = banner.getType(); + final Faction bannerFaction = fme.getFaction(); + banner.getWorld().strikeLightningEffect(banner.getLocation()); + // e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_LIGHTNING_IMPACT,2.0F,0.5F); + final int radius = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Effect-Radius"); + final List effects = SavageFactions.plugin.getConfig().getStringList("fbanners.Effects"); + final int affectorTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + + for (Entity e : banner.getLocation().getWorld().getNearbyEntities(banner.getLocation(), radius, 255, radius)) { + if (e instanceof Player) { + Player player = (Player) e; + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer.getFaction() == bannerFaction) { + for (String effect : effects) { + String[] components = effect.split(":"); + player.addPotionEffect(new PotionEffect(PotionEffectType.getByName(components[0]), 100, Integer.parseInt(components[1]))); + } + ParticleEffect.LAVA.display(1, 1, 1, 1, 10, banner.getLocation(), 16); + ParticleEffect.FLAME.display(1, 1, 1, 1, 10, banner.getLocation(), 16); + + if (banner.getType() != bannerType) { + banner.setType(bannerType); + } + } + } + } + } + }, 0L, 20L); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + banner.setType(Material.AIR); + as.remove(); + banner.getWorld().strikeLightningEffect(banner.getLocation()); + Bukkit.getScheduler().cancelTask(affectorTask); + bannerLocations.remove(bannerFaction.getTag()); + } + }, Long.parseLong(bannerTime + "")); + } else { + fme.msg(TL.WARBANNER_INVALIDLOC); + e.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onFrostWalker(EntityBlockFormEvent event) { + if (event.getEntity() == null || event.getEntity().getType() != EntityType.PLAYER || event.getBlock() == null) { + return; + } + + Player player = (Player) event.getEntity(); + Location location = event.getBlock().getLocation(); + + // only notify every 10 seconds + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + boolean justCheck = fPlayer.getLastFrostwalkerMessage() + 10000 > System.currentTimeMillis(); + if (!justCheck) { + fPlayer.setLastFrostwalkerMessage(); + } + + // Check if they have build permissions here. If not, block this from happening. + if (!playerCanBuildDestroyBlock(player, location, "frostwalk", justCheck)) { + event.setCancelled(true); + } + } + + private boolean canPistonMoveBlock(Faction pistonFaction, Location target) { + + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(target)); + + if (pistonFaction == otherFaction) { + return true; + } + + if (otherFaction.isWilderness()) { + return !Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(target.getWorld().getName()); + + } else if (otherFaction.isSafeZone()) { + return !Conf.safeZoneDenyBuild; + + } else if (otherFaction.isWarZone()) { + return !Conf.warZoneDenyBuild; + + } + + Relation rel = pistonFaction.getRelationTo(otherFaction); + + return !rel.confDenyBuild(otherFaction.hasPlayersOnline()); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { + event.setCancelled(true); + return; + } + FPlayer fme = FPlayers.getInstance().getByPlayer(event.getPlayer()); + if (!fme.hasFaction()) { + return; + } + if (event.getBlock().getType() == SavageFactions.plugin.MOB_SPANWER) { + if (!fme.isAdminBypassing()) { + Access access = fme.getFaction().getAccess(fme, PermissableAction.SPAWNER); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "mine spawners"); + return; + } + } + } + } + + @EventHandler + public void onFarmLandDamage(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + if (!playerCanBuildDestroyBlock(player, event.getBlock().getLocation(), PermissableAction.DESTROY.name(), true)) { + FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock().getLocation())); + Faction myFaction = me.getFaction(); + + me.msg("You can't jump on farmland in the territory of " + otherFaction.getTag(myFaction)); + event.setCancelled(true); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java index ff710b86..36505c0c 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java @@ -19,192 +19,192 @@ import java.util.logging.Level; public class FactionsChatListener implements Listener { - // this is for handling slashless command usage and faction/alliance chat, set at lowest priority so Factions gets to them first - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerEarlyChat(AsyncPlayerChatEvent event) { - Player talkingPlayer = event.getPlayer(); - String msg = event.getMessage(); - FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); - ChatMode chat = me.getChatMode(); - // Is the player entering a password for a warp? - if (me.isEnteringPassword()) { - event.setCancelled(true); - me.sendMessage(ChatColor.DARK_GRAY + event.getMessage().replaceAll("(?s).", "*")); - if (me.getFaction().isWarpPassword(me.getEnteringWarp(), event.getMessage())) { - doWarmup(me.getEnteringWarp(), me); - } else { - // Invalid Password - me.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); - } - me.setEnteringPassword(false, ""); - return; - } + // this is for handling slashless command usage and faction/alliance chat, set at lowest priority so Factions gets to them first + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerEarlyChat(AsyncPlayerChatEvent event) { + Player talkingPlayer = event.getPlayer(); + String msg = event.getMessage(); + FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); + ChatMode chat = me.getChatMode(); + // Is the player entering a password for a warp? + if (me.isEnteringPassword()) { + event.setCancelled(true); + me.sendMessage(ChatColor.DARK_GRAY + event.getMessage().replaceAll("(?s).", "*")); + if (me.getFaction().isWarpPassword(me.getEnteringWarp(), event.getMessage())) { + doWarmup(me.getEnteringWarp(), me); + } else { + // Invalid Password + me.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); + } + me.setEnteringPassword(false, ""); + return; + } - //Is it a MOD chat - if (chat == ChatMode.MOD) { - Faction myFaction = me.getFaction(); + //Is it a MOD chat + if (chat == ChatMode.MOD) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.modChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); + String message = String.format(Conf.modChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); - //Send to all mods - if (me.getRole().isAtLeast(Role.MODERATOR)) { - // Iterates only through the factions' members so we enhance performance. - for (FPlayer fplayer : myFaction.getFPlayers()) { - if (fplayer.getRole().isAtLeast(Role.MODERATOR)) { - fplayer.sendMessage(message); - } else if (fplayer.isSpyingChat() && me != fplayer) { - fplayer.sendMessage("[MCspy]: " + message); - } - } - } else { - // Just in case player gets demoted while in faction chat. - me.msg(TL.COMMAND_CHAT_MOD_ONLY); - event.setCancelled(true); - return; - } + //Send to all mods + if (me.getRole().isAtLeast(Role.MODERATOR)) { + // Iterates only through the factions' members so we enhance performance. + for (FPlayer fplayer : myFaction.getFPlayers()) { + if (fplayer.getRole().isAtLeast(Role.MODERATOR)) { + fplayer.sendMessage(message); + } else if (fplayer.isSpyingChat() && me != fplayer) { + fplayer.sendMessage("[MCspy]: " + message); + } + } + } else { + // Just in case player gets demoted while in faction chat. + me.msg(TL.COMMAND_CHAT_MOD_ONLY); + event.setCancelled(true); + return; + } - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("Mod Chat: " + message)); + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("Mod Chat: " + message)); - event.setCancelled(true); - } else if (chat == ChatMode.FACTION) { - Faction myFaction = me.getFaction(); + event.setCancelled(true); + } else if (chat == ChatMode.FACTION) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.factionChatFormat, me.describeTo(myFaction), msg); - myFaction.sendMessage(message); + String message = String.format(Conf.factionChatFormat, me.describeTo(myFaction), msg); + myFaction.sendMessage(message); - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("FactionChat " + myFaction.getTag() + ": " + message)); + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("FactionChat " + myFaction.getTag() + ": " + message)); - //Send to any players who are spying chat - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (fplayer.isSpyingChat() && fplayer.getFaction() != myFaction && me != fplayer) { - fplayer.sendMessage("[FCspy] " + myFaction.getTag() + ": " + message); - } - } + //Send to any players who are spying chat + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.isSpyingChat() && fplayer.getFaction() != myFaction && me != fplayer) { + fplayer.sendMessage("[FCspy] " + myFaction.getTag() + ": " + message); + } + } - event.setCancelled(true); - } else if (chat == ChatMode.ALLIANCE) { - Faction myFaction = me.getFaction(); + event.setCancelled(true); + } else if (chat == ChatMode.ALLIANCE) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.allianceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); + String message = String.format(Conf.allianceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); - //Send message to our own faction - myFaction.sendMessage(message); + //Send message to our own faction + myFaction.sendMessage(message); - //Send to all our allies - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (myFaction.getRelationTo(fplayer) == Relation.ALLY && !fplayer.isIgnoreAllianceChat()) { - fplayer.sendMessage(message); - } else if (fplayer.isSpyingChat() && me != fplayer) { - fplayer.sendMessage("[ACspy]: " + message); - } - } + //Send to all our allies + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (myFaction.getRelationTo(fplayer) == Relation.ALLY && !fplayer.isIgnoreAllianceChat()) { + fplayer.sendMessage(message); + } else if (fplayer.isSpyingChat() && me != fplayer) { + fplayer.sendMessage("[ACspy]: " + message); + } + } - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("AllianceChat: " + message)); + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("AllianceChat: " + message)); - event.setCancelled(true); - } else if (chat == ChatMode.TRUCE) { - Faction myFaction = me.getFaction(); + event.setCancelled(true); + } else if (chat == ChatMode.TRUCE) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.truceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); + String message = String.format(Conf.truceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); - //Send message to our own faction - myFaction.sendMessage(message); + //Send message to our own faction + myFaction.sendMessage(message); - //Send to all our truces - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (myFaction.getRelationTo(fplayer) == Relation.TRUCE) { - fplayer.sendMessage(message); - } else if (fplayer.isSpyingChat() && fplayer != me) { - fplayer.sendMessage("[TCspy]: " + message); - } - } + //Send to all our truces + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (myFaction.getRelationTo(fplayer) == Relation.TRUCE) { + fplayer.sendMessage(message); + } else if (fplayer.isSpyingChat() && fplayer != me) { + fplayer.sendMessage("[TCspy]: " + message); + } + } - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("TruceChat: " + message)); - event.setCancelled(true); - } - } + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("TruceChat: " + message)); + event.setCancelled(true); + } + } - // this is for handling insertion of the player's faction tag, set at highest priority to give other plugins a chance to modify chat first - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerChat(AsyncPlayerChatEvent event) { - // Are we to insert the Faction tag into the format? - // If we are not to insert it - we are done. - if (!Conf.chatTagEnabled || Conf.chatTagHandledByAnotherPlugin) { - return; - } + // this is for handling insertion of the player's faction tag, set at highest priority to give other plugins a chance to modify chat first + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerChat(AsyncPlayerChatEvent event) { + // Are we to insert the Faction tag into the format? + // If we are not to insert it - we are done. + if (!Conf.chatTagEnabled || Conf.chatTagHandledByAnotherPlugin) { + return; + } - Player talkingPlayer = event.getPlayer(); - String msg = event.getMessage(); - String eventFormat = event.getFormat(); - FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); - int InsertIndex; + Player talkingPlayer = event.getPlayer(); + String msg = event.getMessage(); + String eventFormat = event.getFormat(); + FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); + int InsertIndex; - if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString)) { - // we're using the "replace" method of inserting the faction tags - if (eventFormat.contains("[FACTION_TITLE]")) { - eventFormat = eventFormat.replace("[FACTION_TITLE]", me.getTitle()); - } + if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString)) { + // we're using the "replace" method of inserting the faction tags + if (eventFormat.contains("[FACTION_TITLE]")) { + eventFormat = eventFormat.replace("[FACTION_TITLE]", me.getTitle()); + } - InsertIndex = eventFormat.indexOf(Conf.chatTagReplaceString); - eventFormat = eventFormat.replace(Conf.chatTagReplaceString, ""); - Conf.chatTagPadAfter = false; - Conf.chatTagPadBefore = false; - } else if (!Conf.chatTagInsertAfterString.isEmpty() && eventFormat.contains(Conf.chatTagInsertAfterString)) { - // we're using the "insert after string" method - InsertIndex = eventFormat.indexOf(Conf.chatTagInsertAfterString) + Conf.chatTagInsertAfterString.length(); - } else if (!Conf.chatTagInsertBeforeString.isEmpty() && eventFormat.contains(Conf.chatTagInsertBeforeString)) { - // we're using the "insert before string" method - InsertIndex = eventFormat.indexOf(Conf.chatTagInsertBeforeString); - } else { - // we'll fall back to using the index place method - InsertIndex = Conf.chatTagInsertIndex; - if (InsertIndex > eventFormat.length()) { - return; - } - } + InsertIndex = eventFormat.indexOf(Conf.chatTagReplaceString); + eventFormat = eventFormat.replace(Conf.chatTagReplaceString, ""); + Conf.chatTagPadAfter = false; + Conf.chatTagPadBefore = false; + } else if (!Conf.chatTagInsertAfterString.isEmpty() && eventFormat.contains(Conf.chatTagInsertAfterString)) { + // we're using the "insert after string" method + InsertIndex = eventFormat.indexOf(Conf.chatTagInsertAfterString) + Conf.chatTagInsertAfterString.length(); + } else if (!Conf.chatTagInsertBeforeString.isEmpty() && eventFormat.contains(Conf.chatTagInsertBeforeString)) { + // we're using the "insert before string" method + InsertIndex = eventFormat.indexOf(Conf.chatTagInsertBeforeString); + } else { + // we'll fall back to using the index place method + InsertIndex = Conf.chatTagInsertIndex; + if (InsertIndex > eventFormat.length()) { + return; + } + } - String formatStart = eventFormat.substring(0, InsertIndex) + ((Conf.chatTagPadBefore && !me.getChatTag().isEmpty()) ? " " : ""); - String formatEnd = ((Conf.chatTagPadAfter && !me.getChatTag().isEmpty()) ? " " : "") + eventFormat.substring(InsertIndex); + String formatStart = eventFormat.substring(0, InsertIndex) + ((Conf.chatTagPadBefore && !me.getChatTag().isEmpty()) ? " " : ""); + String formatEnd = ((Conf.chatTagPadAfter && !me.getChatTag().isEmpty()) ? " " : "") + eventFormat.substring(InsertIndex); - String nonColoredMsgFormat = formatStart + me.getChatTag().trim() + formatEnd; + String nonColoredMsgFormat = formatStart + me.getChatTag().trim() + formatEnd; - // Relation Colored? - if (Conf.chatTagRelationColored) { - for (Player listeningPlayer : event.getRecipients()) { - FPlayer you = FPlayers.getInstance().getByPlayer(listeningPlayer); - String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd; - try { - listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); - } catch (UnknownFormatConversionException ex) { - Conf.chatTagInsertIndex = 0; - SavageFactions.plugin.log(Level.SEVERE, "Critical error in chat message formatting!"); - SavageFactions.plugin.log(Level.SEVERE, "NOTE: This has been automatically fixed right now by setting chatTagInsertIndex to 0."); - SavageFactions.plugin.log(Level.SEVERE, "For a more proper fix, please read this regarding chat configuration: http://massivecraft.com/plugins/factions/config#Chat_configuration"); - return; - } - } + // Relation Colored? + if (Conf.chatTagRelationColored) { + for (Player listeningPlayer : event.getRecipients()) { + FPlayer you = FPlayers.getInstance().getByPlayer(listeningPlayer); + String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd; + try { + listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); + } catch (UnknownFormatConversionException ex) { + Conf.chatTagInsertIndex = 0; + SavageFactions.plugin.log(Level.SEVERE, "Critical error in chat message formatting!"); + SavageFactions.plugin.log(Level.SEVERE, "NOTE: This has been automatically fixed right now by setting chatTagInsertIndex to 0."); + SavageFactions.plugin.log(Level.SEVERE, "For a more proper fix, please read this regarding chat configuration: http://massivecraft.com/plugins/factions/config#Chat_configuration"); + return; + } + } - // Messages are sent to players individually - // This still leaves a chance for other plugins to pick it up - event.getRecipients().clear(); - } - // Message with no relation color. - event.setFormat(nonColoredMsgFormat); - } + // Messages are sent to players individually + // This still leaves a chance for other plugins to pick it up + event.getRecipients().clear(); + } + // Message with no relation color. + event.setFormat(nonColoredMsgFormat); + } - private void doWarmup(final String warp, final FPlayer fme) { - WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); - if (player != null) { - player.teleport(fme.getFaction().getWarp(warp).getLocation()); - fme.msg(TL.COMMAND_FWARP_WARPED, warp); - } - } - }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); - } + private void doWarmup(final String warp, final FPlayer fme) { + WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { + @Override + public void run() { + Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); + if (player != null) { + player.teleport(fme.getFaction().getWarp(warp).getLocation()); + fme.msg(TL.COMMAND_FWARP_WARPED, warp); + } + } + }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java index 7ba67a2d..c54a7894 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -31,504 +31,504 @@ import java.util.*; public class FactionsEntityListener implements Listener { - private static final Set badPotionEffects = new LinkedHashSet<>(Arrays.asList(PotionEffectType.BLINDNESS, PotionEffectType.CONFUSION, PotionEffectType.HARM, PotionEffectType.HUNGER, PotionEffectType.POISON, PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.WEAKNESS, PotionEffectType.WITHER)); - - @EventHandler(priority = EventPriority.NORMAL) - public void onEntityDeath(EntityDeathEvent event) { - Entity entity = event.getEntity(); - if (!(entity instanceof Player)) { - return; - } - - Player player = (Player) entity; - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - Faction faction = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); - - PowerLossEvent powerLossEvent = new PowerLossEvent(faction, fplayer); - // Check for no power loss conditions - if (faction.isWarZone()) { - // war zones always override worldsNoPowerLoss either way, thus this layout - if (!Conf.warZonePowerLoss) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WARZONE.toString()); - powerLossEvent.setCancelled(true); - } - if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { - powerLossEvent.setMessage(TL.PLAYER_POWER_LOSS_WARZONE.toString()); - } - } else if (faction.isWilderness() && !Conf.wildernessPowerLoss && !Conf.worldsNoWildernessProtection.contains(player.getWorld().getName())) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WILDERNESS.toString()); - powerLossEvent.setCancelled(true); - } else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WORLD.toString()); - powerLossEvent.setCancelled(true); - } else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful()) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_PEACEFUL.toString()); - powerLossEvent.setCancelled(true); - } else { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOW.toString()); - } - - // call Event - Bukkit.getPluginManager().callEvent(powerLossEvent); - - // Call player onDeath if the event is not cancelled - if (!powerLossEvent.isCancelled()) { - fplayer.onDeath(); - } - // Send the message from the powerLossEvent - final String msg = powerLossEvent.getMessage(); - if (msg != null && !msg.isEmpty()) { - fplayer.msg(msg, fplayer.getPowerRounded(), fplayer.getPowerMaxRounded()); - } - } - - /** - * Who can I hurt? I can never hurt members or allies. I can always hurt enemies. I can hurt neutrals as long as - * they are outside their own territory. - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityDamage(EntityDamageEvent event) { - if (event instanceof EntityDamageByEntityEvent) { - EntityDamageByEntityEvent sub = (EntityDamageByEntityEvent) event; - if (!this.canDamagerHurtDamagee(sub, true)) { - event.setCancelled(true); - } - // event is not cancelled by factions - - Entity damagee = sub.getEntity(); - Entity damager = sub.getDamager(); - if (damagee instanceof Player) { - if (damager instanceof Player) { - FPlayer fdamager = FPlayers.getInstance().getByPlayer((Player) damager); - FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); - if ((fdamagee.getRelationTo(fdamager) == Relation.ALLY) || - (fdamagee.getRelationTo(fdamager) == Relation.TRUCE) || - (fdamagee.getFaction() == fdamager.getFaction())) { - return; - } - } else { - - // this triggers if damagee is a player and damager is mob ( so like if a skeleton hits u ) - if (damager instanceof Projectile) { - // this will trigger if the damager is a projectile - if (((Projectile) damager).getShooter() instanceof Player) { - Player damagerPlayer = (Player) ((Projectile) damager).getShooter(); - FPlayer fdamager = FPlayers.getInstance().getByPlayer(damagerPlayer); - FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); - Relation relation = fdamager.getRelationTo(fdamagee); - if (relation == Relation.ALLY || relation == Relation.TRUCE || - fdamager.getFaction() == fdamagee.getFaction()) { - // this should disable the fly so - return; - } - } else { - // this should trigger if the attacker shootin the arrow is a mob - return; - } - - } - } - } else { - // Protect armor stands/item frames from being damaged in protected territories - if (damagee.getType() == EntityType.ITEM_FRAME || damagee.getType() == EntityType.ARMOR_STAND) { - // Manage projectiles launched by players - if (damager instanceof Projectile && ((Projectile) damager).getShooter() instanceof Entity) { - damager = (Entity) ((Projectile) damager).getShooter(); - } - - // Run the check for a player - if (damager instanceof Player) { - // Generate the action message. - String entityAction; - - if (damagee.getType() == EntityType.ITEM_FRAME) { - entityAction = "item frames"; - } else { - entityAction = "armor stands"; - } - - if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) damager, damagee.getLocation(), "destroy " + entityAction, false)) { - event.setCancelled(true); - } - } else { - // we don't want to let mobs/arrows destroy item frames/armor stands - // so we only have to run the check as if there had been an explosion at the damager location - if (!this.checkExplosionForBlock(damager, damagee.getLocation().getBlock())) { - event.setCancelled(true); - } - } - - // we don't need to go after - return; - } - - //this one should trigger if something other than a player takes damage - if (damager instanceof Player) { - // now itll only go here if the damage is dealt by a player - return; - // we cancel it so fly isnt removed when you hit a mob etc - } - } - if (damagee != null && damagee instanceof Player) { - cancelFStuckTeleport((Player) damagee); - cancelFFly((Player) damagee); - FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damagee); - if (fplayer.isInspectMode()) { - fplayer.setInspectMode(false); - fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); - } - } - if (damager instanceof Player) { - cancelFStuckTeleport((Player) damager); - cancelFFly((Player) damager); - FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damager); - if (fplayer.isInspectMode()) { - fplayer.setInspectMode(false); - fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); - } - } - } else if (Conf.safeZonePreventAllDamageToPlayers && isPlayerInSafeZone(event.getEntity())) { - // Players can not take any damage in a Safe Zone - event.setCancelled(true); - } else if (event.getCause() == EntityDamageEvent.DamageCause.FALL && event.getEntity() instanceof Player) { - Player player = (Player) event.getEntity(); - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer != null && !fPlayer.shouldTakeFallDamage()) { - event.setCancelled(true); // Falling after /f fly - } - } - - // entity took generic damage? - Entity entity = event.getEntity(); - if (entity instanceof Player) { - Player player = (Player) entity; - FPlayer me = FPlayers.getInstance().getByPlayer(player); - cancelFStuckTeleport(player); - if (me.isWarmingUp()) { - me.clearWarmup(); - me.msg(TL.WARMUPS_CANCELLED); - } - } - } - - private void cancelFFly(Player player) { - if (player == null) { - return; - } - - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer.isFlying()) { - fPlayer.setFFlying(false, true); - } - } - - public void cancelFStuckTeleport(Player player) { - if (player == null) { - return; - } - UUID uuid = player.getUniqueId(); - if (SavageFactions.plugin.getStuckMap().containsKey(uuid)) { - FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_STUCK_CANCELLED); - SavageFactions.plugin.getStuckMap().remove(uuid); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityExplode(EntityExplodeEvent event) { - Entity boomer = event.getEntity(); - - // Before we need to check the location where the block is placed - if (!this.checkExplosionForBlock(boomer, event.getLocation().getBlock())) { - event.setCancelled(true); - return; - } - - // Loop the blocklist to run checks on each aimed block - Iterator blockList = event.blockList().iterator(); - - while (blockList.hasNext()) { - Block block = blockList.next(); - - if (!this.checkExplosionForBlock(boomer, block)) { - // The block don't have to explode - blockList.remove(); - } - } - - // Cancel the event if no block will explode - if (event.blockList().isEmpty()) { - event.setCancelled(true); - - // Or handle the exploit of TNT in water/lava - } else if ((boomer instanceof TNTPrimed || boomer instanceof ExplosiveMinecart) && Conf.handleExploitTNTWaterlog) { - // TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior, but... - // this change below provides workaround for waterwalling providing perfect protection, - // and makes cheap (non-obsidian) TNT cannons require minor maintenance between shots - Block center = event.getLocation().getBlock(); - - if (center.isLiquid()) { - // a single surrounding block in all 6 directions is broken if the material is weak enough - List targets = new ArrayList<>(); - targets.add(center.getRelative(0, 0, 1)); - targets.add(center.getRelative(0, 0, -1)); - targets.add(center.getRelative(0, 1, 0)); - targets.add(center.getRelative(0, -1, 0)); - targets.add(center.getRelative(1, 0, 0)); - targets.add(center.getRelative(-1, 0, 0)); - - for (Block target : targets) { - @SuppressWarnings("deprecation") - int id = target.getType().getId(); - // ignore air, bedrock, water, lava, obsidian, enchanting table, etc.... too bad we can't get a blast resistance value through Bukkit yet - if (id != 0 && (id < 7 || id > 11) && id != 49 && id != 90 && id != 116 && id != 119 && id != 120 && id != 130) { - target.breakNaturally(); - } - } - } - } - } - - private boolean checkExplosionForBlock(Entity boomer, Block block) { - Faction faction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); - - if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) { - // faction is peaceful and has explosions set to disabled - return false; - } - - boolean online = faction.hasPlayersOnline(); - - if (boomer instanceof Creeper && ((faction.isWilderness() && Conf.wildernessBlockCreepers && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || - (faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline)) || - (faction.isWarZone() && Conf.warZoneBlockCreepers) || - faction.isSafeZone())) { - // creeper which needs prevention - return false; - } else if ( - // it's a bit crude just using fireball protection for Wither boss too, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever - (boomer instanceof Fireball || boomer instanceof WitherSkull || boomer instanceof Wither) && ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || - (faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || - (faction.isWarZone() && Conf.warZoneBlockFireballs) || - faction.isSafeZone())) { - // ghast fireball which needs prevention - return false; - } else - return (!(boomer instanceof TNTPrimed) && !(boomer instanceof ExplosiveMinecart)) || ((!faction.isWilderness() || !Conf.wildernessBlockTNT || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) && - (!faction.isNormal() || (online ? !Conf.territoryBlockTNT : !Conf.territoryBlockTNTWhenOffline)) && - (!faction.isWarZone() || !Conf.warZoneBlockTNT) && - (!faction.isSafeZone() || !Conf.safeZoneBlockTNT)); - - // No condition retained, destroy the block! - } - - // mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { - EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0d); - if (!this.canDamagerHurtDamagee(sub, false)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPotionSplashEvent(PotionSplashEvent event) { - // see if the potion has a harmful effect - boolean badjuju = false; - for (PotionEffect effect : event.getPotion().getEffects()) { - if (badPotionEffects.contains(effect.getType())) { - badjuju = true; - break; - } - } - if (!badjuju) { - return; - } - - ProjectileSource thrower = event.getPotion().getShooter(); - if (!(thrower instanceof Entity)) { - return; - } - - if (thrower instanceof Player) { - Player player = (Player) thrower; - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (badjuju && fPlayer.getFaction().isPeaceful()) { - event.setCancelled(true); - return; - } - } - - // scan through affected entities to make sure they're all valid targets - for (LivingEntity target : event.getAffectedEntities()) { - EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent((Entity) thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0); - if (!this.canDamagerHurtDamagee(sub, true)) { - event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works - } - } - } - - public boolean isPlayerInSafeZone(Entity damagee) { - if (!(damagee instanceof Player)) { - return false; - } - return Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone(); - } - - public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub) { - return canDamagerHurtDamagee(sub, true); - } - - public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub, boolean notify) { - Entity damager = sub.getDamager(); - Entity damagee = sub.getEntity(); - - if (!(damagee instanceof Player)) { - return true; - } - - FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee); - - if (defender == null || defender.getPlayer() == null) { - return true; - } - - Location defenderLoc = defender.getPlayer().getLocation(); - Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc)); - - // for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source - if (damager instanceof Projectile) { - Projectile projectile = (Projectile) damager; - - if (!(projectile.getShooter() instanceof Entity)) { - return true; - } - - damager = (Entity) projectile.getShooter(); - } - - if (damager == damagee) // ender pearl usage and other self-inflicted damage - { - return true; - } - - // Players can not take attack damage in a SafeZone, or possibly peaceful territory - if (defLocFaction.noPvPInTerritory()) { - if (damager instanceof Player) { - if (notify) { - FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); - attacker.msg(TL.PLAYER_CANTHURT, (defLocFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); - } - return false; - } - return !defLocFaction.noMonstersInTerritory(); - } - - if (!(damager instanceof Player)) { - return true; - } - - FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); - - if (attacker == null || attacker.getPlayer() == null) { - return true; - } - - if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) { - return true; - } - - if (attacker.hasLoginPvpDisabled()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_LOGIN, Conf.noPVPDamageToOthersForXSecondsAfterLogin); - } - return false; - } - - Faction locFaction = Board.getInstance().getFactionAt(new FLocation(attacker)); - - // so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be? - if (locFaction.noPvPInTerritory()) { - if (notify) { - attacker.msg(TL.PLAYER_CANTHURT, (locFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); - } - return false; - } - - if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) { - return true; - } - - if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) { - return true; - } - - Faction defendFaction = defender.getFaction(); - Faction attackFaction = attacker.getFaction(); - - if (attackFaction.isWilderness() && Conf.disablePVPForFactionlessPlayers) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_REQUIREFACTION); - } - return false; - } else if (defendFaction.isWilderness()) { - if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand) { - // Allow PVP vs. Factionless in attacker's faction territory - return true; - } else if (Conf.disablePVPForFactionlessPlayers) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_FACTIONLESS); - } - return false; - } - } - - if (defendFaction.isPeaceful()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_PEACEFUL); - } - return false; - } else if (attackFaction.isPeaceful()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_PEACEFUL); - } - return false; - } - - Relation relation = defendFaction.getRelationTo(attackFaction); - - // You can not hurt neutral factions - if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_NEUTRAL); - } - return false; - } - - // Players without faction may be hurt anywhere - if (!defender.hasFaction()) { - return true; - } - - // You can never hurt faction members or allies - if (relation.isMember() || relation.isAlly()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_CANTHURT, defender.describeTo(attacker)); - } - return false; - } - - boolean ownTerritory = defender.isInOwnTerritory(); - - // You can not hurt neutrals in their own territory. - if (ownTerritory && relation.isNeutral()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_NEUTRALFAIL, defender.describeTo(attacker)); - defender.msg(TL.PLAYER_PVP_TRIED, attacker.describeTo(defender, true)); - } - return false; - } - - // Damage will be dealt. However check if the damage should be reduced. + private static final Set badPotionEffects = new LinkedHashSet<>(Arrays.asList(PotionEffectType.BLINDNESS, PotionEffectType.CONFUSION, PotionEffectType.HARM, PotionEffectType.HUNGER, PotionEffectType.POISON, PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.WEAKNESS, PotionEffectType.WITHER)); + + @EventHandler(priority = EventPriority.NORMAL) + public void onEntityDeath(EntityDeathEvent event) { + Entity entity = event.getEntity(); + if (!(entity instanceof Player)) { + return; + } + + Player player = (Player) entity; + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + Faction faction = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); + + PowerLossEvent powerLossEvent = new PowerLossEvent(faction, fplayer); + // Check for no power loss conditions + if (faction.isWarZone()) { + // war zones always override worldsNoPowerLoss either way, thus this layout + if (!Conf.warZonePowerLoss) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WARZONE.toString()); + powerLossEvent.setCancelled(true); + } + if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { + powerLossEvent.setMessage(TL.PLAYER_POWER_LOSS_WARZONE.toString()); + } + } else if (faction.isWilderness() && !Conf.wildernessPowerLoss && !Conf.worldsNoWildernessProtection.contains(player.getWorld().getName())) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WILDERNESS.toString()); + powerLossEvent.setCancelled(true); + } else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WORLD.toString()); + powerLossEvent.setCancelled(true); + } else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful()) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_PEACEFUL.toString()); + powerLossEvent.setCancelled(true); + } else { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOW.toString()); + } + + // call Event + Bukkit.getPluginManager().callEvent(powerLossEvent); + + // Call player onDeath if the event is not cancelled + if (!powerLossEvent.isCancelled()) { + fplayer.onDeath(); + } + // Send the message from the powerLossEvent + final String msg = powerLossEvent.getMessage(); + if (msg != null && !msg.isEmpty()) { + fplayer.msg(msg, fplayer.getPowerRounded(), fplayer.getPowerMaxRounded()); + } + } + + /** + * Who can I hurt? I can never hurt members or allies. I can always hurt enemies. I can hurt neutrals as long as + * they are outside their own territory. + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityDamage(EntityDamageEvent event) { + if (event instanceof EntityDamageByEntityEvent) { + EntityDamageByEntityEvent sub = (EntityDamageByEntityEvent) event; + if (!this.canDamagerHurtDamagee(sub, true)) { + event.setCancelled(true); + } + // event is not cancelled by factions + + Entity damagee = sub.getEntity(); + Entity damager = sub.getDamager(); + if (damagee instanceof Player) { + if (damager instanceof Player) { + FPlayer fdamager = FPlayers.getInstance().getByPlayer((Player) damager); + FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); + if ((fdamagee.getRelationTo(fdamager) == Relation.ALLY) || + (fdamagee.getRelationTo(fdamager) == Relation.TRUCE) || + (fdamagee.getFaction() == fdamager.getFaction())) { + return; + } + } else { + + // this triggers if damagee is a player and damager is mob ( so like if a skeleton hits u ) + if (damager instanceof Projectile) { + // this will trigger if the damager is a projectile + if (((Projectile) damager).getShooter() instanceof Player) { + Player damagerPlayer = (Player) ((Projectile) damager).getShooter(); + FPlayer fdamager = FPlayers.getInstance().getByPlayer(damagerPlayer); + FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); + Relation relation = fdamager.getRelationTo(fdamagee); + if (relation == Relation.ALLY || relation == Relation.TRUCE || + fdamager.getFaction() == fdamagee.getFaction()) { + // this should disable the fly so + return; + } + } else { + // this should trigger if the attacker shootin the arrow is a mob + return; + } + + } + } + } else { + // Protect armor stands/item frames from being damaged in protected territories + if (damagee.getType() == EntityType.ITEM_FRAME || damagee.getType() == EntityType.ARMOR_STAND) { + // Manage projectiles launched by players + if (damager instanceof Projectile && ((Projectile) damager).getShooter() instanceof Entity) { + damager = (Entity) ((Projectile) damager).getShooter(); + } + + // Run the check for a player + if (damager instanceof Player) { + // Generate the action message. + String entityAction; + + if (damagee.getType() == EntityType.ITEM_FRAME) { + entityAction = "item frames"; + } else { + entityAction = "armor stands"; + } + + if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) damager, damagee.getLocation(), "destroy " + entityAction, false)) { + event.setCancelled(true); + } + } else { + // we don't want to let mobs/arrows destroy item frames/armor stands + // so we only have to run the check as if there had been an explosion at the damager location + if (!this.checkExplosionForBlock(damager, damagee.getLocation().getBlock())) { + event.setCancelled(true); + } + } + + // we don't need to go after + return; + } + + //this one should trigger if something other than a player takes damage + if (damager instanceof Player) { + // now itll only go here if the damage is dealt by a player + return; + // we cancel it so fly isnt removed when you hit a mob etc + } + } + if (damagee != null && damagee instanceof Player) { + cancelFStuckTeleport((Player) damagee); + cancelFFly((Player) damagee); + FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damagee); + if (fplayer.isInspectMode()) { + fplayer.setInspectMode(false); + fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); + } + } + if (damager instanceof Player) { + cancelFStuckTeleport((Player) damager); + cancelFFly((Player) damager); + FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damager); + if (fplayer.isInspectMode()) { + fplayer.setInspectMode(false); + fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); + } + } + } else if (Conf.safeZonePreventAllDamageToPlayers && isPlayerInSafeZone(event.getEntity())) { + // Players can not take any damage in a Safe Zone + event.setCancelled(true); + } else if (event.getCause() == EntityDamageEvent.DamageCause.FALL && event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer != null && !fPlayer.shouldTakeFallDamage()) { + event.setCancelled(true); // Falling after /f fly + } + } + + // entity took generic damage? + Entity entity = event.getEntity(); + if (entity instanceof Player) { + Player player = (Player) entity; + FPlayer me = FPlayers.getInstance().getByPlayer(player); + cancelFStuckTeleport(player); + if (me.isWarmingUp()) { + me.clearWarmup(); + me.msg(TL.WARMUPS_CANCELLED); + } + } + } + + private void cancelFFly(Player player) { + if (player == null) { + return; + } + + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer.isFlying()) { + fPlayer.setFFlying(false, true); + } + } + + public void cancelFStuckTeleport(Player player) { + if (player == null) { + return; + } + UUID uuid = player.getUniqueId(); + if (SavageFactions.plugin.getStuckMap().containsKey(uuid)) { + FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_STUCK_CANCELLED); + SavageFactions.plugin.getStuckMap().remove(uuid); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityExplode(EntityExplodeEvent event) { + Entity boomer = event.getEntity(); + + // Before we need to check the location where the block is placed + if (!this.checkExplosionForBlock(boomer, event.getLocation().getBlock())) { + event.setCancelled(true); + return; + } + + // Loop the blocklist to run checks on each aimed block + Iterator blockList = event.blockList().iterator(); + + while (blockList.hasNext()) { + Block block = blockList.next(); + + if (!this.checkExplosionForBlock(boomer, block)) { + // The block don't have to explode + blockList.remove(); + } + } + + // Cancel the event if no block will explode + if (event.blockList().isEmpty()) { + event.setCancelled(true); + + // Or handle the exploit of TNT in water/lava + } else if ((boomer instanceof TNTPrimed || boomer instanceof ExplosiveMinecart) && Conf.handleExploitTNTWaterlog) { + // TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior, but... + // this change below provides workaround for waterwalling providing perfect protection, + // and makes cheap (non-obsidian) TNT cannons require minor maintenance between shots + Block center = event.getLocation().getBlock(); + + if (center.isLiquid()) { + // a single surrounding block in all 6 directions is broken if the material is weak enough + List targets = new ArrayList<>(); + targets.add(center.getRelative(0, 0, 1)); + targets.add(center.getRelative(0, 0, -1)); + targets.add(center.getRelative(0, 1, 0)); + targets.add(center.getRelative(0, -1, 0)); + targets.add(center.getRelative(1, 0, 0)); + targets.add(center.getRelative(-1, 0, 0)); + + for (Block target : targets) { + @SuppressWarnings("deprecation") + int id = target.getType().getId(); + // ignore air, bedrock, water, lava, obsidian, enchanting table, etc.... too bad we can't get a blast resistance value through Bukkit yet + if (id != 0 && (id < 7 || id > 11) && id != 49 && id != 90 && id != 116 && id != 119 && id != 120 && id != 130) { + target.breakNaturally(); + } + } + } + } + } + + private boolean checkExplosionForBlock(Entity boomer, Block block) { + Faction faction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); + + if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) { + // faction is peaceful and has explosions set to disabled + return false; + } + + boolean online = faction.hasPlayersOnline(); + + if (boomer instanceof Creeper && ((faction.isWilderness() && Conf.wildernessBlockCreepers && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || + (faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline)) || + (faction.isWarZone() && Conf.warZoneBlockCreepers) || + faction.isSafeZone())) { + // creeper which needs prevention + return false; + } else if ( + // it's a bit crude just using fireball protection for Wither boss too, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever + (boomer instanceof Fireball || boomer instanceof WitherSkull || boomer instanceof Wither) && ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || + (faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || + (faction.isWarZone() && Conf.warZoneBlockFireballs) || + faction.isSafeZone())) { + // ghast fireball which needs prevention + return false; + } else + return (!(boomer instanceof TNTPrimed) && !(boomer instanceof ExplosiveMinecart)) || ((!faction.isWilderness() || !Conf.wildernessBlockTNT || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) && + (!faction.isNormal() || (online ? !Conf.territoryBlockTNT : !Conf.territoryBlockTNTWhenOffline)) && + (!faction.isWarZone() || !Conf.warZoneBlockTNT) && + (!faction.isSafeZone() || !Conf.safeZoneBlockTNT)); + + // No condition retained, destroy the block! + } + + // mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { + EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0d); + if (!this.canDamagerHurtDamagee(sub, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPotionSplashEvent(PotionSplashEvent event) { + // see if the potion has a harmful effect + boolean badjuju = false; + for (PotionEffect effect : event.getPotion().getEffects()) { + if (badPotionEffects.contains(effect.getType())) { + badjuju = true; + break; + } + } + if (!badjuju) { + return; + } + + ProjectileSource thrower = event.getPotion().getShooter(); + if (!(thrower instanceof Entity)) { + return; + } + + if (thrower instanceof Player) { + Player player = (Player) thrower; + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (badjuju && fPlayer.getFaction().isPeaceful()) { + event.setCancelled(true); + return; + } + } + + // scan through affected entities to make sure they're all valid targets + for (LivingEntity target : event.getAffectedEntities()) { + EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent((Entity) thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0); + if (!this.canDamagerHurtDamagee(sub, true)) { + event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works + } + } + } + + public boolean isPlayerInSafeZone(Entity damagee) { + if (!(damagee instanceof Player)) { + return false; + } + return Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone(); + } + + public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub) { + return canDamagerHurtDamagee(sub, true); + } + + public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub, boolean notify) { + Entity damager = sub.getDamager(); + Entity damagee = sub.getEntity(); + + if (!(damagee instanceof Player)) { + return true; + } + + FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee); + + if (defender == null || defender.getPlayer() == null) { + return true; + } + + Location defenderLoc = defender.getPlayer().getLocation(); + Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc)); + + // for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source + if (damager instanceof Projectile) { + Projectile projectile = (Projectile) damager; + + if (!(projectile.getShooter() instanceof Entity)) { + return true; + } + + damager = (Entity) projectile.getShooter(); + } + + if (damager == damagee) // ender pearl usage and other self-inflicted damage + { + return true; + } + + // Players can not take attack damage in a SafeZone, or possibly peaceful territory + if (defLocFaction.noPvPInTerritory()) { + if (damager instanceof Player) { + if (notify) { + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); + attacker.msg(TL.PLAYER_CANTHURT, (defLocFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); + } + return false; + } + return !defLocFaction.noMonstersInTerritory(); + } + + if (!(damager instanceof Player)) { + return true; + } + + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); + + if (attacker == null || attacker.getPlayer() == null) { + return true; + } + + if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) { + return true; + } + + if (attacker.hasLoginPvpDisabled()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_LOGIN, Conf.noPVPDamageToOthersForXSecondsAfterLogin); + } + return false; + } + + Faction locFaction = Board.getInstance().getFactionAt(new FLocation(attacker)); + + // so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be? + if (locFaction.noPvPInTerritory()) { + if (notify) { + attacker.msg(TL.PLAYER_CANTHURT, (locFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); + } + return false; + } + + if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) { + return true; + } + + if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) { + return true; + } + + Faction defendFaction = defender.getFaction(); + Faction attackFaction = attacker.getFaction(); + + if (attackFaction.isWilderness() && Conf.disablePVPForFactionlessPlayers) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_REQUIREFACTION); + } + return false; + } else if (defendFaction.isWilderness()) { + if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand) { + // Allow PVP vs. Factionless in attacker's faction territory + return true; + } else if (Conf.disablePVPForFactionlessPlayers) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_FACTIONLESS); + } + return false; + } + } + + if (defendFaction.isPeaceful()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_PEACEFUL); + } + return false; + } else if (attackFaction.isPeaceful()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_PEACEFUL); + } + return false; + } + + Relation relation = defendFaction.getRelationTo(attackFaction); + + // You can not hurt neutral factions + if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_NEUTRAL); + } + return false; + } + + // Players without faction may be hurt anywhere + if (!defender.hasFaction()) { + return true; + } + + // You can never hurt faction members or allies + if (relation.isMember() || relation.isAlly()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_CANTHURT, defender.describeTo(attacker)); + } + return false; + } + + boolean ownTerritory = defender.isInOwnTerritory(); + + // You can not hurt neutrals in their own territory. + if (ownTerritory && relation.isNeutral()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_NEUTRALFAIL, defender.describeTo(attacker)); + defender.msg(TL.PLAYER_PVP_TRIED, attacker.describeTo(defender, true)); + } + return false; + } + + // Damage will be dealt. However check if the damage should be reduced. /* if (damage > 0.0 && ownTerritory && Conf.territoryShieldFactor > 0) { double newDamage = Math.ceil(damage * (1D - Conf.territoryShieldFactor)); @@ -541,236 +541,236 @@ public class FactionsEntityListener implements Listener { } } */ - return true; - } + return true; + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onCreatureSpawn(CreatureSpawnEvent event) { - if (event.getLocation() == null) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onCreatureSpawn(CreatureSpawnEvent event) { + if (event.getLocation() == null) { + return; + } - if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { - event.setCancelled(true); - } - } + if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityTarget(EntityTargetEvent event) { - // if there is a target - Entity target = event.getTarget(); - if (target == null) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityTarget(EntityTargetEvent event) { + // if there is a target + Entity target = event.getTarget(); + if (target == null) { + return; + } - // We are interested in blocking targeting for certain mobs: - if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) { - return; - } + // We are interested in blocking targeting for certain mobs: + if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) { + return; + } - // in case the target is in a safe zone. - if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { - event.setCancelled(true); - } - } + // in case the target is in a safe zone. + if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPaintingBreak(HangingBreakEvent event) { - if (event.getCause() == RemoveCause.EXPLOSION) { - Location loc = event.getEntity().getLocation(); - Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); - if (faction.noExplosionsInTerritory()) { - // faction is peaceful and has explosions set to disabled - event.setCancelled(true); - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPaintingBreak(HangingBreakEvent event) { + if (event.getCause() == RemoveCause.EXPLOSION) { + Location loc = event.getEntity().getLocation(); + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); + if (faction.noExplosionsInTerritory()) { + // faction is peaceful and has explosions set to disabled + event.setCancelled(true); + return; + } - boolean online = faction.hasPlayersOnline(); + boolean online = faction.hasPlayersOnline(); - if ((faction.isWilderness() && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()) && (Conf.wildernessBlockCreepers || Conf.wildernessBlockFireballs || Conf.wildernessBlockTNT)) || - (faction.isNormal() && (online ? (Conf.territoryBlockCreepers || Conf.territoryBlockFireballs || Conf.territoryBlockTNT) : (Conf.territoryBlockCreepersWhenOffline || Conf.territoryBlockFireballsWhenOffline || Conf.territoryBlockTNTWhenOffline))) || - (faction.isWarZone() && (Conf.warZoneBlockCreepers || Conf.warZoneBlockFireballs || Conf.warZoneBlockTNT)) || - faction.isSafeZone()) { - // explosion which needs prevention - event.setCancelled(true); - } - } + if ((faction.isWilderness() && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()) && (Conf.wildernessBlockCreepers || Conf.wildernessBlockFireballs || Conf.wildernessBlockTNT)) || + (faction.isNormal() && (online ? (Conf.territoryBlockCreepers || Conf.territoryBlockFireballs || Conf.territoryBlockTNT) : (Conf.territoryBlockCreepersWhenOffline || Conf.territoryBlockFireballsWhenOffline || Conf.territoryBlockTNTWhenOffline))) || + (faction.isWarZone() && (Conf.warZoneBlockCreepers || Conf.warZoneBlockFireballs || Conf.warZoneBlockTNT)) || + faction.isSafeZone()) { + // explosion which needs prevention + event.setCancelled(true); + } + } - if (!(event instanceof HangingBreakByEntityEvent)) { - return; - } + if (!(event instanceof HangingBreakByEntityEvent)) { + return; + } - Entity breaker = ((HangingBreakByEntityEvent) event).getRemover(); - if (!(breaker instanceof Player)) { - return; - } + Entity breaker = ((HangingBreakByEntityEvent) event).getRemover(); + if (!(breaker instanceof Player)) { + return; + } - if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) breaker, event.getEntity().getLocation(), "remove paintings", false)) { - event.setCancelled(true); - } - } + if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) breaker, event.getEntity().getLocation(), "remove paintings", false)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPaintingPlace(HangingPlaceEvent event) { - if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "place paintings", false)) { - event.setCancelled(true); - // Fix: update player's inventory to avoid items glitches - event.getPlayer().updateInventory(); - } - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPaintingPlace(HangingPlaceEvent event) { + if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "place paintings", false)) { + event.setCancelled(true); + // Fix: update player's inventory to avoid items glitches + event.getPlayer().updateInventory(); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityChangeBlock(EntityChangeBlockEvent event) { - Entity entity = event.getEntity(); + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + Entity entity = event.getEntity(); - // for now, only interested in Enderman and Wither boss tomfoolery - if (!(entity instanceof Enderman) && !(entity instanceof Wither)) { - return; - } + // for now, only interested in Enderman and Wither boss tomfoolery + if (!(entity instanceof Enderman) && !(entity instanceof Wither)) { + return; + } - Location loc = event.getBlock().getLocation(); + Location loc = event.getBlock().getLocation(); - if (entity instanceof Enderman) { - if (stopEndermanBlockManipulation(loc)) { - event.setCancelled(true); - } - } else if (entity instanceof Wither) { - Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); - // it's a bit crude just using fireball protection, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever - if ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName())) || - (faction.isNormal() && (faction.hasPlayersOnline() ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || - (faction.isWarZone() && Conf.warZoneBlockFireballs) || - faction.isSafeZone()) { - event.setCancelled(true); - } - } - } + if (entity instanceof Enderman) { + if (stopEndermanBlockManipulation(loc)) { + event.setCancelled(true); + } + } else if (entity instanceof Wither) { + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); + // it's a bit crude just using fireball protection, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever + if ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName())) || + (faction.isNormal() && (faction.hasPlayersOnline() ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || + (faction.isWarZone() && Conf.warZoneBlockFireballs) || + faction.isSafeZone()) { + event.setCancelled(true); + } + } + } - @EventHandler - public void onTravel(PlayerPortalEvent event) { - if (!SavageFactions.plugin.getConfig().getBoolean("portals.limit", false)) { - return; // Don't do anything if they don't want us to. - } + @EventHandler + public void onTravel(PlayerPortalEvent event) { + if (!SavageFactions.plugin.getConfig().getBoolean("portals.limit", false)) { + return; // Don't do anything if they don't want us to. + } - TravelAgent agent = event.getPortalTravelAgent(); + TravelAgent agent = event.getPortalTravelAgent(); - // If they aren't able to find a portal, it'll try to create one. - if (event.useTravelAgent() && agent.getCanCreatePortal() && agent.findPortal(event.getTo()) == null) { - FLocation loc = new FLocation(event.getTo()); - Faction faction = Board.getInstance().getFactionAt(loc); - if (faction.isWilderness()) { - return; // We don't care about wilderness. - } else if (!faction.isNormal() && !event.getPlayer().isOp()) { - // Don't let non ops make portals in safezone or warzone. - event.setCancelled(true); - return; - } + // If they aren't able to find a portal, it'll try to create one. + if (event.useTravelAgent() && agent.getCanCreatePortal() && agent.findPortal(event.getTo()) == null) { + FLocation loc = new FLocation(event.getTo()); + Faction faction = Board.getInstance().getFactionAt(loc); + if (faction.isWilderness()) { + return; // We don't care about wilderness. + } else if (!faction.isNormal() && !event.getPlayer().isOp()) { + // Don't let non ops make portals in safezone or warzone. + event.setCancelled(true); + return; + } - FPlayer fp = FPlayers.getInstance().getByPlayer(event.getPlayer()); - String mininumRelation = SavageFactions.plugin.getConfig().getString("portals.minimum-relation", "MEMBER"); // Defaults to Neutral if typed wrong. - if (!fp.getFaction().getRelationTo(faction).isAtLeast(Relation.fromString(mininumRelation))) { - event.setCancelled(true); - } - } - } + FPlayer fp = FPlayers.getInstance().getByPlayer(event.getPlayer()); + String mininumRelation = SavageFactions.plugin.getConfig().getString("portals.minimum-relation", "MEMBER"); // Defaults to Neutral if typed wrong. + if (!fp.getFaction().getRelationTo(faction).isAtLeast(Relation.fromString(mininumRelation))) { + event.setCancelled(true); + } + } + } - @EventHandler - public void onHit(EntityDamageByEntityEvent e) { - if (e.getDamager() instanceof Player) { - if (e.getEntity() instanceof Player) { - Player victim = (Player) e.getEntity(); - Player attacker = (Player) e.getDamager(); - FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); - FPlayer fattacker = FPlayers.getInstance().getByPlayer(attacker); - if (fattacker.getRelationTo(fvictim) == Relation.TRUCE) { - fattacker.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fattacker)); - e.setCancelled(true); - } - } - } - } + @EventHandler + public void onHit(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Player) { + if (e.getEntity() instanceof Player) { + Player victim = (Player) e.getEntity(); + Player attacker = (Player) e.getDamager(); + FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); + FPlayer fattacker = FPlayers.getInstance().getByPlayer(attacker); + if (fattacker.getRelationTo(fvictim) == Relation.TRUCE) { + fattacker.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fattacker)); + e.setCancelled(true); + } + } + } + } - @EventHandler - public void onBowHit(EntityDamageByEntityEvent e) { - if (e.getDamager() instanceof Projectile) { - if (e.getEntity() instanceof Player) { - Projectile arrow = ((Projectile) e.getDamager()); - if (arrow.getShooter() instanceof Player) { - Player damager = (Player) ((Projectile) e.getDamager()).getShooter(); - Player victim = (Player) e.getEntity(); - FPlayer fdamager = FPlayers.getInstance().getByPlayer(damager); - FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); - if (fvictim.getRelationTo(fdamager) == Relation.TRUCE) { - fdamager.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fdamager)); - e.setCancelled(true); - } - if (fvictim.getRelationTo(fdamager) == Relation.ENEMY) { - if (fvictim.isFlying()) { - fvictim.setFFlying(false, true); - } - } - } - } - } - } + @EventHandler + public void onBowHit(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Projectile) { + if (e.getEntity() instanceof Player) { + Projectile arrow = ((Projectile) e.getDamager()); + if (arrow.getShooter() instanceof Player) { + Player damager = (Player) ((Projectile) e.getDamager()).getShooter(); + Player victim = (Player) e.getEntity(); + FPlayer fdamager = FPlayers.getInstance().getByPlayer(damager); + FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); + if (fvictim.getRelationTo(fdamager) == Relation.TRUCE) { + fdamager.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fdamager)); + e.setCancelled(true); + } + if (fvictim.getRelationTo(fdamager) == Relation.ENEMY) { + if (fvictim.isFlying()) { + fvictim.setFFlying(false, true); + } + } + } + } + } + } - // For disabling interactions with item frames in another faction's territory - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - // only need to check for item frames - if (event.getRightClicked().getType() != EntityType.ITEM_FRAME) { - return; - } + // For disabling interactions with item frames in another faction's territory + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { + // only need to check for item frames + if (event.getRightClicked().getType() != EntityType.ITEM_FRAME) { + return; + } - Player player = event.getPlayer(); - Entity entity = event.getRightClicked(); + Player player = event.getPlayer(); + Entity entity = event.getRightClicked(); - if (!FactionsBlockListener.playerCanBuildDestroyBlock(player, entity.getLocation(), "use item frames", false)) { - event.setCancelled(true); - } - } + if (!FactionsBlockListener.playerCanBuildDestroyBlock(player, entity.getLocation(), "use item frames", false)) { + event.setCancelled(true); + } + } - // For disabling interactions with armor stands in another faction's territory - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { - Entity entity = event.getRightClicked(); + // For disabling interactions with armor stands in another faction's territory + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { + Entity entity = event.getRightClicked(); - // only need to check for armor stand and item frames - if (entity.getType() != EntityType.ARMOR_STAND) { - return; - } + // only need to check for armor stand and item frames + if (entity.getType() != EntityType.ARMOR_STAND) { + return; + } - if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), entity.getLocation(), "use armor stands", false)) { - event.setCancelled(true); - } - } + if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), entity.getLocation(), "use armor stands", false)) { + event.setCancelled(true); + } + } - private boolean stopEndermanBlockManipulation(Location loc) { - if (loc == null) { - return false; - } - // quick check to see if all Enderman deny options are enabled; if so, no need to check location - if (Conf.wildernessDenyEndermanBlocks && - Conf.territoryDenyEndermanBlocks && - Conf.territoryDenyEndermanBlocksWhenOffline && - Conf.safeZoneDenyEndermanBlocks && - Conf.warZoneDenyEndermanBlocks) { - return true; - } + private boolean stopEndermanBlockManipulation(Location loc) { + if (loc == null) { + return false; + } + // quick check to see if all Enderman deny options are enabled; if so, no need to check location + if (Conf.wildernessDenyEndermanBlocks && + Conf.territoryDenyEndermanBlocks && + Conf.territoryDenyEndermanBlocksWhenOffline && + Conf.safeZoneDenyEndermanBlocks && + Conf.warZoneDenyEndermanBlocks) { + return true; + } - FLocation fLoc = new FLocation(loc); - Faction claimFaction = Board.getInstance().getFactionAt(fLoc); + FLocation fLoc = new FLocation(loc); + Faction claimFaction = Board.getInstance().getFactionAt(fLoc); - if (claimFaction.isWilderness()) { - return Conf.wildernessDenyEndermanBlocks; - } else if (claimFaction.isNormal()) { - return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline; - } else if (claimFaction.isSafeZone()) { - return Conf.safeZoneDenyEndermanBlocks; - } else if (claimFaction.isWarZone()) { - return Conf.warZoneDenyEndermanBlocks; - } + if (claimFaction.isWilderness()) { + return Conf.wildernessDenyEndermanBlocks; + } else if (claimFaction.isNormal()) { + return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline; + } else if (claimFaction.isSafeZone()) { + return Conf.safeZoneDenyEndermanBlocks; + } else if (claimFaction.isWarZone()) { + return Conf.warZoneDenyEndermanBlocks; + } - return false; - } + return false; + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java index 0639d02c..f9ca6adb 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java @@ -14,52 +14,52 @@ import org.bukkit.event.player.PlayerTeleportEvent; public class FactionsExploitListener implements Listener { - public static boolean clippingThrough(Location target, Location from, double thickness) { - return ((from.getX() > target.getX() && (from.getX() - target.getX() < thickness)) || (target.getX() > from.getX() && (target.getX() - from.getX() < thickness)) || (from.getZ() > target.getZ() && (from.getZ() - target.getZ() < thickness)) || (target.getZ() > from.getZ() && (target.getZ() - from.getZ() < thickness))); - } + public static boolean clippingThrough(Location target, Location from, double thickness) { + return ((from.getX() > target.getX() && (from.getX() - target.getX() < thickness)) || (target.getX() > from.getX() && (target.getX() - from.getX() < thickness)) || (from.getZ() > target.getZ() && (from.getZ() - target.getZ() < thickness)) || (target.getZ() > from.getZ() && (target.getZ() - from.getZ() < thickness))); + } - @SuppressWarnings("deprecation") - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void obsidianGenerator(BlockFromToEvent event) { - if (!Conf.handleExploitObsidianGenerators) { - return; - } + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void obsidianGenerator(BlockFromToEvent event) { + if (!Conf.handleExploitObsidianGenerators) { + return; + } - // thanks to ObGenBlocker and WorldGuard for this method - Block block = event.getToBlock(); - int source = event.getBlock().getType().getId(); - int target = block.getType().getId(); - if ((target == 55 || target == 132) && (source == 0 || source == 10 || source == 11)) { - block.setType(Material.AIR); - } - } + // thanks to ObGenBlocker and WorldGuard for this method + Block block = event.getToBlock(); + int source = event.getBlock().getType().getId(); + int target = block.getType().getId(); + if ((target == 55 || target == 132) && (source == 0 || source == 10 || source == 11)) { + block.setType(Material.AIR); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void enderPearlTeleport(PlayerTeleportEvent event) { - if (!Conf.handleExploitEnderPearlClipping) { - return; - } - if (event.getCause() != PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void enderPearlTeleport(PlayerTeleportEvent event) { + if (!Conf.handleExploitEnderPearlClipping) { + return; + } + if (event.getCause() != PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { + return; + } - // this exploit works when the target location is within 0.31 blocks or so of a door or glass block or similar... - Location target = event.getTo(); - Location from = event.getFrom(); + // this exploit works when the target location is within 0.31 blocks or so of a door or glass block or similar... + Location target = event.getTo(); + Location from = event.getFrom(); - // blocks who occupy less than 1 block width or length wise need to be handled differently - Material mat = event.getTo().getBlock().getType(); - if (((mat == SavageFactions.plugin.THIN_GLASS - || mat == SavageFactions.plugin.IRON_FENCE) && clippingThrough(target, from, 0.65)) - || ((mat == SavageFactions.plugin.FENCE || mat == SavageFactions.plugin.NETHER_FENCE) && clippingThrough(target, from, 0.45))) { - event.setTo(from); - return; - } + // blocks who occupy less than 1 block width or length wise need to be handled differently + Material mat = event.getTo().getBlock().getType(); + if (((mat == SavageFactions.plugin.THIN_GLASS + || mat == SavageFactions.plugin.IRON_FENCE) && clippingThrough(target, from, 0.65)) + || ((mat == SavageFactions.plugin.FENCE || mat == SavageFactions.plugin.NETHER_FENCE) && clippingThrough(target, from, 0.45))) { + event.setTo(from); + return; + } - // simple fix otherwise: ender pearl target locations are standardized to be in the center (X/Z) of the target block, not at the edges - target.setX(target.getBlockX() + 0.5); - target.setZ(target.getBlockZ() + 0.5); - event.setTo(target); + // simple fix otherwise: ender pearl target locations are standardized to be in the center (X/Z) of the target block, not at the edges + target.setX(target.getBlockX() + 0.5); + target.setZ(target.getBlockZ() + 0.5); + event.setTo(target); - } + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java index 8ba1daa0..1b5b236c 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -48,856 +48,856 @@ import java.util.logging.Level; public class FactionsPlayerListener implements Listener { - HashMap fallMap = new HashMap<>(); - - // Holds the next time a player can have a map shown. - private HashMap showTimes = new HashMap<>(); - // for handling people who repeatedly spam attempts to open a door (or similar) in another faction's territory - private Map interactSpammers = new HashMap<>(); - - public FactionsPlayerListener() { - for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { - initPlayer(player); - } - } - - public static Boolean isSystemFaction(Faction faction) { - return faction.isSafeZone() || - faction.isWarZone() || - faction.isWilderness(); - } - - public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { - String name = player.getName(); - if (Conf.playersWhoBypassAllProtection.contains(name)) { - return true; - } - - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - if (me.isAdminBypassing()) { - return true; - } - - FLocation loc = new FLocation(location); - Faction otherFaction = Board.getInstance().getFactionAt(loc); - Faction myFaction = me.getFaction(); - Relation rel = myFaction.getRelationTo(otherFaction); - - // Also cancel if player doesn't have ownership rights for this claim - if (Conf.ownedAreasEnabled && myFaction == otherFaction && !myFaction.playerHasOwnershipRights(me, loc)) { - if (!justCheck) { - me.msg("You can't use that in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); - } - return false; - } - - if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) { - return true; - } - - if (otherFaction.hasPlayersOnline()) { - if (!Conf.territoryDenyUseageMaterials.contains(material)) { - return true; // Item isn't one we're preventing for online factions. - } - } else { - if (!Conf.territoryDenyUseageMaterialsWhenOffline.contains(material)) { - return true; // Item isn't one we're preventing for offline factions. - } - } - - if (otherFaction.isWilderness()) { - if (!Conf.wildernessDenyUseage || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) { - return true; // This is not faction territory. Use whatever you like here. - } - - if (!justCheck) { - me.msg(TL.PLAYER_USE_WILDERNESS, TextUtil.getMaterialName(material)); - } - - return false; - } else if (otherFaction.isSafeZone()) { - if (!Conf.safeZoneDenyUseage || Permission.MANAGE_SAFE_ZONE.has(player)) { - return true; - } - - if (!justCheck) { - me.msg(TL.PLAYER_USE_SAFEZONE, TextUtil.getMaterialName(material)); - } - - return false; - } else if (otherFaction.isWarZone()) { - if (!Conf.warZoneDenyUseage || Permission.MANAGE_WAR_ZONE.has(player)) { - return true; - } - - if (!justCheck) { - me.msg(TL.PLAYER_USE_WARZONE, TextUtil.getMaterialName(material)); - } - - return false; - } - - // Cancel if we are not in our own territory - if (rel.confDenyUseage()) { - if (!justCheck) { - me.msg(TL.PLAYER_USE_TERRITORY, TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); - } - - return false; - } - - Access access = otherFaction.getAccess(me, PermissableAction.ITEM); - if (access != null && access != Access.UNDEFINED) { - // TODO: Update this once new access values are added other than just allow / deny. - if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { - return true; - } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { - me.msg("You can't use items in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); - return false; - } else if (access == Access.DENY) { - me.msg(TL.GENERIC_NOPERMISSION, PermissableAction.ITEM); - return false; - } - } - - return true; - } - - @SuppressWarnings("deprecation") - public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { - if (Conf.playersWhoBypassAllProtection.contains(player.getName())) - return true; - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - if (me.isAdminBypassing()) - return true; - - Material material = block.getType(); - // Dupe fix. - FLocation loc = new FLocation(block); - Faction otherFaction = Board.getInstance().getFactionAt(loc); - Faction myFaction = me.getFaction(); - Relation rel = myFaction.getRelationTo(otherFaction); - - // no door/chest/whatever protection in wilderness, war zones, or safe zones - if (!otherFaction.isNormal()) - return true; - - if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) - return true; - - if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc) && player.getItemInHand().getType() != null) { - - if (player.getItemInHand().getType().toString().toUpperCase().contains("DOOR")) - return false; - } - - PermissableAction action = null; - - if (SavageFactions.plugin.mc113) { - switch (block.getType()) { - case LEVER: - action = PermissableAction.LEVER; - break; - - case ACACIA_BUTTON: - case BIRCH_BUTTON: - case DARK_OAK_BUTTON: - case JUNGLE_BUTTON: - case OAK_BUTTON: - case SPRUCE_BUTTON: - case STONE_BUTTON: - action = PermissableAction.BUTTON; - break; - - case ACACIA_DOOR: - case BIRCH_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case OAK_DOOR: - case SPRUCE_DOOR: - case DARK_OAK_DOOR: - - case ACACIA_TRAPDOOR: - case BIRCH_TRAPDOOR: - case DARK_OAK_TRAPDOOR: - case IRON_TRAPDOOR: - case JUNGLE_TRAPDOOR: - case OAK_TRAPDOOR: - case SPRUCE_TRAPDOOR: - - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case JUNGLE_FENCE_GATE: - case OAK_FENCE_GATE: - case SPRUCE_FENCE_GATE: - action = PermissableAction.DOOR; - break; - - case CHEST: - case TRAPPED_CHEST: - case CHEST_MINECART: - - case SHULKER_BOX: - case BLACK_SHULKER_BOX: - case BLUE_SHULKER_BOX: - case BROWN_SHULKER_BOX: - case CYAN_SHULKER_BOX: - case GRAY_SHULKER_BOX: - case GREEN_SHULKER_BOX: - case LIGHT_BLUE_SHULKER_BOX: - case LIGHT_GRAY_SHULKER_BOX: - case LIME_SHULKER_BOX: - case MAGENTA_SHULKER_BOX: - case ORANGE_SHULKER_BOX: - case PINK_SHULKER_BOX: - case PURPLE_SHULKER_BOX: - case RED_SHULKER_BOX: - case WHITE_SHULKER_BOX: - case YELLOW_SHULKER_BOX: - - case FURNACE: - case DROPPER: - case DISPENSER: - case ENCHANTING_TABLE: - case BREWING_STAND: - case CAULDRON: - case HOPPER: - case BEACON: - case JUKEBOX: - - case ANVIL: - case CHIPPED_ANVIL: - case DAMAGED_ANVIL: - action = PermissableAction.CONTAINER; - break; - default: - // Check for doors that might have diff material name in old version. - if (block.getType().name().contains("DOOR")) { - action = PermissableAction.DOOR; - } - break; - } - } else { - if (block.getType().toString().toUpperCase().contains("BUTTON")) { - action = PermissableAction.BUTTON; - } - - switch (block.getType()) { - case LEVER: - action = PermissableAction.LEVER; - break; - case DARK_OAK_DOOR: - case ACACIA_DOOR: - case BIRCH_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case SPRUCE_DOOR: - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case JUNGLE_FENCE_GATE: - case SPRUCE_FENCE_GATE: - action = PermissableAction.DOOR; - break; - case CHEST: - case ENDER_CHEST: - case TRAPPED_CHEST: - case DISPENSER: - case ENCHANTING_TABLE: - case DROPPER: - case FURNACE: - case HOPPER: - case ANVIL: - case CHIPPED_ANVIL: - case DAMAGED_ANVIL: - case BREWING_STAND: - action = PermissableAction.CONTAINER; - break; - default: - // Check for doors that might have diff material name in old version. - if (block.getType().name().contains("DOOR")) - action = PermissableAction.DOOR; - break; - } - } - - // We only care about some material types. - if (otherFaction.hasPlayersOnline()) { - if (!Conf.territoryProtectedMaterials.contains(material)) - return true; - } else { - if (!Conf.territoryProtectedMaterialsWhenOffline.contains(material)) - return true; - } - - // Move up access check to check for exceptions - Access access = otherFaction.getAccess(me, action); - boolean doTerritoryEnemyProtectedCheck = true; - - if (action != null && (action.equals(PermissableAction.CONTAINER) || - action.equals(PermissableAction.DOOR))) { - if (access == Access.ALLOW) { - doTerritoryEnemyProtectedCheck = false; - } - } - - // Did not nest the boolean so that it stands out when Im looking - // through the code later. - if (doTerritoryEnemyProtectedCheck) { - // You may use any block unless it is another faction's territory... - if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials) || (rel.isTruce() && Conf.territoryTruceProtectMaterials)) { - if (!justCheck) { - me.msg(TL.PLAYER_USE_TERRITORY, (material == SavageFactions.plugin.SOIL ? "trample " : "use ") + TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); - } - return false; - } - } - - if (access != Access.ALLOW && me.getRole() != Role.LEADER) { - // TODO: Update this once new access values are added other than just allow / deny. - if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { - return true; - } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { - me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); - return false; - } else if (access == Access.DENY) { - me.msg(TL.GENERIC_NOPERMISSION, action); - return false; - } - } - return true; - } - - public static boolean preventCommand(String fullCmd, Player player) { - if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty() && Conf.permanentFactionMemberDenyCommands.isEmpty() && Conf.warzoneDenyCommands.isEmpty())) { - return false; - } - - fullCmd = fullCmd.toLowerCase(); - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - - String shortCmd; // command without the slash at the beginning - if (fullCmd.startsWith("/")) { - shortCmd = fullCmd.substring(1); - } else { - shortCmd = fullCmd; - fullCmd = "/" + fullCmd; - } - - if (me.hasFaction() && - !me.isAdminBypassing() && - !Conf.permanentFactionMemberDenyCommands.isEmpty() && - me.getFaction().isPermanent() && - isCommandInList(fullCmd, shortCmd, Conf.permanentFactionMemberDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_PERMANENT, fullCmd); - return true; - } - - Faction at = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); - if (at.isWilderness() && !Conf.wildernessDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.wildernessDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_WILDERNESS, fullCmd); - return true; - } - - Relation rel = at.getRelationTo(me); - if (at.isNormal() && rel.isAlly() && !Conf.territoryAllyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryAllyDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_ALLY, fullCmd); - return false; - } - - if (at.isNormal() && rel.isNeutral() && !Conf.territoryNeutralDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryNeutralDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_NEUTRAL, fullCmd); - return true; - } - - if (at.isNormal() && rel.isEnemy() && !Conf.territoryEnemyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryEnemyDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_ENEMY, fullCmd); - return true; - } - - if (at.isWarZone() && !Conf.warzoneDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.warzoneDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_WARZONE, fullCmd); - return true; - } - - return false; - } - - private static boolean isCommandInList(String fullCmd, String shortCmd, Iterator iter) { - String cmdCheck; - while (iter.hasNext()) { - cmdCheck = iter.next(); - if (cmdCheck == null) { - iter.remove(); - continue; - } - - cmdCheck = cmdCheck.toLowerCase(); - if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck)) { - return true; - } - } - return false; - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerJoin(PlayerJoinEvent event) { - initPlayer(event.getPlayer()); - } - - private void initPlayer(Player player) { - // Make sure that all online players do have a fplayer. - final FPlayer me = FPlayers.getInstance().getByPlayer(player); - ((MemoryFPlayer) me).setName(player.getName()); - - // Update the lastLoginTime for this fplayer - me.setLastLoginTime(System.currentTimeMillis()); - - // Store player's current FLocation and notify them where they are - me.setLastStoodAt(new FLocation(player.getLocation())); - - me.login(); // set kills / deaths - - // Check for Faction announcements. Let's delay this so they actually see it. - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - if (me.isOnline()) { - me.getFaction().sendUnreadAnnouncements(me); - } - } - }, 33L); // Don't ask me why. - - if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false)) { - FScoreboard.init(me); - FScoreboard.get(me).setDefaultSidebar(new FDefaultSidebar(), SavageFactions.plugin.getConfig().getInt("scoreboard.default-update-interval", 20)); - FScoreboard.get(me).setSidebarVisibility(me.showScoreboard()); - } - - Faction myFaction = me.getFaction(); - if (!myFaction.isWilderness()) { - for (FPlayer other : myFaction.getFPlayersWhereOnline(true)) { - if (other != me && other.isMonitoringJoins()) { - other.msg(TL.FACTION_LOGIN, me.getName()); - } - } - } - - - fallMap.put(me.getPlayer(), false); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - fallMap.remove(me.getPlayer()); - - } - }, 180L); - - - if (me.isSpyingChat() && !player.hasPermission(Permission.CHATSPY.node)) { - me.setSpyingChat(false); - SavageFactions.plugin.log(Level.INFO, "Found %s spying chat without permission on login. Disabled their chat spying.", player.getName()); - } - - if (me.isAdminBypassing() && !player.hasPermission(Permission.BYPASS.node)) { - me.setIsAdminBypassing(false); - SavageFactions.plugin.log(Level.INFO, "Found %s on admin Bypass without permission on login. Disabled it for them.", player.getName()); - } - - - // If they have the permission, don't let them autoleave. Bad inverted setter :\ - me.setAutoLeave(!player.hasPermission(Permission.AUTO_LEAVE_BYPASS.node)); - me.setTakeFallDamage(true); - } - - @EventHandler - public void onPlayerFall(EntityDamageEvent e) { - if (e.getEntity() instanceof Player) { - if (e.getCause() == EntityDamageEvent.DamageCause.FALL) { - Player player = (Player) e.getEntity(); - if (fallMap.containsKey(player)) { - e.setCancelled(true); - fallMap.remove(player); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerQuit(PlayerQuitEvent event) { - FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); - - // Make sure player's power is up to date when they log off. - me.getPower(); - // and update their last login time to point to when the logged off, for auto-remove routine - me.setLastLoginTime(System.currentTimeMillis()); - - me.logout(); // cache kills / deaths - - // if player is waiting for fstuck teleport but leaves, remove - if (SavageFactions.plugin.getStuckMap().containsKey(me.getPlayer().getUniqueId())) { - FPlayers.getInstance().getByPlayer(me.getPlayer()).msg(TL.COMMAND_STUCK_CANCELLED); - SavageFactions.plugin.getStuckMap().remove(me.getPlayer().getUniqueId()); - SavageFactions.plugin.getTimers().remove(me.getPlayer().getUniqueId()); - } - - Faction myFaction = me.getFaction(); - if (!myFaction.isWilderness()) { - myFaction.memberLoggedOff(); - } - - if (!myFaction.isWilderness()) { - for (FPlayer player : myFaction.getFPlayersWhereOnline(true)) { - if (player != me && player.isMonitoringJoins()) { - player.msg(TL.FACTION_LOGOUT, me.getName()); - } - } - } - - CmdSeeChunk.seeChunkMap.remove(event.getPlayer().getName()); - - FScoreboard.remove(me); - } - - public String parseAllPlaceholders(String string, Faction faction, Player player) { - string = TagUtil.parsePlaceholders(player, string); - - string = string.replace("{Faction}", faction.getTag()) - .replace("{online}", faction.getOnlinePlayers().size() + "") - .replace("{offline}", faction.getFPlayers().size() - faction.getOnlinePlayers().size() + "") - .replace("{chunks}", faction.getAllClaims().size() + "") - .replace("{power}", faction.getPower() + "") - .replace("{leader}", faction.getFPlayerAdmin() + ""); - - return string; - } - - public void enableFly(FPlayer me) { - if (SavageFactions.plugin.getConfig().getBoolean("ffly.AutoEnable")) { - - me.setFlying(true); - CmdFly.flyMap.put(me.getName(), true); - if (CmdFly.id == -1) { - if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { - CmdFly.startParticles(); - } - } - if (CmdFly.flyid == -1) { - CmdFly.startFlyCheck(); - } - } - } - - //inspect - @EventHandler - public void onInspect(PlayerInteractEvent e) { - if (e.getAction().name().contains("BLOCK")) { - FPlayer fplayer = FPlayers.getInstance().getByPlayer(e.getPlayer()); - if (!fplayer.isInspectMode()) { - return; - } - e.setCancelled(true); - if (!fplayer.isAdminBypassing()) { - if (!fplayer.hasFaction()) { - fplayer.setInspectMode(false); - fplayer.msg(TL.COMMAND_INSPECT_DISABLED_NOFAC); - return; - } - if (fplayer.getFaction() != Board.getInstance().getFactionAt(new FLocation(e.getPlayer().getLocation()))) { - fplayer.msg(TL.COMMAND_INSPECT_NOTINCLAIM); - return; - } - } else { - fplayer.msg(TL.COMMAND_INSPECT_BYPASS); - } - List info = CoreProtect.getInstance().getAPI().blockLookup(e.getClickedBlock(), 0); - if (info.size() == 0) { - e.getPlayer().sendMessage(TL.COMMAND_INSPECT_NODATA.toString()); - return; - } - Player player = e.getPlayer(); - CoreProtectAPI coAPI = CoreProtect.getInstance().getAPI(); - player.sendMessage(TL.COMMAND_INSPECT_HEADER.toString().replace("{x}", e.getClickedBlock().getX() + "") - .replace("{y}", e.getClickedBlock().getY() + "") - .replace("{z}", e.getClickedBlock().getZ() + "")); - String rowFormat = TL.COMMAND_INSPECT_ROW.toString(); - for (int i = 0; i < info.size(); i++) { - CoreProtectAPI.ParseResult row = coAPI.parseResult(info.get(0)); - player.sendMessage(rowFormat - .replace("{time}", convertTime(row.getTime())) - .replace("{action}", row.getActionString()) - .replace("{player}", row.getPlayer()) - .replace("{block-type}", row.getType().toString().toLowerCase())); - } - } - } - - //For disabling enderpearl throws - @EventHandler - public void onPearl(PlayerInteractEvent e) { - Player player = e.getPlayer(); - if (player.getItemInHand().getType() == Material.ENDER_PEARL) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer.isFlying()) { - if (Conf.noEnderpearlsInFly) { - fPlayer.msg(TL.COMMAND_FLY_NO_EPEARL); - e.setCancelled(true); - } - } - } - } - - //For Blocking Homes and Blocking Teleportation To Homes - @EventHandler - public void onPlayerHomeCheck(PlayerTeleportEvent event) throws Exception { - if (event.getPlayer().hasMetadata("NPC")){ - return; - } - if (event.getPlayer().hasPermission("factions.homes.bypass")) { - return; - } - if (Bukkit.getPluginManager().getPlugin("Essentials") == null) { - return; - } - boolean isHome = false; - for (String str : SavageFactions.plugin.ess.getUser(event.getPlayer()).getHomes()) { - Location home = SavageFactions.plugin.ess.getUser(event.getPlayer()).getHome(str); - if (home.getBlockX() == event.getTo().getBlockX() && home.getBlockY() == event.getTo().getBlockY() && home.getBlockZ() == event.getTo().getBlockZ()) { - isHome = true; - } - } - if (!isHome) { - return; - } - Location loc = event.getTo(); - FLocation floc = new FLocation(event.getTo()); - Faction fac = Board.getInstance().getFactionAt(floc); - Player player = event.getPlayer(); - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - User user = SavageFactions.plugin.ess.getUser(event.getPlayer()); - List homes = user.getHomes(); - if (fac.isWilderness() || FPlayers.getInstance().getByPlayer(event.getPlayer()).getFactionId().equals(fac.getId())) { - return; - } - //Warzone and SafeZone Home Initializers - if (fac.isWarZone() || fac.isSafeZone() && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-system-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-system-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - - if (fplayer.getFaction().getRelationTo(fac) == Relation.ENEMY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-enemy-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-enemy-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - if (fplayer.getFaction().getRelationTo(fac) == Relation.NEUTRAL && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-neutral-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-neutral-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - if (fplayer.getFaction().getRelationTo(fac) == Relation.ALLY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-ally-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-ally-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - if (fplayer.getFaction().getRelationTo(fac) == Relation.TRUCE && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-truce-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-truce-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - } - - - //Colors a String - public String color(String s) { - return ChatColor.translateAlternateColorCodes('&', s); - } - - - private String convertTime(int time) { - String result = String.valueOf(Math.round((System.currentTimeMillis() / 1000L - time) / 36.0D) / 100.0D); - return (result.length() == 3 ? result + "0" : result) + "/hrs ago"; - } - - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); - FPlayer me = FPlayers.getInstance().getByPlayer(player); - - // clear visualization - if (event.getFrom().getBlockX() != event.getTo().getBlockX() || event.getFrom().getBlockY() != event.getTo().getBlockY() || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { - VisualizeUtil.clear(event.getPlayer()); - if (me.isWarmingUp()) { - me.clearWarmup(); - me.msg(TL.WARMUPS_CANCELLED); - } - } - - // quick check to make sure player is moving between chunks; good performance boost - if (event.getFrom().getBlockX() >> 4 == event.getTo().getBlockX() >> 4 && event.getFrom().getBlockZ() >> 4 == event.getTo().getBlockZ() >> 4 && event.getFrom().getWorld() == event.getTo().getWorld()) { - return; - } - - - // Did we change coord? - FLocation from = me.getLastStoodAt(); - FLocation to = new FLocation(event.getTo()); - - if (from.equals(to)) { - return; - } - - // Yes we did change coord (: - - me.setLastStoodAt(to); - - // Did we change "host"(faction)? - Faction factionFrom = Board.getInstance().getFactionAt(from); - Faction factionTo = Board.getInstance().getFactionAt(to); - boolean changedFaction = (factionFrom != factionTo); - - - if (changedFaction) { - Bukkit.getServer().getPluginManager().callEvent(new FPlayerEnteredFactionEvent(factionTo, factionFrom, me)); - if (SavageFactions.plugin.getConfig().getBoolean("Title.Show-Title")) { - String title = SavageFactions.plugin.getConfig().getString("Title.Format.Title"); - title = title.replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); - title = parseAllPlaceholders(title, factionTo, player); - String subTitle = SavageFactions.plugin.getConfig().getString("Title.Format.Subtitle").replace("{Description}", factionTo.getDescription()).replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); - subTitle = parseAllPlaceholders(subTitle, factionTo, player); - if (!SavageFactions.plugin.mc17) { - if (!SavageFactions.plugin.mc18) { - me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle), SavageFactions.plugin.getConfig().getInt("Title.Options.FadeInTime"), - SavageFactions.plugin.getConfig().getInt("Title.Options.ShowTime"), - SavageFactions.plugin.getConfig().getInt("Title.Options.FadeOutTime")); - } else { - me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle)); - } - - - } - - } - - if (!SavageFactions.plugin.factionsFlight) { - return; - } - - - // enable fly :) - if (me.hasFaction() && !me.isFlying()) { - if (factionTo == me.getFaction()) { - enableFly(me); - } - // bypass checks - Relation relationTo = factionTo.getRelationTo(me); - if ((factionTo.isWilderness() && me.canflyinWilderness()) || - (factionTo.isWarZone() && me.canflyinWarzone()) || - (factionTo.isSafeZone() && me.canflyinSafezone()) || - (relationTo == Relation.ENEMY && me.canflyinEnemy()) || - (relationTo == Relation.ALLY && me.canflyinAlly()) || - (relationTo == Relation.TRUCE && me.canflyinTruce()) || - (relationTo == Relation.NEUTRAL && me.canflyinNeutral() && !isSystemFaction(factionTo))) { - enableFly(me); - } - - } - } - - - if (me.isMapAutoUpdating()) { - if (showTimes.containsKey(player.getUniqueId()) && (showTimes.get(player.getUniqueId()) > System.currentTimeMillis())) { - if (SavageFactions.plugin.getConfig().getBoolean("findfactionsexploit.log", false)) { - SavageFactions.plugin.log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); - } - } else { - me.sendFancyMessage(Board.getInstance().getMap(me, to, player.getLocation().getYaw())); - showTimes.put(player.getUniqueId(), System.currentTimeMillis() + SavageFactions.plugin.getConfig().getLong("findfactionsexploit.cooldown", 2000)); - } - } else { - Faction myFaction = me.getFaction(); - String ownersTo = myFaction.getOwnerListString(to); - if (changedFaction) { - me.sendFactionHereMessage(factionFrom); - if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty()) { - me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); - } - } else if (Conf.ownedAreasEnabled && Conf.ownedMessageInsideTerritory && myFaction == factionTo && !myFaction.isWilderness()) { - String ownersFrom = myFaction.getOwnerListString(from); - if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo)) { - if (!ownersTo.isEmpty()) { - me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); - } else if (!TL.GENERIC_PUBLICLAND.toString().isEmpty()) { - me.sendMessage(TL.GENERIC_PUBLICLAND.toString()); - } - } - } - } - - if (me.getAutoClaimFor() != null) { - me.attemptClaim(me.getAutoClaimFor(), event.getTo(), true); - } else if (me.isAutoSafeClaimEnabled()) { - if (!Permission.MANAGE_SAFE_ZONE.has(player)) { - me.setIsAutoSafeClaimEnabled(false); - } else { - if (!Board.getInstance().getFactionAt(to).isSafeZone()) { - Board.getInstance().setFactionAt(Factions.getInstance().getSafeZone(), to); - me.msg(TL.PLAYER_SAFEAUTO); - } - } - } else if (me.isAutoWarClaimEnabled()) { - if (!Permission.MANAGE_WAR_ZONE.has(player)) { - me.setIsAutoWarClaimEnabled(false); - } else { - if (!Board.getInstance().getFactionAt(to).isWarZone()) { - Board.getInstance().setFactionAt(Factions.getInstance().getWarZone(), to); - me.msg(TL.PLAYER_WARAUTO); - } - } - } - } - - @EventHandler - public void onClose(InventoryCloseEvent e) { - FPlayer fme = FPlayers.getInstance().getById(e.getPlayer().getUniqueId().toString()); - if (fme.isInVault()) - fme.setInVault(false); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerInteract(PlayerInteractEvent event) { - /// Prevents the use of montster eggs in oned land. + HashMap fallMap = new HashMap<>(); + + // Holds the next time a player can have a map shown. + private HashMap showTimes = new HashMap<>(); + // for handling people who repeatedly spam attempts to open a door (or similar) in another faction's territory + private Map interactSpammers = new HashMap<>(); + + public FactionsPlayerListener() { + for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { + initPlayer(player); + } + } + + public static Boolean isSystemFaction(Faction faction) { + return faction.isSafeZone() || + faction.isWarZone() || + faction.isWilderness(); + } + + public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { + String name = player.getName(); + if (Conf.playersWhoBypassAllProtection.contains(name)) { + return true; + } + + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + if (me.isAdminBypassing()) { + return true; + } + + FLocation loc = new FLocation(location); + Faction otherFaction = Board.getInstance().getFactionAt(loc); + Faction myFaction = me.getFaction(); + Relation rel = myFaction.getRelationTo(otherFaction); + + // Also cancel if player doesn't have ownership rights for this claim + if (Conf.ownedAreasEnabled && myFaction == otherFaction && !myFaction.playerHasOwnershipRights(me, loc)) { + if (!justCheck) { + me.msg("You can't use that in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); + } + return false; + } + + if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) { + return true; + } + + if (otherFaction.hasPlayersOnline()) { + if (!Conf.territoryDenyUseageMaterials.contains(material)) { + return true; // Item isn't one we're preventing for online factions. + } + } else { + if (!Conf.territoryDenyUseageMaterialsWhenOffline.contains(material)) { + return true; // Item isn't one we're preventing for offline factions. + } + } + + if (otherFaction.isWilderness()) { + if (!Conf.wildernessDenyUseage || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) { + return true; // This is not faction territory. Use whatever you like here. + } + + if (!justCheck) { + me.msg(TL.PLAYER_USE_WILDERNESS, TextUtil.getMaterialName(material)); + } + + return false; + } else if (otherFaction.isSafeZone()) { + if (!Conf.safeZoneDenyUseage || Permission.MANAGE_SAFE_ZONE.has(player)) { + return true; + } + + if (!justCheck) { + me.msg(TL.PLAYER_USE_SAFEZONE, TextUtil.getMaterialName(material)); + } + + return false; + } else if (otherFaction.isWarZone()) { + if (!Conf.warZoneDenyUseage || Permission.MANAGE_WAR_ZONE.has(player)) { + return true; + } + + if (!justCheck) { + me.msg(TL.PLAYER_USE_WARZONE, TextUtil.getMaterialName(material)); + } + + return false; + } + + // Cancel if we are not in our own territory + if (rel.confDenyUseage()) { + if (!justCheck) { + me.msg(TL.PLAYER_USE_TERRITORY, TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); + } + + return false; + } + + Access access = otherFaction.getAccess(me, PermissableAction.ITEM); + if (access != null && access != Access.UNDEFINED) { + // TODO: Update this once new access values are added other than just allow / deny. + if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { + return true; + } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { + me.msg("You can't use items in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); + return false; + } else if (access == Access.DENY) { + me.msg(TL.GENERIC_NOPERMISSION, PermissableAction.ITEM); + return false; + } + } + + return true; + } + + @SuppressWarnings("deprecation") + public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { + if (Conf.playersWhoBypassAllProtection.contains(player.getName())) + return true; + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + if (me.isAdminBypassing()) + return true; + + Material material = block.getType(); + // Dupe fix. + FLocation loc = new FLocation(block); + Faction otherFaction = Board.getInstance().getFactionAt(loc); + Faction myFaction = me.getFaction(); + Relation rel = myFaction.getRelationTo(otherFaction); + + // no door/chest/whatever protection in wilderness, war zones, or safe zones + if (!otherFaction.isNormal()) + return true; + + if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) + return true; + + if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc) && player.getItemInHand().getType() != null) { + + if (player.getItemInHand().getType().toString().toUpperCase().contains("DOOR")) + return false; + } + + PermissableAction action = null; + + if (SavageFactions.plugin.mc113) { + switch (block.getType()) { + case LEVER: + action = PermissableAction.LEVER; + break; + + case ACACIA_BUTTON: + case BIRCH_BUTTON: + case DARK_OAK_BUTTON: + case JUNGLE_BUTTON: + case OAK_BUTTON: + case SPRUCE_BUTTON: + case STONE_BUTTON: + action = PermissableAction.BUTTON; + break; + + case ACACIA_DOOR: + case BIRCH_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case OAK_DOOR: + case SPRUCE_DOOR: + case DARK_OAK_DOOR: + + case ACACIA_TRAPDOOR: + case BIRCH_TRAPDOOR: + case DARK_OAK_TRAPDOOR: + case IRON_TRAPDOOR: + case JUNGLE_TRAPDOOR: + case OAK_TRAPDOOR: + case SPRUCE_TRAPDOOR: + + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case JUNGLE_FENCE_GATE: + case OAK_FENCE_GATE: + case SPRUCE_FENCE_GATE: + action = PermissableAction.DOOR; + break; + + case CHEST: + case TRAPPED_CHEST: + case CHEST_MINECART: + + case SHULKER_BOX: + case BLACK_SHULKER_BOX: + case BLUE_SHULKER_BOX: + case BROWN_SHULKER_BOX: + case CYAN_SHULKER_BOX: + case GRAY_SHULKER_BOX: + case GREEN_SHULKER_BOX: + case LIGHT_BLUE_SHULKER_BOX: + case LIGHT_GRAY_SHULKER_BOX: + case LIME_SHULKER_BOX: + case MAGENTA_SHULKER_BOX: + case ORANGE_SHULKER_BOX: + case PINK_SHULKER_BOX: + case PURPLE_SHULKER_BOX: + case RED_SHULKER_BOX: + case WHITE_SHULKER_BOX: + case YELLOW_SHULKER_BOX: + + case FURNACE: + case DROPPER: + case DISPENSER: + case ENCHANTING_TABLE: + case BREWING_STAND: + case CAULDRON: + case HOPPER: + case BEACON: + case JUKEBOX: + + case ANVIL: + case CHIPPED_ANVIL: + case DAMAGED_ANVIL: + action = PermissableAction.CONTAINER; + break; + default: + // Check for doors that might have diff material name in old version. + if (block.getType().name().contains("DOOR")) { + action = PermissableAction.DOOR; + } + break; + } + } else { + if (block.getType().toString().toUpperCase().contains("BUTTON")) { + action = PermissableAction.BUTTON; + } + + switch (block.getType()) { + case LEVER: + action = PermissableAction.LEVER; + break; + case DARK_OAK_DOOR: + case ACACIA_DOOR: + case BIRCH_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case SPRUCE_DOOR: + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case JUNGLE_FENCE_GATE: + case SPRUCE_FENCE_GATE: + action = PermissableAction.DOOR; + break; + case CHEST: + case ENDER_CHEST: + case TRAPPED_CHEST: + case DISPENSER: + case ENCHANTING_TABLE: + case DROPPER: + case FURNACE: + case HOPPER: + case ANVIL: + case CHIPPED_ANVIL: + case DAMAGED_ANVIL: + case BREWING_STAND: + action = PermissableAction.CONTAINER; + break; + default: + // Check for doors that might have diff material name in old version. + if (block.getType().name().contains("DOOR")) + action = PermissableAction.DOOR; + break; + } + } + + // We only care about some material types. + if (otherFaction.hasPlayersOnline()) { + if (!Conf.territoryProtectedMaterials.contains(material)) + return true; + } else { + if (!Conf.territoryProtectedMaterialsWhenOffline.contains(material)) + return true; + } + + // Move up access check to check for exceptions + Access access = otherFaction.getAccess(me, action); + boolean doTerritoryEnemyProtectedCheck = true; + + if (action != null && (action.equals(PermissableAction.CONTAINER) || + action.equals(PermissableAction.DOOR))) { + if (access == Access.ALLOW) { + doTerritoryEnemyProtectedCheck = false; + } + } + + // Did not nest the boolean so that it stands out when Im looking + // through the code later. + if (doTerritoryEnemyProtectedCheck) { + // You may use any block unless it is another faction's territory... + if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials) || (rel.isTruce() && Conf.territoryTruceProtectMaterials)) { + if (!justCheck) { + me.msg(TL.PLAYER_USE_TERRITORY, (material == SavageFactions.plugin.SOIL ? "trample " : "use ") + TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); + } + return false; + } + } + + if (access != Access.ALLOW && me.getRole() != Role.LEADER) { + // TODO: Update this once new access values are added other than just allow / deny. + if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { + return true; + } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { + me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); + return false; + } else if (access == Access.DENY) { + me.msg(TL.GENERIC_NOPERMISSION, action); + return false; + } + } + return true; + } + + public static boolean preventCommand(String fullCmd, Player player) { + if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty() && Conf.permanentFactionMemberDenyCommands.isEmpty() && Conf.warzoneDenyCommands.isEmpty())) { + return false; + } + + fullCmd = fullCmd.toLowerCase(); + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + + String shortCmd; // command without the slash at the beginning + if (fullCmd.startsWith("/")) { + shortCmd = fullCmd.substring(1); + } else { + shortCmd = fullCmd; + fullCmd = "/" + fullCmd; + } + + if (me.hasFaction() && + !me.isAdminBypassing() && + !Conf.permanentFactionMemberDenyCommands.isEmpty() && + me.getFaction().isPermanent() && + isCommandInList(fullCmd, shortCmd, Conf.permanentFactionMemberDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_PERMANENT, fullCmd); + return true; + } + + Faction at = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); + if (at.isWilderness() && !Conf.wildernessDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.wildernessDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_WILDERNESS, fullCmd); + return true; + } + + Relation rel = at.getRelationTo(me); + if (at.isNormal() && rel.isAlly() && !Conf.territoryAllyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryAllyDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_ALLY, fullCmd); + return false; + } + + if (at.isNormal() && rel.isNeutral() && !Conf.territoryNeutralDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryNeutralDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_NEUTRAL, fullCmd); + return true; + } + + if (at.isNormal() && rel.isEnemy() && !Conf.territoryEnemyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryEnemyDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_ENEMY, fullCmd); + return true; + } + + if (at.isWarZone() && !Conf.warzoneDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.warzoneDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_WARZONE, fullCmd); + return true; + } + + return false; + } + + private static boolean isCommandInList(String fullCmd, String shortCmd, Iterator iter) { + String cmdCheck; + while (iter.hasNext()) { + cmdCheck = iter.next(); + if (cmdCheck == null) { + iter.remove(); + continue; + } + + cmdCheck = cmdCheck.toLowerCase(); + if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck)) { + return true; + } + } + return false; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerJoin(PlayerJoinEvent event) { + initPlayer(event.getPlayer()); + } + + private void initPlayer(Player player) { + // Make sure that all online players do have a fplayer. + final FPlayer me = FPlayers.getInstance().getByPlayer(player); + ((MemoryFPlayer) me).setName(player.getName()); + + // Update the lastLoginTime for this fplayer + me.setLastLoginTime(System.currentTimeMillis()); + + // Store player's current FLocation and notify them where they are + me.setLastStoodAt(new FLocation(player.getLocation())); + + me.login(); // set kills / deaths + + // Check for Faction announcements. Let's delay this so they actually see it. + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + if (me.isOnline()) { + me.getFaction().sendUnreadAnnouncements(me); + } + } + }, 33L); // Don't ask me why. + + if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false)) { + FScoreboard.init(me); + FScoreboard.get(me).setDefaultSidebar(new FDefaultSidebar(), SavageFactions.plugin.getConfig().getInt("scoreboard.default-update-interval", 20)); + FScoreboard.get(me).setSidebarVisibility(me.showScoreboard()); + } + + Faction myFaction = me.getFaction(); + if (!myFaction.isWilderness()) { + for (FPlayer other : myFaction.getFPlayersWhereOnline(true)) { + if (other != me && other.isMonitoringJoins()) { + other.msg(TL.FACTION_LOGIN, me.getName()); + } + } + } + + + fallMap.put(me.getPlayer(), false); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + fallMap.remove(me.getPlayer()); + + } + }, 180L); + + + if (me.isSpyingChat() && !player.hasPermission(Permission.CHATSPY.node)) { + me.setSpyingChat(false); + SavageFactions.plugin.log(Level.INFO, "Found %s spying chat without permission on login. Disabled their chat spying.", player.getName()); + } + + if (me.isAdminBypassing() && !player.hasPermission(Permission.BYPASS.node)) { + me.setIsAdminBypassing(false); + SavageFactions.plugin.log(Level.INFO, "Found %s on admin Bypass without permission on login. Disabled it for them.", player.getName()); + } + + + // If they have the permission, don't let them autoleave. Bad inverted setter :\ + me.setAutoLeave(!player.hasPermission(Permission.AUTO_LEAVE_BYPASS.node)); + me.setTakeFallDamage(true); + } + + @EventHandler + public void onPlayerFall(EntityDamageEvent e) { + if (e.getEntity() instanceof Player) { + if (e.getCause() == EntityDamageEvent.DamageCause.FALL) { + Player player = (Player) e.getEntity(); + if (fallMap.containsKey(player)) { + e.setCancelled(true); + fallMap.remove(player); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerQuit(PlayerQuitEvent event) { + FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); + + // Make sure player's power is up to date when they log off. + me.getPower(); + // and update their last login time to point to when the logged off, for auto-remove routine + me.setLastLoginTime(System.currentTimeMillis()); + + me.logout(); // cache kills / deaths + + // if player is waiting for fstuck teleport but leaves, remove + if (SavageFactions.plugin.getStuckMap().containsKey(me.getPlayer().getUniqueId())) { + FPlayers.getInstance().getByPlayer(me.getPlayer()).msg(TL.COMMAND_STUCK_CANCELLED); + SavageFactions.plugin.getStuckMap().remove(me.getPlayer().getUniqueId()); + SavageFactions.plugin.getTimers().remove(me.getPlayer().getUniqueId()); + } + + Faction myFaction = me.getFaction(); + if (!myFaction.isWilderness()) { + myFaction.memberLoggedOff(); + } + + if (!myFaction.isWilderness()) { + for (FPlayer player : myFaction.getFPlayersWhereOnline(true)) { + if (player != me && player.isMonitoringJoins()) { + player.msg(TL.FACTION_LOGOUT, me.getName()); + } + } + } + + CmdSeeChunk.seeChunkMap.remove(event.getPlayer().getName()); + + FScoreboard.remove(me); + } + + public String parseAllPlaceholders(String string, Faction faction, Player player) { + string = TagUtil.parsePlaceholders(player, string); + + string = string.replace("{Faction}", faction.getTag()) + .replace("{online}", faction.getOnlinePlayers().size() + "") + .replace("{offline}", faction.getFPlayers().size() - faction.getOnlinePlayers().size() + "") + .replace("{chunks}", faction.getAllClaims().size() + "") + .replace("{power}", faction.getPower() + "") + .replace("{leader}", faction.getFPlayerAdmin() + ""); + + return string; + } + + public void enableFly(FPlayer me) { + if (SavageFactions.plugin.getConfig().getBoolean("ffly.AutoEnable")) { + + me.setFlying(true); + CmdFly.flyMap.put(me.getName(), true); + if (CmdFly.id == -1) { + if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { + CmdFly.startParticles(); + } + } + if (CmdFly.flyid == -1) { + CmdFly.startFlyCheck(); + } + } + } + + //inspect + @EventHandler + public void onInspect(PlayerInteractEvent e) { + if (e.getAction().name().contains("BLOCK")) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(e.getPlayer()); + if (!fplayer.isInspectMode()) { + return; + } + e.setCancelled(true); + if (!fplayer.isAdminBypassing()) { + if (!fplayer.hasFaction()) { + fplayer.setInspectMode(false); + fplayer.msg(TL.COMMAND_INSPECT_DISABLED_NOFAC); + return; + } + if (fplayer.getFaction() != Board.getInstance().getFactionAt(new FLocation(e.getPlayer().getLocation()))) { + fplayer.msg(TL.COMMAND_INSPECT_NOTINCLAIM); + return; + } + } else { + fplayer.msg(TL.COMMAND_INSPECT_BYPASS); + } + List info = CoreProtect.getInstance().getAPI().blockLookup(e.getClickedBlock(), 0); + if (info.size() == 0) { + e.getPlayer().sendMessage(TL.COMMAND_INSPECT_NODATA.toString()); + return; + } + Player player = e.getPlayer(); + CoreProtectAPI coAPI = CoreProtect.getInstance().getAPI(); + player.sendMessage(TL.COMMAND_INSPECT_HEADER.toString().replace("{x}", e.getClickedBlock().getX() + "") + .replace("{y}", e.getClickedBlock().getY() + "") + .replace("{z}", e.getClickedBlock().getZ() + "")); + String rowFormat = TL.COMMAND_INSPECT_ROW.toString(); + for (int i = 0; i < info.size(); i++) { + CoreProtectAPI.ParseResult row = coAPI.parseResult(info.get(0)); + player.sendMessage(rowFormat + .replace("{time}", convertTime(row.getTime())) + .replace("{action}", row.getActionString()) + .replace("{player}", row.getPlayer()) + .replace("{block-type}", row.getType().toString().toLowerCase())); + } + } + } + + //For disabling enderpearl throws + @EventHandler + public void onPearl(PlayerInteractEvent e) { + Player player = e.getPlayer(); + if (player.getItemInHand().getType() == Material.ENDER_PEARL) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer.isFlying()) { + if (Conf.noEnderpearlsInFly) { + fPlayer.msg(TL.COMMAND_FLY_NO_EPEARL); + e.setCancelled(true); + } + } + } + } + + //For Blocking Homes and Blocking Teleportation To Homes + @EventHandler + public void onPlayerHomeCheck(PlayerTeleportEvent event) throws Exception { + if (event.getPlayer().hasMetadata("NPC")) { + return; + } + if (event.getPlayer().hasPermission("factions.homes.bypass")) { + return; + } + if (Bukkit.getPluginManager().getPlugin("Essentials") == null) { + return; + } + boolean isHome = false; + for (String str : SavageFactions.plugin.ess.getUser(event.getPlayer()).getHomes()) { + Location home = SavageFactions.plugin.ess.getUser(event.getPlayer()).getHome(str); + if (home.getBlockX() == event.getTo().getBlockX() && home.getBlockY() == event.getTo().getBlockY() && home.getBlockZ() == event.getTo().getBlockZ()) { + isHome = true; + } + } + if (!isHome) { + return; + } + Location loc = event.getTo(); + FLocation floc = new FLocation(event.getTo()); + Faction fac = Board.getInstance().getFactionAt(floc); + Player player = event.getPlayer(); + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + User user = SavageFactions.plugin.ess.getUser(event.getPlayer()); + List homes = user.getHomes(); + if (fac.isWilderness() || FPlayers.getInstance().getByPlayer(event.getPlayer()).getFactionId().equals(fac.getId())) { + return; + } + //Warzone and SafeZone Home Initializers + if (fac.isWarZone() || fac.isSafeZone() && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-system-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-system-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + + if (fplayer.getFaction().getRelationTo(fac) == Relation.ENEMY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-enemy-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-enemy-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + if (fplayer.getFaction().getRelationTo(fac) == Relation.NEUTRAL && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-neutral-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-neutral-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + if (fplayer.getFaction().getRelationTo(fac) == Relation.ALLY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-ally-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-ally-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + if (fplayer.getFaction().getRelationTo(fac) == Relation.TRUCE && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-truce-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-truce-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + } + + + //Colors a String + public String color(String s) { + return ChatColor.translateAlternateColorCodes('&', s); + } + + + private String convertTime(int time) { + String result = String.valueOf(Math.round((System.currentTimeMillis() / 1000L - time) / 36.0D) / 100.0D); + return (result.length() == 3 ? result + "0" : result) + "/hrs ago"; + } + + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + FPlayer me = FPlayers.getInstance().getByPlayer(player); + + // clear visualization + if (event.getFrom().getBlockX() != event.getTo().getBlockX() || event.getFrom().getBlockY() != event.getTo().getBlockY() || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { + VisualizeUtil.clear(event.getPlayer()); + if (me.isWarmingUp()) { + me.clearWarmup(); + me.msg(TL.WARMUPS_CANCELLED); + } + } + + // quick check to make sure player is moving between chunks; good performance boost + if (event.getFrom().getBlockX() >> 4 == event.getTo().getBlockX() >> 4 && event.getFrom().getBlockZ() >> 4 == event.getTo().getBlockZ() >> 4 && event.getFrom().getWorld() == event.getTo().getWorld()) { + return; + } + + + // Did we change coord? + FLocation from = me.getLastStoodAt(); + FLocation to = new FLocation(event.getTo()); + + if (from.equals(to)) { + return; + } + + // Yes we did change coord (: + + me.setLastStoodAt(to); + + // Did we change "host"(faction)? + Faction factionFrom = Board.getInstance().getFactionAt(from); + Faction factionTo = Board.getInstance().getFactionAt(to); + boolean changedFaction = (factionFrom != factionTo); + + + if (changedFaction) { + Bukkit.getServer().getPluginManager().callEvent(new FPlayerEnteredFactionEvent(factionTo, factionFrom, me)); + if (SavageFactions.plugin.getConfig().getBoolean("Title.Show-Title")) { + String title = SavageFactions.plugin.getConfig().getString("Title.Format.Title"); + title = title.replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); + title = parseAllPlaceholders(title, factionTo, player); + String subTitle = SavageFactions.plugin.getConfig().getString("Title.Format.Subtitle").replace("{Description}", factionTo.getDescription()).replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); + subTitle = parseAllPlaceholders(subTitle, factionTo, player); + if (!SavageFactions.plugin.mc17) { + if (!SavageFactions.plugin.mc18) { + me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle), SavageFactions.plugin.getConfig().getInt("Title.Options.FadeInTime"), + SavageFactions.plugin.getConfig().getInt("Title.Options.ShowTime"), + SavageFactions.plugin.getConfig().getInt("Title.Options.FadeOutTime")); + } else { + me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle)); + } + + + } + + } + + if (!SavageFactions.plugin.factionsFlight) { + return; + } + + + // enable fly :) + if (me.hasFaction() && !me.isFlying()) { + if (factionTo == me.getFaction()) { + enableFly(me); + } + // bypass checks + Relation relationTo = factionTo.getRelationTo(me); + if ((factionTo.isWilderness() && me.canflyinWilderness()) || + (factionTo.isWarZone() && me.canflyinWarzone()) || + (factionTo.isSafeZone() && me.canflyinSafezone()) || + (relationTo == Relation.ENEMY && me.canflyinEnemy()) || + (relationTo == Relation.ALLY && me.canflyinAlly()) || + (relationTo == Relation.TRUCE && me.canflyinTruce()) || + (relationTo == Relation.NEUTRAL && me.canflyinNeutral() && !isSystemFaction(factionTo))) { + enableFly(me); + } + + } + } + + + if (me.isMapAutoUpdating()) { + if (showTimes.containsKey(player.getUniqueId()) && (showTimes.get(player.getUniqueId()) > System.currentTimeMillis())) { + if (SavageFactions.plugin.getConfig().getBoolean("findfactionsexploit.log", false)) { + SavageFactions.plugin.log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); + } + } else { + me.sendFancyMessage(Board.getInstance().getMap(me, to, player.getLocation().getYaw())); + showTimes.put(player.getUniqueId(), System.currentTimeMillis() + SavageFactions.plugin.getConfig().getLong("findfactionsexploit.cooldown", 2000)); + } + } else { + Faction myFaction = me.getFaction(); + String ownersTo = myFaction.getOwnerListString(to); + if (changedFaction) { + me.sendFactionHereMessage(factionFrom); + if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty()) { + me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); + } + } else if (Conf.ownedAreasEnabled && Conf.ownedMessageInsideTerritory && myFaction == factionTo && !myFaction.isWilderness()) { + String ownersFrom = myFaction.getOwnerListString(from); + if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo)) { + if (!ownersTo.isEmpty()) { + me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); + } else if (!TL.GENERIC_PUBLICLAND.toString().isEmpty()) { + me.sendMessage(TL.GENERIC_PUBLICLAND.toString()); + } + } + } + } + + if (me.getAutoClaimFor() != null) { + me.attemptClaim(me.getAutoClaimFor(), event.getTo(), true); + } else if (me.isAutoSafeClaimEnabled()) { + if (!Permission.MANAGE_SAFE_ZONE.has(player)) { + me.setIsAutoSafeClaimEnabled(false); + } else { + if (!Board.getInstance().getFactionAt(to).isSafeZone()) { + Board.getInstance().setFactionAt(Factions.getInstance().getSafeZone(), to); + me.msg(TL.PLAYER_SAFEAUTO); + } + } + } else if (me.isAutoWarClaimEnabled()) { + if (!Permission.MANAGE_WAR_ZONE.has(player)) { + me.setIsAutoWarClaimEnabled(false); + } else { + if (!Board.getInstance().getFactionAt(to).isWarZone()) { + Board.getInstance().setFactionAt(Factions.getInstance().getWarZone(), to); + me.msg(TL.PLAYER_WARAUTO); + } + } + } + } + + @EventHandler + public void onClose(InventoryCloseEvent e) { + FPlayer fme = FPlayers.getInstance().getById(e.getPlayer().getUniqueId().toString()); + if (fme.isInVault()) + fme.setInVault(false); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + /// Prevents the use of montster eggs in oned land. /*if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { if (event.hasItem() || event.hasBlock()) { ItemStack itemStack = event.getItem(); @@ -915,159 +915,159 @@ public class FactionsPlayerListener implements Listener { } } }*/ - // only need to check right-clicks and physical as of MC 1.4+; good performance boost - if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) - return; + // only need to check right-clicks and physical as of MC 1.4+; good performance boost + if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) + return; - Block block = event.getClickedBlock(); - Player player = event.getPlayer(); + Block block = event.getClickedBlock(); + Player player = event.getPlayer(); - if (block == null) - return; // clicked in air, apparently + if (block == null) + return; // clicked in air, apparently - if (!canPlayerUseBlock(player, block, false)) { - event.setCancelled(true); - if (Conf.handleExploitInteractionSpam) { - String name = player.getName(); - InteractAttemptSpam attempt = interactSpammers.get(name); - if (attempt == null) { - attempt = new InteractAttemptSpam(); - interactSpammers.put(name, attempt); - } + if (!canPlayerUseBlock(player, block, false)) { + event.setCancelled(true); + if (Conf.handleExploitInteractionSpam) { + String name = player.getName(); + InteractAttemptSpam attempt = interactSpammers.get(name); + if (attempt == null) { + attempt = new InteractAttemptSpam(); + interactSpammers.put(name, attempt); + } - int count = attempt.increment(); - if (count >= 10) { - FPlayer me = FPlayers.getInstance().getByPlayer(player); - me.msg(TL.PLAYER_OUCH); - player.damage(NumberConversions.floor((double) count / 10)); - } - } - return; - } + int count = attempt.increment(); + if (count >= 10) { + FPlayer me = FPlayers.getInstance().getByPlayer(player); + me.msg(TL.PLAYER_OUCH); + player.damage(NumberConversions.floor((double) count / 10)); + } + } + return; + } - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { - return; // only interested on right-clicks for below - } + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; // only interested on right-clicks for below + } - if (!playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false)) { - event.setCancelled(true); - } - } + if (!playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false)) { + event.setCancelled(true); + } + } - @EventHandler - public void onPlayerBoneMeal(PlayerInteractEvent event) { - Block block = event.getClickedBlock(); + @EventHandler + public void onPlayerBoneMeal(PlayerInteractEvent event) { + Block block = event.getClickedBlock(); - if (event.getAction() == Action.RIGHT_CLICK_BLOCK && block.getType() == MultiversionMaterials.GRASS_BLOCK.parseMaterial() - && event.hasItem() && event.getItem().getType() == MultiversionMaterials.BONE_MEAL.parseMaterial()) { - if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), block.getLocation(), PermissableAction.BUILD.name(), true)) { - FPlayer me = FPlayers.getInstance().getById(event.getPlayer().getUniqueId().toString()); - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); - Faction myFaction = me.getFaction(); + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && block.getType() == MultiversionMaterials.GRASS_BLOCK.parseMaterial() + && event.hasItem() && event.getItem().getType() == MultiversionMaterials.BONE_MEAL.parseMaterial()) { + if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), block.getLocation(), PermissableAction.BUILD.name(), true)) { + FPlayer me = FPlayers.getInstance().getById(event.getPlayer().getUniqueId().toString()); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); + Faction myFaction = me.getFaction(); - me.msg("You can't use bone meal in the territory of " + otherFaction.getTag(myFaction)); - event.setCancelled(true); - } - } - } + me.msg("You can't use bone meal in the territory of " + otherFaction.getTag(myFaction)); + event.setCancelled(true); + } + } + } - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerRespawn(PlayerRespawnEvent event) { - FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerRespawn(PlayerRespawnEvent event) { + FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); - me.getPower(); // update power, so they won't have gained any while dead + me.getPower(); // update power, so they won't have gained any while dead - Location home = me.getFaction().getHome(); - if (Conf.homesEnabled && - Conf.homesTeleportToOnDeath && - home != null && - (Conf.homesRespawnFromNoPowerLossWorlds || !Conf.worldsNoPowerLoss.contains(event.getPlayer().getWorld().getName()))) { - event.setRespawnLocation(home); - } - } + Location home = me.getFaction().getHome(); + if (Conf.homesEnabled && + Conf.homesTeleportToOnDeath && + home != null && + (Conf.homesRespawnFromNoPowerLossWorlds || !Conf.worldsNoPowerLoss.contains(event.getPlayer().getWorld().getName()))) { + event.setRespawnLocation(home); + } + } - // For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected), - // but these separate bucket events below always fire without fail - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { - Block block = event.getBlockClicked(); - Player player = event.getPlayer(); + // For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected), + // but these separate bucket events below always fire without fail + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { + Block block = event.getBlockClicked(); + Player player = event.getPlayer(); - if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { - event.setCancelled(true); - } - } + if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerBucketFill(PlayerBucketFillEvent event) { - Block block = event.getBlockClicked(); - Player player = event.getPlayer(); + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerBucketFill(PlayerBucketFillEvent event) { + Block block = event.getBlockClicked(); + Player player = event.getPlayer(); - if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { - event.setCancelled(true); - } - } + if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerInteractGUI(InventoryClickEvent event) { - if (event.getClickedInventory() == null) { - return; - } - if (event.getClickedInventory().getHolder() instanceof FactionGUI) { - event.setCancelled(true); - ((FactionGUI) event.getClickedInventory().getHolder()).onClick(event.getRawSlot(), event.getClick()); - } - } + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerInteractGUI(InventoryClickEvent event) { + if (event.getClickedInventory() == null) { + return; + } + if (event.getClickedInventory().getHolder() instanceof FactionGUI) { + event.setCancelled(true); + ((FactionGUI) event.getClickedInventory().getHolder()).onClick(event.getRawSlot(), event.getClick()); + } + } - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerMoveGUI(InventoryDragEvent event) { - if (event.getInventory().getHolder() instanceof FactionGUI) { - event.setCancelled(true); - } - } + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerMoveGUI(InventoryDragEvent event) { + if (event.getInventory().getHolder() instanceof FactionGUI) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerKick(PlayerKickEvent event) { - FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); - if (badGuy == null) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerKick(PlayerKickEvent event) { + FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); + if (badGuy == null) { + return; + } - // if player was banned (not just kicked), get rid of their stored info - if (Conf.removePlayerDataWhenBanned && event.getReason().equals("Banned by admin.")) { - if (badGuy.getRole() == Role.LEADER) { - badGuy.getFaction().promoteNewLeader(); - } + // if player was banned (not just kicked), get rid of their stored info + if (Conf.removePlayerDataWhenBanned && event.getReason().equals("Banned by admin.")) { + if (badGuy.getRole() == Role.LEADER) { + badGuy.getFaction().promoteNewLeader(); + } - badGuy.leave(false); - badGuy.remove(); - } - } + badGuy.leave(false); + badGuy.remove(); + } + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - final public void onFactionJoin(FPlayerJoinEvent event) { - FTeamWrapper.applyUpdatesLater(event.getFaction()); - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + final public void onFactionJoin(FPlayerJoinEvent event) { + FTeamWrapper.applyUpdatesLater(event.getFaction()); + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onFactionLeave(FPlayerLeaveEvent event) { - FTeamWrapper.applyUpdatesLater(event.getFaction()); - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onFactionLeave(FPlayerLeaveEvent event) { + FTeamWrapper.applyUpdatesLater(event.getFaction()); + } - private static class InteractAttemptSpam { - private int attempts = 0; - private long lastAttempt = System.currentTimeMillis(); + private static class InteractAttemptSpam { + private int attempts = 0; + private long lastAttempt = System.currentTimeMillis(); - // returns the current attempt count - public int increment() { - long now = System.currentTimeMillis(); - if (now > lastAttempt + 2000) { - attempts = 1; - } else { - attempts++; - } - lastAttempt = now; - return attempts; - } - } + // returns the current attempt count + public int increment() { + long now = System.currentTimeMillis(); + if (now > lastAttempt + 2000) { + attempts = 1; + } else { + attempts++; + } + lastAttempt = now; + return attempts; + } + } } diff --git a/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java b/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java index d21d3898..03b6f565 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java @@ -11,152 +11,152 @@ import java.lang.reflect.Method; import java.util.*; public class BufferedObjective { - private static final Method addEntryMethod; - private static final int MAX_LINE_LENGTH; + private static final Method addEntryMethod; + private static final int MAX_LINE_LENGTH; - static { - // Check for long line support. - // We require use of Spigot's `addEntry(String)` method on - // Teams, as adding OfflinePlayers to a team is far too slow. + static { + // Check for long line support. + // We require use of Spigot's `addEntry(String)` method on + // Teams, as adding OfflinePlayers to a team is far too slow. - Method addEntryMethodLookup = null; - try { - addEntryMethodLookup = Team.class.getMethod("addEntry", String.class); - } catch (NoSuchMethodException ignored) { - } + Method addEntryMethodLookup = null; + try { + addEntryMethodLookup = Team.class.getMethod("addEntry", String.class); + } catch (NoSuchMethodException ignored) { + } - addEntryMethod = addEntryMethodLookup; + addEntryMethod = addEntryMethodLookup; - if (addEntryMethod != null) { - MAX_LINE_LENGTH = 48; - } else { - MAX_LINE_LENGTH = 16; - } - } + if (addEntryMethod != null) { + MAX_LINE_LENGTH = 48; + } else { + MAX_LINE_LENGTH = 16; + } + } - private final Scoreboard scoreboard; - private final String baseName; - private final Map contents = new HashMap<>(); - private Objective current; - private List currentTeams = new ArrayList<>(); - private String title; - private DisplaySlot displaySlot; - private int objPtr; - private int teamPtr; - private boolean requiresUpdate = false; + private final Scoreboard scoreboard; + private final String baseName; + private final Map contents = new HashMap<>(); + private Objective current; + private List currentTeams = new ArrayList<>(); + private String title; + private DisplaySlot displaySlot; + private int objPtr; + private int teamPtr; + private boolean requiresUpdate = false; - public BufferedObjective(Scoreboard scoreboard) { - this.scoreboard = scoreboard; - this.baseName = createBaseName(); + public BufferedObjective(Scoreboard scoreboard) { + this.scoreboard = scoreboard; + this.baseName = createBaseName(); - current = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); - } + current = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); + } - private String createBaseName() { - Random random = new Random(); - StringBuilder builder = new StringBuilder(); - while (builder.length() < 14) { - builder.append(Integer.toHexString(random.nextInt())); - } - return builder.toString().substring(0, 14); - } + private String createBaseName() { + Random random = new Random(); + StringBuilder builder = new StringBuilder(); + while (builder.length() < 14) { + builder.append(Integer.toHexString(random.nextInt())); + } + return builder.toString().substring(0, 14); + } - public void setTitle(String title) { - if (this.title == null || !this.title.equals(title)) { - this.title = title; - requiresUpdate = true; - } - } + public void setTitle(String title) { + if (this.title == null || !this.title.equals(title)) { + this.title = title; + requiresUpdate = true; + } + } - public void setDisplaySlot(DisplaySlot slot) { - this.displaySlot = slot; - current.setDisplaySlot(slot); - } + public void setDisplaySlot(DisplaySlot slot) { + this.displaySlot = slot; + current.setDisplaySlot(slot); + } - public void setAllLines(List lines) { - if (lines.size() != contents.size()) { - contents.clear(); - } - for (int i = 0; i < lines.size(); i++) { - setLine(lines.size() - i, lines.get(i)); - } - } + public void setAllLines(List lines) { + if (lines.size() != contents.size()) { + contents.clear(); + } + for (int i = 0; i < lines.size(); i++) { + setLine(lines.size() - i, lines.get(i)); + } + } - public void setLine(int lineNumber, String content) { - if (content.length() > MAX_LINE_LENGTH) { - content = content.substring(0, MAX_LINE_LENGTH); - } - content = ChatColor.translateAlternateColorCodes('&', content); + public void setLine(int lineNumber, String content) { + if (content.length() > MAX_LINE_LENGTH) { + content = content.substring(0, MAX_LINE_LENGTH); + } + content = ChatColor.translateAlternateColorCodes('&', content); - if (contents.get(lineNumber) == null || !contents.get(lineNumber).equals(content)) { - contents.put(lineNumber, content); - requiresUpdate = true; - } - } + if (contents.get(lineNumber) == null || !contents.get(lineNumber).equals(content)) { + contents.put(lineNumber, content); + requiresUpdate = true; + } + } - // Hides the objective from the display slot until flip() is called - public void hide() { - if (displaySlot != null) { - scoreboard.clearSlot(displaySlot); - } - } + // Hides the objective from the display slot until flip() is called + public void hide() { + if (displaySlot != null) { + scoreboard.clearSlot(displaySlot); + } + } - public void flip() { - if (!requiresUpdate) { - return; - } - requiresUpdate = false; + public void flip() { + if (!requiresUpdate) { + return; + } + requiresUpdate = false; - Objective buffer = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); - buffer.setDisplayName(title); + Objective buffer = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); + buffer.setDisplayName(title); - List bufferTeams = new ArrayList<>(); + List bufferTeams = new ArrayList<>(); - for (Map.Entry entry : contents.entrySet()) { - if (entry.getValue().length() > 16) { - Team team = scoreboard.registerNewTeam(getNextTeamName()); - bufferTeams.add(team); + for (Map.Entry entry : contents.entrySet()) { + if (entry.getValue().length() > 16) { + Team team = scoreboard.registerNewTeam(getNextTeamName()); + bufferTeams.add(team); - Iterator split = Splitter.fixedLength(16).split(entry.getValue()).iterator(); + Iterator split = Splitter.fixedLength(16).split(entry.getValue()).iterator(); - team.setPrefix(split.next()); - String name = split.next(); - if (split.hasNext()) { // We only guarantee two splits - team.setSuffix(split.next()); - } + team.setPrefix(split.next()); + String name = split.next(); + if (split.hasNext()) { // We only guarantee two splits + team.setSuffix(split.next()); + } - try { - addEntryMethod.invoke(team, name); - } catch (ReflectiveOperationException ignored) { - } - buffer.getScore(name).setScore(entry.getKey()); - } else { - buffer.getScore(entry.getValue()).setScore(entry.getKey()); - } - } + try { + addEntryMethod.invoke(team, name); + } catch (ReflectiveOperationException ignored) { + } + buffer.getScore(name).setScore(entry.getKey()); + } else { + buffer.getScore(entry.getValue()).setScore(entry.getKey()); + } + } - if (displaySlot != null) { - buffer.setDisplaySlot(displaySlot); - } + if (displaySlot != null) { + buffer.setDisplaySlot(displaySlot); + } - // Unregister _ALL_ the old things - current.unregister(); + // Unregister _ALL_ the old things + current.unregister(); - Iterator it = currentTeams.iterator(); - while (it.hasNext()) { - it.next().unregister(); - it.remove(); - } + Iterator it = currentTeams.iterator(); + while (it.hasNext()) { + it.next().unregister(); + it.remove(); + } - current = buffer; - currentTeams = bufferTeams; - } + current = buffer; + currentTeams = bufferTeams; + } - private String getNextObjectiveName() { - return baseName + "_" + ((objPtr++) % 2); - } + private String getNextObjectiveName() { + return baseName + "_" + ((objPtr++) % 2); + } - private String getNextTeamName() { - return baseName.substring(0, 10) + "_" + ((teamPtr++) % 999999); - } + private String getNextTeamName() { + return baseName.substring(0, 10) + "_" + ((teamPtr++) % 999999); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java b/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java index 91b2c1e4..61f667f4 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java @@ -13,137 +13,137 @@ import java.util.HashMap; import java.util.Map; public class FScoreboard { - private static final Map fscoreboards = new HashMap<>(); + private static final Map fscoreboards = new HashMap<>(); - private final Scoreboard scoreboard; - private final FPlayer fplayer; - private final BufferedObjective bufferedObjective; - private FSidebarProvider defaultProvider; - private FSidebarProvider temporaryProvider; - private boolean removed = false; + private final Scoreboard scoreboard; + private final FPlayer fplayer; + private final BufferedObjective bufferedObjective; + private FSidebarProvider defaultProvider; + private FSidebarProvider temporaryProvider; + private boolean removed = false; - private FScoreboard(FPlayer fplayer) { - this.fplayer = fplayer; + private FScoreboard(FPlayer fplayer) { + this.fplayer = fplayer; - if (isSupportedByServer()) { - this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); - this.bufferedObjective = new BufferedObjective(scoreboard); + if (isSupportedByServer()) { + this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + this.bufferedObjective = new BufferedObjective(scoreboard); - fplayer.getPlayer().setScoreboard(scoreboard); - } else { - this.scoreboard = null; - this.bufferedObjective = null; - } - } + fplayer.getPlayer().setScoreboard(scoreboard); + } else { + this.scoreboard = null; + this.bufferedObjective = null; + } + } - // Glowstone doesn't support scoreboards. - // All references to this and related workarounds can be safely - // removed when scoreboards are supported. - public static boolean isSupportedByServer() { - return Bukkit.getScoreboardManager() != null; - } + // Glowstone doesn't support scoreboards. + // All references to this and related workarounds can be safely + // removed when scoreboards are supported. + public static boolean isSupportedByServer() { + return Bukkit.getScoreboardManager() != null; + } - public static void init(FPlayer fplayer) { - FScoreboard fboard = new FScoreboard(fplayer); - fscoreboards.put(fplayer, fboard); + public static void init(FPlayer fplayer) { + FScoreboard fboard = new FScoreboard(fplayer); + fscoreboards.put(fplayer, fboard); - if (fplayer.hasFaction()) { - FTeamWrapper.applyUpdates(fplayer.getFaction()); - } - FTeamWrapper.track(fboard); - } + if (fplayer.hasFaction()) { + FTeamWrapper.applyUpdates(fplayer.getFaction()); + } + FTeamWrapper.track(fboard); + } - public static void remove(FPlayer fplayer) { - FScoreboard fboard = fscoreboards.remove(fplayer); + public static void remove(FPlayer fplayer) { + FScoreboard fboard = fscoreboards.remove(fplayer); - if (fboard != null) { - fboard.removed = true; - FTeamWrapper.untrack(fboard); - } - } + if (fboard != null) { + fboard.removed = true; + FTeamWrapper.untrack(fboard); + } + } - public static FScoreboard get(FPlayer fplayer) { - return fscoreboards.get(fplayer); - } + public static FScoreboard get(FPlayer fplayer) { + return fscoreboards.get(fplayer); + } - public static FScoreboard get(Player player) { - return fscoreboards.get(FPlayers.getInstance().getByPlayer(player)); - } + public static FScoreboard get(Player player) { + return fscoreboards.get(FPlayers.getInstance().getByPlayer(player)); + } - protected FPlayer getFPlayer() { - return fplayer; - } + protected FPlayer getFPlayer() { + return fplayer; + } - protected Scoreboard getScoreboard() { - return scoreboard; - } + protected Scoreboard getScoreboard() { + return scoreboard; + } - public void setSidebarVisibility(boolean visible) { - if (!isSupportedByServer()) { - return; - } + public void setSidebarVisibility(boolean visible) { + if (!isSupportedByServer()) { + return; + } - bufferedObjective.setDisplaySlot(visible ? DisplaySlot.SIDEBAR : null); - } + bufferedObjective.setDisplaySlot(visible ? DisplaySlot.SIDEBAR : null); + } - public void setDefaultSidebar(final FSidebarProvider provider, int updateInterval) { - if (!isSupportedByServer()) { - return; - } + public void setDefaultSidebar(final FSidebarProvider provider, int updateInterval) { + if (!isSupportedByServer()) { + return; + } - defaultProvider = provider; - if (temporaryProvider == null) { - // We have no temporary provider; update the BufferedObjective! - updateObjective(); - } + defaultProvider = provider; + if (temporaryProvider == null) { + // We have no temporary provider; update the BufferedObjective! + updateObjective(); + } - new BukkitRunnable() { - @Override - public void run() { - if (removed || provider != defaultProvider) { - cancel(); - return; - } + new BukkitRunnable() { + @Override + public void run() { + if (removed || provider != defaultProvider) { + cancel(); + return; + } - if (temporaryProvider == null) { - updateObjective(); - } - } - }.runTaskTimer(SavageFactions.plugin, updateInterval, updateInterval); - } + if (temporaryProvider == null) { + updateObjective(); + } + } + }.runTaskTimer(SavageFactions.plugin, updateInterval, updateInterval); + } - public void setTemporarySidebar(final FSidebarProvider provider) { - if (!isSupportedByServer()) { - return; - } + public void setTemporarySidebar(final FSidebarProvider provider) { + if (!isSupportedByServer()) { + return; + } - temporaryProvider = provider; - updateObjective(); + temporaryProvider = provider; + updateObjective(); - new BukkitRunnable() { - @Override - public void run() { - if (removed) { - return; - } + new BukkitRunnable() { + @Override + public void run() { + if (removed) { + return; + } - if (temporaryProvider == provider) { - temporaryProvider = null; - updateObjective(); - } - } - }.runTaskLater(SavageFactions.plugin, SavageFactions.plugin.getConfig().getInt("scoreboard.expiration", 7) * 20); - } + if (temporaryProvider == provider) { + temporaryProvider = null; + updateObjective(); + } + } + }.runTaskLater(SavageFactions.plugin, SavageFactions.plugin.getConfig().getInt("scoreboard.expiration", 7) * 20); + } - private void updateObjective() { - FSidebarProvider provider = temporaryProvider != null ? temporaryProvider : defaultProvider; + private void updateObjective() { + FSidebarProvider provider = temporaryProvider != null ? temporaryProvider : defaultProvider; - if (provider == null) { - bufferedObjective.hide(); - } else { - bufferedObjective.setTitle(provider.getTitle(fplayer)); - bufferedObjective.setAllLines(provider.getLines(fplayer)); - bufferedObjective.flip(); - } - } + if (provider == null) { + bufferedObjective.hide(); + } else { + bufferedObjective.setTitle(provider.getTitle(fplayer)); + bufferedObjective.setAllLines(provider.getLines(fplayer)); + bufferedObjective.flip(); + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java b/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java index a40640f4..6ce4976c 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java @@ -10,32 +10,32 @@ import java.util.List; public abstract class FSidebarProvider { - public abstract String getTitle(FPlayer fplayer); + public abstract String getTitle(FPlayer fplayer); - public abstract List getLines(FPlayer fplayer); + public abstract List getLines(FPlayer fplayer); - public String replaceTags(FPlayer fPlayer, String s) { - s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); + public String replaceTags(FPlayer fPlayer, String s) { + s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); - return qualityAssure(TagUtil.parsePlain(fPlayer, s)); - } + return qualityAssure(TagUtil.parsePlain(fPlayer, s)); + } - public String replaceTags(Faction faction, FPlayer fPlayer, String s) { - // Run through Placeholder API first - s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); + public String replaceTags(Faction faction, FPlayer fPlayer, String s) { + // Run through Placeholder API first + s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); - return qualityAssure(TagUtil.parsePlain(faction, fPlayer, s)); - } + return qualityAssure(TagUtil.parsePlain(faction, fPlayer, s)); + } - private String qualityAssure(String line) { - if (line.contains("{notFrozen}") || line.contains("{notPermanent}")) { - return "n/a"; // we dont support support these error variables in scoreboards - } - if (line.contains("{ig}")) { - // since you can't really fit a whole "Faction Home: world, x, y, z" on one line - // we assume it's broken up into two lines, so returning our tl will suffice. - return TL.COMMAND_SHOW_NOHOME.toString(); - } - return SavageFactions.plugin.txt.parse(line); // finally add color :) - } + private String qualityAssure(String line) { + if (line.contains("{notFrozen}") || line.contains("{notPermanent}")) { + return "n/a"; // we dont support support these error variables in scoreboards + } + if (line.contains("{ig}")) { + // since you can't really fit a whole "Faction Home: world, x, y, z" on one line + // we assume it's broken up into two lines, so returning our tl will suffice. + return TL.COMMAND_SHOW_NOHOME.toString(); + } + return SavageFactions.plugin.txt.parse(line); // finally add color :) + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java b/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java index f2f442d2..88ee2663 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java @@ -12,215 +12,215 @@ import org.bukkit.scoreboard.Team; import java.util.*; public class FTeamWrapper { - private static final Map wrappers = new HashMap<>(); - private static final List tracking = new ArrayList<>(); - private static final Set updating = new HashSet<>(); - private static int factionTeamPtr; - private final Map teams = new HashMap<>(); - private final String teamName; - private final Faction faction; - private final Set members = new HashSet<>(); + private static final Map wrappers = new HashMap<>(); + private static final List tracking = new ArrayList<>(); + private static final Set updating = new HashSet<>(); + private static int factionTeamPtr; + private final Map teams = new HashMap<>(); + private final String teamName; + private final Faction faction; + private final Set members = new HashSet<>(); - private FTeamWrapper(Faction faction) { - this.teamName = "faction_" + (factionTeamPtr++); - this.faction = faction; + private FTeamWrapper(Faction faction) { + this.teamName = "faction_" + (factionTeamPtr++); + this.faction = faction; - for (FScoreboard fboard : tracking) { - add(fboard); - } - } + for (FScoreboard fboard : tracking) { + add(fboard); + } + } - public static void applyUpdatesLater(final Faction faction) { - if (!FScoreboard.isSupportedByServer()) { - return; - } + public static void applyUpdatesLater(final Faction faction) { + if (!FScoreboard.isSupportedByServer()) { + return; + } - if (faction.isWilderness()) { - return; - } + if (faction.isWilderness()) { + return; + } - if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { - return; - } + if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { + return; + } - if (updating.add(faction)) { - Bukkit.getScheduler().runTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - updating.remove(faction); - applyUpdates(faction); - } - }); - } - } + if (updating.add(faction)) { + Bukkit.getScheduler().runTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + updating.remove(faction); + applyUpdates(faction); + } + }); + } + } - public static void applyUpdates(Faction faction) { - if (!FScoreboard.isSupportedByServer()) { - return; - } + public static void applyUpdates(Faction faction) { + if (!FScoreboard.isSupportedByServer()) { + return; + } - if (faction.isWilderness()) { - return; - } + if (faction.isWilderness()) { + return; + } - if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { - return; - } + if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { + return; + } - if (updating.contains(faction)) { - // Faction will be updated soon. - return; - } + if (updating.contains(faction)) { + // Faction will be updated soon. + return; + } - FTeamWrapper wrapper = wrappers.get(faction); - Set factionMembers = faction.getFPlayers(); + FTeamWrapper wrapper = wrappers.get(faction); + Set factionMembers = faction.getFPlayers(); - if (wrapper != null && Factions.getInstance().getFactionById(faction.getId()) == null) { - // Faction was disbanded - wrapper.unregister(); - wrappers.remove(faction); - return; - } + if (wrapper != null && Factions.getInstance().getFactionById(faction.getId()) == null) { + // Faction was disbanded + wrapper.unregister(); + wrappers.remove(faction); + return; + } - if (wrapper == null) { - wrapper = new FTeamWrapper(faction); - wrappers.put(faction, wrapper); - } + if (wrapper == null) { + wrapper = new FTeamWrapper(faction); + wrappers.put(faction, wrapper); + } - for (OfflinePlayer player : wrapper.getPlayers()) { - if (!player.isOnline() || !factionMembers.contains(FPlayers.getInstance().getByOfflinePlayer(player))) { - // Player is offline or no longer in faction - wrapper.removePlayer(player); - } - } + for (OfflinePlayer player : wrapper.getPlayers()) { + if (!player.isOnline() || !factionMembers.contains(FPlayers.getInstance().getByOfflinePlayer(player))) { + // Player is offline or no longer in faction + wrapper.removePlayer(player); + } + } - for (FPlayer fmember : factionMembers) { - if (!fmember.isOnline()) { - continue; - } + for (FPlayer fmember : factionMembers) { + if (!fmember.isOnline()) { + continue; + } - // Scoreboard might not have player; add him/her - wrapper.addPlayer(fmember.getPlayer()); - } + // Scoreboard might not have player; add him/her + wrapper.addPlayer(fmember.getPlayer()); + } - wrapper.updatePrefixes(); - } + wrapper.updatePrefixes(); + } - public static void updatePrefixes(Faction faction) { - if (!FScoreboard.isSupportedByServer()) { - return; - } + public static void updatePrefixes(Faction faction) { + if (!FScoreboard.isSupportedByServer()) { + return; + } - if (!wrappers.containsKey(faction)) { - applyUpdates(faction); - } else { - wrappers.get(faction).updatePrefixes(); - } - } + if (!wrappers.containsKey(faction)) { + applyUpdates(faction); + } else { + wrappers.get(faction).updatePrefixes(); + } + } - protected static void track(FScoreboard fboard) { - if (!FScoreboard.isSupportedByServer()) { - return; - } - tracking.add(fboard); - for (FTeamWrapper wrapper : wrappers.values()) { - wrapper.add(fboard); - } - } + protected static void track(FScoreboard fboard) { + if (!FScoreboard.isSupportedByServer()) { + return; + } + tracking.add(fboard); + for (FTeamWrapper wrapper : wrappers.values()) { + wrapper.add(fboard); + } + } - protected static void untrack(FScoreboard fboard) { - if (!FScoreboard.isSupportedByServer()) { - return; - } - tracking.remove(fboard); - for (FTeamWrapper wrapper : wrappers.values()) { - wrapper.remove(fboard); - } - } + protected static void untrack(FScoreboard fboard) { + if (!FScoreboard.isSupportedByServer()) { + return; + } + tracking.remove(fboard); + for (FTeamWrapper wrapper : wrappers.values()) { + wrapper.remove(fboard); + } + } - private void add(FScoreboard fboard) { - Scoreboard board = fboard.getScoreboard(); - Team team = board.registerNewTeam(teamName); - teams.put(fboard, team); + private void add(FScoreboard fboard) { + Scoreboard board = fboard.getScoreboard(); + Team team = board.registerNewTeam(teamName); + teams.put(fboard, team); - for (OfflinePlayer player : getPlayers()) { - team.addPlayer(player); - } + for (OfflinePlayer player : getPlayers()) { + team.addPlayer(player); + } - updatePrefix(fboard); - } + updatePrefix(fboard); + } - private void remove(FScoreboard fboard) { - teams.remove(fboard).unregister(); - } + private void remove(FScoreboard fboard) { + teams.remove(fboard).unregister(); + } - private void updatePrefixes() { - if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { - for (FScoreboard fboard : teams.keySet()) { - updatePrefix(fboard); - } - } - } + private void updatePrefixes() { + if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { + for (FScoreboard fboard : teams.keySet()) { + updatePrefix(fboard); + } + } + } - private void updatePrefix(FScoreboard fboard) { - if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { - FPlayer fplayer = fboard.getFPlayer(); - Team team = teams.get(fboard); - boolean focused = false; + private void updatePrefix(FScoreboard fboard) { + if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { + FPlayer fplayer = fboard.getFPlayer(); + Team team = teams.get(fboard); + boolean focused = false; - if (SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members", false)) { - team.setCanSeeFriendlyInvisibles(true); - } + if (SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members", false)) { + team.setCanSeeFriendlyInvisibles(true); + } - if ((SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) && (fplayer.getFaction() != null) && (fplayer.getFaction().getFocused() != null)) { - for (FPlayer fp : faction.getFPlayersWhereOnline(true)) { - if (fplayer.getFaction().getFocused().equalsIgnoreCase(fp.getName())) { - team.setPrefix(ChatColor.translateAlternateColorCodes('&', SavageFactions.plugin.getConfig().getString("ffocus.Prefix", "&7»&b"))); - focused = true; - } - } - } - if (!focused) { - String prefix = TL.DEFAULT_PREFIX.toString(); + if ((SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) && (fplayer.getFaction() != null) && (fplayer.getFaction().getFocused() != null)) { + for (FPlayer fp : faction.getFPlayersWhereOnline(true)) { + if (fplayer.getFaction().getFocused().equalsIgnoreCase(fp.getName())) { + team.setPrefix(ChatColor.translateAlternateColorCodes('&', SavageFactions.plugin.getConfig().getString("ffocus.Prefix", "&7»&b"))); + focused = true; + } + } + } + if (!focused) { + String prefix = TL.DEFAULT_PREFIX.toString(); - prefix = PlaceholderAPI.setPlaceholders(fplayer.getPlayer(), prefix); - prefix = PlaceholderAPI.setBracketPlaceholders(fplayer.getPlayer(), prefix); - prefix = prefix.replace("{relationcolor}", faction.getRelationTo(fplayer).getColor().toString()); - prefix = prefix.replace("{faction}", - faction.getTag().substring(0, Math.min("{faction}".length() + 16 - prefix.length(), faction.getTag().length()))); - if ((team.getPrefix() == null) || (!team.getPrefix().equals(prefix))) { - team.setPrefix(prefix); - } - } - } - } + prefix = PlaceholderAPI.setPlaceholders(fplayer.getPlayer(), prefix); + prefix = PlaceholderAPI.setBracketPlaceholders(fplayer.getPlayer(), prefix); + prefix = prefix.replace("{relationcolor}", faction.getRelationTo(fplayer).getColor().toString()); + prefix = prefix.replace("{faction}", + faction.getTag().substring(0, Math.min("{faction}".length() + 16 - prefix.length(), faction.getTag().length()))); + if ((team.getPrefix() == null) || (!team.getPrefix().equals(prefix))) { + team.setPrefix(prefix); + } + } + } + } - private void addPlayer(OfflinePlayer player) { - if (members.add(player)) { - for (Team team : teams.values()) { - team.addPlayer(player); - } - } - } + private void addPlayer(OfflinePlayer player) { + if (members.add(player)) { + for (Team team : teams.values()) { + team.addPlayer(player); + } + } + } - private void removePlayer(OfflinePlayer player) { - if (members.remove(player)) { - for (Team team : teams.values()) { - team.removePlayer(player); - } - } - } + private void removePlayer(OfflinePlayer player) { + if (members.remove(player)) { + for (Team team : teams.values()) { + team.removePlayer(player); + } + } + } - private Set getPlayers() { - return new HashSet<>(this.members); - } + private Set getPlayers() { + return new HashSet<>(this.members); + } - private void unregister() { - for (Team team : teams.values()) { - team.unregister(); - } - teams.clear(); - } + private void unregister() { + for (Team team : teams.values()) { + team.unregister(); + } + teams.clear(); + } } diff --git a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java index 5bdf32fa..64c68708 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java @@ -10,32 +10,32 @@ import java.util.ListIterator; public class FDefaultSidebar extends FSidebarProvider { - @Override - public String getTitle(FPlayer fplayer) { - return replaceTags(fplayer, SavageFactions.plugin.getConfig().getString("scoreboard.default-title", "{name}")); - } + @Override + public String getTitle(FPlayer fplayer) { + return replaceTags(fplayer, SavageFactions.plugin.getConfig().getString("scoreboard.default-title", "{name}")); + } - @Override - public List getLines(FPlayer fplayer) { - if (fplayer.hasFaction()) { - return getOutput(fplayer, "scoreboard.default"); - } else if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.factionless-enabled", false)) { - return getOutput(fplayer, "scoreboard.factionless"); - } - return getOutput(fplayer, "scoreboard.default"); // no faction, factionless-board disabled - } + @Override + public List getLines(FPlayer fplayer) { + if (fplayer.hasFaction()) { + return getOutput(fplayer, "scoreboard.default"); + } else if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.factionless-enabled", false)) { + return getOutput(fplayer, "scoreboard.factionless"); + } + return getOutput(fplayer, "scoreboard.default"); // no faction, factionless-board disabled + } - public List getOutput(FPlayer fplayer, String list) { - List lines = SavageFactions.plugin.getConfig().getStringList(list); + public List getOutput(FPlayer fplayer, String list) { + List lines = SavageFactions.plugin.getConfig().getStringList(list); - if (lines == null || lines.isEmpty()) { - return new ArrayList<>(); - } + if (lines == null || lines.isEmpty()) { + return new ArrayList<>(); + } - ListIterator it = lines.listIterator(); - while (it.hasNext()) { - it.set(replaceTags(fplayer, it.next())); - } - return lines; - } + ListIterator it = lines.listIterator(); + while (it.hasNext()) { + it.set(replaceTags(fplayer, it.next())); + } + return lines; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java index 93759678..4820387c 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java @@ -9,25 +9,25 @@ import java.util.List; import java.util.ListIterator; public class FInfoSidebar extends FSidebarProvider { - private final Faction faction; + private final Faction faction; - public FInfoSidebar(Faction faction) { - this.faction = faction; - } + public FInfoSidebar(Faction faction) { + this.faction = faction; + } - @Override - public String getTitle(FPlayer fplayer) { - return faction.getRelationTo(fplayer).getColor() + faction.getTag(); - } + @Override + public String getTitle(FPlayer fplayer) { + return faction.getRelationTo(fplayer).getColor() + faction.getTag(); + } - @Override - public List getLines(FPlayer fplayer) { - List lines = SavageFactions.plugin.getConfig().getStringList("scoreboard.finfo"); + @Override + public List getLines(FPlayer fplayer) { + List lines = SavageFactions.plugin.getConfig().getStringList("scoreboard.finfo"); - ListIterator it = lines.listIterator(); - while (it.hasNext()) { - it.set(replaceTags(faction, fplayer, it.next())); - } - return lines; - } + ListIterator it = lines.listIterator(); + while (it.hasNext()) { + it.set(replaceTags(faction, fplayer, it.next())); + } + return lines; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java index 037a9c03..4c33f291 100644 --- a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java +++ b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java @@ -18,80 +18,80 @@ import org.bukkit.event.Event; public class PlayerFactionExpression extends SimpleExpression { - static { - Skript.registerExpression(PlayerFactionExpression.class, String.class, ExpressionType.SIMPLE, "[the] faction of %player%", "[the] %player%['s] faction"); - } + static { + Skript.registerExpression(PlayerFactionExpression.class, String.class, ExpressionType.SIMPLE, "[the] faction of %player%", "[the] %player%['s] faction"); + } - Expression playerExpression; + Expression playerExpression; - @Override - public Class getReturnType() { - return String.class; - } + @Override + public Class getReturnType() { + return String.class; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public boolean isSingle() { + return true; + } - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { - playerExpression = (Expression) exprs[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + playerExpression = (Expression) exprs[0]; + return true; + } - @Override - public String toString(Event event, boolean debug) { - return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); - } + @Override + public String toString(Event event, boolean debug) { + return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); + } - @Override - protected String[] get(Event event) { - Player player = playerExpression.getSingle(event); + @Override + protected String[] get(Event event) { + Player player = playerExpression.getSingle(event); - if (player != null) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - return new String[]{fPlayer.getFaction().getTag()}; - } + if (player != null) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + return new String[]{fPlayer.getFaction().getTag()}; + } - return null; + return null; - } + } - @Override - public Class[] acceptChange(final Changer.ChangeMode mode) { - if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { - return CollectionUtils.array(String.class); - } - return null; - } + @Override + public Class[] acceptChange(final Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { + return CollectionUtils.array(String.class); + } + return null; + } - @Override - public void change(Event event, Object[] delta, Changer.ChangeMode mode) { - Player player = playerExpression.getSingle(event); - if (player == null) { - return; - } + @Override + public void change(Event event, Object[] delta, Changer.ChangeMode mode) { + Player player = playerExpression.getSingle(event); + if (player == null) { + return; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - switch (mode) { - case DELETE: - case RESET: - fPlayer.setFaction(Factions.getInstance().getWilderness()); - break; - case SET: - Faction faction = Factions.getInstance().getByTag((String) delta[0]); - if (faction == null) { - faction = Factions.getInstance().getWilderness(); - } - fPlayer.setFaction(faction); - break; - default: - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + switch (mode) { + case DELETE: + case RESET: + fPlayer.setFaction(Factions.getInstance().getWilderness()); + break; + case SET: + Faction faction = Factions.getInstance().getByTag((String) delta[0]); + if (faction == null) { + faction = Factions.getInstance().getWilderness(); + } + fPlayer.setFaction(faction); + break; + default: + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java index 928da2e5..f4d2c4c2 100644 --- a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java +++ b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java @@ -16,80 +16,80 @@ import org.bukkit.event.Event; public class PlayerPowerExpression extends SimpleExpression { - static { - Skript.registerExpression(PlayerPowerExpression.class, Number.class, ExpressionType.SIMPLE, "[the] power of %player%", "[the] %player%['s] power"); - } + static { + Skript.registerExpression(PlayerPowerExpression.class, Number.class, ExpressionType.SIMPLE, "[the] power of %player%", "[the] %player%['s] power"); + } - Expression playerExpression; + Expression playerExpression; - @Override - public Class getReturnType() { - return Double.class; - } + @Override + public Class getReturnType() { + return Double.class; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public boolean isSingle() { + return true; + } - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { - playerExpression = (Expression) exprs[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + playerExpression = (Expression) exprs[0]; + return true; + } - @Override - public String toString(Event event, boolean debug) { - return "Player Power with expression player" + playerExpression.toString(event, debug); - } + @Override + public String toString(Event event, boolean debug) { + return "Player Power with expression player" + playerExpression.toString(event, debug); + } - @Override - protected Double[] get(Event event) { - Player player = playerExpression.getSingle(event); + @Override + protected Double[] get(Event event) { + Player player = playerExpression.getSingle(event); - if (player != null) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - return new Double[]{fPlayer.getFaction().getPower()}; - } + if (player != null) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + return new Double[]{fPlayer.getFaction().getPower()}; + } - return null; + return null; - } + } - @Override - public Class[] acceptChange(final Changer.ChangeMode mode) { - if (mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.ADD || mode == Changer.ChangeMode.REMOVE) { - return CollectionUtils.array(Number.class); - } - return null; - } + @Override + public Class[] acceptChange(final Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.ADD || mode == Changer.ChangeMode.REMOVE) { + return CollectionUtils.array(Number.class); + } + return null; + } - @Override - public void change(Event event, Object[] delta, Changer.ChangeMode mode) { - Player player = playerExpression.getSingle(event); - if (player == null) { - return; - } + @Override + public void change(Event event, Object[] delta, Changer.ChangeMode mode) { + Player player = playerExpression.getSingle(event); + if (player == null) { + return; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - switch (mode) { - case ADD: - fPlayer.alterPower(Double.valueOf((Long) delta[0])); - break; - case REMOVE: - fPlayer.alterPower(Double.valueOf((Long) delta[0]) * -1); - break; - case RESET: - fPlayer.alterPower(fPlayer.getPowerMax() * -1); - break; - default: - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + switch (mode) { + case ADD: + fPlayer.alterPower(Double.valueOf((Long) delta[0])); + break; + case REMOVE: + fPlayer.alterPower(Double.valueOf((Long) delta[0]) * -1); + break; + case RESET: + fPlayer.alterPower(fPlayer.getPowerMax() * -1); + break; + default: + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java index 13d96ade..238c6134 100644 --- a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java +++ b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java @@ -16,77 +16,77 @@ import org.bukkit.event.Event; public class PlayerRoleExpression extends SimpleExpression { - static { - Skript.registerExpression(PlayerRoleExpression.class, String.class, ExpressionType.SIMPLE, "[the] role of %player%", "[the] %player%['s] role"); - } + static { + Skript.registerExpression(PlayerRoleExpression.class, String.class, ExpressionType.SIMPLE, "[the] role of %player%", "[the] %player%['s] role"); + } - Expression playerExpression; + Expression playerExpression; - @Override - public Class getReturnType() { - return String.class; - } + @Override + public Class getReturnType() { + return String.class; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public boolean isSingle() { + return true; + } - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { - playerExpression = (Expression) exprs[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + playerExpression = (Expression) exprs[0]; + return true; + } - @Override - public String toString(Event event, boolean debug) { - return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); - } + @Override + public String toString(Event event, boolean debug) { + return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); + } - @Override - protected String[] get(Event event) { - Player player = playerExpression.getSingle(event); + @Override + protected String[] get(Event event) { + Player player = playerExpression.getSingle(event); - if (player != null) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - return new String[]{fPlayer.getRole().toString()}; - } + if (player != null) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + return new String[]{fPlayer.getRole().toString()}; + } - return null; + return null; - } + } - @Override - public Class[] acceptChange(final Changer.ChangeMode mode) { - if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { - return CollectionUtils.array(String.class); - } - return null; - } + @Override + public Class[] acceptChange(final Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { + return CollectionUtils.array(String.class); + } + return null; + } - @Override - public void change(Event event, Object[] delta, Changer.ChangeMode mode) { - Player player = playerExpression.getSingle(event); - if (player == null) { - return; - } + @Override + public void change(Event event, Object[] delta, Changer.ChangeMode mode) { + Player player = playerExpression.getSingle(event); + if (player == null) { + return; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - switch (mode) { - case DELETE: - case RESET: - fPlayer.setRole(Role.RECRUIT); - break; - case SET: - fPlayer.setRole(Role.fromString(((String) delta[0]).toLowerCase())); - break; - default: - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + switch (mode) { + case DELETE: + case RESET: + fPlayer.setRole(Role.RECRUIT); + break; + case SET: + fPlayer.setRole(Role.fromString(((String) delta[0]).toLowerCase())); + break; + default: + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/struct/BanInfo.java b/src/main/java/com/massivecraft/factions/struct/BanInfo.java index 365d7a31..8aacfe24 100644 --- a/src/main/java/com/massivecraft/factions/struct/BanInfo.java +++ b/src/main/java/com/massivecraft/factions/struct/BanInfo.java @@ -2,41 +2,41 @@ package com.massivecraft.factions.struct; public class BanInfo { - // FPlayer IDs - private final String banner; - private final String banned; - private final long time; + // FPlayer IDs + private final String banner; + private final String banned; + private final long time; - public BanInfo(String banner, String banned, long time) { - this.banner = banner; - this.banned = banned; - this.time = time; - } + public BanInfo(String banner, String banned, long time) { + this.banner = banner; + this.banned = banned; + this.time = time; + } - /** - * Get the FPlayer ID of the player who issued the ban. - * - * @return FPlayer ID. - */ - public String getBanner() { - return this.banner; - } + /** + * Get the FPlayer ID of the player who issued the ban. + * + * @return FPlayer ID. + */ + public String getBanner() { + return this.banner; + } - /** - * Get the FPlayer ID of the player who got banned. - * - * @return FPlayer ID. - */ - public String getBanned() { - return banned; - } + /** + * Get the FPlayer ID of the player who got banned. + * + * @return FPlayer ID. + */ + public String getBanned() { + return banned; + } - /** - * Get the server time when the ban was issued. - * - * @return system timestamp. - */ - public long getTime() { - return time; - } + /** + * Get the server time when the ban was issued. + * + * @return system timestamp. + */ + public long getTime() { + return time; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/ChatMode.java b/src/main/java/com/massivecraft/factions/struct/ChatMode.java index 34536416..42471a1e 100644 --- a/src/main/java/com/massivecraft/factions/struct/ChatMode.java +++ b/src/main/java/com/massivecraft/factions/struct/ChatMode.java @@ -3,40 +3,40 @@ package com.massivecraft.factions.struct; import com.massivecraft.factions.zcore.util.TL; public enum ChatMode { - MOD(4, TL.CHAT_MOD), - FACTION(3, TL.CHAT_FACTION), - ALLIANCE(2, TL.CHAT_ALLIANCE), - TRUCE(1, TL.CHAT_TRUCE), - PUBLIC(0, TL.CHAT_PUBLIC); + MOD(4, TL.CHAT_MOD), + FACTION(3, TL.CHAT_FACTION), + ALLIANCE(2, TL.CHAT_ALLIANCE), + TRUCE(1, TL.CHAT_TRUCE), + PUBLIC(0, TL.CHAT_PUBLIC); - public final int value; - public final TL nicename; + public final int value; + public final TL nicename; - ChatMode(final int value, final TL nicename) { - this.value = value; - this.nicename = nicename; - } + ChatMode(final int value, final TL nicename) { + this.value = value; + this.nicename = nicename; + } - public boolean isAtLeast(ChatMode role) { - return this.value >= role.value; - } + public boolean isAtLeast(ChatMode role) { + return this.value >= role.value; + } - public boolean isAtMost(ChatMode role) { - return this.value <= role.value; - } + public boolean isAtMost(ChatMode role) { + return this.value <= role.value; + } - @Override - public String toString() { - return this.nicename.toString(); - } + @Override + public String toString() { + return this.nicename.toString(); + } - public ChatMode getNext() { - if (this == PUBLIC) { - return ALLIANCE; - } - if (this == ALLIANCE) { - return FACTION; - } - return PUBLIC; - } + public ChatMode getNext() { + if (this == PUBLIC) { + return ALLIANCE; + } + if (this == ALLIANCE) { + return FACTION; + } + return PUBLIC; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/Permission.java b/src/main/java/com/massivecraft/factions/struct/Permission.java index 3184485d..c174df31 100644 --- a/src/main/java/com/massivecraft/factions/struct/Permission.java +++ b/src/main/java/com/massivecraft/factions/struct/Permission.java @@ -1,125 +1,125 @@ -package com.massivecraft.factions.struct; - -import com.massivecraft.factions.SavageFactions; -import org.bukkit.command.CommandSender; - -public enum Permission { - MANAGE_SAFE_ZONE("managesafezone"), - MANAGE_WAR_ZONE("managewarzone"), - OWNERSHIP_BYPASS("ownershipbypass"), - ADMIN("admin"), - ADMIN_ANY("admin.any"), - AHOME("ahome"), - ANNOUNCE("announce"), - AUTOCLAIM("autoclaim"), - AUTO_LEAVE_BYPASS("autoleavebypass"), - BAN("ban"), - BYPASS("bypass"), - CHAT("chat"), - CHATSPY("chatspy"), - CLAIM("claim"), - CLAIMAT("claimat"), - CLAIM_LINE("claim.line"), - CLAIM_RADIUS("claim.radius"), - CONFIG("config"), - CONVERT("convert"), - CREATE("create"), - DEFAULTRANK("defaultrank"), - DEINVITE("deinvite"), - DESCRIPTION("description"), - DISBAND("disband"), - DISBAND_ANY("disband.any"), - FLY("fly"), - FOCUS("focus"), - HELP("help"), - HOME("home"), - INVITE("invite"), - JOIN("join"), - JOIN_ANY("join.any"), - JOIN_OTHERS("join.others"), - KICK("kick"), - KICK_ANY("kick.any"), - LEAVE("leave"), - LIST("list"), - LOCK("lock"), - MAP("map"), - MAPHEIGHT("mapheight"), - MOD("mod"), - COLEADER("coleader"), - MOD_ANY("mod.any"), - COLEADER_ANY("coleader.any"), - MODIFY_POWER("modifypower"), - MONEY_BALANCE("money.balance"), - MONEY_BALANCE_ANY("money.balance.any"), - MONEY_DEPOSIT("money.deposit"), - MONEY_WITHDRAW("money.withdraw"), - MONEY_WITHDRAW_ANY("money.withdraw.any"), - MONEY_F2F("money.f2f"), - MONEY_F2P("money.f2p"), - MONEY_P2F("money.p2f"), - MONITOR_LOGINS("monitorlogins"), - NO_BOOM("noboom"), - OPEN("open"), - OWNER("owner"), - OWNERLIST("ownerlist"), - SET_PEACEFUL("setpeaceful"), - SET_PERMANENT("setpermanent"), - SET_PERMANENTPOWER("setpermanentpower"), - SHOW_INVITES("showinvites"), - PAYPALSET("setpaypal"), - PERMISSIONS("permissions"), - POWERBOOST("powerboost"), - POWER("power"), - POWER_ANY("power.any"), - PROMOTE("promote"), - RELATION("relation"), - RELOAD("reload"), - SAVE("save"), - SETHOME("sethome"), - SETHOME_ANY("sethome.any"), - SHOW("show"), - STATUS("status"), - STEALTH("stealth"), - STUCK("stuck"), - TAG("tag"), - TNT("tnt"), - TITLE("title"), - TITLE_COLOR("title.color"), - TOGGLE_ALLIANCE_CHAT("togglealliancechat"), - UNCLAIM("unclaim"), - UNCLAIM_ALL("unclaimall"), - VERSION("version"), - SCOREBOARD("scoreboard"), - SEECHUNK("seechunk"), - SETWARP("setwarp"), - TOP("top"), - VAULT("vault"), - GETVAULT("getvault"), - SETMAXVAULTS("setmaxvaults"), - RULES("rules"), - CHECKPOINT("checkpoint"), - UPGRADES("upgrades"), - BANNER("banner"), - TPBANNER("tpbanner"), - KILLHOLOS("killholos"), - INSPECT("inspect"), - TNTFILL("tntfill"), - COORD("coords"), - SHOWCLAIMS("showclaims"), - WARP("warp"), - CHEST("Chest"); - - public final String node; - - Permission(final String node) { - this.node = "factions." + node; - } - - public boolean has(CommandSender sender, boolean informSenderIfNot) { - return SavageFactions.plugin.perm.has(sender, this.node, informSenderIfNot); - } - - public boolean has(CommandSender sender) { - return has(sender, false); - } -} +package com.massivecraft.factions.struct; + +import com.massivecraft.factions.SavageFactions; +import org.bukkit.command.CommandSender; + +public enum Permission { + MANAGE_SAFE_ZONE("managesafezone"), + MANAGE_WAR_ZONE("managewarzone"), + OWNERSHIP_BYPASS("ownershipbypass"), + ADMIN("admin"), + ADMIN_ANY("admin.any"), + AHOME("ahome"), + ANNOUNCE("announce"), + AUTOCLAIM("autoclaim"), + AUTO_LEAVE_BYPASS("autoleavebypass"), + BAN("ban"), + BYPASS("bypass"), + CHAT("chat"), + CHATSPY("chatspy"), + CLAIM("claim"), + CLAIMAT("claimat"), + CLAIM_LINE("claim.line"), + CLAIM_RADIUS("claim.radius"), + CONFIG("config"), + CONVERT("convert"), + CREATE("create"), + DEFAULTRANK("defaultrank"), + DEINVITE("deinvite"), + DESCRIPTION("description"), + DISBAND("disband"), + DISBAND_ANY("disband.any"), + FLY("fly"), + FOCUS("focus"), + HELP("help"), + HOME("home"), + INVITE("invite"), + JOIN("join"), + JOIN_ANY("join.any"), + JOIN_OTHERS("join.others"), + KICK("kick"), + KICK_ANY("kick.any"), + LEAVE("leave"), + LIST("list"), + LOCK("lock"), + MAP("map"), + MAPHEIGHT("mapheight"), + MOD("mod"), + COLEADER("coleader"), + MOD_ANY("mod.any"), + COLEADER_ANY("coleader.any"), + MODIFY_POWER("modifypower"), + MONEY_BALANCE("money.balance"), + MONEY_BALANCE_ANY("money.balance.any"), + MONEY_DEPOSIT("money.deposit"), + MONEY_WITHDRAW("money.withdraw"), + MONEY_WITHDRAW_ANY("money.withdraw.any"), + MONEY_F2F("money.f2f"), + MONEY_F2P("money.f2p"), + MONEY_P2F("money.p2f"), + MONITOR_LOGINS("monitorlogins"), + NO_BOOM("noboom"), + OPEN("open"), + OWNER("owner"), + OWNERLIST("ownerlist"), + SET_PEACEFUL("setpeaceful"), + SET_PERMANENT("setpermanent"), + SET_PERMANENTPOWER("setpermanentpower"), + SHOW_INVITES("showinvites"), + PAYPALSET("setpaypal"), + PERMISSIONS("permissions"), + POWERBOOST("powerboost"), + POWER("power"), + POWER_ANY("power.any"), + PROMOTE("promote"), + RELATION("relation"), + RELOAD("reload"), + SAVE("save"), + SETHOME("sethome"), + SETHOME_ANY("sethome.any"), + SHOW("show"), + STATUS("status"), + STEALTH("stealth"), + STUCK("stuck"), + TAG("tag"), + TNT("tnt"), + TITLE("title"), + TITLE_COLOR("title.color"), + TOGGLE_ALLIANCE_CHAT("togglealliancechat"), + UNCLAIM("unclaim"), + UNCLAIM_ALL("unclaimall"), + VERSION("version"), + SCOREBOARD("scoreboard"), + SEECHUNK("seechunk"), + SETWARP("setwarp"), + TOP("top"), + VAULT("vault"), + GETVAULT("getvault"), + SETMAXVAULTS("setmaxvaults"), + RULES("rules"), + CHECKPOINT("checkpoint"), + UPGRADES("upgrades"), + BANNER("banner"), + TPBANNER("tpbanner"), + KILLHOLOS("killholos"), + INSPECT("inspect"), + TNTFILL("tntfill"), + COORD("coords"), + SHOWCLAIMS("showclaims"), + WARP("warp"), + CHEST("Chest"); + + public final String node; + + Permission(final String node) { + this.node = "factions." + node; + } + + public boolean has(CommandSender sender, boolean informSenderIfNot) { + return SavageFactions.plugin.perm.has(sender, this.node, informSenderIfNot); + } + + public boolean has(CommandSender sender) { + return has(sender, false); + } +} diff --git a/src/main/java/com/massivecraft/factions/struct/Relation.java b/src/main/java/com/massivecraft/factions/struct/Relation.java index 2072352b..66d6039f 100644 --- a/src/main/java/com/massivecraft/factions/struct/Relation.java +++ b/src/main/java/com/massivecraft/factions/struct/Relation.java @@ -15,221 +15,221 @@ import java.util.List; public enum Relation implements Permissable { - MEMBER(4, TL.RELATION_MEMBER_SINGULAR.toString()), - ALLY(3, TL.RELATION_ALLY_SINGULAR.toString()), - TRUCE(2, TL.RELATION_TRUCE_SINGULAR.toString()), - NEUTRAL(1, TL.RELATION_NEUTRAL_SINGULAR.toString()), - ENEMY(0, TL.RELATION_ENEMY_SINGULAR.toString()); + MEMBER(4, TL.RELATION_MEMBER_SINGULAR.toString()), + ALLY(3, TL.RELATION_ALLY_SINGULAR.toString()), + TRUCE(2, TL.RELATION_TRUCE_SINGULAR.toString()), + NEUTRAL(1, TL.RELATION_NEUTRAL_SINGULAR.toString()), + ENEMY(0, TL.RELATION_ENEMY_SINGULAR.toString()); - public final int value; - public final String nicename; + public final int value; + public final String nicename; - Relation(final int value, final String nicename) { - this.value = value; - this.nicename = nicename; - } + Relation(final int value, final String nicename) { + this.value = value; + this.nicename = nicename; + } - public static Relation fromString(String s) { - // Because Java 6 doesn't allow String switches :( - if (s.equalsIgnoreCase(MEMBER.nicename)) { - return MEMBER; - } else if (s.equalsIgnoreCase(ALLY.nicename)) { - return ALLY; - } else if (s.equalsIgnoreCase(TRUCE.nicename)) { - return TRUCE; - } else if (s.equalsIgnoreCase(ENEMY.nicename)) { - return ENEMY; - } else { - return NEUTRAL; // If they somehow mess things up, go back to default behavior. - } - } + public static Relation fromString(String s) { + // Because Java 6 doesn't allow String switches :( + if (s.equalsIgnoreCase(MEMBER.nicename)) { + return MEMBER; + } else if (s.equalsIgnoreCase(ALLY.nicename)) { + return ALLY; + } else if (s.equalsIgnoreCase(TRUCE.nicename)) { + return TRUCE; + } else if (s.equalsIgnoreCase(ENEMY.nicename)) { + return ENEMY; + } else { + return NEUTRAL; // If they somehow mess things up, go back to default behavior. + } + } - @Override - public String toString() { - return this.nicename; - } + @Override + public String toString() { + return this.nicename; + } - public String getTranslation() { - try { - return TL.valueOf("RELATION_" + name() + "_SINGULAR").toString(); - } catch (IllegalArgumentException e) { - return toString(); - } - } + public String getTranslation() { + try { + return TL.valueOf("RELATION_" + name() + "_SINGULAR").toString(); + } catch (IllegalArgumentException e) { + return toString(); + } + } - public String getPluralTranslation() { - for (TL t : TL.values()) { - if (t.name().equalsIgnoreCase("RELATION_" + name() + "_PLURAL")) { - return t.toString(); - } - } - return toString(); - } + public String getPluralTranslation() { + for (TL t : TL.values()) { + if (t.name().equalsIgnoreCase("RELATION_" + name() + "_PLURAL")) { + return t.toString(); + } + } + return toString(); + } - public boolean isMember() { - return this == MEMBER; - } + public boolean isMember() { + return this == MEMBER; + } - public boolean isAlly() { - return this == ALLY; - } + public boolean isAlly() { + return this == ALLY; + } - public boolean isTruce() { - return this == TRUCE; - } + public boolean isTruce() { + return this == TRUCE; + } - public boolean isNeutral() { - return this == NEUTRAL; - } + public boolean isNeutral() { + return this == NEUTRAL; + } - public boolean isEnemy() { - return this == ENEMY; - } + public boolean isEnemy() { + return this == ENEMY; + } - public boolean isAtLeast(Relation relation) { - return this.value >= relation.value; - } + public boolean isAtLeast(Relation relation) { + return this.value >= relation.value; + } - public boolean isAtMost(Relation relation) { - return this.value <= relation.value; - } + public boolean isAtMost(Relation relation) { + return this.value <= relation.value; + } - public ChatColor getColor() { + public ChatColor getColor() { - switch (this) { - case MEMBER: - return Conf.colorMember; - case ALLY: - return Conf.colorAlly; - case NEUTRAL: - return Conf.colorNeutral; - case TRUCE: - return Conf.colorTruce; - default: - return Conf.colorEnemy; - } - } + switch (this) { + case MEMBER: + return Conf.colorMember; + case ALLY: + return Conf.colorAlly; + case NEUTRAL: + return Conf.colorNeutral; + case TRUCE: + return Conf.colorTruce; + default: + return Conf.colorEnemy; + } + } - // return appropriate Conf setting for DenyBuild based on this relation and their online status - public boolean confDenyBuild(boolean online) { - if (isMember()) { - return false; - } + // return appropriate Conf setting for DenyBuild based on this relation and their online status + public boolean confDenyBuild(boolean online) { + if (isMember()) { + return false; + } - if (online) { - if (isEnemy()) { - return Conf.territoryEnemyDenyBuild; - } else if (isAlly()) { - return Conf.territoryAllyDenyBuild; - } else if (isTruce()) { - return Conf.territoryTruceDenyBuild; - } else { - return Conf.territoryDenyBuild; - } - } else { - if (isEnemy()) { - return Conf.territoryEnemyDenyBuildWhenOffline; - } else if (isAlly()) { - return Conf.territoryAllyDenyBuildWhenOffline; - } else if (isTruce()) { - return Conf.territoryTruceDenyBuildWhenOffline; - } else { - return Conf.territoryDenyBuildWhenOffline; - } - } - } + if (online) { + if (isEnemy()) { + return Conf.territoryEnemyDenyBuild; + } else if (isAlly()) { + return Conf.territoryAllyDenyBuild; + } else if (isTruce()) { + return Conf.territoryTruceDenyBuild; + } else { + return Conf.territoryDenyBuild; + } + } else { + if (isEnemy()) { + return Conf.territoryEnemyDenyBuildWhenOffline; + } else if (isAlly()) { + return Conf.territoryAllyDenyBuildWhenOffline; + } else if (isTruce()) { + return Conf.territoryTruceDenyBuildWhenOffline; + } else { + return Conf.territoryDenyBuildWhenOffline; + } + } + } - // return appropriate Conf setting for PainBuild based on this relation and their online status - public boolean confPainBuild(boolean online) { - if (isMember()) { - return false; - } + // return appropriate Conf setting for PainBuild based on this relation and their online status + public boolean confPainBuild(boolean online) { + if (isMember()) { + return false; + } - if (online) { - if (isEnemy()) { - return Conf.territoryEnemyPainBuild; - } else if (isAlly()) { - return Conf.territoryAllyPainBuild; - } else if (isTruce()) { - return Conf.territoryTrucePainBuild; - } else { - return Conf.territoryPainBuild; - } - } else { - if (isEnemy()) { - return Conf.territoryEnemyPainBuildWhenOffline; - } else if (isAlly()) { - return Conf.territoryAllyPainBuildWhenOffline; - } else if (isTruce()) { - return Conf.territoryTrucePainBuildWhenOffline; - } else { - return Conf.territoryPainBuildWhenOffline; - } - } - } + if (online) { + if (isEnemy()) { + return Conf.territoryEnemyPainBuild; + } else if (isAlly()) { + return Conf.territoryAllyPainBuild; + } else if (isTruce()) { + return Conf.territoryTrucePainBuild; + } else { + return Conf.territoryPainBuild; + } + } else { + if (isEnemy()) { + return Conf.territoryEnemyPainBuildWhenOffline; + } else if (isAlly()) { + return Conf.territoryAllyPainBuildWhenOffline; + } else if (isTruce()) { + return Conf.territoryTrucePainBuildWhenOffline; + } else { + return Conf.territoryPainBuildWhenOffline; + } + } + } - // return appropriate Conf setting for DenyUseage based on this relation - public boolean confDenyUseage() { - if (isMember()) { - return false; - } else if (isEnemy()) { - return Conf.territoryEnemyDenyUseage; - } else if (isAlly()) { - return Conf.territoryAllyDenyUseage; - } else if (isTruce()) { - return Conf.territoryTruceDenyUseage; - } else { - return Conf.territoryDenyUseage; - } - } + // return appropriate Conf setting for DenyUseage based on this relation + public boolean confDenyUseage() { + if (isMember()) { + return false; + } else if (isEnemy()) { + return Conf.territoryEnemyDenyUseage; + } else if (isAlly()) { + return Conf.territoryAllyDenyUseage; + } else if (isTruce()) { + return Conf.territoryTruceDenyUseage; + } else { + return Conf.territoryDenyUseage; + } + } - public double getRelationCost() { - if (isEnemy()) { - return Conf.econCostEnemy; - } else if (isAlly()) { - return Conf.econCostAlly; - } else if (isTruce()) { - return Conf.econCostTruce; - } else { - return Conf.econCostNeutral; - } - } + public double getRelationCost() { + if (isEnemy()) { + return Conf.econCostEnemy; + } else if (isAlly()) { + return Conf.econCostAlly; + } else if (isTruce()) { + return Conf.econCostTruce; + } else { + return Conf.econCostNeutral; + } + } - // Utility method to build items for F Perm GUI - @Override - public ItemStack buildItem() { - final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); + // Utility method to build items for F Perm GUI + @Override + public ItemStack buildItem() { + final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); - String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); - List lore = new ArrayList<>(); + String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); + List lore = new ArrayList<>(); - Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase())); - if (material == null) { - return null; - } + Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase())); + if (material == null) { + return null; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { - lore.add(replacePlaceholders(loreLine)); - } + for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine)); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - public String replacePlaceholders(String string) { - string = ChatColor.translateAlternateColorCodes('&', string); + public String replacePlaceholders(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); - String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); + String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); - string = string.replace("{relation-color}", getColor().toString()); - string = string.replace("{relation}", permissableName); + string = string.replace("{relation-color}", getColor().toString()); + string = string.replace("{relation}", permissableName); - return string; - } + return string; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/Role.java b/src/main/java/com/massivecraft/factions/struct/Role.java index 92a94629..226e912e 100644 --- a/src/main/java/com/massivecraft/factions/struct/Role.java +++ b/src/main/java/com/massivecraft/factions/struct/Role.java @@ -15,140 +15,140 @@ import java.util.ArrayList; import java.util.List; public enum Role implements Permissable { - LEADER(4, TL.ROLE_LEADER), - COLEADER(3, TL.ROLE_COLEADER), - MODERATOR(2, TL.ROLE_MODERATOR), - NORMAL(1, TL.ROLE_NORMAL), - RECRUIT(0, TL.ROLE_RECRUIT); + LEADER(4, TL.ROLE_LEADER), + COLEADER(3, TL.ROLE_COLEADER), + MODERATOR(2, TL.ROLE_MODERATOR), + NORMAL(1, TL.ROLE_NORMAL), + RECRUIT(0, TL.ROLE_RECRUIT); - public final int value; - public final String nicename; - public final TL translation; + public final int value; + public final String nicename; + public final TL translation; - Role(final int value, final TL translation) { - this.value = value; - this.nicename = translation.toString(); - this.translation = translation; - } + Role(final int value, final TL translation) { + this.value = value; + this.nicename = translation.toString(); + this.translation = translation; + } - public static Role getRelative(Role role, int relative) { - return Role.getByValue(role.value + relative); - } + public static Role getRelative(Role role, int relative) { + return Role.getByValue(role.value + relative); + } - public static Role getByValue(int value) { - switch (value) { - case 0: - return RECRUIT; - case 1: - return NORMAL; - case 2: - return MODERATOR; - case 3: - return COLEADER; - case 4: - return LEADER; - } + public static Role getByValue(int value) { + switch (value) { + case 0: + return RECRUIT; + case 1: + return NORMAL; + case 2: + return MODERATOR; + case 3: + return COLEADER; + case 4: + return LEADER; + } - return null; - } + return null; + } - public static Role fromString(String check) { - switch (check.toLowerCase()) { - case "leader": - case "admin": - return LEADER; - case "coleader": - return COLEADER; - case "mod": - case "moderator": - return MODERATOR; - case "normal": - case "member": - return NORMAL; - case "recruit": - case "rec": - return RECRUIT; - } + public static Role fromString(String check) { + switch (check.toLowerCase()) { + case "leader": + case "admin": + return LEADER; + case "coleader": + return COLEADER; + case "mod": + case "moderator": + return MODERATOR; + case "normal": + case "member": + return NORMAL; + case "recruit": + case "rec": + return RECRUIT; + } - return null; - } + return null; + } - public boolean isAtLeast(Role role) { - return this.value >= role.value; - } + public boolean isAtLeast(Role role) { + return this.value >= role.value; + } - public boolean isAtMost(Role role) { - return this.value <= role.value; - } + public boolean isAtMost(Role role) { + return this.value <= role.value; + } - @Override - public String toString() { - return this.nicename; - } + @Override + public String toString() { + return this.nicename; + } - public TL getTranslation() { - return translation; - } + public TL getTranslation() { + return translation; + } - public String getPrefix() { + public String getPrefix() { - switch (this) { - case LEADER: - return Conf.prefixLeader; - case COLEADER: - return Conf.prefixCoLeader; - case MODERATOR: - return Conf.prefixMod; - case NORMAL: - return Conf.prefixNormal; - case RECRUIT: - return Conf.prefixRecruit; - } + switch (this) { + case LEADER: + return Conf.prefixLeader; + case COLEADER: + return Conf.prefixCoLeader; + case MODERATOR: + return Conf.prefixMod; + case NORMAL: + return Conf.prefixNormal; + case RECRUIT: + return Conf.prefixRecruit; + } - return ""; - } + return ""; + } - // Utility method to build items for F Perm GUI - @Override - public ItemStack buildItem() { - final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); + // Utility method to build items for F Perm GUI + @Override + public ItemStack buildItem() { + final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); - String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); - List lore = new ArrayList<>(); + String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); + List lore = new ArrayList<>(); - Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase(), "STAINED_CLAY")); - if (material == null) { - return null; - } + Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase(), "STAINED_CLAY")); + if (material == null) { + return null; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { - lore.add(replacePlaceholders(loreLine)); - } + for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine)); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); - } + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); + } - item.setItemMeta(itemMeta); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - public String replacePlaceholders(String string) { - string = ChatColor.translateAlternateColorCodes('&', string); + public String replacePlaceholders(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); - String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); + String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); - string = string.replace("{relation-color}", ChatColor.GREEN.toString()); - string = string.replace("{relation}", permissableName); + string = string.replace("{relation-color}", ChatColor.GREEN.toString()); + string = string.replace("{relation}", permissableName); - return string; - } + return string; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/AsciiCompass.java b/src/main/java/com/massivecraft/factions/util/AsciiCompass.java index a4149c94..f2096851 100644 --- a/src/main/java/com/massivecraft/factions/util/AsciiCompass.java +++ b/src/main/java/com/massivecraft/factions/util/AsciiCompass.java @@ -7,104 +7,104 @@ import java.util.ArrayList; public class AsciiCompass { - public static Point getCompassPointForDirection(double inDegrees) { - double degrees = (inDegrees - 180) % 360; - if (degrees < 0) { - degrees += 360; - } + public static Point getCompassPointForDirection(double inDegrees) { + double degrees = (inDegrees - 180) % 360; + if (degrees < 0) { + degrees += 360; + } - if (0 <= degrees && degrees < 22.5) { - return Point.N; - } else if (22.5 <= degrees && degrees < 67.5) { - return Point.NE; - } else if (67.5 <= degrees && degrees < 112.5) { - return Point.E; - } else if (112.5 <= degrees && degrees < 157.5) { - return Point.SE; - } else if (157.5 <= degrees && degrees < 202.5) { - return Point.S; - } else if (202.5 <= degrees && degrees < 247.5) { - return Point.SW; - } else if (247.5 <= degrees && degrees < 292.5) { - return Point.W; - } else if (292.5 <= degrees && degrees < 337.5) { - return Point.NW; - } else if (337.5 <= degrees && degrees < 360.0) { - return Point.N; - } else { - return null; - } - } + if (0 <= degrees && degrees < 22.5) { + return Point.N; + } else if (22.5 <= degrees && degrees < 67.5) { + return Point.NE; + } else if (67.5 <= degrees && degrees < 112.5) { + return Point.E; + } else if (112.5 <= degrees && degrees < 157.5) { + return Point.SE; + } else if (157.5 <= degrees && degrees < 202.5) { + return Point.S; + } else if (202.5 <= degrees && degrees < 247.5) { + return Point.SW; + } else if (247.5 <= degrees && degrees < 292.5) { + return Point.W; + } else if (292.5 <= degrees && degrees < 337.5) { + return Point.NW; + } else if (337.5 <= degrees && degrees < 360.0) { + return Point.N; + } else { + return null; + } + } - public static ArrayList getAsciiCompass(Point point, ChatColor colorActive, String colorDefault) { - ArrayList ret = new ArrayList<>(); - String row; + public static ArrayList getAsciiCompass(Point point, ChatColor colorActive, String colorDefault) { + ArrayList ret = new ArrayList<>(); + String row; - row = ""; - row += Point.NW.toString(Point.NW == point, colorActive, colorDefault); - row += Point.N.toString(Point.N == point, colorActive, colorDefault); - row += Point.NE.toString(Point.NE == point, colorActive, colorDefault); - ret.add(row); + row = ""; + row += Point.NW.toString(Point.NW == point, colorActive, colorDefault); + row += Point.N.toString(Point.N == point, colorActive, colorDefault); + row += Point.NE.toString(Point.NE == point, colorActive, colorDefault); + ret.add(row); - row = ""; - row += Point.W.toString(Point.W == point, colorActive, colorDefault); - row += colorDefault + "+"; - row += Point.E.toString(Point.E == point, colorActive, colorDefault); - ret.add(row); + row = ""; + row += Point.W.toString(Point.W == point, colorActive, colorDefault); + row += colorDefault + "+"; + row += Point.E.toString(Point.E == point, colorActive, colorDefault); + ret.add(row); - row = ""; - row += Point.SW.toString(Point.SW == point, colorActive, colorDefault); - row += Point.S.toString(Point.S == point, colorActive, colorDefault); - row += Point.SE.toString(Point.SE == point, colorActive, colorDefault); - ret.add(row); + row = ""; + row += Point.SW.toString(Point.SW == point, colorActive, colorDefault); + row += Point.S.toString(Point.S == point, colorActive, colorDefault); + row += Point.SE.toString(Point.SE == point, colorActive, colorDefault); + ret.add(row); - return ret; - } + return ret; + } - public static ArrayList getAsciiCompass(double inDegrees, ChatColor colorActive, String colorDefault) { - return getAsciiCompass(getCompassPointForDirection(inDegrees), colorActive, colorDefault); - } + public static ArrayList getAsciiCompass(double inDegrees, ChatColor colorActive, String colorDefault) { + return getAsciiCompass(getCompassPointForDirection(inDegrees), colorActive, colorDefault); + } - public enum Point { + public enum Point { - N('N'), - NE('/'), - E('E'), - SE('\\'), - S('S'), - SW('/'), - W('W'), - NW('\\'); + N('N'), + NE('/'), + E('E'), + SE('\\'), + S('S'), + SW('/'), + W('W'), + NW('\\'); - public final char asciiChar; + public final char asciiChar; - Point(final char asciiChar) { - this.asciiChar = asciiChar; - } + Point(final char asciiChar) { + this.asciiChar = asciiChar; + } - @Override - public String toString() { - return String.valueOf(this.asciiChar); - } + @Override + public String toString() { + return String.valueOf(this.asciiChar); + } - public String getTranslation() { - if (this == N) { - return TL.COMPASS_SHORT_NORTH.toString(); - } - if (this == E) { - return TL.COMPASS_SHORT_EAST.toString(); - } - if (this == S) { - return TL.COMPASS_SHORT_SOUTH.toString(); - } - if (this == W) { - return TL.COMPASS_SHORT_WEST.toString(); - } - return toString(); - } + public String getTranslation() { + if (this == N) { + return TL.COMPASS_SHORT_NORTH.toString(); + } + if (this == E) { + return TL.COMPASS_SHORT_EAST.toString(); + } + if (this == S) { + return TL.COMPASS_SHORT_SOUTH.toString(); + } + if (this == W) { + return TL.COMPASS_SHORT_WEST.toString(); + } + return toString(); + } - public String toString(boolean isActive, ChatColor colorActive, String colorDefault) { - return (isActive ? colorActive : colorDefault) + getTranslation(); - } - } + public String toString(boolean isActive, ChatColor colorActive, String colorDefault) { + return (isActive ? colorActive : colorDefault) + getTranslation(); + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java b/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java index 0cc7fd62..aae7392a 100644 --- a/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java +++ b/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java @@ -10,84 +10,84 @@ import java.util.logging.Level; public class AutoLeaveProcessTask extends BukkitRunnable { - private transient boolean readyToGo = false; - private transient boolean finished = false; - private transient ListIterator iterator; - private transient double toleranceMillis; + private transient boolean readyToGo = false; + private transient boolean finished = false; + private transient ListIterator iterator; + private transient double toleranceMillis; - public AutoLeaveProcessTask() { - ArrayList fplayers = (ArrayList) FPlayers.getInstance().getAllFPlayers(); - this.iterator = fplayers.listIterator(); - this.toleranceMillis = Conf.autoLeaveAfterDaysOfInactivity * 24 * 60 * 60 * 1000; - this.readyToGo = true; - this.finished = false; - } + public AutoLeaveProcessTask() { + ArrayList fplayers = (ArrayList) FPlayers.getInstance().getAllFPlayers(); + this.iterator = fplayers.listIterator(); + this.toleranceMillis = Conf.autoLeaveAfterDaysOfInactivity * 24 * 60 * 60 * 1000; + this.readyToGo = true; + this.finished = false; + } - public void run() { - if (Conf.autoLeaveAfterDaysOfInactivity <= 0.0 || Conf.autoLeaveRoutineMaxMillisecondsPerTick <= 0.0) { - this.stop(); - return; - } + public void run() { + if (Conf.autoLeaveAfterDaysOfInactivity <= 0.0 || Conf.autoLeaveRoutineMaxMillisecondsPerTick <= 0.0) { + this.stop(); + return; + } - if (!readyToGo) { - return; - } - // this is set so it only does one iteration at a time, no matter how frequently the timer fires - readyToGo = false; - // and this is tracked to keep one iteration from dragging on too long and possibly choking the system if there are a very large number of players to go through - long loopStartTime = System.currentTimeMillis(); + if (!readyToGo) { + return; + } + // this is set so it only does one iteration at a time, no matter how frequently the timer fires + readyToGo = false; + // and this is tracked to keep one iteration from dragging on too long and possibly choking the system if there are a very large number of players to go through + long loopStartTime = System.currentTimeMillis(); - while (iterator.hasNext()) { - long now = System.currentTimeMillis(); + while (iterator.hasNext()) { + long now = System.currentTimeMillis(); - // if this iteration has been running for maximum time, stop to take a breather until next tick - if (now > loopStartTime + Conf.autoLeaveRoutineMaxMillisecondsPerTick) { - readyToGo = true; - return; - } + // if this iteration has been running for maximum time, stop to take a breather until next tick + if (now > loopStartTime + Conf.autoLeaveRoutineMaxMillisecondsPerTick) { + readyToGo = true; + return; + } - FPlayer fplayer = iterator.next(); + FPlayer fplayer = iterator.next(); - // Check if they should be exempt from this. - if (!fplayer.willAutoLeave()) { - SavageFactions.plugin.debug(Level.INFO, fplayer.getName() + " was going to be auto-removed but was set not to."); - continue; - } + // Check if they should be exempt from this. + if (!fplayer.willAutoLeave()) { + SavageFactions.plugin.debug(Level.INFO, fplayer.getName() + " was going to be auto-removed but was set not to."); + continue; + } - if (fplayer.isOffline() && now - fplayer.getLastLoginTime() > toleranceMillis) { - if (Conf.logFactionLeave || Conf.logFactionKick) { - SavageFactions.plugin.log("Player " + fplayer.getName() + " was auto-removed due to inactivity."); - } + if (fplayer.isOffline() && now - fplayer.getLastLoginTime() > toleranceMillis) { + if (Conf.logFactionLeave || Conf.logFactionKick) { + SavageFactions.plugin.log("Player " + fplayer.getName() + " was auto-removed due to inactivity."); + } - // if player is faction admin, sort out the faction since he's going away - if (fplayer.getRole() == Role.LEADER) { - Faction faction = fplayer.getFaction(); - if (faction != null) { - fplayer.getFaction().promoteNewLeader(true); - } - } + // if player is faction admin, sort out the faction since he's going away + if (fplayer.getRole() == Role.LEADER) { + Faction faction = fplayer.getFaction(); + if (faction != null) { + fplayer.getFaction().promoteNewLeader(true); + } + } - fplayer.leave(false); - iterator.remove(); // go ahead and remove this list's link to the FPlayer object - if (Conf.autoLeaveDeleteFPlayerData) { - fplayer.remove(); - } - } - } + fplayer.leave(false); + iterator.remove(); // go ahead and remove this list's link to the FPlayer object + if (Conf.autoLeaveDeleteFPlayerData) { + fplayer.remove(); + } + } + } - // looks like we've finished - this.stop(); - } + // looks like we've finished + this.stop(); + } - // we're done, shut down - public void stop() { - readyToGo = false; - finished = true; + // we're done, shut down + public void stop() { + readyToGo = false; + finished = true; - this.cancel(); - } + this.cancel(); + } - public boolean isFinished() { - return finished; - } + public boolean isFinished() { + return finished; + } } diff --git a/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java b/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java index a13ca1d3..4ffd75b6 100644 --- a/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java +++ b/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java @@ -5,24 +5,24 @@ import com.massivecraft.factions.SavageFactions; public class AutoLeaveTask implements Runnable { - private static AutoLeaveProcessTask task; - double rate; + private static AutoLeaveProcessTask task; + double rate; - public AutoLeaveTask() { - this.rate = Conf.autoLeaveRoutineRunsEveryXMinutes; - } + public AutoLeaveTask() { + this.rate = Conf.autoLeaveRoutineRunsEveryXMinutes; + } - public synchronized void run() { - if (task != null && !task.isFinished()) { - return; - } + public synchronized void run() { + if (task != null && !task.isFinished()) { + return; + } - task = new AutoLeaveProcessTask(); - task.runTaskTimer(SavageFactions.plugin, 1, 1); + task = new AutoLeaveProcessTask(); + task.runTaskTimer(SavageFactions.plugin, 1, 1); - // maybe setting has been changed? if so, restart this task at new rate - if (this.rate != Conf.autoLeaveRoutineRunsEveryXMinutes) { - SavageFactions.plugin.startAutoLeaveTask(true); - } - } + // maybe setting has been changed? if so, restart this task at new rate + if (this.rate != Conf.autoLeaveRoutineRunsEveryXMinutes) { + SavageFactions.plugin.startAutoLeaveTask(true); + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java b/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java index f83b7328..ce552584 100644 --- a/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java +++ b/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java @@ -15,151 +15,151 @@ import java.util.UUID; public class ClipPlaceholderAPIManager extends PlaceholderExpansion implements Relational { - // Identifier for this expansion - @Override - public String getIdentifier() { - return "factionsuuid"; - } + // Identifier for this expansion + @Override + public String getIdentifier() { + return "factionsuuid"; + } - @Override - public String getAuthor() { - return "drtshock"; - } + @Override + public String getAuthor() { + return "drtshock"; + } - // Since we are registering this expansion from the dependency, this can be null - @Override - public String getPlugin() { - return null; - } + // Since we are registering this expansion from the dependency, this can be null + @Override + public String getPlugin() { + return null; + } - // Return the plugin version since this expansion is bundled with the dependency - @Override - public String getVersion() { - return SavageFactions.plugin.getDescription().getVersion(); - } + // Return the plugin version since this expansion is bundled with the dependency + @Override + public String getVersion() { + return SavageFactions.plugin.getDescription().getVersion(); + } - // Relational placeholders - @Override - public String onPlaceholderRequest(Player p1, Player p2, String placeholder) { - if (p1 == null || p2 == null || placeholder == null) { - return ""; - } + // Relational placeholders + @Override + public String onPlaceholderRequest(Player p1, Player p2, String placeholder) { + if (p1 == null || p2 == null || placeholder == null) { + return ""; + } - FPlayer fp1 = FPlayers.getInstance().getByPlayer(p1); - FPlayer fp2 = FPlayers.getInstance().getByPlayer(p2); - if (fp1 == null || fp2 == null) { - return ""; - } + FPlayer fp1 = FPlayers.getInstance().getByPlayer(p1); + FPlayer fp2 = FPlayers.getInstance().getByPlayer(p2); + if (fp1 == null || fp2 == null) { + return ""; + } - switch (placeholder) { - case "relation": - String relationName = fp1.getRelationTo(fp2).nicename; - return relationName != null ? relationName : ""; - case "relation_color": - ChatColor color = fp1.getColorTo(fp2); - return color != null ? color.toString() : ""; - } + switch (placeholder) { + case "relation": + String relationName = fp1.getRelationTo(fp2).nicename; + return relationName != null ? relationName : ""; + case "relation_color": + ChatColor color = fp1.getColorTo(fp2); + return color != null ? color.toString() : ""; + } - return null; - } + return null; + } - @Override - public String onPlaceholderRequest(Player player, String placeholder) { - if (player == null || placeholder == null) { - return ""; - } + @Override + public String onPlaceholderRequest(Player player, String placeholder) { + if (player == null || placeholder == null) { + return ""; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - Faction faction = fPlayer.getFaction(); - switch (placeholder) { - // First list player stuff - case "player_name": - return fPlayer.getName(); - case "player_lastseen": - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fPlayer.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; - return fPlayer.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fPlayer.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - case "player_group": - return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fPlayer.getId()))); - case "player_balance": - return Econ.isSetup() ? Econ.getFriendlyBalance(fPlayer) : TL.ECON_OFF.format("balance"); - case "player_power": - return String.valueOf(fPlayer.getPowerRounded()); - case "player_maxpower": - return String.valueOf(fPlayer.getPowerMaxRounded()); - case "player_kills": - return String.valueOf(fPlayer.getKills()); - case "player_deaths": - return String.valueOf(fPlayer.getDeaths()); - case "player_role_prefix": - return String.valueOf(fPlayer.getRolePrefix()); - case "player_role": - return fPlayer.hasFaction() ? fPlayer.getRole().getPrefix() : ""; - // Then Faction stuff - case "faction_name": - return fPlayer.hasFaction() ? faction.getTag() : ""; - case "faction_power": - return String.valueOf(faction.getPowerRounded()); - case "faction_powermax": - return String.valueOf(faction.getPowerMaxRounded()); - case "faction_description": - return faction.getDescription(); - case "faction_claims": - return String.valueOf(faction.getAllClaims().size()); - case "faction_founded": - return TL.sdf.format(faction.getFoundedDate()); - case "faction_joining": - return (faction.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); - case "faction_peaceful": - return faction.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; - case "faction_powerboost": - double powerBoost = faction.getPowerBoost(); - return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); - case "faction_leader": - FPlayer fAdmin = faction.getFPlayerAdmin(); - return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); - case "faction_warps": - return String.valueOf(faction.getWarps().size()); - case "faction_raidable": - boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && faction.getLandRounded() >= faction.getPowerRounded(); - return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); - case "faction_home_world": - return faction.hasHome() ? faction.getHome().getWorld().getName() : ""; - case "faction_home_x": - return faction.hasHome() ? String.valueOf(faction.getHome().getBlockX()) : ""; - case "faction_home_y": - return faction.hasHome() ? String.valueOf(faction.getHome().getBlockY()) : ""; - case "faction_home_z": - return faction.hasHome() ? String.valueOf(faction.getHome().getBlockZ()) : ""; - case "facion_land_value": - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(faction.getLandRounded())) : TL.ECON_OFF.format("value"); - case "faction_land_refund": - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(faction.getLandRounded())) : TL.ECON_OFF.format("refund"); - case "faction_bank_balance": - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.getBalance(faction.getAccountId())) : TL.ECON_OFF.format("balance"); - case "faction_allies": - return String.valueOf(faction.getRelationCount(Relation.ALLY)); - case "faction_enemies": - return String.valueOf(faction.getRelationCount(Relation.ENEMY)); - case "faction_truces": - return String.valueOf(faction.getRelationCount(Relation.TRUCE)); - case "faction_online": - return String.valueOf(faction.getOnlinePlayers().size()); - case "faction_offline": - return String.valueOf(faction.getFPlayers().size() - faction.getOnlinePlayers().size()); - case "faction_size": - return String.valueOf(faction.getFPlayers().size()); - case "faction_kills": - return String.valueOf(faction.getKills()); - case "faction_deaths": - return String.valueOf(faction.getDeaths()); - case "faction_maxvaults": - return String.valueOf(faction.getMaxVaults()); - case "faction_name_at_location": - Faction factionAtLocation = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); - return factionAtLocation != null ? factionAtLocation.getTag() : Factions.getInstance().getWilderness().getTag(); - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + Faction faction = fPlayer.getFaction(); + switch (placeholder) { + // First list player stuff + case "player_name": + return fPlayer.getName(); + case "player_lastseen": + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fPlayer.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + return fPlayer.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fPlayer.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + case "player_group": + return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fPlayer.getId()))); + case "player_balance": + return Econ.isSetup() ? Econ.getFriendlyBalance(fPlayer) : TL.ECON_OFF.format("balance"); + case "player_power": + return String.valueOf(fPlayer.getPowerRounded()); + case "player_maxpower": + return String.valueOf(fPlayer.getPowerMaxRounded()); + case "player_kills": + return String.valueOf(fPlayer.getKills()); + case "player_deaths": + return String.valueOf(fPlayer.getDeaths()); + case "player_role_prefix": + return String.valueOf(fPlayer.getRolePrefix()); + case "player_role": + return fPlayer.hasFaction() ? fPlayer.getRole().getPrefix() : ""; + // Then Faction stuff + case "faction_name": + return fPlayer.hasFaction() ? faction.getTag() : ""; + case "faction_power": + return String.valueOf(faction.getPowerRounded()); + case "faction_powermax": + return String.valueOf(faction.getPowerMaxRounded()); + case "faction_description": + return faction.getDescription(); + case "faction_claims": + return String.valueOf(faction.getAllClaims().size()); + case "faction_founded": + return TL.sdf.format(faction.getFoundedDate()); + case "faction_joining": + return (faction.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); + case "faction_peaceful": + return faction.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; + case "faction_powerboost": + double powerBoost = faction.getPowerBoost(); + return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); + case "faction_leader": + FPlayer fAdmin = faction.getFPlayerAdmin(); + return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); + case "faction_warps": + return String.valueOf(faction.getWarps().size()); + case "faction_raidable": + boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && faction.getLandRounded() >= faction.getPowerRounded(); + return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); + case "faction_home_world": + return faction.hasHome() ? faction.getHome().getWorld().getName() : ""; + case "faction_home_x": + return faction.hasHome() ? String.valueOf(faction.getHome().getBlockX()) : ""; + case "faction_home_y": + return faction.hasHome() ? String.valueOf(faction.getHome().getBlockY()) : ""; + case "faction_home_z": + return faction.hasHome() ? String.valueOf(faction.getHome().getBlockZ()) : ""; + case "facion_land_value": + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(faction.getLandRounded())) : TL.ECON_OFF.format("value"); + case "faction_land_refund": + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(faction.getLandRounded())) : TL.ECON_OFF.format("refund"); + case "faction_bank_balance": + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.getBalance(faction.getAccountId())) : TL.ECON_OFF.format("balance"); + case "faction_allies": + return String.valueOf(faction.getRelationCount(Relation.ALLY)); + case "faction_enemies": + return String.valueOf(faction.getRelationCount(Relation.ENEMY)); + case "faction_truces": + return String.valueOf(faction.getRelationCount(Relation.TRUCE)); + case "faction_online": + return String.valueOf(faction.getOnlinePlayers().size()); + case "faction_offline": + return String.valueOf(faction.getFPlayers().size() - faction.getOnlinePlayers().size()); + case "faction_size": + return String.valueOf(faction.getFPlayers().size()); + case "faction_kills": + return String.valueOf(faction.getKills()); + case "faction_deaths": + return String.valueOf(faction.getDeaths()); + case "faction_maxvaults": + return String.valueOf(faction.getMaxVaults()); + case "faction_name_at_location": + Faction factionAtLocation = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); + return factionAtLocation != null ? factionAtLocation.getTag() : Factions.getInstance().getWilderness().getTag(); + } - return null; - } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java index f5b2b975..2f0ed3e9 100644 --- a/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java @@ -15,52 +15,52 @@ import java.util.Map; public final class EnumTypeAdapter> extends TypeAdapter { - public static final TypeAdapterFactory ENUM_FACTORY = newEnumTypeHierarchyFactory(); - private final Map nameToConstant = new HashMap<>(); - private final Map constantToName = new HashMap<>(); + public static final TypeAdapterFactory ENUM_FACTORY = newEnumTypeHierarchyFactory(); + private final Map nameToConstant = new HashMap<>(); + private final Map constantToName = new HashMap<>(); - public EnumTypeAdapter(Class classOfT) { - try { - for (T constant : classOfT.getEnumConstants()) { - String name = constant.name(); - SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class); - if (annotation != null) { - name = annotation.value(); - } - nameToConstant.put(name, constant); - constantToName.put(constant, name); - } - } catch (NoSuchFieldException e) { - // ignore since it could be a modified enum - } - } + public EnumTypeAdapter(Class classOfT) { + try { + for (T constant : classOfT.getEnumConstants()) { + String name = constant.name(); + SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class); + if (annotation != null) { + name = annotation.value(); + } + nameToConstant.put(name, constant); + constantToName.put(constant, name); + } + } catch (NoSuchFieldException e) { + // ignore since it could be a modified enum + } + } - public static TypeAdapterFactory newEnumTypeHierarchyFactory() { - return new TypeAdapterFactory() { - @SuppressWarnings({"rawtypes", "unchecked"}) - public TypeAdapter create(Gson gson, TypeToken typeToken) { - Class rawType = typeToken.getRawType(); - if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) { - return null; - } - if (!rawType.isEnum()) { - rawType = rawType.getSuperclass(); // handle anonymous subclasses - } - return (TypeAdapter) new EnumTypeAdapter(rawType); - } - }; - } + public static TypeAdapterFactory newEnumTypeHierarchyFactory() { + return new TypeAdapterFactory() { + @SuppressWarnings({"rawtypes", "unchecked"}) + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Class rawType = typeToken.getRawType(); + if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) { + return null; + } + if (!rawType.isEnum()) { + rawType = rawType.getSuperclass(); // handle anonymous subclasses + } + return (TypeAdapter) new EnumTypeAdapter(rawType); + } + }; + } - public T read(JsonReader in) throws IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - return nameToConstant.get(in.nextString()); - } + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return nameToConstant.get(in.nextString()); + } - public void write(JsonWriter out, T value) throws IOException { - out.value(value == null ? null : constantToName.get(value)); - } + public void write(JsonWriter out, T value) throws IOException { + out.value(value == null ? null : constantToName.get(value)); + } } diff --git a/src/main/java/com/massivecraft/factions/util/FactionGUI.java b/src/main/java/com/massivecraft/factions/util/FactionGUI.java index d4b181bf..37d02903 100644 --- a/src/main/java/com/massivecraft/factions/util/FactionGUI.java +++ b/src/main/java/com/massivecraft/factions/util/FactionGUI.java @@ -4,8 +4,8 @@ import org.bukkit.event.inventory.ClickType; public interface FactionGUI { - void onClick(int slot, ClickType action); + void onClick(int slot, ClickType action); - void build(); + void build(); } diff --git a/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java index 0b941b1d..518d2b3c 100644 --- a/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java @@ -8,20 +8,20 @@ import java.lang.reflect.Type; public class InventoryTypeAdapter implements JsonSerializer, JsonDeserializer { - @Override - public JsonElement serialize(Inventory inventory, Type type, JsonSerializationContext jsonSerializationContext) { + @Override + public JsonElement serialize(Inventory inventory, Type type, JsonSerializationContext jsonSerializationContext) { - JsonObject object = new JsonObject(); - object.add("contents", new JsonPrimitive(InventoryUtil.toBase64(inventory))); - return object; - } + JsonObject object = new JsonObject(); + object.add("contents", new JsonPrimitive(InventoryUtil.toBase64(inventory))); + return object; + } - @Override - public Inventory deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { - JsonObject object = jsonElement.getAsJsonObject(); - return InventoryUtil.fromBase64(object.get("contents").getAsString()); - } + @Override + public Inventory deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { + JsonObject object = jsonElement.getAsJsonObject(); + return InventoryUtil.fromBase64(object.get("contents").getAsString()); + } } diff --git a/src/main/java/com/massivecraft/factions/util/InventoryUtil.java b/src/main/java/com/massivecraft/factions/util/InventoryUtil.java index 98f31df6..a64ad690 100644 --- a/src/main/java/com/massivecraft/factions/util/InventoryUtil.java +++ b/src/main/java/com/massivecraft/factions/util/InventoryUtil.java @@ -14,78 +14,78 @@ import java.io.IOException; public class InventoryUtil { - public static String InventoryToString(ItemStack[] items) throws IllegalStateException { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); - dataOutput.writeInt(items.length); - for (ItemStack item : items) { - dataOutput.writeObject(item); - } - dataOutput.close(); - return Base64Coder.encodeLines(outputStream.toByteArray()); - } catch (Exception e) { - throw new IllegalStateException("Unable to save item stacks.", e); - } - } + public static String InventoryToString(ItemStack[] items) throws IllegalStateException { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + dataOutput.writeInt(items.length); + for (ItemStack item : items) { + dataOutput.writeObject(item); + } + dataOutput.close(); + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + throw new IllegalStateException("Unable to save item stacks.", e); + } + } - public static ItemStack[] StringToInventory(String data) throws IOException { - try { - ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); - BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); - ItemStack[] items = new ItemStack[dataInput.readInt()]; - for (int i = 0; i < items.length; i++) { - items[i] = (ItemStack) dataInput.readObject(); - } - dataInput.close(); - return items; - } catch (ClassNotFoundException e) { - throw new IOException("Unable to decode class type.", e); - } - } + public static ItemStack[] StringToInventory(String data) throws IOException { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + ItemStack[] items = new ItemStack[dataInput.readInt()]; + for (int i = 0; i < items.length; i++) { + items[i] = (ItemStack) dataInput.readObject(); + } + dataInput.close(); + return items; + } catch (ClassNotFoundException e) { + throw new IOException("Unable to decode class type.", e); + } + } - public static String toBase64(Inventory inventory) { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + public static String toBase64(Inventory inventory) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); - // Write the size of the inventory - dataOutput.writeInt(inventory.getSize()); + // Write the size of the inventory + dataOutput.writeInt(inventory.getSize()); - // Save every element in the list - for (int i = 0; i < inventory.getSize(); i++) { - dataOutput.writeObject(inventory.getItem(i)); - } + // Save every element in the list + for (int i = 0; i < inventory.getSize(); i++) { + dataOutput.writeObject(inventory.getItem(i)); + } - // Serialize that array - dataOutput.close(); - return Base64Coder.encodeLines(outputStream.toByteArray()); - } catch (Exception e) { - throw new IllegalStateException("Cannot into itemstacksz!", e); - } - } + // Serialize that array + dataOutput.close(); + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + throw new IllegalStateException("Cannot into itemstacksz!", e); + } + } - public static String toBase64(ItemStack[] is, int size) { - Inventory inventory = Bukkit.createInventory(null, size); - inventory.setContents(is); - return toBase64(inventory); - } + public static String toBase64(ItemStack[] is, int size) { + Inventory inventory = Bukkit.createInventory(null, size); + inventory.setContents(is); + return toBase64(inventory); + } - public static Inventory fromBase64(String data) { - try { - ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); - BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); - Inventory inventory = Bukkit.getServer().createInventory(null, dataInput.readInt()); + public static Inventory fromBase64(String data) { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + Inventory inventory = Bukkit.getServer().createInventory(null, dataInput.readInt()); - // Read the serialized inventory - for (int i = 0; i < inventory.getSize(); i++) { - inventory.setItem(i, (ItemStack) dataInput.readObject()); - } - dataInput.close(); - return inventory; - } catch (Exception e) { - } - return null; - } + // Read the serialized inventory + for (int i = 0; i < inventory.getSize(); i++) { + inventory.setItem(i, (ItemStack) dataInput.readObject()); + } + dataInput.close(); + return inventory; + } catch (Exception e) { + } + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/util/LazyLocation.java b/src/main/java/com/massivecraft/factions/util/LazyLocation.java index a141bbc7..1682d8d3 100644 --- a/src/main/java/com/massivecraft/factions/util/LazyLocation.java +++ b/src/main/java/com/massivecraft/factions/util/LazyLocation.java @@ -12,90 +12,90 @@ import java.io.Serializable; */ public class LazyLocation implements Serializable { - private static final long serialVersionUID = -6049901271320963314L; - private transient Location location = null; - private String worldName; - private double x; - private double y; - private double z; - private float pitch; - private float yaw; + private static final long serialVersionUID = -6049901271320963314L; + private transient Location location = null; + private String worldName; + private double x; + private double y; + private double z; + private float pitch; + private float yaw; - public LazyLocation(Location loc) { - setLocation(loc); - } + public LazyLocation(Location loc) { + setLocation(loc); + } - public LazyLocation(final String worldName, final double x, final double y, final double z) { - this(worldName, x, y, z, 0, 0); - } + public LazyLocation(final String worldName, final double x, final double y, final double z) { + this(worldName, x, y, z, 0, 0); + } - public LazyLocation(final String worldName, final double x, final double y, final double z, final float yaw, final float pitch) { - this.worldName = worldName; - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; - } + public LazyLocation(final String worldName, final double x, final double y, final double z, final float yaw, final float pitch) { + this.worldName = worldName; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } - // This returns the actual Location - public final Location getLocation() { - // make sure Location is initialized before returning it - initLocation(); - return location; - } + // This returns the actual Location + public final Location getLocation() { + // make sure Location is initialized before returning it + initLocation(); + return location; + } - // change the Location - public final void setLocation(Location loc) { - this.location = loc; - this.worldName = loc.getWorld().getName(); - this.x = loc.getX(); - this.y = loc.getY(); - this.z = loc.getZ(); - this.yaw = loc.getYaw(); - this.pitch = loc.getPitch(); - } + // change the Location + public final void setLocation(Location loc) { + this.location = loc; + this.worldName = loc.getWorld().getName(); + this.x = loc.getX(); + this.y = loc.getY(); + this.z = loc.getZ(); + this.yaw = loc.getYaw(); + this.pitch = loc.getPitch(); + } - // This initializes the Location - private void initLocation() { - // if location is already initialized, simply return - if (location != null) { - return; - } + // This initializes the Location + private void initLocation() { + // if location is already initialized, simply return + if (location != null) { + return; + } - // get World; hopefully it's initialized at this point - World world = Bukkit.getWorld(worldName); - if (world == null) { - return; - } + // get World; hopefully it's initialized at this point + World world = Bukkit.getWorld(worldName); + if (world == null) { + return; + } - // store the Location for future calls, and pass it on - location = new Location(world, x, y, z, yaw, pitch); - } + // store the Location for future calls, and pass it on + location = new Location(world, x, y, z, yaw, pitch); + } - public final String getWorldName() { - return worldName; - } + public final String getWorldName() { + return worldName; + } - public final double getX() { - return x; - } + public final double getX() { + return x; + } - public final double getY() { - return y; - } + public final double getY() { + return y; + } - public final double getZ() { - return z; - } + public final double getZ() { + return z; + } - public final double getPitch() { - return pitch; - } + public final double getPitch() { + return pitch; + } - public final double getYaw() { - return yaw; - } + public final double getYaw() { + return yaw; + } } diff --git a/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java index 6c5880a7..99905a00 100644 --- a/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java @@ -10,41 +10,41 @@ import java.util.logging.Level; public class LocationTypeAdapter implements JsonSerializer, JsonDeserializer { - @Override - public JsonElement serialize(Location location, Type type, JsonSerializationContext jsonSerializationContext) { - JsonObject object = new JsonObject(); - try { - object.add("x", new JsonPrimitive(location.getX())); - object.add("y", new JsonPrimitive(location.getY())); - object.add("z", new JsonPrimitive(location.getZ())); - object.add("world", new JsonPrimitive(location.getWorld().toString())); - return object; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Location."); - return object; - } - } + @Override + public JsonElement serialize(Location location, Type type, JsonSerializationContext jsonSerializationContext) { + JsonObject object = new JsonObject(); + try { + object.add("x", new JsonPrimitive(location.getX())); + object.add("y", new JsonPrimitive(location.getY())); + object.add("z", new JsonPrimitive(location.getZ())); + object.add("world", new JsonPrimitive(location.getWorld().toString())); + return object; + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Location."); + return object; + } + } - @Override - public Location deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { - JsonObject object = jsonElement.getAsJsonObject(); - try { + @Override + public Location deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { + JsonObject object = jsonElement.getAsJsonObject(); + try { - return new Location(Bukkit.getWorld(object.get("world").getAsString()), - object.get("x").getAsDouble(), - object.get("y").getAsDouble(), - object.get("z").getAsDouble()); - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while" + - " deserializing a Location."); - return null; - } + return new Location(Bukkit.getWorld(object.get("world").getAsString()), + object.get("x").getAsDouble(), + object.get("y").getAsDouble(), + object.get("z").getAsDouble()); + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while" + + " deserializing a Location."); + return null; + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java index e1d6b60b..a95843d3 100644 --- a/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java @@ -16,89 +16,89 @@ import java.util.logging.Level; public class MapFLocToStringSetTypeAdapter implements JsonDeserializer>>, JsonSerializer>> { - @Override - public Map> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - try { - JsonObject obj = json.getAsJsonObject(); - if (obj == null) { - return null; - } + @Override + public Map> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + JsonObject obj = json.getAsJsonObject(); + if (obj == null) { + return null; + } - Map> locationMap = new ConcurrentHashMap<>(); - Set nameSet; - Iterator iter; - String worldName; - String[] coords; - int x, z; + Map> locationMap = new ConcurrentHashMap<>(); + Set nameSet; + Iterator iter; + String worldName; + String[] coords; + int x, z; - for (Entry entry : obj.entrySet()) { - worldName = entry.getKey(); - for (Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { - coords = entry2.getKey().trim().split("[,\\s]+"); - x = Integer.parseInt(coords[0]); - z = Integer.parseInt(coords[1]); + for (Entry entry : obj.entrySet()) { + worldName = entry.getKey(); + for (Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { + coords = entry2.getKey().trim().split("[,\\s]+"); + x = Integer.parseInt(coords[0]); + z = Integer.parseInt(coords[1]); - nameSet = new HashSet<>(); - iter = entry2.getValue().getAsJsonArray().iterator(); - while (iter.hasNext()) { - nameSet.add(iter.next().getAsString()); - } + nameSet = new HashSet<>(); + iter = entry2.getValue().getAsJsonArray().iterator(); + while (iter.hasNext()) { + nameSet.add(iter.next().getAsString()); + } - locationMap.put(new FLocation(worldName, x, z), nameSet); - } - } + locationMap.put(new FLocation(worldName, x, z), nameSet); + } + } - return locationMap; + return locationMap; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a Map of FLocations to String Sets."); - return null; - } - } + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a Map of FLocations to String Sets."); + return null; + } + } - @Override - public JsonElement serialize(Map> src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject obj = new JsonObject(); + @Override + public JsonElement serialize(Map> src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); - try { - if (src != null) { - FLocation loc; - String locWorld; - Set nameSet; - Iterator iter; - JsonArray nameArray; - JsonPrimitive nameElement; + try { + if (src != null) { + FLocation loc; + String locWorld; + Set nameSet; + Iterator iter; + JsonArray nameArray; + JsonPrimitive nameElement; - for (Entry> entry : src.entrySet()) { - loc = entry.getKey(); - locWorld = loc.getWorldName(); - nameSet = entry.getValue(); + for (Entry> entry : src.entrySet()) { + loc = entry.getKey(); + locWorld = loc.getWorldName(); + nameSet = entry.getValue(); - if (nameSet == null || nameSet.isEmpty()) { - continue; - } + if (nameSet == null || nameSet.isEmpty()) { + continue; + } - nameArray = new JsonArray(); - iter = nameSet.iterator(); - while (iter.hasNext()) { - nameElement = new JsonPrimitive(iter.next()); - nameArray.add(nameElement); - } + nameArray = new JsonArray(); + iter = nameSet.iterator(); + while (iter.hasNext()) { + nameElement = new JsonPrimitive(iter.next()); + nameArray.add(nameElement); + } - if (!obj.has(locWorld)) { - obj.add(locWorld, new JsonObject()); - } + if (!obj.has(locWorld)) { + obj.add(locWorld, new JsonObject()); + } - obj.get(locWorld).getAsJsonObject().add(loc.getCoordString(), nameArray); - } - } - return obj; + obj.get(locWorld).getAsJsonObject().add(loc.getCoordString(), nameArray); + } + } + return obj; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Map of FLocations to String Sets."); - return obj; - } - } + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Map of FLocations to String Sets."); + return obj; + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/MiscUtil.java b/src/main/java/com/massivecraft/factions/util/MiscUtil.java index 07ff1b49..76536007 100644 --- a/src/main/java/com/massivecraft/factions/util/MiscUtil.java +++ b/src/main/java/com/massivecraft/factions/util/MiscUtil.java @@ -18,113 +18,113 @@ import java.util.logging.Level; public class MiscUtil { - /// TODO create tag whitelist!! - public static HashSet substanceChars = - new HashSet<>(Arrays.asList("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""))); + /// TODO create tag whitelist!! + public static HashSet substanceChars = + new HashSet<>(Arrays.asList("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""))); - public static EntityType creatureTypeFromEntity(Entity entity) { - if (!(entity instanceof Creature)) { - return null; - } + public static EntityType creatureTypeFromEntity(Entity entity) { + if (!(entity instanceof Creature)) { + return null; + } - String name = entity.getClass().getSimpleName(); - name = name.substring(5); // Remove "Craft" + String name = entity.getClass().getSimpleName(); + name = name.substring(5); // Remove "Craft" - return EntityType.fromName(name); - } + return EntityType.fromName(name); + } - // Inclusive range - public static long[] range(long start, long end) { - long[] values = new long[(int) Math.abs(end - start) + 1]; + // Inclusive range + public static long[] range(long start, long end) { + long[] values = new long[(int) Math.abs(end - start) + 1]; - if (end < start) { - long oldstart = start; - start = end; - end = oldstart; - } + if (end < start) { + long oldstart = start; + start = end; + end = oldstart; + } - for (long i = start; i <= end; i++) { - values[(int) (i - start)] = i; - } + for (long i = start; i <= end; i++) { + values[(int) (i - start)] = i; + } - return values; - } + return values; + } - public static String getComparisonString(String str) { - StringBuilder ret = new StringBuilder(); + public static String getComparisonString(String str) { + StringBuilder ret = new StringBuilder(); - str = ChatColor.stripColor(str); - str = str.toLowerCase(); + str = ChatColor.stripColor(str); + str = str.toLowerCase(); - for (char c : str.toCharArray()) { - if (substanceChars.contains(String.valueOf(c))) { - ret.append(c); - } - } - return ret.toString().toLowerCase(); - } + for (char c : str.toCharArray()) { + if (substanceChars.contains(String.valueOf(c))) { + ret.append(c); + } + } + return ret.toString().toLowerCase(); + } - public static ArrayList validateTag(String str) { - ArrayList errors = new ArrayList<>(); + public static ArrayList validateTag(String str) { + ArrayList errors = new ArrayList<>(); - if (getComparisonString(str).length() < Conf.factionTagLengthMin) { - errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOSHORT.toString(), Conf.factionTagLengthMin)); - } + if (getComparisonString(str).length() < Conf.factionTagLengthMin) { + errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOSHORT.toString(), Conf.factionTagLengthMin)); + } - if (str.length() > Conf.factionTagLengthMax) { - errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOLONG.toString(), Conf.factionTagLengthMax)); - } + if (str.length() > Conf.factionTagLengthMax) { + errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOLONG.toString(), Conf.factionTagLengthMax)); + } - for (char c : str.toCharArray()) { - if (!substanceChars.contains(String.valueOf(c))) { - errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_ALPHANUMERIC.toString(), c)); - } - } + for (char c : str.toCharArray()) { + if (!substanceChars.contains(String.valueOf(c))) { + errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_ALPHANUMERIC.toString(), c)); + } + } - return errors; - } + return errors; + } - public static Iterable rankOrder(Iterable players) { - List admins = new ArrayList<>(); - List coleaders = new ArrayList<>(); - List moderators = new ArrayList<>(); - List normal = new ArrayList<>(); - List recruit = new ArrayList<>(); + public static Iterable rankOrder(Iterable players) { + List admins = new ArrayList<>(); + List coleaders = new ArrayList<>(); + List moderators = new ArrayList<>(); + List normal = new ArrayList<>(); + List recruit = new ArrayList<>(); - for (FPlayer player : players) { + for (FPlayer player : players) { - // Fix for some data being broken when we added the recruit rank. - if (player.getRole() == null) { - player.setRole(Role.NORMAL); - SavageFactions.plugin.log(Level.WARNING, String.format("Player %s had null role. Setting them to normal. This isn't good D:", player.getName())); - } + // Fix for some data being broken when we added the recruit rank. + if (player.getRole() == null) { + player.setRole(Role.NORMAL); + SavageFactions.plugin.log(Level.WARNING, String.format("Player %s had null role. Setting them to normal. This isn't good D:", player.getName())); + } - switch (player.getRole()) { - case LEADER: - admins.add(player); - break; - case COLEADER: - admins.add(player); - break; - case MODERATOR: - moderators.add(player); - break; - case NORMAL: - normal.add(player); - break; - case RECRUIT: - recruit.add(player); - break; - } - } + switch (player.getRole()) { + case LEADER: + admins.add(player); + break; + case COLEADER: + admins.add(player); + break; + case MODERATOR: + moderators.add(player); + break; + case NORMAL: + normal.add(player); + break; + case RECRUIT: + recruit.add(player); + break; + } + } - List ret = new ArrayList<>(); - ret.addAll(admins); - ret.addAll(coleaders); - ret.addAll(moderators); - ret.addAll(normal); - ret.addAll(recruit); - return ret; - } + List ret = new ArrayList<>(); + ret.addAll(admins); + ret.addAll(coleaders); + ret.addAll(moderators); + ret.addAll(normal); + ret.addAll(recruit); + return ret; + } } diff --git a/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java b/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java index df243e72..6ded7b7d 100644 --- a/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java +++ b/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java @@ -7,968 +7,968 @@ import java.util.HashMap; public enum MultiversionMaterials { - ACACIA_BOAT("BOAT_ACACIA", 0), - ACACIA_BUTTON("WOOD_BUTTON", 0), - ACACIA_DOOR("ACACIA_DOOR", 0), - ACACIA_FENCE("ACACIA_FENCE", 0), - ACACIA_FENCE_GATE("ACACIA_FENCE_GATE", 0), - ACACIA_LEAVES("LEAVES_2", 0), - ACACIA_LOG("LOG_2", 0), - ACACIA_PLANKS("WOOD", 4), - ACACIA_PRESSURE_PLATE("WOOD_PLATE", 0), - ACACIA_SAPLING("SAPLING", 4), - ACACIA_SLAB("WOOD_STEP", 4), - ACACIA_STAIRS("ACACIA_STAIRS", 4), - ACACIA_TRAPDOOR("TRAP_DOOR", 0), - ACACIA_WOOD("LOG_2", 0), - ACTIVATOR_RAIL("ACTIVATOR_RAIL", 0), - AIR("AIR", 0), - ALLIUM("STONE", 0), - ANDESITE("STONE", 5), - ANVIL("ANVIL", 0), - APPLE("APPLE", 0), - ARMOR_STAND("ARMOR_STAND", 0), - ARROW("ARROW", 0), - ATTACHED_MELON_STEM("MELON_STEM", 7), - ATTACHED_PUMPKIN_STEM("PUMPKIN_STEM", 7), - AZURE_BLUET("RED_ROSE", 3), - BAKED_POTATO("BAKED_POTATO", 0), - BARRIER("BARRIER", 0), - BAT_SPAWN_EGG("MONSTER_EGG", 0), - BEACON("BEACON", 0), - BEDROCK("BEDROCK", 0), - BEEF("RAW_BEEF", 0), - BEETROOT("BEETROOT", 0), - BEETROOTS("BEETROOT", 0), - BEETROOT_SEEDS("BEETROOT_SEEDS", 0), - BEETROOT_SOUP("BEETROOT_SOUP", 0), - BIRCH_BOAT("BOAT_BIRCH", 0), - BIRCH_BUTTON("WOOD_BUTTON", 0), - BIRCH_DOOR("BIRCH_DOOR", 0), - BIRCH_FENCE("BIRCH_FENCE", 0), - BIRCH_FENCE_GATE("BIRCH_FENCE_GATE", 0), - BIRCH_LEAVES("LEAVES", 2), - BIRCH_LOG("LOG", 2), - BIRCH_PLANKS("WOOD", 2), - BIRCH_PRESSURE_PLATE("WOOD_PLATE", 0), - BIRCH_SAPLING("SAPLING", 2), - BIRCH_SLAB("WOOD_STEP", 2), - BIRCH_STAIRS("BIRCH_WOOD_STAIRS", 0), - BIRCH_TRAPDOOR("TRAP_DOOR", 0), - BIRCH_WOOD("LOG", 2), - BLACK_BANNER("BANNER", 0), - BLACK_BED("BED", 15), - BLACK_CARPET("CARPET", 15), - BLACK_CONCRETE("CONCRETE", 15), - BLACK_CONCRETE_POWDER("CONCRETE_POWDER", 15), - BLACK_GLAZED_TERRACOTTA("BLACK_GLAZED_TERRACOTTA", 0), - BLACK_SHULKER_BOX("BLACK_SHULKER_BOX", 0), - BLACK_STAINED_GLASS("STAINED_GLASS", 15), - BLACK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 15), - BLACK_TERRACOTTA("STAINED_CLAY", 15), - BLACK_WALL_BANNER("WALL_BANNER", 0), - BLACK_WOOL("WOOL", 15), - BLAZE_POWDER("BLAZE_POWDER", 0), - BLAZE_ROD("BLAZE_ROD", 0), - BLAZE_SPAWN_EGG("MONSTER_EGG", 0), - BLUE_BANNER("BANNER", 11), - BLUE_BED("BED", 4), - BLUE_CARPET("CARPET", 11), - BLUE_CONCRETE("CONCRETE", 11), - BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 11), - BLUE_GLAZED_TERRACOTTA("BLUE_GLAZED_TERRACOTTA", 0), - BLUE_ICE("PACKED_ICE", 0), - BLUE_ORCHID("RED_ROSE", 1), - BLUE_SHULKER_BOX("BLUE_SHULKER_BOX", 0), - BLUE_STAINED_GLASS("STAINED_GLASS", 11), - BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 11), - BLUE_TERRACOTTA("STAINED_CLAY", 11), - BLUE_WALL_BANNER("WALL_BANNER", 11), - BLUE_WOOL("WOOL", 11), - BONE("BONE", 0), - BONE_BLOCK("BONE_BLOCK", 0), - BONE_MEAL("INK_SACK", 15), - BOOK("BOOK", 0), - BOOKSHELF("BOOKSHELF", 0), - BOW("BOW", 0), - BOWL("BOWL", 0), - BRAIN_CORAL("STONE", 0), - BRAIN_CORAL_BLOCK("STONE", 0), - BRAIN_CORAL_FAN("STONE", 0), - BREAD("BREAD", 0), - BREWING_STAND("BREWING_STAND", 0), - BRICK("CLAY_BRICK", 0), - BRICKS("BRICK", 0), - BRICK_SLAB("STEP", 4), - BRICK_STAIRS("BRICK_STAIRS", 0), - BROWN_BANNER("BANNER", 3), - BROWN_BED("BED", 12), - BROWN_CARPET("CARPET", 12), - BROWN_CONCRETE("CONCRETE", 12), - BROWN_CONCRETE_POWDER("CONCRETE_POWDER", 12), - BROWN_GLAZED_TERRACOTTA("BROWN_GLAZED_TERRACOTTA", 0), - BROWN_MUSHROOM("BROWN_MUSHROOM", 0), - BROWN_MUSHROOM_BLOCK("BROWN_MUSHROOM", 0), //UNSURE - BROWN_SHULKER_BOX("BROWN_SHULKER_BOX", 0), - BROWN_STAINED_GLASS("STAINED_GLASS", 12), - BROWN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 12), - BROWN_TERRACOTTA("STAINED_CLAY", 12), - BROWN_WALL_BANNER("WALL_BANNER", 3), - BROWN_WOOL("WOOL", 12), - BUBBLE_COLUMN("STONE", 0), - BUBBLE_CORAL("STONE", 0), - BUBBLE_CORAL_BLOCK("STONE", 0), - BUBBLE_CORAL_FAN("STONE", 0), - BUCKET("BUCKET", 0), - CACTUS("CACTUS", 0), - CACTUS_GREEN("INK_SACK", 2), - CAKE("CAKE", 0), - CARROT("CARROT_ITEM", 0), - CARROTS("CARROT", 0), - CARROT_ON_A_STICK("CARROT_STICK", 0), - CARVED_PUMPKIN("PUMPKIN", 0), - CAULDRON("CAULDRON", 0), - CAVE_AIR("AIR", 0), - CAVE_SPIDER_SPAWN_EGG("MONSTER_EGG", 0), - CHAINMAIL_BOOTS("CHAINMAIL_BOOTS", 0), - CHAINMAIL_CHESTPLATE("CHAINMAIL_CHESTPLATE", 0), - CHAINMAIL_HELMET("CHAINMAIL_HELMET", 0), - CHAINMAIL_LEGGINGS("CHAINMAIL_LEGGINGS", 0), - CHAIN_COMMAND_BLOCK("COMMAND_CHAIN", 0), - CHARCOAL("COAL", 1), - CHEST("CHEST", 0), - CHEST_MINECART("STORAGE_MINECART", 0), - CHICKEN("RAW_CHICKEN", 0), - CHICKEN_SPAWN_EGG("MONSTER_EGG", 0), - CHIPPED_ANVIL("ANVIL", 1), - CHISELED_QUARTZ_BLOCK("QUARTZ_BLOCK", 1), - CHISELED_RED_SANDSTONE("RED_SANDSTONE", 1), - CHISELED_SANDSTONE("SANDSTONE", 1), - CHISELED_STONE_BRICKS("SMOOTH_BRICK", 3), - CHORUS_FLOWER("CHORUS_FLOWER", 0), - CHORUS_FRUIT("CHORUS_FRUIT", 0), - CHORUS_PLANT("CHORUS_PLANT", 0), - CLAY("CLAY", 0), - CLAY_BALL("CLAY_BALL", 0), - CLOCK("WATCH", 0), - COAL("COAL", 0), - COAL_BLOCK("COAL_BLOCK", 0), - COAL_ORE("COAL_ORE", 0), - COARSE_DIRT("DIRT", 1), - COBBLESTONE("COBBLESTONE", 0), - COBBLESTONE_SLAB("STEP", 3), - COBBLESTONE_STAIRS("COBBLESTONE_STAIRS", 0), - COBBLESTONE_WALL("COBBLE_WALL", 0), - COBWEB("WEB", 0), - COCOA("COCOA", 0), - COCOA_BEANS("INK_SACK", 3), - COD("RAW_FISH", 0), - COD_BUCKET("BUCKET", 0), - COD_SPAWN_EGG("MONSTER_EGG", 0), - COMMAND_BLOCK("COMMAND", 0), - COMMAND_BLOCK_MINECART("COMMAND_MINECART", 0), - COMPARATOR("REDSTONE_COMPARATOR", 0), - COMPASS("COMPASS", 0), - CONDUIT("STONE", 0), - COOKED_BEEF("COOKED_BEEF", 0), - COOKED_CHICKEN("COOKED_CHICKEN", 0), - COOKED_COD("COOKED_FISH", 0), - COOKED_MUTTON("COOKED_MUTTON", 0), - COOKED_PORKCHOP("GRILLED_PORK", 0), - COOKED_RABBIT("COOKED_RABBIT", 0), - COOKED_SALMON("COOKED_FISH", 1), - COOKIE("COOKIE", 0), - COW_SPAWN_EGG("MONSTER_EGG", 0), - CRACKED_STONE_BRICKS("SMOOTH_BRICK", 2), - CRAFTING_TABLE("WORKBENCH", 0), - CREEPER_HEAD("SKULL", 0), - CREEPER_SPAWN_EGG("MONSTER_EGG", 0), - CREEPER_WALL_HEAD("SKULL", 0), - CUT_RED_SANDSTONE("STONE", 0), - CUT_SANDSTONE("STONE", 0), - CYAN_BANNER("BANNER", 6), - CYAN_BED("BED", 9), - CYAN_CARPET("CARPET", 9), - CYAN_CONCRETE("CONCRETE", 9), - CYAN_CONCRETE_POWDER("CONCRETE_POWDER", 9), - CYAN_DYE("INK_SACK", 6), - CYAN_GLAZED_TERRACOTTA("CYAN_GLAZED_TERRACOTTA", 0), - CYAN_SHULKER_BOX("CYAN_SHULKER_BOX", 0), - CYAN_STAINED_GLASS("STAINED_GLASS", 9), - CYAN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 9), - CYAN_TERRACOTTA("STAINED_CLAY", 9), - CYAN_WALL_BANNER("WALL_BANNER", 0), - CYAN_WOOL("WOOL", 9), - DAMAGED_ANVIL("ANVIL", 2), - DANDELION("YELLOW_FLOWER", 0), - DANDELION_YELLOW("INK_SACK", 11), - DARK_OAK_BOAT("BOAT_DARK_OAK", 0), - DARK_OAK_BUTTON("WOOD_BUTTON", 0), - DARK_OAK_DOOR("DARK_OAK_DOOR", 0), - DARK_OAK_FENCE("DARK_OAK_FENCE", 0), - DARK_OAK_FENCE_GATE("DARK_OAK_FENCE_GATE", 0), - DARK_OAK_LEAVES("LEAVES_2", 1), - DARK_OAK_LOG("LOG_2", 1), - DARK_OAK_PLANKS("WOOD", 5), - DARK_OAK_PRESSURE_PLATE("WOOD_PLATE", 0), - DARK_OAK_SAPLING("SAPLING", 5), - DARK_OAK_SLAB("WOOD_STEP", 0), - DARK_OAK_STAIRS("DARK_OAK_STAIRS", 0), - DARK_OAK_TRAPDOOR("TRAP_DOOR", 0), - DARK_OAK_WOOD("LOG_2", 1), - DARK_PRISMARINE("PRISMARINE", 2), - DARK_PRISMARINE_SLAB("STONE", 0), - DARK_PRISMARINE_STAIRS("STONE", 0), - DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR", 0), - DEAD_BRAIN_CORAL_BLOCK("STONE", 0), - DEAD_BUBBLE_CORAL_BLOCK("STONE", 0), - DEAD_BUSH("DEAD_BUSH", 0), - DEAD_FIRE_CORAL_BLOCK("STONE", 0), - DEAD_HORN_CORAL_BLOCK("STONE", 0), - DEAD_TUBE_CORAL_BLOCK("STONE", 0), - DEBUG_STICK("STICK", 0), - DETECTOR_RAIL("DETECTOR_RAIL", 0), - DIAMOND("DIAMOND", 0), - DIAMOND_AXE("DIAMOND_AXE", 0), - DIAMOND_BLOCK("DIAMOND_BLOCK", 0), - DIAMOND_BOOTS("DIAMOND_BOOTS", 0), - DIAMOND_CHESTPLATE("DIAMOND_CHESTPLATE", 0), - DIAMOND_HELMET("DIAMOND_HELMET", 0), - DIAMOND_HOE("DIAMOND_HOE", 0), - DIAMOND_HORSE_ARMOR("DIAMOND_BARDING", 0), - DIAMOND_LEGGINGS("DIAMOND_LEGGINGS", 0), - DIAMOND_ORE("DIAMOND_ORE", 0), - DIAMOND_PICKAXE("DIAMOND_PICKAXE", 0), - DIAMOND_SHOVEL("DIAMOND_SPADE", 0), - DIAMOND_SWORD("DIAMOND_SWORD", 0), - DIORITE("STONE", 3), - DIRT("DIRT", 0), - DISPENSER("DISPENSER", 0), - DOLPHIN_SPAWN_EGG("MONSTER_EGG", 0), - DONKEY_SPAWN_EGG("MONSTER_EGG", 0), - DRAGON_BREATH("DRAGONS_BREATH", 0), - DRAGON_EGG("DRAGON_EGG", 0), - DRAGON_HEAD("SKULL", 5), - DRAGON_WALL_HEAD("SKULL", 0), - DRIED_KELP("STONE", 0), - DRIED_KELP_BLOCK("STONE", 0), - DROPPER("DROPPER", 0), - DROWNED_SPAWN_EGG("MONSTER_EGG", 0), - EGG("EGG", 0), - ELDER_GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), - ELYTRA("ELYTRA", 0), - EMERALD("EMERALD", 0), - EMERALD_BLOCK("EMERALD_BLOCK", 0), - EMERALD_ORE("EMERALD_ORE", 0), - ENCHANTED_BOOK("ENCHANTED_BOOK", 0), - ENCHANTED_GOLDEN_APPLE("GOLDEN_APPLE", 1), - ENCHANTING_TABLE("ENCHANTING_TABLE", 0), - ENDERMAN_SPAWN_EGG("MONSTER_EGG", 0), - ENDERMITE_SPAWN_EGG("MONSTER_EGG", 0), - ENDER_CHEST("ENDER_CHEST", 0), - ENDER_EYE("EYE_OF_ENDER", 0), - ENDER_PEARL("ENDER_PEARL", 0), - END_CRYSTAL("END_CRYSTAL", 0), - END_GATEWAY("END_GATEWAY", 0), - END_PORTAL("ENDER_PORTAL", 0), - END_PORTAL_FRAME("ENDER_PORTAL_FRAME", 0), - END_ROD("END_ROD", 0), - END_STONE("ENDER_STONE", 0), - END_STONE_BRICKS("END_BRICKS", 0), - EVOKER_SPAWN_EGG("MONSTER_EGG", 0), - EXPERIENCE_BOTTLE("EXP_BOTTLE", 0), - FARMLAND("SOIL", 0), - FEATHER("FEATHER", 0), - FERMENTED_SPIDER_EYE("FERMENTED_SPIDER_EYE", 0), - FERN("LONG_GRASS", 2), - FILLED_MAP("MAP", 0), - FIRE("FIRE", 0), - FIREWORK_ROCKET("FIREWORK", 0), - FIREWORK_STAR("FIREWORK_CHARGE", 0), - FIRE_CHARGE("FIREBALL", 0), - FIRE_CORAL("STONE", 0), - FIRE_CORAL_BLOCK("STONE", 0), - FIRE_CORAL_FAN("STONE", 0), - FISHING_ROD("FISHING_ROD", 0), - FLINT("FLINT", 0), - FLINT_AND_STEEL("FLINT_AND_STEEL", 0), - FLOWER_POT("FLOWER_POT", 0), - FROSTED_ICE("FROSTED_ICE", 0), - FURNACE("FURNACE", 0), - FURNACE_MINECART("POWERED_MINECART", 0), - GHAST_SPAWN_EGG("MONSTER_EGG", 0), - GHAST_TEAR("GHAST_TEAR", 0), - GLASS("GLASS", 0), - GLASS_BOTTLE("GLASS_BOTTLE", 0), - GLASS_PANE("THIN_GLASS", 0), - GLISTERING_MELON_SLICE("SPECKLED_MELON", 0), - GLOWSTONE("GLOWSTONE", 0), - GLOWSTONE_DUST("GLOWSTONE_DUST", 0), - GOLDEN_APPLE("GOLDEN_APPLE", 0), - GOLDEN_AXE("GOLD_AXE", 0), - GOLDEN_BOOTS("GOLD_BOOTS", 0), - GOLDEN_CARROT("GOLDEN_CARROT", 0), - GOLDEN_CHESTPLATE("GOLD_CHESTPLATE", 0), - GOLDEN_HELMET("GOLD_HELMET", 0), - GOLDEN_HOE("GOLD_HOE", 0), - GOLDEN_HORSE_ARMOR("GOLD_BARDING", 0), - GOLDEN_LEGGINGS("GOLD_LEGGINGS", 0), - GOLDEN_PICKAXE("GOLD_PICKAXE", 0), - GOLDEN_SHOVEL("GOLD_SPADE", 0), - GOLDEN_SWORD("GOLD_SWORD", 0), - GOLD_BLOCK("GOLD_BLOCK", 0), - GOLD_INGOT("GOLD_INGOT", 0), - GOLD_NUGGET("GOLD_NUGGET", 0), - GOLD_ORE("GOLD_ORE", 0), - GRANITE("STONE", 1), - GRASS("GRASS", 0), - GRASS_BLOCK("GRASS", 0), - GRASS_PATH("GRASS_PATH", 0), - GRAVEL("GRAVEL", 0), - GRAY_BANNER("BANNER", 8), - GRAY_BED("BED", 7), - GRAY_CARPET("CARPET", 7), - GRAY_CONCRETE("CONCRETE", 7), - GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 7), - GRAY_DYE("INK_SACK", 8), - GRAY_GLAZED_TERRACOTTA("GRAY_GLAZED_TERRACOTTA", 0), - GRAY_SHULKER_BOX("GRAY_SHULKER_BOX", 0), - GRAY_STAINED_GLASS("STAINED_GLASS", 7), - GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 7), - GRAY_TERRACOTTA("STAINED_CLAY", 7), - GRAY_WALL_BANNER("WALL_BANNER", 0), - GRAY_WOOL("WOOL", 7), - GREEN_BANNER("BANNER", 2), - GREEN_BED("BED", 13), - GREEN_CARPET("CARPET", 13), - GREEN_CONCRETE("CONCRETE", 13), - GREEN_CONCRETE_POWDER("CONCRETE_POWDER", 13), - GREEN_GLAZED_TERRACOTTA("GREEN_GLAZED_TERRACOTTA", 0), - GREEN_SHULKER_BOX("GREEN_SHULKER_BOX", 0), - GREEN_STAINED_GLASS("STAINED_GLASS", 13), - GREEN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 13), - GREEN_TERRACOTTA("STAINED_CLAY", 13), - GREEN_WALL_BANNER("WALL_BANNER", 0), - GREEN_WOOL("WOOL", 13), - GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), - GUNPOWDER("SULPHUR", 0), - HAY_BLOCK("HAY_BLOCK", 0), - HEART_OF_THE_SEA("STONE", 0), - HEAVY_WEIGHTED_PRESSURE_PLATE("IRON_PLATE", 0), - HOPPER("HOPPER", 0), - HOPPER_MINECART("HOPPER_MINECART", 0), - HORN_CORAL("STONE", 0), - HORN_CORAL_BLOCK("STONE", 0), - HORN_CORAL_FAN("STONE", 0), - HORSE_SPAWN_EGG("MONSTER_EGG", 0), - HUSK_SPAWN_EGG("MONSTER_EGG", 0), - ICE("ICE", 0), - INFESTED_CHISELED_STONE_BRICKS("MONSTER_EGGS", 5), - INFESTED_COBBLESTONE("MONSTER_EGGS", 1), - INFESTED_CRACKED_STONE_BRICKS("MONSTER_EGGS", 4), - INFESTED_MOSSY_STONE_BRICKS("MONSTER_EGGS", 3), - INFESTED_STONE("MONSTER_EGGS", 0), - INFESTED_STONE_BRICKS("MONSTER_EGGS", 2), - INK_SAC("INK_SACK", 0), - IRON_AXE("IRON_AXE", 0), - IRON_BARS("IRON_FENCE", 0), - IRON_BLOCK("IRON_BLOCK", 0), - IRON_BOOTS("IRON_BOOTS", 0), - IRON_CHESTPLATE("IRON_CHESTPLATE", 0), - IRON_DOOR("IRON_DOOR", 0), - IRON_HELMET("IRON_HELMET", 0), - IRON_HOE("IRON_HOE", 0), - IRON_HORSE_ARMOR("IRON_BARDING", 0), - IRON_INGOT("IRON_INGOT", 0), - IRON_LEGGINGS("IRON_LEGGINGS", 0), - IRON_NUGGET("IRON_NUGGET", 0), - IRON_ORE("IRON_ORE", 0), - IRON_PICKAXE("IRON_PICKAXE", 0), - IRON_SHOVEL("IRON_SPADE", 0), - IRON_SWORD("IRON_SWORD", 0), - IRON_TRAPDOOR("IRON_TRAPDOOR", 0), - ITEM_FRAME("ITEM_FRAME", 0), - JACK_O_LANTERN("JACK_O_LANTERN", 0), - JUKEBOX("JUKEBOX", 0), - JUNGLE_BOAT("BOAT_JUNGLE", 0), - JUNGLE_BUTTON("WOOD_BUTTON", 0), - JUNGLE_DOOR("JUNGLE_DOOR", 0), - JUNGLE_FENCE("JUNGLE_FENCE", 0), - JUNGLE_FENCE_GATE("JUNGLE_FENCE_GATE", 0), - JUNGLE_LEAVES("LEAVES", 3), - JUNGLE_LOG("LOG", 3), - JUNGLE_PLANKS("WOOD", 3), - JUNGLE_PRESSURE_PLATE("WOOD_PLATE", 0), - JUNGLE_SAPLING("SAPLING", 3), - JUNGLE_SLAB("WOOD_STEP", 3), - JUNGLE_STAIRS("JUNGLE_WOOD_STAIRS", 0), - JUNGLE_TRAPDOOR("TRAP_DOOR", 0), - JUNGLE_WOOD("LOG", 3), - KELP("STONE", 0), - KELP_PLANT("STONE", 0), - KNOWLEDGE_BOOK("KNOWLEDGE_BOOK", 0), - LADDER("LADDER", 0), - LAPIS_BLOCK("LAPIS_BLOCK", 0), - LAPIS_LAZULI("INK_SACK", 4), - LAPIS_ORE("LAPIS_ORE", 0), - LARGE_FERN("DOUBLE_PLANT", 3), - LAVA("LAVA", 0), - LAVA_BUCKET("LAVA_BUCKET", 0), - LEAD("LEASH", 0), - LEATHER("LEATHER", 0), - LEATHER_BOOTS("LEATHER_BOOTS", 0), - LEATHER_CHESTPLATE("LEATHER_CHESTPLATE", 0), - LEATHER_HELMET("LEATHER_HELMET", 0), - LEATHER_LEGGINGS("LEATHER_LEGGINGS", 0), - LEVER("LEVER", 0), - LIGHT_BLUE_BANNER("BANNER", 12), - LIGHT_BLUE_BED("BED", 3), - LIGHT_BLUE_CARPET("CARPET", 3), - LIGHT_BLUE_CONCRETE("CONCRETE", 3), - LIGHT_BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 3), - LIGHT_BLUE_DYE("INK_SACK", 12), - LIGHT_BLUE_GLAZED_TERRACOTTA("LIGHT_BLUE_GLAZED_TERRACOTTA", 0), - LIGHT_BLUE_SHULKER_BOX("LIGHT_BLUE_SHULKER_BOX", 0), - LIGHT_BLUE_STAINED_GLASS("STAINED_GLASS", 3), - LIGHT_BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 3), - LIGHT_BLUE_TERRACOTTA("STAINED_CLAY", 3), - LIGHT_BLUE_WALL_BANNER("BANNER", 0), - LIGHT_BLUE_WOOL("WOOL", 3), - LIGHT_GRAY_BANNER("BANNER", 7), - LIGHT_GRAY_BED("BED", 8), - LIGHT_GRAY_CARPET("CARPET", 8), - LIGHT_GRAY_CONCRETE("CONCRETE", 8), - LIGHT_GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 8), - LIGHT_GRAY_DYE("INK_SACK", 7), - LIGHT_GRAY_GLAZED_TERRACOTTA("SILVER_GLAZED_TERRACOTTA", 0), - LIGHT_GRAY_SHULKER_BOX("SILVER_SHULKER_BOX", 0), - LIGHT_GRAY_STAINED_GLASS("STAINED_GLASS", 8), - LIGHT_GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 8), - LIGHT_GRAY_TERRACOTTA("STAINED_CLAY", 8), - LIGHT_GRAY_WALL_BANNER("WALL_BANNER", 0), - LIGHT_GRAY_WOOL("WOOL", 8), - LIGHT_WEIGHTED_PRESSURE_PLATE("GOLD_PLATE", 0), - LILAC("DOUBLE_PLANT", 1), - LILY_PAD("WATER_LILY", 0), - LIME_BANNER("BANNER", 10), - LIME_BED("BED", 5), - LIME_CARPET("CARPET", 5), - LIME_CONCRETE("CONCRETE", 5), - LIME_CONCRETE_POWDER("CONCRETE_POWDER", 5), - LIME_DYE("INK_SACK", 10), - LIME_GLAZED_TERRACOTTA("LIME_GLAZED_TERRACOTTA", 0), - LIME_SHULKER_BOX("LIME_SHULKER_BOX", 0), - LIME_STAINED_GLASS("STAINED_GLASS", 5), - LIME_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 5), - LIME_TERRACOTTA("STAINED_CLAY", 5), - LIME_WALL_BANNER("WALL_BANNER", 0), - LIME_WOOL("WOOL", 5), - LINGERING_POTION("LINGERING_POTION", 0), - LLAMA_SPAWN_EGG("MONSTER_EGG", 0), - MAGENTA_BANNER("BANNER", 13), - MAGENTA_BED("BED", 2), - MAGENTA_CARPET("CARPET", 2), - MAGENTA_CONCRETE("CONCRETE", 2), - MAGENTA_CONCRETE_POWDER("CONCRETE_POWDER", 2), - MAGENTA_DYE("INK_SACK", 13), - MAGENTA_GLAZED_TERRACOTTA("MAGENTA_GLAZED_TERRACOTTA", 0), - MAGENTA_SHULKER_BOX("MAGENTA_SHULKER_BOX", 0), - MAGENTA_STAINED_GLASS("STAINED_GLASS", 2), - MAGENTA_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 2), - MAGENTA_TERRACOTTA("STAINED_CLAY", 2), - MAGENTA_WALL_BANNER("WALL_BANNER", 0), - MAGENTA_WOOL("WOOL", 2), - MAGMA_BLOCK("MAGMA", 0), - MAGMA_CREAM("MAGMA_CREAM", 0), - MAGMA_CUBE_SPAWN_EGG("MONSTER_EGG", 0), - MAP("MAP", 0), - MELON("MELON_BLOCK", 0), - MELON_SEEDS("MELON_SEEDS", 0), - MELON_SLICE("MELON", 0), - MELON_STEM("MELON_STEM", 0), - MILK_BUCKET("MILK_BUCKET", 0), - MINECART("MINECART", 0), - MOOSHROOM_SPAWN_EGG("MONSTER_EGG", 0), - MOSSY_COBBLESTONE("MOSSY_COBBLESTONE", 0), - MOSSY_COBBLESTONE_WALL("COBBLE_WALL", 1), - MOSSY_STONE_BRICKS("SMOOTH_BRICK", 1), - MOVING_PISTON("PISTON_MOVING_PIECE", 0), - MULE_SPAWN_EGG("MONSTER_EGG", 0), - MUSHROOM_STEM("BROWN_MUSHROOM", 0), - MUSHROOM_STEW("MUSHROOM_SOUP", 0), - MUSIC_DISC_11("GOLD_RECORD", 0), - MUSIC_DISC_13("GREEN_RECORD", 0), - MUSIC_DISC_BLOCKS("RECORD_3", 0), - MUSIC_DISC_CAT("RECORD_4", 0), - MUSIC_DISC_CHIRP("RECORD_5", 0), - MUSIC_DISC_FAR("RECORD_6", 0), - MUSIC_DISC_MALL("RECORD_7", 0), - MUSIC_DISC_MELLOHI("RECORD_8", 0), - MUSIC_DISC_STAL("RECORD_9", 0), - MUSIC_DISC_STRAD("RECORD_10", 0), - MUSIC_DISC_WAIT("RECORD_11", 0), - MUSIC_DISC_WARD("RECORD_12", 0), - MUTTON("MUTTON", 0), - MYCELIUM("MYCEL", 0), - NAME_TAG("NAME_TAG", 0), - NAUTILUS_SHELL("STONE", 0), - NETHERRACK("NETHERRACK", 0), - NETHER_BRICK("NETHER_BRICK", 0), - NETHER_BRICKS("NETHER_BRICK", 0), - NETHER_BRICK_FENCE("NETHER_FENCE", 0), - NETHER_BRICK_SLAB("STEP", 6), - NETHER_BRICK_STAIRS("NETHER_BRICK_STAIRS", 0), - NETHER_PORTAL("PORTAL", 0), - NETHER_QUARTZ_ORE("QUARTZ_ORE", 0), - NETHER_STAR("NETHER_STAR", 0), - NETHER_WART("NETHER_STALK", 0), - NETHER_WART_BLOCK("NETHER_WART_BLOCK", 0), - NOTE_BLOCK("NOTE_BLOCK", 0), - OAK_BOAT("BOAT", 0), - OAK_BUTTON("WOOD_BUTTON", 0), - OAK_DOOR("WOOD_DOOR", 0), - OAK_FENCE("FENCE", 0), - OAK_FENCE_GATE("FENCE_GATE", 0), - OAK_LEAVES("LEAVES", 0), - OAK_LOG("LOG", 0), - OAK_PLANKS("WOOD", 0), - OAK_PRESSURE_PLATE("WOOD_PLATE", 0), - OAK_SAPLING("SAPLING", 0), - OAK_SLAB("WOOD_STEP", 0), - OAK_STAIRS("WOOD_STAIRS", 0), - OAK_TRAPDOOR("TRAP_DOOR", 0), - OAK_WOOD("LOG", 0), - OBSERVER("OBSERVER", 0), - OBSIDIAN("OBSIDIAN", 0), - OCELOT_SPAWN_EGG("RECORD_12", 0), - ORANGE_BANNER("BANNER", 14), - ORANGE_BED("BED", 1), - ORANGE_CARPET("CARPET", 1), - ORANGE_CONCRETE("CONCRETE", 1), - ORANGE_CONCRETE_POWDER("CONCRETE_POWDER", 1), - ORANGE_DYE("INK_SACK", 14), - ORANGE_GLAZED_TERRACOTTA("ORANGE_GLAZED_TERRACOTTA", 0), - ORANGE_SHULKER_BOX("ORANGE_SHULKER_BOX", 0), - ORANGE_STAINED_GLASS("STAINED_GLASS", 1), - ORANGE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 1), - ORANGE_TERRACOTTA("STAINED_CLAY", 1), - ORANGE_TULIP("RED_ROSE", 5), - ORANGE_WALL_BANNER("WALL_BANNER", 0), - ORANGE_WOOL("WOOL", 1), - OXEYE_DAISY("RED_ROSE", 8), - PACKED_ICE("PACKED_ICE", 0), - PAINTING("PAINTING", 0), - PAPER("PAPER", 0), - PARROT_SPAWN_EGG("MONSTER_EGG", 0), - PEONY("DOUBLE_PLANT", 5), - PETRIFIED_OAK_SLAB("STONE", 0), - PHANTOM_MEMBRANE("STONE", 0), - PHANTOM_SPAWN_EGG("MONSTER_EGG", 0), - PIG_SPAWN_EGG("MONSTER_EGG", 0), - PINK_BANNER("BANNER", 9), - PINK_BED("BED", 6), - PINK_CARPET("CARPET", 6), - PINK_CONCRETE("CONCRETE", 6), - PINK_CONCRETE_POWDER("CONCRETE_POWDER", 6), - PINK_DYE("INK_SACK", 9), - PINK_GLAZED_TERRACOTTA("PINK_GLAZED_TERRACOTTA", 0), - PINK_SHULKER_BOX("PINK_SHULKER_BOX", 0), - PINK_STAINED_GLASS("STAINED_GLASS", 6), - PINK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 6), - PINK_TERRACOTTA("STAINED_CLAY", 6), - PINK_TULIP("RED_ROSE", 7), - PINK_WALL_BANNER("WALL_BANNER", 0), - PINK_WOOL("WOOL", 6), - PISTON("PISTON_BASE", 0), - PISTON_HEAD("PISTON_EXTENSION", 0), - PLAYER_HEAD("SKULL", 0), - PLAYER_WALL_HEAD("SKULL", 0), - PODZOL("DIRT", 2), - POISONOUS_POTATO("POISONOUS_POTATO", 0), - POLAR_BEAR_SPAWN_EGG("MONSTER_EGG", 0), - POLISHED_ANDESITE("STONE", 6), - POLISHED_DIORITE("STONE", 4), - POLISHED_GRANITE("STONE", 2), - POPPED_CHORUS_FRUIT("CHORUS_FRUIT_POPPED", 0), - POPPY("RED_ROSE", 0), - PORKCHOP("PORK", 0), - POTATO("POTATO_ITEM", 0), - POTATOES("POTATO", 0), - POTION("POTION", 0), - POTTED_ACACIA_SAPLING("FLOWER_POT", 0), - POTTED_ALLIUM("FLOWER_POT", 0), - POTTED_AZURE_BLUET("FLOWER_POT", 0), - POTTED_BIRCH_SAPLING("FLOWER_POT", 0), - POTTED_BLUE_ORCHID("FLOWER_POT", 0), - POTTED_BROWN_MUSHROOM("FLOWER_POT", 0), - POTTED_CACTUS("FLOWER_POT", 0), - POTTED_DANDELION("FLOWER_POT", 0), - POTTED_DARK_OAK_SAPLING("FLOWER_POT", 0), - POTTED_DEAD_BUSH("FLOWER_POT", 0), - POTTED_FERN("FLOWER_POT", 0), - POTTED_JUNGLE_SAPLING("FLOWER_POT", 0), - POTTED_OAK_SAPLING("FLOWER_POT", 0), - POTTED_ORANGE_TULIP("FLOWER_POT", 0), - POTTED_OXEYE_DAISY("FLOWER_POT", 0), - POTTED_PINK_TULIP("FLOWER_POT", 0), - POTTED_POPPY("FLOWER_POT", 0), - POTTED_RED_MUSHROOM("FLOWER_POT", 0), - POTTED_RED_TULIP("FLOWER_POT", 0), - POTTED_SPRUCE_SAPLING("FLOWER_POT", 0), - POTTED_WHITE_TULIP("FLOWER_POT", 0), - POWERED_RAIL("POWERED_RAIL", 0), - PRISMARINE("PRISMARINE", 0), - PRISMARINE_BRICKS("PRISMARINE", 1), - PRISMARINE_BRICK_SLAB("STONE", 0), - PRISMARINE_BRICK_STAIRS("STONE", 0), - PRISMARINE_CRYSTALS("PRISMARINE_CRYSTALS", 0), - PRISMARINE_SHARD("PRISMARINE_SHARD", 0), - PRISMARINE_SLAB("STONE", 0), - PRISMARINE_STAIRS("STONE", 0), - PUFFERFISH("RAW_FISH", 3), - PUFFERFISH_BUCKET("STONE", 0), - PUFFERFISH_SPAWN_EGG("MONSTER_EGG", 0), - PUMPKIN("PUMPKIN", 0), - PUMPKIN_PIE("PUMPKIN_PIE", 0), - PUMPKIN_SEEDS("PUMPKIN_SEEDS", 0), - PUMPKIN_STEM("PUMPKIN_STEM", 0), - PURPLE_BANNER("BANNER", 5), - PURPLE_BED("BED", 10), - PURPLE_CARPET("CARPET", 10), - PURPLE_CONCRETE("CONCRETE", 10), - PURPLE_CONCRETE_POWDER("CONCRETE_POWDER", 10), - PURPLE_DYE("INK_SACK", 5), - PURPLE_GLAZED_TERRACOTTA("PURPLE_GLAZED_TERRACOTTA", 0), - PURPLE_SHULKER_BOX("PURPLE_SHULKER_BOX", 0), - PURPLE_STAINED_GLASS("STAINED_GLASS", 10), - PURPLE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 10), - PURPLE_TERRACOTTA("STAINED_CLAY", 10), - PURPLE_WALL_BANNER("WALL_BANNER", 0), - PURPLE_WOOL("WOOL", 10), - PURPUR_BLOCK("PURPUR_BLOCK", 0), - PURPUR_PILLAR("PURPUR_PILLAR", 0), - PURPUR_SLAB("PURPUR_SLAB", 0), - PURPUR_STAIRS("PURPUR_STAIRS", 0), - QUARTZ("QUARTZ", 0), - QUARTZ_BLOCK("QUARTZ_BLOCK", 0), - QUARTZ_PILLAR("QUARTZ_BLOCK", 2), - QUARTZ_SLAB("STEP", 7), - QUARTZ_STAIRS("QUARTZ_STAIRS", 0), - RABBIT("RABBIT", 0), - RABBIT_FOOT("RABBIT_FOOT", 0), - RABBIT_HIDE("RABBIT_HIDE", 0), - RABBIT_SPAWN_EGG("MONSTER_EGG", 0), - RABBIT_STEW("RABBIT_STEW", 0), - RAIL("RAILS", 0), - REDSTONE("REDSTONE", 0), - REDSTONE_BLOCK("REDSTONE_BLOCK", 0), - REDSTONE_LAMP("REDSTONE_LAMP_OFF", 0), - REDSTONE_ORE("REDSTONE_ORE", 0), - REDSTONE_TORCH("REDSTONE_TORCH_ON", 0), - REDSTONE_WALL_TORCH("REDSTONE_TORCH_ON", 1), - REDSTONE_WIRE("REDSTONE_WIRE", 0), - RED_BANNER("BANNER", 1), - RED_BED("BED", 14), - RED_CARPET("CARPET", 14), - RED_CONCRETE("CONCRETE", 14), - RED_CONCRETE_POWDER("CONCRETE_POWDER", 14), - RED_GLAZED_TERRACOTTA("RED_GLAZED_TERRACOTTA", 0), - RED_MUSHROOM("RED_MUSHROOM", 0), - RED_MUSHROOM_BLOCK("RED_MUSHROOM", 0), - RED_NETHER_BRICKS("RED_NETHER_BRICK", 0), - RED_SAND("SAND", 1), - RED_SANDSTONE("RED_SANDSTONE", 0), - RED_SANDSTONE_SLAB("STONE_SLAB2", 0), - RED_SANDSTONE_STAIRS("RED_SANDSTONE_STAIRS", 0), - RED_SHULKER_BOX("RED_SHULKER_BOX", 0), - RED_STAINED_GLASS("STAINED_GLASS", 14), - RED_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 14), - RED_TERRACOTTA("STAINED_CLAY", 14), - RED_TULIP("RED_ROSE", 4), - RED_WALL_BANNER("WALL_BANNER", 0), - RED_WOOL("WOOL", 14), - REPEATER("DIODE", 0), - REPEATING_COMMAND_BLOCK("COMMAND_REPEATING", 0), - ROSE_BUSH("DOUBLE_PLANT", 4), - ROSE_RED("INK_SACK", 1), - ROTTEN_FLESH("ROTTEN_FLESH", 0), - SADDLE("SADDLE", 0), - SALMON("RAW_FISH", 1), - SALMON_BUCKET("BUCKET", 0), - SALMON_SPAWN_EGG("MONSTER_EGG", 0), - SAND("SAND", 0), - SANDSTONE("SANDSTONE", 0), - SANDSTONE_SLAB("STEP", 1), - SANDSTONE_STAIRS("SANDSTONE_STAIRS", 0), - SCUTE("STONE", 0), - SEAGRASS("STONE", 0), - SEA_LANTERN("SEA_LANTERN", 0), - SEA_PICKLE("STONE", 0), - SHEARS("SHEARS", 0), - SHEEP_SPAWN_EGG("MONSTER_EGG", 0), - SHIELD("SHIELD", 0), - SHULKER_BOX("PURPLE_SHULKER_BOX", 0), - SHULKER_SHELL("SHULKER_SHELL", 0), - SHULKER_SPAWN_EGG("MONSTER_EGG", 0), - SIGN("SIGN", 0), - SILVERFISH_SPAWN_EGG("MONSTER_EGG", 0), - SKELETON_HORSE_SPAWN_EGG("MONSTER_EGG", 0), - SKELETON_SKULL("SKULL", 0), - SKELETON_SPAWN_EGG("MONSTER_EGG", 0), - SKELETON_WALL_SKULL("SKULL", 0), - SLIME_BALL("SLIME_BALL", 0), - SLIME_BLOCK("SLIME_BLOCK", 0), - SLIME_SPAWN_EGG("MONSTER_EGG", 0), - SMOOTH_QUARTZ("STONE", 0), - SMOOTH_RED_SANDSTONE("RED_SANDSTONE", 2), - SMOOTH_SANDSTONE("SANDSTONE", 2), - SMOOTH_STONE("STEP", 0), - SNOW("SNOW", 0), - SNOWBALL("SNOW_BALL", 0), - SNOW_BLOCK("SNOW_BLOCK", 0), - SOUL_SAND("SOUL_SAND", 0), - SPAWNER("MOB_SPAWNER", 0), - SPECTRAL_ARROW("SPECTRAL_ARROW", 0), - SPIDER_EYE("SPIDER_EYE", 0), - SPIDER_SPAWN_EGG("MONSTER_EGG", 0), - SPLASH_POTION("SPLASH_POTION", 0), - SPONGE("SPONGE", 0), - SPRUCE_BOAT("BOAT_SPRUCE", 0), - SPRUCE_BUTTON("WOOD_BUTTON", 0), - SPRUCE_DOOR("SPRUCE_DOOR", 0), - SPRUCE_FENCE("SPRUCE_FENCE", 0), - SPRUCE_FENCE_GATE("SPRUCE_FENCE_GATE", 0), - SPRUCE_LEAVES("LEAVES", 1), - SPRUCE_LOG("LOG", 1), - SPRUCE_PLANKS("WOOD", 1), - SPRUCE_PRESSURE_PLATE("WOOD_PLATE", 0), - SPRUCE_SAPLING("SAPLING", 1), - SPRUCE_SLAB("WOOD_STEP", 1), - SPRUCE_STAIRS("SPRUCE_WOOD_STAIRS", 0), - SPRUCE_TRAPDOOR("TRAP_DOOR", 0), - SPRUCE_WOOD("LOG", 1), - SQUID_SPAWN_EGG("MONSTER_EGG", 0), - STICK("STICK", 0), - STICKY_PISTON("PISTON_STICKY_BASE", 0), - STONE("STONE", 0), - STONE_AXE("STONE_AXE", 0), - STONE_BRICKS("SMOOTH_BRICK", 0), - STONE_BRICK_SLAB("STEP", 5), - STONE_BRICK_STAIRS("SMOOTH_STAIRS", 0), - STONE_BUTTON("STONE_BUTTON", 0), - STONE_HOE("STONE_HOE", 0), - STONE_PICKAXE("STONE_PICKAXE", 0), - STONE_PRESSURE_PLATE("STONE_PLATE", 0), - STONE_SHOVEL("STONE_SPADE", 0), - STONE_SLAB("STEP", 0), - STONE_SWORD("STONE_SWORD", 0), - STRAY_SPAWN_EGG("MONSTER_EGG", 0), - STRING("STRING", 0), - STRIPPED_ACACIA_LOG("STONE", 0), - STRIPPED_ACACIA_WOOD("STONE", 0), - STRIPPED_BIRCH_LOG("STONE", 0), - STRIPPED_BIRCH_WOOD("STONE", 0), - STRIPPED_DARK_OAK_LOG("STONE", 0), - STRIPPED_DARK_OAK_WOOD("STONE", 0), - STRIPPED_JUNGLE_LOG("STONE", 0), - STRIPPED_JUNGLE_WOOD("STONE", 0), - STRIPPED_OAK_LOG("STONE", 0), - STRIPPED_OAK_WOOD("STONE", 0), - STRIPPED_SPRUCE_LOG("STONE", 0), - STRIPPED_SPRUCE_WOOD("STONE", 0), - STRUCTURE_BLOCK("STRUCTURE_BLOCK", 0), - STRUCTURE_VOID("STRUCTURE_VOID", 0), - SUGAR("SUGAR", 0), - SUGAR_CANE("SUGAR_CANE", 0), - SUNFLOWER("DOUBLE_PLANT", 0), - TALL_GRASS("DOUBLE_PLANT", 2), - TALL_SEAGRASS("STONE", 0), - TERRACOTTA("HARD_CLAY", 0), - TIPPED_ARROW("TIPPED_ARROW", 0), - TNT("TNT", 0), - TNT_MINECART("EXPLOSIVE_MINECART", 0), - TORCH("TORCH", 0), - TOTEM_OF_UNDYING("TOTEM", 0), - TRAPPED_CHEST("TRAPPED_CHEST", 0), - TRIDENT("STONE", 0), - TRIPWIRE("TRIPWIRE", 0), - TRIPWIRE_HOOK("TRIPWIRE_HOOK", 0), - TROPICAL_FISH("RAW_FISH", 0), - TROPICAL_FISH_BUCKET("BUCKET", 0), - TROPICAL_FISH_SPAWN_EGG("MONSTER_EGG", 0), - TUBE_CORAL("STONE", 0), - TUBE_CORAL_BLOCK("STONE", 0), - TUBE_CORAL_FAN("STONE", 0), - TURTLE_EGG("MONSTER_EGG", 0), - TURTLE_HELMET("STONE", 0), - TURTLE_SPAWN_EGG("MONSTER_EGG", 0), - VEX_SPAWN_EGG("MONSTER_EGG", 0), - VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), - VINDICATOR_SPAWN_EGG("MONSTER_EGG", 0), - VINE("VINE", 0), - VOID_AIR("AIR", 0), - WALL_SIGN("WALL_SIGN", 0), - WALL_TORCH("TORCH", 1), - WATER("WATER", 0), - WATER_BUCKET("WATER_BUCKET", 0), - WET_SPONGE("SPONGE", 1), - WHEAT("WHEAT", 0), - WHEAT_SEEDS("SEEDS", 0), - WHITE_BANNER("BANNER", 15), - WHITE_BED("BED", 0), - WHITE_CARPET("CARPET", 0), - WHITE_CONCRETE("CONCRETE", 0), - WHITE_CONCRETE_POWDER("CONCRETE_POWDER", 0), - WHITE_GLAZED_TERRACOTTA("WHITE_GLAZED_TERRACOTTA", 0), - WHITE_SHULKER_BOX("WHITE_SHULKER_BOX", 0), - WHITE_STAINED_GLASS("STAINED_GLASS", 0), - WHITE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 0), - WHITE_TERRACOTTA("TERRACOTTA", 0), - WHITE_TULIP("RED_ROSE", 6), - WHITE_WALL_BANNER("WALL_BANNER", 0), - WHITE_WOOL("WOOL", 0), - WITCH_SPAWN_EGG("MONSTER_EGG", 0), - WITHER_SKELETON_SKULL("SKULL", 0), - WITHER_SKELETON_SPAWN_EGG("MONSTER_EGG", 0), - WITHER_SKELETON_WALL_SKULL("SKULL", 0), - WOLF_SPAWN_EGG("MONSTER_EGG", 0), - WOODEN_AXE("WOOD_AXE", 0), - WOODEN_HOE("WOOD_HOE", 0), - WOODEN_PICKAXE("WOOD_PICKAXE", 0), - WOODEN_SHOVEL("WOOD_SPADE", 0), - WOODEN_SWORD("WOOD_SWORD", 0), - WRITABLE_BOOK("BOOK_AND_QUILL", 0), - WRITTEN_BOOK("WRITTEN_BOOK", 0), - YELLOW_BANNER("BANNER", 11), - YELLOW_BED("BED", 4), - YELLOW_CARPET("CARPET", 4), - YELLOW_CONCRETE("CONCRETE", 4), - YELLOW_CONCRETE_POWDER("CONCRETE_POWDER", 4), - YELLOW_GLAZED_TERRACOTTA("YELLOW_GLAZED_TERRACOTTA", 0), - YELLOW_SHULKER_BOX("YELLOW_SHULKER_BOX", 0), - YELLOW_STAINED_GLASS("STAINED_GLASS", 4), - YELLOW_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 4), - YELLOW_TERRACOTTA("STAINED_CLAY", 4), - YELLOW_WALL_BANNER("WALL_BANNER", 0), - YELLOW_WOOL("WOOL", 4), - ZOMBIE_HEAD("SKULL", 0), - ZOMBIE_HORSE_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_PIGMAN_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_WALL_HEAD("SKULL", 0), - ; + ACACIA_BOAT("BOAT_ACACIA", 0), + ACACIA_BUTTON("WOOD_BUTTON", 0), + ACACIA_DOOR("ACACIA_DOOR", 0), + ACACIA_FENCE("ACACIA_FENCE", 0), + ACACIA_FENCE_GATE("ACACIA_FENCE_GATE", 0), + ACACIA_LEAVES("LEAVES_2", 0), + ACACIA_LOG("LOG_2", 0), + ACACIA_PLANKS("WOOD", 4), + ACACIA_PRESSURE_PLATE("WOOD_PLATE", 0), + ACACIA_SAPLING("SAPLING", 4), + ACACIA_SLAB("WOOD_STEP", 4), + ACACIA_STAIRS("ACACIA_STAIRS", 4), + ACACIA_TRAPDOOR("TRAP_DOOR", 0), + ACACIA_WOOD("LOG_2", 0), + ACTIVATOR_RAIL("ACTIVATOR_RAIL", 0), + AIR("AIR", 0), + ALLIUM("STONE", 0), + ANDESITE("STONE", 5), + ANVIL("ANVIL", 0), + APPLE("APPLE", 0), + ARMOR_STAND("ARMOR_STAND", 0), + ARROW("ARROW", 0), + ATTACHED_MELON_STEM("MELON_STEM", 7), + ATTACHED_PUMPKIN_STEM("PUMPKIN_STEM", 7), + AZURE_BLUET("RED_ROSE", 3), + BAKED_POTATO("BAKED_POTATO", 0), + BARRIER("BARRIER", 0), + BAT_SPAWN_EGG("MONSTER_EGG", 0), + BEACON("BEACON", 0), + BEDROCK("BEDROCK", 0), + BEEF("RAW_BEEF", 0), + BEETROOT("BEETROOT", 0), + BEETROOTS("BEETROOT", 0), + BEETROOT_SEEDS("BEETROOT_SEEDS", 0), + BEETROOT_SOUP("BEETROOT_SOUP", 0), + BIRCH_BOAT("BOAT_BIRCH", 0), + BIRCH_BUTTON("WOOD_BUTTON", 0), + BIRCH_DOOR("BIRCH_DOOR", 0), + BIRCH_FENCE("BIRCH_FENCE", 0), + BIRCH_FENCE_GATE("BIRCH_FENCE_GATE", 0), + BIRCH_LEAVES("LEAVES", 2), + BIRCH_LOG("LOG", 2), + BIRCH_PLANKS("WOOD", 2), + BIRCH_PRESSURE_PLATE("WOOD_PLATE", 0), + BIRCH_SAPLING("SAPLING", 2), + BIRCH_SLAB("WOOD_STEP", 2), + BIRCH_STAIRS("BIRCH_WOOD_STAIRS", 0), + BIRCH_TRAPDOOR("TRAP_DOOR", 0), + BIRCH_WOOD("LOG", 2), + BLACK_BANNER("BANNER", 0), + BLACK_BED("BED", 15), + BLACK_CARPET("CARPET", 15), + BLACK_CONCRETE("CONCRETE", 15), + BLACK_CONCRETE_POWDER("CONCRETE_POWDER", 15), + BLACK_GLAZED_TERRACOTTA("BLACK_GLAZED_TERRACOTTA", 0), + BLACK_SHULKER_BOX("BLACK_SHULKER_BOX", 0), + BLACK_STAINED_GLASS("STAINED_GLASS", 15), + BLACK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 15), + BLACK_TERRACOTTA("STAINED_CLAY", 15), + BLACK_WALL_BANNER("WALL_BANNER", 0), + BLACK_WOOL("WOOL", 15), + BLAZE_POWDER("BLAZE_POWDER", 0), + BLAZE_ROD("BLAZE_ROD", 0), + BLAZE_SPAWN_EGG("MONSTER_EGG", 0), + BLUE_BANNER("BANNER", 11), + BLUE_BED("BED", 4), + BLUE_CARPET("CARPET", 11), + BLUE_CONCRETE("CONCRETE", 11), + BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 11), + BLUE_GLAZED_TERRACOTTA("BLUE_GLAZED_TERRACOTTA", 0), + BLUE_ICE("PACKED_ICE", 0), + BLUE_ORCHID("RED_ROSE", 1), + BLUE_SHULKER_BOX("BLUE_SHULKER_BOX", 0), + BLUE_STAINED_GLASS("STAINED_GLASS", 11), + BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 11), + BLUE_TERRACOTTA("STAINED_CLAY", 11), + BLUE_WALL_BANNER("WALL_BANNER", 11), + BLUE_WOOL("WOOL", 11), + BONE("BONE", 0), + BONE_BLOCK("BONE_BLOCK", 0), + BONE_MEAL("INK_SACK", 15), + BOOK("BOOK", 0), + BOOKSHELF("BOOKSHELF", 0), + BOW("BOW", 0), + BOWL("BOWL", 0), + BRAIN_CORAL("STONE", 0), + BRAIN_CORAL_BLOCK("STONE", 0), + BRAIN_CORAL_FAN("STONE", 0), + BREAD("BREAD", 0), + BREWING_STAND("BREWING_STAND", 0), + BRICK("CLAY_BRICK", 0), + BRICKS("BRICK", 0), + BRICK_SLAB("STEP", 4), + BRICK_STAIRS("BRICK_STAIRS", 0), + BROWN_BANNER("BANNER", 3), + BROWN_BED("BED", 12), + BROWN_CARPET("CARPET", 12), + BROWN_CONCRETE("CONCRETE", 12), + BROWN_CONCRETE_POWDER("CONCRETE_POWDER", 12), + BROWN_GLAZED_TERRACOTTA("BROWN_GLAZED_TERRACOTTA", 0), + BROWN_MUSHROOM("BROWN_MUSHROOM", 0), + BROWN_MUSHROOM_BLOCK("BROWN_MUSHROOM", 0), //UNSURE + BROWN_SHULKER_BOX("BROWN_SHULKER_BOX", 0), + BROWN_STAINED_GLASS("STAINED_GLASS", 12), + BROWN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 12), + BROWN_TERRACOTTA("STAINED_CLAY", 12), + BROWN_WALL_BANNER("WALL_BANNER", 3), + BROWN_WOOL("WOOL", 12), + BUBBLE_COLUMN("STONE", 0), + BUBBLE_CORAL("STONE", 0), + BUBBLE_CORAL_BLOCK("STONE", 0), + BUBBLE_CORAL_FAN("STONE", 0), + BUCKET("BUCKET", 0), + CACTUS("CACTUS", 0), + CACTUS_GREEN("INK_SACK", 2), + CAKE("CAKE", 0), + CARROT("CARROT_ITEM", 0), + CARROTS("CARROT", 0), + CARROT_ON_A_STICK("CARROT_STICK", 0), + CARVED_PUMPKIN("PUMPKIN", 0), + CAULDRON("CAULDRON", 0), + CAVE_AIR("AIR", 0), + CAVE_SPIDER_SPAWN_EGG("MONSTER_EGG", 0), + CHAINMAIL_BOOTS("CHAINMAIL_BOOTS", 0), + CHAINMAIL_CHESTPLATE("CHAINMAIL_CHESTPLATE", 0), + CHAINMAIL_HELMET("CHAINMAIL_HELMET", 0), + CHAINMAIL_LEGGINGS("CHAINMAIL_LEGGINGS", 0), + CHAIN_COMMAND_BLOCK("COMMAND_CHAIN", 0), + CHARCOAL("COAL", 1), + CHEST("CHEST", 0), + CHEST_MINECART("STORAGE_MINECART", 0), + CHICKEN("RAW_CHICKEN", 0), + CHICKEN_SPAWN_EGG("MONSTER_EGG", 0), + CHIPPED_ANVIL("ANVIL", 1), + CHISELED_QUARTZ_BLOCK("QUARTZ_BLOCK", 1), + CHISELED_RED_SANDSTONE("RED_SANDSTONE", 1), + CHISELED_SANDSTONE("SANDSTONE", 1), + CHISELED_STONE_BRICKS("SMOOTH_BRICK", 3), + CHORUS_FLOWER("CHORUS_FLOWER", 0), + CHORUS_FRUIT("CHORUS_FRUIT", 0), + CHORUS_PLANT("CHORUS_PLANT", 0), + CLAY("CLAY", 0), + CLAY_BALL("CLAY_BALL", 0), + CLOCK("WATCH", 0), + COAL("COAL", 0), + COAL_BLOCK("COAL_BLOCK", 0), + COAL_ORE("COAL_ORE", 0), + COARSE_DIRT("DIRT", 1), + COBBLESTONE("COBBLESTONE", 0), + COBBLESTONE_SLAB("STEP", 3), + COBBLESTONE_STAIRS("COBBLESTONE_STAIRS", 0), + COBBLESTONE_WALL("COBBLE_WALL", 0), + COBWEB("WEB", 0), + COCOA("COCOA", 0), + COCOA_BEANS("INK_SACK", 3), + COD("RAW_FISH", 0), + COD_BUCKET("BUCKET", 0), + COD_SPAWN_EGG("MONSTER_EGG", 0), + COMMAND_BLOCK("COMMAND", 0), + COMMAND_BLOCK_MINECART("COMMAND_MINECART", 0), + COMPARATOR("REDSTONE_COMPARATOR", 0), + COMPASS("COMPASS", 0), + CONDUIT("STONE", 0), + COOKED_BEEF("COOKED_BEEF", 0), + COOKED_CHICKEN("COOKED_CHICKEN", 0), + COOKED_COD("COOKED_FISH", 0), + COOKED_MUTTON("COOKED_MUTTON", 0), + COOKED_PORKCHOP("GRILLED_PORK", 0), + COOKED_RABBIT("COOKED_RABBIT", 0), + COOKED_SALMON("COOKED_FISH", 1), + COOKIE("COOKIE", 0), + COW_SPAWN_EGG("MONSTER_EGG", 0), + CRACKED_STONE_BRICKS("SMOOTH_BRICK", 2), + CRAFTING_TABLE("WORKBENCH", 0), + CREEPER_HEAD("SKULL", 0), + CREEPER_SPAWN_EGG("MONSTER_EGG", 0), + CREEPER_WALL_HEAD("SKULL", 0), + CUT_RED_SANDSTONE("STONE", 0), + CUT_SANDSTONE("STONE", 0), + CYAN_BANNER("BANNER", 6), + CYAN_BED("BED", 9), + CYAN_CARPET("CARPET", 9), + CYAN_CONCRETE("CONCRETE", 9), + CYAN_CONCRETE_POWDER("CONCRETE_POWDER", 9), + CYAN_DYE("INK_SACK", 6), + CYAN_GLAZED_TERRACOTTA("CYAN_GLAZED_TERRACOTTA", 0), + CYAN_SHULKER_BOX("CYAN_SHULKER_BOX", 0), + CYAN_STAINED_GLASS("STAINED_GLASS", 9), + CYAN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 9), + CYAN_TERRACOTTA("STAINED_CLAY", 9), + CYAN_WALL_BANNER("WALL_BANNER", 0), + CYAN_WOOL("WOOL", 9), + DAMAGED_ANVIL("ANVIL", 2), + DANDELION("YELLOW_FLOWER", 0), + DANDELION_YELLOW("INK_SACK", 11), + DARK_OAK_BOAT("BOAT_DARK_OAK", 0), + DARK_OAK_BUTTON("WOOD_BUTTON", 0), + DARK_OAK_DOOR("DARK_OAK_DOOR", 0), + DARK_OAK_FENCE("DARK_OAK_FENCE", 0), + DARK_OAK_FENCE_GATE("DARK_OAK_FENCE_GATE", 0), + DARK_OAK_LEAVES("LEAVES_2", 1), + DARK_OAK_LOG("LOG_2", 1), + DARK_OAK_PLANKS("WOOD", 5), + DARK_OAK_PRESSURE_PLATE("WOOD_PLATE", 0), + DARK_OAK_SAPLING("SAPLING", 5), + DARK_OAK_SLAB("WOOD_STEP", 0), + DARK_OAK_STAIRS("DARK_OAK_STAIRS", 0), + DARK_OAK_TRAPDOOR("TRAP_DOOR", 0), + DARK_OAK_WOOD("LOG_2", 1), + DARK_PRISMARINE("PRISMARINE", 2), + DARK_PRISMARINE_SLAB("STONE", 0), + DARK_PRISMARINE_STAIRS("STONE", 0), + DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR", 0), + DEAD_BRAIN_CORAL_BLOCK("STONE", 0), + DEAD_BUBBLE_CORAL_BLOCK("STONE", 0), + DEAD_BUSH("DEAD_BUSH", 0), + DEAD_FIRE_CORAL_BLOCK("STONE", 0), + DEAD_HORN_CORAL_BLOCK("STONE", 0), + DEAD_TUBE_CORAL_BLOCK("STONE", 0), + DEBUG_STICK("STICK", 0), + DETECTOR_RAIL("DETECTOR_RAIL", 0), + DIAMOND("DIAMOND", 0), + DIAMOND_AXE("DIAMOND_AXE", 0), + DIAMOND_BLOCK("DIAMOND_BLOCK", 0), + DIAMOND_BOOTS("DIAMOND_BOOTS", 0), + DIAMOND_CHESTPLATE("DIAMOND_CHESTPLATE", 0), + DIAMOND_HELMET("DIAMOND_HELMET", 0), + DIAMOND_HOE("DIAMOND_HOE", 0), + DIAMOND_HORSE_ARMOR("DIAMOND_BARDING", 0), + DIAMOND_LEGGINGS("DIAMOND_LEGGINGS", 0), + DIAMOND_ORE("DIAMOND_ORE", 0), + DIAMOND_PICKAXE("DIAMOND_PICKAXE", 0), + DIAMOND_SHOVEL("DIAMOND_SPADE", 0), + DIAMOND_SWORD("DIAMOND_SWORD", 0), + DIORITE("STONE", 3), + DIRT("DIRT", 0), + DISPENSER("DISPENSER", 0), + DOLPHIN_SPAWN_EGG("MONSTER_EGG", 0), + DONKEY_SPAWN_EGG("MONSTER_EGG", 0), + DRAGON_BREATH("DRAGONS_BREATH", 0), + DRAGON_EGG("DRAGON_EGG", 0), + DRAGON_HEAD("SKULL", 5), + DRAGON_WALL_HEAD("SKULL", 0), + DRIED_KELP("STONE", 0), + DRIED_KELP_BLOCK("STONE", 0), + DROPPER("DROPPER", 0), + DROWNED_SPAWN_EGG("MONSTER_EGG", 0), + EGG("EGG", 0), + ELDER_GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), + ELYTRA("ELYTRA", 0), + EMERALD("EMERALD", 0), + EMERALD_BLOCK("EMERALD_BLOCK", 0), + EMERALD_ORE("EMERALD_ORE", 0), + ENCHANTED_BOOK("ENCHANTED_BOOK", 0), + ENCHANTED_GOLDEN_APPLE("GOLDEN_APPLE", 1), + ENCHANTING_TABLE("ENCHANTING_TABLE", 0), + ENDERMAN_SPAWN_EGG("MONSTER_EGG", 0), + ENDERMITE_SPAWN_EGG("MONSTER_EGG", 0), + ENDER_CHEST("ENDER_CHEST", 0), + ENDER_EYE("EYE_OF_ENDER", 0), + ENDER_PEARL("ENDER_PEARL", 0), + END_CRYSTAL("END_CRYSTAL", 0), + END_GATEWAY("END_GATEWAY", 0), + END_PORTAL("ENDER_PORTAL", 0), + END_PORTAL_FRAME("ENDER_PORTAL_FRAME", 0), + END_ROD("END_ROD", 0), + END_STONE("ENDER_STONE", 0), + END_STONE_BRICKS("END_BRICKS", 0), + EVOKER_SPAWN_EGG("MONSTER_EGG", 0), + EXPERIENCE_BOTTLE("EXP_BOTTLE", 0), + FARMLAND("SOIL", 0), + FEATHER("FEATHER", 0), + FERMENTED_SPIDER_EYE("FERMENTED_SPIDER_EYE", 0), + FERN("LONG_GRASS", 2), + FILLED_MAP("MAP", 0), + FIRE("FIRE", 0), + FIREWORK_ROCKET("FIREWORK", 0), + FIREWORK_STAR("FIREWORK_CHARGE", 0), + FIRE_CHARGE("FIREBALL", 0), + FIRE_CORAL("STONE", 0), + FIRE_CORAL_BLOCK("STONE", 0), + FIRE_CORAL_FAN("STONE", 0), + FISHING_ROD("FISHING_ROD", 0), + FLINT("FLINT", 0), + FLINT_AND_STEEL("FLINT_AND_STEEL", 0), + FLOWER_POT("FLOWER_POT", 0), + FROSTED_ICE("FROSTED_ICE", 0), + FURNACE("FURNACE", 0), + FURNACE_MINECART("POWERED_MINECART", 0), + GHAST_SPAWN_EGG("MONSTER_EGG", 0), + GHAST_TEAR("GHAST_TEAR", 0), + GLASS("GLASS", 0), + GLASS_BOTTLE("GLASS_BOTTLE", 0), + GLASS_PANE("THIN_GLASS", 0), + GLISTERING_MELON_SLICE("SPECKLED_MELON", 0), + GLOWSTONE("GLOWSTONE", 0), + GLOWSTONE_DUST("GLOWSTONE_DUST", 0), + GOLDEN_APPLE("GOLDEN_APPLE", 0), + GOLDEN_AXE("GOLD_AXE", 0), + GOLDEN_BOOTS("GOLD_BOOTS", 0), + GOLDEN_CARROT("GOLDEN_CARROT", 0), + GOLDEN_CHESTPLATE("GOLD_CHESTPLATE", 0), + GOLDEN_HELMET("GOLD_HELMET", 0), + GOLDEN_HOE("GOLD_HOE", 0), + GOLDEN_HORSE_ARMOR("GOLD_BARDING", 0), + GOLDEN_LEGGINGS("GOLD_LEGGINGS", 0), + GOLDEN_PICKAXE("GOLD_PICKAXE", 0), + GOLDEN_SHOVEL("GOLD_SPADE", 0), + GOLDEN_SWORD("GOLD_SWORD", 0), + GOLD_BLOCK("GOLD_BLOCK", 0), + GOLD_INGOT("GOLD_INGOT", 0), + GOLD_NUGGET("GOLD_NUGGET", 0), + GOLD_ORE("GOLD_ORE", 0), + GRANITE("STONE", 1), + GRASS("GRASS", 0), + GRASS_BLOCK("GRASS", 0), + GRASS_PATH("GRASS_PATH", 0), + GRAVEL("GRAVEL", 0), + GRAY_BANNER("BANNER", 8), + GRAY_BED("BED", 7), + GRAY_CARPET("CARPET", 7), + GRAY_CONCRETE("CONCRETE", 7), + GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 7), + GRAY_DYE("INK_SACK", 8), + GRAY_GLAZED_TERRACOTTA("GRAY_GLAZED_TERRACOTTA", 0), + GRAY_SHULKER_BOX("GRAY_SHULKER_BOX", 0), + GRAY_STAINED_GLASS("STAINED_GLASS", 7), + GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 7), + GRAY_TERRACOTTA("STAINED_CLAY", 7), + GRAY_WALL_BANNER("WALL_BANNER", 0), + GRAY_WOOL("WOOL", 7), + GREEN_BANNER("BANNER", 2), + GREEN_BED("BED", 13), + GREEN_CARPET("CARPET", 13), + GREEN_CONCRETE("CONCRETE", 13), + GREEN_CONCRETE_POWDER("CONCRETE_POWDER", 13), + GREEN_GLAZED_TERRACOTTA("GREEN_GLAZED_TERRACOTTA", 0), + GREEN_SHULKER_BOX("GREEN_SHULKER_BOX", 0), + GREEN_STAINED_GLASS("STAINED_GLASS", 13), + GREEN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 13), + GREEN_TERRACOTTA("STAINED_CLAY", 13), + GREEN_WALL_BANNER("WALL_BANNER", 0), + GREEN_WOOL("WOOL", 13), + GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), + GUNPOWDER("SULPHUR", 0), + HAY_BLOCK("HAY_BLOCK", 0), + HEART_OF_THE_SEA("STONE", 0), + HEAVY_WEIGHTED_PRESSURE_PLATE("IRON_PLATE", 0), + HOPPER("HOPPER", 0), + HOPPER_MINECART("HOPPER_MINECART", 0), + HORN_CORAL("STONE", 0), + HORN_CORAL_BLOCK("STONE", 0), + HORN_CORAL_FAN("STONE", 0), + HORSE_SPAWN_EGG("MONSTER_EGG", 0), + HUSK_SPAWN_EGG("MONSTER_EGG", 0), + ICE("ICE", 0), + INFESTED_CHISELED_STONE_BRICKS("MONSTER_EGGS", 5), + INFESTED_COBBLESTONE("MONSTER_EGGS", 1), + INFESTED_CRACKED_STONE_BRICKS("MONSTER_EGGS", 4), + INFESTED_MOSSY_STONE_BRICKS("MONSTER_EGGS", 3), + INFESTED_STONE("MONSTER_EGGS", 0), + INFESTED_STONE_BRICKS("MONSTER_EGGS", 2), + INK_SAC("INK_SACK", 0), + IRON_AXE("IRON_AXE", 0), + IRON_BARS("IRON_FENCE", 0), + IRON_BLOCK("IRON_BLOCK", 0), + IRON_BOOTS("IRON_BOOTS", 0), + IRON_CHESTPLATE("IRON_CHESTPLATE", 0), + IRON_DOOR("IRON_DOOR", 0), + IRON_HELMET("IRON_HELMET", 0), + IRON_HOE("IRON_HOE", 0), + IRON_HORSE_ARMOR("IRON_BARDING", 0), + IRON_INGOT("IRON_INGOT", 0), + IRON_LEGGINGS("IRON_LEGGINGS", 0), + IRON_NUGGET("IRON_NUGGET", 0), + IRON_ORE("IRON_ORE", 0), + IRON_PICKAXE("IRON_PICKAXE", 0), + IRON_SHOVEL("IRON_SPADE", 0), + IRON_SWORD("IRON_SWORD", 0), + IRON_TRAPDOOR("IRON_TRAPDOOR", 0), + ITEM_FRAME("ITEM_FRAME", 0), + JACK_O_LANTERN("JACK_O_LANTERN", 0), + JUKEBOX("JUKEBOX", 0), + JUNGLE_BOAT("BOAT_JUNGLE", 0), + JUNGLE_BUTTON("WOOD_BUTTON", 0), + JUNGLE_DOOR("JUNGLE_DOOR", 0), + JUNGLE_FENCE("JUNGLE_FENCE", 0), + JUNGLE_FENCE_GATE("JUNGLE_FENCE_GATE", 0), + JUNGLE_LEAVES("LEAVES", 3), + JUNGLE_LOG("LOG", 3), + JUNGLE_PLANKS("WOOD", 3), + JUNGLE_PRESSURE_PLATE("WOOD_PLATE", 0), + JUNGLE_SAPLING("SAPLING", 3), + JUNGLE_SLAB("WOOD_STEP", 3), + JUNGLE_STAIRS("JUNGLE_WOOD_STAIRS", 0), + JUNGLE_TRAPDOOR("TRAP_DOOR", 0), + JUNGLE_WOOD("LOG", 3), + KELP("STONE", 0), + KELP_PLANT("STONE", 0), + KNOWLEDGE_BOOK("KNOWLEDGE_BOOK", 0), + LADDER("LADDER", 0), + LAPIS_BLOCK("LAPIS_BLOCK", 0), + LAPIS_LAZULI("INK_SACK", 4), + LAPIS_ORE("LAPIS_ORE", 0), + LARGE_FERN("DOUBLE_PLANT", 3), + LAVA("LAVA", 0), + LAVA_BUCKET("LAVA_BUCKET", 0), + LEAD("LEASH", 0), + LEATHER("LEATHER", 0), + LEATHER_BOOTS("LEATHER_BOOTS", 0), + LEATHER_CHESTPLATE("LEATHER_CHESTPLATE", 0), + LEATHER_HELMET("LEATHER_HELMET", 0), + LEATHER_LEGGINGS("LEATHER_LEGGINGS", 0), + LEVER("LEVER", 0), + LIGHT_BLUE_BANNER("BANNER", 12), + LIGHT_BLUE_BED("BED", 3), + LIGHT_BLUE_CARPET("CARPET", 3), + LIGHT_BLUE_CONCRETE("CONCRETE", 3), + LIGHT_BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 3), + LIGHT_BLUE_DYE("INK_SACK", 12), + LIGHT_BLUE_GLAZED_TERRACOTTA("LIGHT_BLUE_GLAZED_TERRACOTTA", 0), + LIGHT_BLUE_SHULKER_BOX("LIGHT_BLUE_SHULKER_BOX", 0), + LIGHT_BLUE_STAINED_GLASS("STAINED_GLASS", 3), + LIGHT_BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 3), + LIGHT_BLUE_TERRACOTTA("STAINED_CLAY", 3), + LIGHT_BLUE_WALL_BANNER("BANNER", 0), + LIGHT_BLUE_WOOL("WOOL", 3), + LIGHT_GRAY_BANNER("BANNER", 7), + LIGHT_GRAY_BED("BED", 8), + LIGHT_GRAY_CARPET("CARPET", 8), + LIGHT_GRAY_CONCRETE("CONCRETE", 8), + LIGHT_GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 8), + LIGHT_GRAY_DYE("INK_SACK", 7), + LIGHT_GRAY_GLAZED_TERRACOTTA("SILVER_GLAZED_TERRACOTTA", 0), + LIGHT_GRAY_SHULKER_BOX("SILVER_SHULKER_BOX", 0), + LIGHT_GRAY_STAINED_GLASS("STAINED_GLASS", 8), + LIGHT_GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 8), + LIGHT_GRAY_TERRACOTTA("STAINED_CLAY", 8), + LIGHT_GRAY_WALL_BANNER("WALL_BANNER", 0), + LIGHT_GRAY_WOOL("WOOL", 8), + LIGHT_WEIGHTED_PRESSURE_PLATE("GOLD_PLATE", 0), + LILAC("DOUBLE_PLANT", 1), + LILY_PAD("WATER_LILY", 0), + LIME_BANNER("BANNER", 10), + LIME_BED("BED", 5), + LIME_CARPET("CARPET", 5), + LIME_CONCRETE("CONCRETE", 5), + LIME_CONCRETE_POWDER("CONCRETE_POWDER", 5), + LIME_DYE("INK_SACK", 10), + LIME_GLAZED_TERRACOTTA("LIME_GLAZED_TERRACOTTA", 0), + LIME_SHULKER_BOX("LIME_SHULKER_BOX", 0), + LIME_STAINED_GLASS("STAINED_GLASS", 5), + LIME_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 5), + LIME_TERRACOTTA("STAINED_CLAY", 5), + LIME_WALL_BANNER("WALL_BANNER", 0), + LIME_WOOL("WOOL", 5), + LINGERING_POTION("LINGERING_POTION", 0), + LLAMA_SPAWN_EGG("MONSTER_EGG", 0), + MAGENTA_BANNER("BANNER", 13), + MAGENTA_BED("BED", 2), + MAGENTA_CARPET("CARPET", 2), + MAGENTA_CONCRETE("CONCRETE", 2), + MAGENTA_CONCRETE_POWDER("CONCRETE_POWDER", 2), + MAGENTA_DYE("INK_SACK", 13), + MAGENTA_GLAZED_TERRACOTTA("MAGENTA_GLAZED_TERRACOTTA", 0), + MAGENTA_SHULKER_BOX("MAGENTA_SHULKER_BOX", 0), + MAGENTA_STAINED_GLASS("STAINED_GLASS", 2), + MAGENTA_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 2), + MAGENTA_TERRACOTTA("STAINED_CLAY", 2), + MAGENTA_WALL_BANNER("WALL_BANNER", 0), + MAGENTA_WOOL("WOOL", 2), + MAGMA_BLOCK("MAGMA", 0), + MAGMA_CREAM("MAGMA_CREAM", 0), + MAGMA_CUBE_SPAWN_EGG("MONSTER_EGG", 0), + MAP("MAP", 0), + MELON("MELON_BLOCK", 0), + MELON_SEEDS("MELON_SEEDS", 0), + MELON_SLICE("MELON", 0), + MELON_STEM("MELON_STEM", 0), + MILK_BUCKET("MILK_BUCKET", 0), + MINECART("MINECART", 0), + MOOSHROOM_SPAWN_EGG("MONSTER_EGG", 0), + MOSSY_COBBLESTONE("MOSSY_COBBLESTONE", 0), + MOSSY_COBBLESTONE_WALL("COBBLE_WALL", 1), + MOSSY_STONE_BRICKS("SMOOTH_BRICK", 1), + MOVING_PISTON("PISTON_MOVING_PIECE", 0), + MULE_SPAWN_EGG("MONSTER_EGG", 0), + MUSHROOM_STEM("BROWN_MUSHROOM", 0), + MUSHROOM_STEW("MUSHROOM_SOUP", 0), + MUSIC_DISC_11("GOLD_RECORD", 0), + MUSIC_DISC_13("GREEN_RECORD", 0), + MUSIC_DISC_BLOCKS("RECORD_3", 0), + MUSIC_DISC_CAT("RECORD_4", 0), + MUSIC_DISC_CHIRP("RECORD_5", 0), + MUSIC_DISC_FAR("RECORD_6", 0), + MUSIC_DISC_MALL("RECORD_7", 0), + MUSIC_DISC_MELLOHI("RECORD_8", 0), + MUSIC_DISC_STAL("RECORD_9", 0), + MUSIC_DISC_STRAD("RECORD_10", 0), + MUSIC_DISC_WAIT("RECORD_11", 0), + MUSIC_DISC_WARD("RECORD_12", 0), + MUTTON("MUTTON", 0), + MYCELIUM("MYCEL", 0), + NAME_TAG("NAME_TAG", 0), + NAUTILUS_SHELL("STONE", 0), + NETHERRACK("NETHERRACK", 0), + NETHER_BRICK("NETHER_BRICK", 0), + NETHER_BRICKS("NETHER_BRICK", 0), + NETHER_BRICK_FENCE("NETHER_FENCE", 0), + NETHER_BRICK_SLAB("STEP", 6), + NETHER_BRICK_STAIRS("NETHER_BRICK_STAIRS", 0), + NETHER_PORTAL("PORTAL", 0), + NETHER_QUARTZ_ORE("QUARTZ_ORE", 0), + NETHER_STAR("NETHER_STAR", 0), + NETHER_WART("NETHER_STALK", 0), + NETHER_WART_BLOCK("NETHER_WART_BLOCK", 0), + NOTE_BLOCK("NOTE_BLOCK", 0), + OAK_BOAT("BOAT", 0), + OAK_BUTTON("WOOD_BUTTON", 0), + OAK_DOOR("WOOD_DOOR", 0), + OAK_FENCE("FENCE", 0), + OAK_FENCE_GATE("FENCE_GATE", 0), + OAK_LEAVES("LEAVES", 0), + OAK_LOG("LOG", 0), + OAK_PLANKS("WOOD", 0), + OAK_PRESSURE_PLATE("WOOD_PLATE", 0), + OAK_SAPLING("SAPLING", 0), + OAK_SLAB("WOOD_STEP", 0), + OAK_STAIRS("WOOD_STAIRS", 0), + OAK_TRAPDOOR("TRAP_DOOR", 0), + OAK_WOOD("LOG", 0), + OBSERVER("OBSERVER", 0), + OBSIDIAN("OBSIDIAN", 0), + OCELOT_SPAWN_EGG("RECORD_12", 0), + ORANGE_BANNER("BANNER", 14), + ORANGE_BED("BED", 1), + ORANGE_CARPET("CARPET", 1), + ORANGE_CONCRETE("CONCRETE", 1), + ORANGE_CONCRETE_POWDER("CONCRETE_POWDER", 1), + ORANGE_DYE("INK_SACK", 14), + ORANGE_GLAZED_TERRACOTTA("ORANGE_GLAZED_TERRACOTTA", 0), + ORANGE_SHULKER_BOX("ORANGE_SHULKER_BOX", 0), + ORANGE_STAINED_GLASS("STAINED_GLASS", 1), + ORANGE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 1), + ORANGE_TERRACOTTA("STAINED_CLAY", 1), + ORANGE_TULIP("RED_ROSE", 5), + ORANGE_WALL_BANNER("WALL_BANNER", 0), + ORANGE_WOOL("WOOL", 1), + OXEYE_DAISY("RED_ROSE", 8), + PACKED_ICE("PACKED_ICE", 0), + PAINTING("PAINTING", 0), + PAPER("PAPER", 0), + PARROT_SPAWN_EGG("MONSTER_EGG", 0), + PEONY("DOUBLE_PLANT", 5), + PETRIFIED_OAK_SLAB("STONE", 0), + PHANTOM_MEMBRANE("STONE", 0), + PHANTOM_SPAWN_EGG("MONSTER_EGG", 0), + PIG_SPAWN_EGG("MONSTER_EGG", 0), + PINK_BANNER("BANNER", 9), + PINK_BED("BED", 6), + PINK_CARPET("CARPET", 6), + PINK_CONCRETE("CONCRETE", 6), + PINK_CONCRETE_POWDER("CONCRETE_POWDER", 6), + PINK_DYE("INK_SACK", 9), + PINK_GLAZED_TERRACOTTA("PINK_GLAZED_TERRACOTTA", 0), + PINK_SHULKER_BOX("PINK_SHULKER_BOX", 0), + PINK_STAINED_GLASS("STAINED_GLASS", 6), + PINK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 6), + PINK_TERRACOTTA("STAINED_CLAY", 6), + PINK_TULIP("RED_ROSE", 7), + PINK_WALL_BANNER("WALL_BANNER", 0), + PINK_WOOL("WOOL", 6), + PISTON("PISTON_BASE", 0), + PISTON_HEAD("PISTON_EXTENSION", 0), + PLAYER_HEAD("SKULL", 0), + PLAYER_WALL_HEAD("SKULL", 0), + PODZOL("DIRT", 2), + POISONOUS_POTATO("POISONOUS_POTATO", 0), + POLAR_BEAR_SPAWN_EGG("MONSTER_EGG", 0), + POLISHED_ANDESITE("STONE", 6), + POLISHED_DIORITE("STONE", 4), + POLISHED_GRANITE("STONE", 2), + POPPED_CHORUS_FRUIT("CHORUS_FRUIT_POPPED", 0), + POPPY("RED_ROSE", 0), + PORKCHOP("PORK", 0), + POTATO("POTATO_ITEM", 0), + POTATOES("POTATO", 0), + POTION("POTION", 0), + POTTED_ACACIA_SAPLING("FLOWER_POT", 0), + POTTED_ALLIUM("FLOWER_POT", 0), + POTTED_AZURE_BLUET("FLOWER_POT", 0), + POTTED_BIRCH_SAPLING("FLOWER_POT", 0), + POTTED_BLUE_ORCHID("FLOWER_POT", 0), + POTTED_BROWN_MUSHROOM("FLOWER_POT", 0), + POTTED_CACTUS("FLOWER_POT", 0), + POTTED_DANDELION("FLOWER_POT", 0), + POTTED_DARK_OAK_SAPLING("FLOWER_POT", 0), + POTTED_DEAD_BUSH("FLOWER_POT", 0), + POTTED_FERN("FLOWER_POT", 0), + POTTED_JUNGLE_SAPLING("FLOWER_POT", 0), + POTTED_OAK_SAPLING("FLOWER_POT", 0), + POTTED_ORANGE_TULIP("FLOWER_POT", 0), + POTTED_OXEYE_DAISY("FLOWER_POT", 0), + POTTED_PINK_TULIP("FLOWER_POT", 0), + POTTED_POPPY("FLOWER_POT", 0), + POTTED_RED_MUSHROOM("FLOWER_POT", 0), + POTTED_RED_TULIP("FLOWER_POT", 0), + POTTED_SPRUCE_SAPLING("FLOWER_POT", 0), + POTTED_WHITE_TULIP("FLOWER_POT", 0), + POWERED_RAIL("POWERED_RAIL", 0), + PRISMARINE("PRISMARINE", 0), + PRISMARINE_BRICKS("PRISMARINE", 1), + PRISMARINE_BRICK_SLAB("STONE", 0), + PRISMARINE_BRICK_STAIRS("STONE", 0), + PRISMARINE_CRYSTALS("PRISMARINE_CRYSTALS", 0), + PRISMARINE_SHARD("PRISMARINE_SHARD", 0), + PRISMARINE_SLAB("STONE", 0), + PRISMARINE_STAIRS("STONE", 0), + PUFFERFISH("RAW_FISH", 3), + PUFFERFISH_BUCKET("STONE", 0), + PUFFERFISH_SPAWN_EGG("MONSTER_EGG", 0), + PUMPKIN("PUMPKIN", 0), + PUMPKIN_PIE("PUMPKIN_PIE", 0), + PUMPKIN_SEEDS("PUMPKIN_SEEDS", 0), + PUMPKIN_STEM("PUMPKIN_STEM", 0), + PURPLE_BANNER("BANNER", 5), + PURPLE_BED("BED", 10), + PURPLE_CARPET("CARPET", 10), + PURPLE_CONCRETE("CONCRETE", 10), + PURPLE_CONCRETE_POWDER("CONCRETE_POWDER", 10), + PURPLE_DYE("INK_SACK", 5), + PURPLE_GLAZED_TERRACOTTA("PURPLE_GLAZED_TERRACOTTA", 0), + PURPLE_SHULKER_BOX("PURPLE_SHULKER_BOX", 0), + PURPLE_STAINED_GLASS("STAINED_GLASS", 10), + PURPLE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 10), + PURPLE_TERRACOTTA("STAINED_CLAY", 10), + PURPLE_WALL_BANNER("WALL_BANNER", 0), + PURPLE_WOOL("WOOL", 10), + PURPUR_BLOCK("PURPUR_BLOCK", 0), + PURPUR_PILLAR("PURPUR_PILLAR", 0), + PURPUR_SLAB("PURPUR_SLAB", 0), + PURPUR_STAIRS("PURPUR_STAIRS", 0), + QUARTZ("QUARTZ", 0), + QUARTZ_BLOCK("QUARTZ_BLOCK", 0), + QUARTZ_PILLAR("QUARTZ_BLOCK", 2), + QUARTZ_SLAB("STEP", 7), + QUARTZ_STAIRS("QUARTZ_STAIRS", 0), + RABBIT("RABBIT", 0), + RABBIT_FOOT("RABBIT_FOOT", 0), + RABBIT_HIDE("RABBIT_HIDE", 0), + RABBIT_SPAWN_EGG("MONSTER_EGG", 0), + RABBIT_STEW("RABBIT_STEW", 0), + RAIL("RAILS", 0), + REDSTONE("REDSTONE", 0), + REDSTONE_BLOCK("REDSTONE_BLOCK", 0), + REDSTONE_LAMP("REDSTONE_LAMP_OFF", 0), + REDSTONE_ORE("REDSTONE_ORE", 0), + REDSTONE_TORCH("REDSTONE_TORCH_ON", 0), + REDSTONE_WALL_TORCH("REDSTONE_TORCH_ON", 1), + REDSTONE_WIRE("REDSTONE_WIRE", 0), + RED_BANNER("BANNER", 1), + RED_BED("BED", 14), + RED_CARPET("CARPET", 14), + RED_CONCRETE("CONCRETE", 14), + RED_CONCRETE_POWDER("CONCRETE_POWDER", 14), + RED_GLAZED_TERRACOTTA("RED_GLAZED_TERRACOTTA", 0), + RED_MUSHROOM("RED_MUSHROOM", 0), + RED_MUSHROOM_BLOCK("RED_MUSHROOM", 0), + RED_NETHER_BRICKS("RED_NETHER_BRICK", 0), + RED_SAND("SAND", 1), + RED_SANDSTONE("RED_SANDSTONE", 0), + RED_SANDSTONE_SLAB("STONE_SLAB2", 0), + RED_SANDSTONE_STAIRS("RED_SANDSTONE_STAIRS", 0), + RED_SHULKER_BOX("RED_SHULKER_BOX", 0), + RED_STAINED_GLASS("STAINED_GLASS", 14), + RED_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 14), + RED_TERRACOTTA("STAINED_CLAY", 14), + RED_TULIP("RED_ROSE", 4), + RED_WALL_BANNER("WALL_BANNER", 0), + RED_WOOL("WOOL", 14), + REPEATER("DIODE", 0), + REPEATING_COMMAND_BLOCK("COMMAND_REPEATING", 0), + ROSE_BUSH("DOUBLE_PLANT", 4), + ROSE_RED("INK_SACK", 1), + ROTTEN_FLESH("ROTTEN_FLESH", 0), + SADDLE("SADDLE", 0), + SALMON("RAW_FISH", 1), + SALMON_BUCKET("BUCKET", 0), + SALMON_SPAWN_EGG("MONSTER_EGG", 0), + SAND("SAND", 0), + SANDSTONE("SANDSTONE", 0), + SANDSTONE_SLAB("STEP", 1), + SANDSTONE_STAIRS("SANDSTONE_STAIRS", 0), + SCUTE("STONE", 0), + SEAGRASS("STONE", 0), + SEA_LANTERN("SEA_LANTERN", 0), + SEA_PICKLE("STONE", 0), + SHEARS("SHEARS", 0), + SHEEP_SPAWN_EGG("MONSTER_EGG", 0), + SHIELD("SHIELD", 0), + SHULKER_BOX("PURPLE_SHULKER_BOX", 0), + SHULKER_SHELL("SHULKER_SHELL", 0), + SHULKER_SPAWN_EGG("MONSTER_EGG", 0), + SIGN("SIGN", 0), + SILVERFISH_SPAWN_EGG("MONSTER_EGG", 0), + SKELETON_HORSE_SPAWN_EGG("MONSTER_EGG", 0), + SKELETON_SKULL("SKULL", 0), + SKELETON_SPAWN_EGG("MONSTER_EGG", 0), + SKELETON_WALL_SKULL("SKULL", 0), + SLIME_BALL("SLIME_BALL", 0), + SLIME_BLOCK("SLIME_BLOCK", 0), + SLIME_SPAWN_EGG("MONSTER_EGG", 0), + SMOOTH_QUARTZ("STONE", 0), + SMOOTH_RED_SANDSTONE("RED_SANDSTONE", 2), + SMOOTH_SANDSTONE("SANDSTONE", 2), + SMOOTH_STONE("STEP", 0), + SNOW("SNOW", 0), + SNOWBALL("SNOW_BALL", 0), + SNOW_BLOCK("SNOW_BLOCK", 0), + SOUL_SAND("SOUL_SAND", 0), + SPAWNER("MOB_SPAWNER", 0), + SPECTRAL_ARROW("SPECTRAL_ARROW", 0), + SPIDER_EYE("SPIDER_EYE", 0), + SPIDER_SPAWN_EGG("MONSTER_EGG", 0), + SPLASH_POTION("SPLASH_POTION", 0), + SPONGE("SPONGE", 0), + SPRUCE_BOAT("BOAT_SPRUCE", 0), + SPRUCE_BUTTON("WOOD_BUTTON", 0), + SPRUCE_DOOR("SPRUCE_DOOR", 0), + SPRUCE_FENCE("SPRUCE_FENCE", 0), + SPRUCE_FENCE_GATE("SPRUCE_FENCE_GATE", 0), + SPRUCE_LEAVES("LEAVES", 1), + SPRUCE_LOG("LOG", 1), + SPRUCE_PLANKS("WOOD", 1), + SPRUCE_PRESSURE_PLATE("WOOD_PLATE", 0), + SPRUCE_SAPLING("SAPLING", 1), + SPRUCE_SLAB("WOOD_STEP", 1), + SPRUCE_STAIRS("SPRUCE_WOOD_STAIRS", 0), + SPRUCE_TRAPDOOR("TRAP_DOOR", 0), + SPRUCE_WOOD("LOG", 1), + SQUID_SPAWN_EGG("MONSTER_EGG", 0), + STICK("STICK", 0), + STICKY_PISTON("PISTON_STICKY_BASE", 0), + STONE("STONE", 0), + STONE_AXE("STONE_AXE", 0), + STONE_BRICKS("SMOOTH_BRICK", 0), + STONE_BRICK_SLAB("STEP", 5), + STONE_BRICK_STAIRS("SMOOTH_STAIRS", 0), + STONE_BUTTON("STONE_BUTTON", 0), + STONE_HOE("STONE_HOE", 0), + STONE_PICKAXE("STONE_PICKAXE", 0), + STONE_PRESSURE_PLATE("STONE_PLATE", 0), + STONE_SHOVEL("STONE_SPADE", 0), + STONE_SLAB("STEP", 0), + STONE_SWORD("STONE_SWORD", 0), + STRAY_SPAWN_EGG("MONSTER_EGG", 0), + STRING("STRING", 0), + STRIPPED_ACACIA_LOG("STONE", 0), + STRIPPED_ACACIA_WOOD("STONE", 0), + STRIPPED_BIRCH_LOG("STONE", 0), + STRIPPED_BIRCH_WOOD("STONE", 0), + STRIPPED_DARK_OAK_LOG("STONE", 0), + STRIPPED_DARK_OAK_WOOD("STONE", 0), + STRIPPED_JUNGLE_LOG("STONE", 0), + STRIPPED_JUNGLE_WOOD("STONE", 0), + STRIPPED_OAK_LOG("STONE", 0), + STRIPPED_OAK_WOOD("STONE", 0), + STRIPPED_SPRUCE_LOG("STONE", 0), + STRIPPED_SPRUCE_WOOD("STONE", 0), + STRUCTURE_BLOCK("STRUCTURE_BLOCK", 0), + STRUCTURE_VOID("STRUCTURE_VOID", 0), + SUGAR("SUGAR", 0), + SUGAR_CANE("SUGAR_CANE", 0), + SUNFLOWER("DOUBLE_PLANT", 0), + TALL_GRASS("DOUBLE_PLANT", 2), + TALL_SEAGRASS("STONE", 0), + TERRACOTTA("HARD_CLAY", 0), + TIPPED_ARROW("TIPPED_ARROW", 0), + TNT("TNT", 0), + TNT_MINECART("EXPLOSIVE_MINECART", 0), + TORCH("TORCH", 0), + TOTEM_OF_UNDYING("TOTEM", 0), + TRAPPED_CHEST("TRAPPED_CHEST", 0), + TRIDENT("STONE", 0), + TRIPWIRE("TRIPWIRE", 0), + TRIPWIRE_HOOK("TRIPWIRE_HOOK", 0), + TROPICAL_FISH("RAW_FISH", 0), + TROPICAL_FISH_BUCKET("BUCKET", 0), + TROPICAL_FISH_SPAWN_EGG("MONSTER_EGG", 0), + TUBE_CORAL("STONE", 0), + TUBE_CORAL_BLOCK("STONE", 0), + TUBE_CORAL_FAN("STONE", 0), + TURTLE_EGG("MONSTER_EGG", 0), + TURTLE_HELMET("STONE", 0), + TURTLE_SPAWN_EGG("MONSTER_EGG", 0), + VEX_SPAWN_EGG("MONSTER_EGG", 0), + VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), + VINDICATOR_SPAWN_EGG("MONSTER_EGG", 0), + VINE("VINE", 0), + VOID_AIR("AIR", 0), + WALL_SIGN("WALL_SIGN", 0), + WALL_TORCH("TORCH", 1), + WATER("WATER", 0), + WATER_BUCKET("WATER_BUCKET", 0), + WET_SPONGE("SPONGE", 1), + WHEAT("WHEAT", 0), + WHEAT_SEEDS("SEEDS", 0), + WHITE_BANNER("BANNER", 15), + WHITE_BED("BED", 0), + WHITE_CARPET("CARPET", 0), + WHITE_CONCRETE("CONCRETE", 0), + WHITE_CONCRETE_POWDER("CONCRETE_POWDER", 0), + WHITE_GLAZED_TERRACOTTA("WHITE_GLAZED_TERRACOTTA", 0), + WHITE_SHULKER_BOX("WHITE_SHULKER_BOX", 0), + WHITE_STAINED_GLASS("STAINED_GLASS", 0), + WHITE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 0), + WHITE_TERRACOTTA("TERRACOTTA", 0), + WHITE_TULIP("RED_ROSE", 6), + WHITE_WALL_BANNER("WALL_BANNER", 0), + WHITE_WOOL("WOOL", 0), + WITCH_SPAWN_EGG("MONSTER_EGG", 0), + WITHER_SKELETON_SKULL("SKULL", 0), + WITHER_SKELETON_SPAWN_EGG("MONSTER_EGG", 0), + WITHER_SKELETON_WALL_SKULL("SKULL", 0), + WOLF_SPAWN_EGG("MONSTER_EGG", 0), + WOODEN_AXE("WOOD_AXE", 0), + WOODEN_HOE("WOOD_HOE", 0), + WOODEN_PICKAXE("WOOD_PICKAXE", 0), + WOODEN_SHOVEL("WOOD_SPADE", 0), + WOODEN_SWORD("WOOD_SWORD", 0), + WRITABLE_BOOK("BOOK_AND_QUILL", 0), + WRITTEN_BOOK("WRITTEN_BOOK", 0), + YELLOW_BANNER("BANNER", 11), + YELLOW_BED("BED", 4), + YELLOW_CARPET("CARPET", 4), + YELLOW_CONCRETE("CONCRETE", 4), + YELLOW_CONCRETE_POWDER("CONCRETE_POWDER", 4), + YELLOW_GLAZED_TERRACOTTA("YELLOW_GLAZED_TERRACOTTA", 0), + YELLOW_SHULKER_BOX("YELLOW_SHULKER_BOX", 0), + YELLOW_STAINED_GLASS("STAINED_GLASS", 4), + YELLOW_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 4), + YELLOW_TERRACOTTA("STAINED_CLAY", 4), + YELLOW_WALL_BANNER("WALL_BANNER", 0), + YELLOW_WOOL("WOOL", 4), + ZOMBIE_HEAD("SKULL", 0), + ZOMBIE_HORSE_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_PIGMAN_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_WALL_HEAD("SKULL", 0), + ; - static int newV = -1; - private static HashMap cachedSearch = new HashMap<>(); - String m; - int data; + static int newV = -1; + private static HashMap cachedSearch = new HashMap<>(); + String m; + int data; - MultiversionMaterials(String m, int data) { - this.m = m; - this.data = data; - } + MultiversionMaterials(String m, int data) { + this.m = m; + this.data = data; + } - public static boolean isNewVersion() { - if (newV == 0) return false; - if (newV == 1) return true; + public static boolean isNewVersion() { + if (newV == 0) return false; + if (newV == 1) return true; - Material mat = Material.matchMaterial("RED_WOOL"); - if (mat != null) { - newV = 1; - return true; - } + Material mat = Material.matchMaterial("RED_WOOL"); + if (mat != null) { + newV = 1; + return true; + } - newV = 0; - return false; - } + newV = 0; + return false; + } - public static MultiversionMaterials requestXMaterial(String name, byte data) { - if (cachedSearch.containsKey(name.toUpperCase() + "," + data)) { - return cachedSearch.get(name.toUpperCase() + "," + data); - } - for (MultiversionMaterials mat : MultiversionMaterials.values()) { - if (name.toUpperCase().equals(mat.m) && ((byte) mat.data) == data) { - cachedSearch.put(mat.m + "," + data, mat); - return mat; - } - } - return null; - } + public static MultiversionMaterials requestXMaterial(String name, byte data) { + if (cachedSearch.containsKey(name.toUpperCase() + "," + data)) { + return cachedSearch.get(name.toUpperCase() + "," + data); + } + for (MultiversionMaterials mat : MultiversionMaterials.values()) { + if (name.toUpperCase().equals(mat.m) && ((byte) mat.data) == data) { + cachedSearch.put(mat.m + "," + data, mat); + return mat; + } + } + return null; + } - public static MultiversionMaterials fromString(String key) { - try { - return MultiversionMaterials.valueOf(key); - } catch (IllegalArgumentException e) { - String[] split = key.split(":"); + public static MultiversionMaterials fromString(String key) { + try { + return MultiversionMaterials.valueOf(key); + } catch (IllegalArgumentException e) { + String[] split = key.split(":"); - return split.length == 1 ? requestXMaterial(key, (byte) 0) : requestXMaterial(split[0], (byte) Integer.parseInt(split[1])); - } - } + return split.length == 1 ? requestXMaterial(key, (byte) 0) : requestXMaterial(split[0], (byte) Integer.parseInt(split[1])); + } + } - public ItemStack parseItem() { - Material mat = parseMaterial(); - if (isNewVersion()) { - return new ItemStack(mat); - } - return new ItemStack(mat, 1, (byte) data); - } + public ItemStack parseItem() { + Material mat = parseMaterial(); + if (isNewVersion()) { + return new ItemStack(mat); + } + return new ItemStack(mat, 1, (byte) data); + } - public boolean isSameMaterial(ItemStack comp) { - if (isNewVersion()) { - return comp.getType() == this.parseMaterial(); - } - if (comp.getType() == this.parseMaterial() && - (int) comp.getData().getData() == this.data) { - return true; - } - MultiversionMaterials xmat = fromMaterial(comp.getType()); - if (isDamageable(xmat)) { - return this.parseMaterial() == comp.getType(); - } - return false; - } + public boolean isSameMaterial(ItemStack comp) { + if (isNewVersion()) { + return comp.getType() == this.parseMaterial(); + } + if (comp.getType() == this.parseMaterial() && + (int) comp.getData().getData() == this.data) { + return true; + } + MultiversionMaterials xmat = fromMaterial(comp.getType()); + if (isDamageable(xmat)) { + return this.parseMaterial() == comp.getType(); + } + return false; + } - public MultiversionMaterials fromMaterial(Material mat) { - try { - return MultiversionMaterials.valueOf(mat.toString()); - } catch (IllegalArgumentException e) { - for (MultiversionMaterials xmat : MultiversionMaterials.values()) { - if (xmat.m.equals(mat.toString())) { - return xmat; - } - } - } - return null; - } + public MultiversionMaterials fromMaterial(Material mat) { + try { + return MultiversionMaterials.valueOf(mat.toString()); + } catch (IllegalArgumentException e) { + for (MultiversionMaterials xmat : MultiversionMaterials.values()) { + if (xmat.m.equals(mat.toString())) { + return xmat; + } + } + } + return null; + } - public boolean isDamageable(MultiversionMaterials type) { - String[] split = type.toString().split("_"); + public boolean isDamageable(MultiversionMaterials type) { + String[] split = type.toString().split("_"); - switch (split[split.length - 1]) { - case "HELMET": - case "CHESTPLATE": - case "LEGGINGS": - case "BOOTS": - case "SWORD": - case "AXE": - case "PICKAXE": - case "SHOVEL": - case "HOE": - case "ELYTRA": - case "TURTLE_HELMET": - case "TRIDENT": - case "HORSE_ARMOR": - case "SHEARS": - return true; - default: - return false; - } - } + switch (split[split.length - 1]) { + case "HELMET": + case "CHESTPLATE": + case "LEGGINGS": + case "BOOTS": + case "SWORD": + case "AXE": + case "PICKAXE": + case "SHOVEL": + case "HOE": + case "ELYTRA": + case "TURTLE_HELMET": + case "TRIDENT": + case "HORSE_ARMOR": + case "SHEARS": + return true; + default: + return false; + } + } - public Material parseMaterial() { - Material mat = Material.matchMaterial(this.toString()); - return mat != null ? mat : Material.matchMaterial(m); - } + public Material parseMaterial() { + Material mat = Material.matchMaterial(this.toString()); + return mat != null ? mat : Material.matchMaterial(m); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java index 72f5376d..d689c6f0 100644 --- a/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java @@ -9,51 +9,51 @@ import java.util.logging.Level; public class MyLocationTypeAdapter implements JsonDeserializer, JsonSerializer { - private static final String WORLD = "world"; - private static final String X = "x"; - private static final String Y = "y"; - private static final String Z = "z"; - private static final String YAW = "yaw"; - private static final String PITCH = "pitch"; + private static final String WORLD = "world"; + private static final String X = "x"; + private static final String Y = "y"; + private static final String Z = "z"; + private static final String YAW = "yaw"; + private static final String PITCH = "pitch"; - @Override - public LazyLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - try { - JsonObject obj = json.getAsJsonObject(); + @Override + public LazyLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + JsonObject obj = json.getAsJsonObject(); - String worldName = obj.get(WORLD).getAsString(); - double x = obj.get(X).getAsDouble(); - double y = obj.get(Y).getAsDouble(); - double z = obj.get(Z).getAsDouble(); - float yaw = obj.get(YAW).getAsFloat(); - float pitch = obj.get(PITCH).getAsFloat(); + String worldName = obj.get(WORLD).getAsString(); + double x = obj.get(X).getAsDouble(); + double y = obj.get(Y).getAsDouble(); + double z = obj.get(Z).getAsDouble(); + float yaw = obj.get(YAW).getAsFloat(); + float pitch = obj.get(PITCH).getAsFloat(); - return new LazyLocation(worldName, x, y, z, yaw, pitch); + return new LazyLocation(worldName, x, y, z, yaw, pitch); - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a LazyLocation."); - return null; - } - } + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a LazyLocation."); + return null; + } + } - @Override - public JsonElement serialize(LazyLocation src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject obj = new JsonObject(); + @Override + public JsonElement serialize(LazyLocation src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); - try { - obj.addProperty(WORLD, src.getWorldName()); - obj.addProperty(X, src.getX()); - obj.addProperty(Y, src.getY()); - obj.addProperty(Z, src.getZ()); - obj.addProperty(YAW, src.getYaw()); - obj.addProperty(PITCH, src.getPitch()); + try { + obj.addProperty(WORLD, src.getWorldName()); + obj.addProperty(X, src.getX()); + obj.addProperty(Y, src.getY()); + obj.addProperty(Z, src.getZ()); + obj.addProperty(YAW, src.getYaw()); + obj.addProperty(PITCH, src.getPitch()); - return obj; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a LazyLocation."); - return obj; - } - } + return obj; + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a LazyLocation."); + return obj; + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java b/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java index ab152c08..cf4ff3b7 100644 --- a/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java +++ b/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java @@ -40,1559 +40,1559 @@ import java.util.Map.Entry; * @version 1.7 */ public enum ParticleEffect { - /** - * A particle effect which is displayed by exploding tnt and creepers: - *
      - *
    • It looks like a white cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - EXPLOSION_NORMAL("explode", 0, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by exploding ghast fireballs and wither skulls: - *
      - *
    • It looks like a gray ball which is fading away - *
    • The speed value slightly influences the size of this particle effect - *
    - */ - EXPLOSION_LARGE("largeexplode", 1, -1), - /** - * A particle effect which is displayed by exploding tnt and creepers: - *
      - *
    • It looks like a crowd of gray balls which are fading away - *
    • The speed value has no influence on this particle effect - *
    - */ - EXPLOSION_HUGE("hugeexplosion", 2, -1), - /** - * A particle effect which is displayed by launching fireworks: - *
      - *
    • It looks like a white star which is sparkling - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - FIREWORKS_SPARK("fireworksSpark", 3, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by swimming entities and arrows in water: - *
      - *
    • It looks like a bubble - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - WATER_BUBBLE("bubble", 4, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_WATER), - /** - * A particle effect which is displayed by swimming entities and shaking wolves: - *
      - *
    • It looks like a blue drop - *
    • The speed value has no influence on this particle effect - *
    - */ - WATER_SPLASH("splash", 5, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed on water when fishing: - *
      - *
    • It looks like a blue droplet - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - WATER_WAKE("wake", 6, 7, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by water: - *
      - *
    • It looks like a tiny blue square - *
    • The speed value has no influence on this particle effect - *
    - */ - SUSPENDED("suspended", 7, -1, ParticleProperty.REQUIRES_WATER), - /** - * A particle effect which is displayed by air when close to bedrock and the in the void: - *
      - *
    • It looks like a tiny gray square - *
    • The speed value has no influence on this particle effect - *
    - */ - SUSPENDED_DEPTH("depthSuspend", 8, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed when landing a critical hit and by arrows: - *
      - *
    • It looks like a light brown cross - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - CRIT("crit", 9, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed when landing a hit with an enchanted weapon: - *
      - *
    • It looks like a cyan star - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - CRIT_MAGIC("magicCrit", 10, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by primed tnt, torches, droppers, dispensers, end portals, brewing stands and monster spawners: - *
      - *
    • It looks like a little gray cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - SMOKE_NORMAL("smoke", 11, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by fire, minecarts with furnace and blazes: - *
      - *
    • It looks like a large gray cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - SMOKE_LARGE("largesmoke", 12, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed when splash potions or bottles o' enchanting hit something: - *
      - *
    • It looks like a white swirl - *
    • The speed value causes the particle to only move upwards when set to 0 - *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 - *
    - */ - SPELL("spell", 13, -1), - /** - * A particle effect which is displayed when instant splash potions hit something: - *
      - *
    • It looks like a white cross - *
    • The speed value causes the particle to only move upwards when set to 0 - *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 - *
    - */ - SPELL_INSTANT("instantSpell", 14, -1), - /** - * A particle effect which is displayed by entities with active potion effects: - *
      - *
    • It looks like a colored swirl - *
    • The speed value causes the particle to be colored black when set to 0 - *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed - *
    - */ - SPELL_MOB("mobSpell", 15, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed by entities with active potion effects applied through a beacon: - *
      - *
    • It looks like a transparent colored swirl - *
    • The speed value causes the particle to be always colored black when set to 0 - *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed - *
    - */ - SPELL_MOB_AMBIENT("mobSpellAmbient", 16, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed by witches: - *
      - *
    • It looks like a purple cross - *
    • The speed value causes the particle to only move upwards when set to 0 - *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 - *
    - */ - SPELL_WITCH("witchMagic", 17, -1), - /** - * A particle effect which is displayed by blocks beneath a water source: - *
      - *
    • It looks like a blue drip - *
    • The speed value has no influence on this particle effect - *
    - */ - DRIP_WATER("dripWater", 18, -1), - /** - * A particle effect which is displayed by blocks beneath a lava source: - *
      - *
    • It looks like an orange drip - *
    • The speed value has no influence on this particle effect - *
    - */ - DRIP_LAVA("dripLava", 19, -1), - /** - * A particle effect which is displayed when attacking a villager in a village: - *
      - *
    • It looks like a cracked gray heart - *
    • The speed value has no influence on this particle effect - *
    - */ - VILLAGER_ANGRY("angryVillager", 20, -1), - /** - * A particle effect which is displayed when using bone meal and trading with a villager in a village: - *
      - *
    • It looks like a green star - *
    • The speed value has no influence on this particle effect - *
    - */ - VILLAGER_HAPPY("happyVillager", 21, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by mycelium: - *
      - *
    • It looks like a tiny gray square - *
    • The speed value has no influence on this particle effect - *
    - */ - TOWN_AURA("townaura", 22, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by note blocks: - *
      - *
    • It looks like a colored note - *
    • The speed value causes the particle to be colored green when set to 0 - *
    - */ - NOTE("note", 23, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed by nether portals, endermen, ender pearls, eyes of ender, ender chests and dragon eggs: - *
      - *
    • It looks like a purple cloud - *
    • The speed value influences the spread of this particle effect - *
    - */ - PORTAL("portal", 24, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by enchantment tables which are nearby bookshelves: - *
      - *
    • It looks like a cryptic white letter - *
    • The speed value influences the spread of this particle effect - *
    - */ - ENCHANTMENT_TABLE("enchantmenttable", 25, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by torches, active furnaces, magma cubes and monster spawners: - *
      - *
    • It looks like a tiny flame - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - FLAME("flame", 26, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by lava: - *
      - *
    • It looks like a spark - *
    • The speed value has no influence on this particle effect - *
    - */ - LAVA("lava", 27, -1), - /** - * A particle effect which is currently unused: - *
      - *
    • It looks like a transparent gray square - *
    • The speed value has no influence on this particle effect - *
    - */ - FOOTSTEP("footstep", 28, -1), - /** - * A particle effect which is displayed when a mob dies: - *
      - *
    • It looks like a large white cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - CLOUD("cloud", 29, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by redstone ore, powered redstone, redstone torches and redstone repeaters: - *
      - *
    • It looks like a tiny colored cloud - *
    • The speed value causes the particle to be colored red when set to 0 - *
    - */ - REDSTONE("reddust", 30, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed when snowballs hit a block: - *
      - *
    • It looks like a little piece with the snowball texture - *
    • The speed value has no influence on this particle effect - *
    - */ - SNOWBALL("snowballpoof", 31, -1), - /** - * A particle effect which is currently unused: - *
      - *
    • It looks like a tiny white cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - SNOW_SHOVEL("snowshovel", 32, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by slimes: - *
      - *
    • It looks like a tiny part of the slimeball icon - *
    • The speed value has no influence on this particle effect - *
    - */ - SLIME("slime", 33, -1), - /** - * A particle effect which is displayed when breeding and taming animals: - *
      - *
    • It looks like a red heart - *
    • The speed value has no influence on this particle effect - *
    - */ - HEART("heart", 34, -1), - /** - * A particle effect which is displayed by barriers: - *
      - *
    • It looks like a red box with a slash through it - *
    • The speed value has no influence on this particle effect - *
    - */ - BARRIER("barrier", 35, 8), - /** - * A particle effect which is displayed when breaking a tool or eggs hit a block: - *
      - *
    • It looks like a little piece with an item texture - *
    - */ - ITEM_CRACK("iconcrack", 36, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), - /** - * A particle effect which is displayed when breaking blocks or sprinting: - *
      - *
    • It looks like a little piece with a block texture - *
    • The speed value has no influence on this particle effect - *
    - */ - BLOCK_CRACK("blockcrack", 37, -1, ParticleProperty.REQUIRES_DATA), - /** - * A particle effect which is displayed when falling: - *
      - *
    • It looks like a little piece with a block texture - *
    - */ - BLOCK_DUST("blockdust", 38, 7, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), - /** - * A particle effect which is displayed when rain hits the ground: - *
      - *
    • It looks like a blue droplet - *
    • The speed value has no influence on this particle effect - *
    - */ - WATER_DROP("droplet", 39, 8), - /** - * A particle effect which is currently unused: - *
      - *
    • It has no visual effect - *
    - */ - ITEM_TAKE("take", 40, 8), - /** - * A particle effect which is displayed by elder guardians: - *
      - *
    • It looks like the shape of the elder guardian - *
    • The speed value has no influence on this particle effect - *
    • The offset values have no influence on this particle effect - *
    - */ - MOB_APPEARANCE("mobappearance", 41, 8); - - private static final Map NAME_MAP = new HashMap(); - private static final Map ID_MAP = new HashMap(); - - // Initialize map for quick name and id lookup - static { - for (ParticleEffect effect : values()) { - NAME_MAP.put(effect.name, effect); - ID_MAP.put(effect.id, effect); - } - } - - private final String name; - private final int id; - private final int requiredVersion; - private final List properties; - - /** - * Construct a new particle effect - * - * @param name Name of this particle effect - * @param id Id of this particle effect - * @param requiredVersion Version which is required (1.x) - * @param properties Properties of this particle effect - */ - ParticleEffect(String name, int id, int requiredVersion, ParticleProperty... properties) { - this.name = name; - this.id = id; - this.requiredVersion = requiredVersion; - this.properties = Arrays.asList(properties); - } - - /** - * Returns the particle effect with the given name - * - * @param name Name of the particle effect - * @return The particle effect - */ - public static ParticleEffect fromName(String name) { - for (Entry entry : NAME_MAP.entrySet()) { - if (!entry.getKey().equalsIgnoreCase(name)) { - continue; - } - return entry.getValue(); - } - return null; - } - - /** - * Returns the particle effect with the given id - * - * @param id Id of the particle effect - * @return The particle effect - */ - public static ParticleEffect fromId(int id) { - for (Entry entry : ID_MAP.entrySet()) { - if (entry.getKey() != id) { - continue; - } - return entry.getValue(); - } - return null; - } - - /** - * Determine if water is at a certain location - * - * @param location Location to check - * @return Whether water is at this location or not - */ - private static boolean isWater(Location location) { - Material material = location.getBlock().getType(); - return material == Material.WATER || material == SavageFactions.plugin.STATIONARY_WATER; - } - - /** - * Determine if the distance between @param location and one of the players exceeds 256 - * - * @param location Location to check - * @return Whether the distance exceeds 256 or not - */ - private static boolean isLongDistance(Location location, List players) { - String world = location.getWorld().getName(); - for (Player player : players) { - Location playerLocation = player.getLocation(); - if (!world.equals(playerLocation.getWorld().getName()) || playerLocation.distanceSquared(location) < 65536) { - continue; - } - return true; - } - return false; - } - - /** - * Determine if the data type for a particle effect is correct - * - * @param effect Particle effect - * @param data Particle data - * @return Whether the data type is correct or not - */ - private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) { - return ((effect == BLOCK_CRACK || effect == BLOCK_DUST) && data instanceof BlockData) || (effect == ITEM_CRACK && data instanceof ItemData); - } - - /** - * Determine if the color type for a particle effect is correct - * - * @param effect Particle effect - * @param color Particle color - * @return Whether the color type is correct or not - */ - private static boolean isColorCorrect(ParticleEffect effect, ParticleColor color) { - return ((effect == SPELL_MOB || effect == SPELL_MOB_AMBIENT || effect == REDSTONE) && color instanceof OrdinaryColor) || (effect == NOTE && color instanceof NoteColor); - } - - /** - * Returns the name of this particle effect - * - * @return The name - */ - public String getName() { - return name; - } - - /** - * Returns the id of this particle effect - * - * @return The id - */ - public int getId() { - return id; - } - - /** - * Returns the required version for this particle effect (1.x) - * - * @return The required version - */ - public int getRequiredVersion() { - return requiredVersion; - } - - /** - * Determine if this particle effect has a specific property - * - * @param property - property to check. - * @return Whether it has the property or not - */ - public boolean hasProperty(ParticleProperty property) { - return properties.contains(property); - } - - /** - * Determine if this particle effect is supported by your current server version - * - * @return Whether the particle effect is supported or not - */ - public boolean isSupported() { - if (requiredVersion == -1) { - return true; - } - return ParticlePacket.getVersion() >= requiredVersion; - } - - /** - * Displays a particle effect which is only visible for all players within a certain range in the world of @param center - * - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect requires water and none is at the center location - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, null).sendTo(center, range); - } - - /** - * Displays a particle effect which is only visible for the specified players - * - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect requires water and none is at the center location - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), null).sendTo(center, players); - } - - /** - * Displays a particle effect which is only visible for the specified players - * - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect requires water and none is at the center location - * @see #display(float, float, float, float, int, Location, List) - */ - public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - display(offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); - } - - /** - * Displays a single particle which flies into a determined direction and is only visible for all players within a certain range in the world of @param center - * - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location - * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (!hasProperty(ParticleProperty.DIRECTIONAL)) { - throw new IllegalArgumentException("This particle effect is not directional"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, direction, speed, range > 256, null).sendTo(center, range); - } - - /** - * Displays a single particle which flies into a determined direction and is only visible for the specified players - * - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location - * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (!hasProperty(ParticleProperty.DIRECTIONAL)) { - throw new IllegalArgumentException("This particle effect is not directional"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, direction, speed, isLongDistance(center, players), null).sendTo(center, players); - } - - /** - * Displays a single particle which flies into a determined direction and is only visible for the specified players - * - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location - * @see #display(Vector, float, Location, List) - */ - public void display(Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - display(direction, speed, center, Arrays.asList(players)); - } - - /** - * Displays a single particle which is colored and only visible for all players within a certain range in the world of @param center - * - * @param color Color of the particle - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect - * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(ParticleColor color, Location center, double range) throws ParticleVersionException, ParticleColorException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.COLORABLE)) { - throw new ParticleColorException("This particle effect is not colorable"); - } - if (!isColorCorrect(this, color)) { - throw new ParticleColorException("The particle color type is incorrect"); - } - new ParticlePacket(this, color, range > 256).sendTo(center, range); - } - - /** - * Displays a single particle which is colored and only visible for the specified players - * - * @param color Color of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect - * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(ParticleColor color, Location center, List players) throws ParticleVersionException, ParticleColorException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.COLORABLE)) { - throw new ParticleColorException("This particle effect is not colorable"); - } - if (!isColorCorrect(this, color)) { - throw new ParticleColorException("The particle color type is incorrect"); - } - new ParticlePacket(this, color, isLongDistance(center, players)).sendTo(center, players); - } - - /** - * Displays a single particle which is colored and only visible for the specified players - * - * @param color Color of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect - * @see #display(ParticleColor, Location, List) - */ - public void display(ParticleColor color, Location center, Player... players) throws ParticleVersionException, ParticleColorException { - display(color, center, Arrays.asList(players)); - } - - /** - * Displays a particle effect which requires additional data and is only visible for all players within a certain range in the world of @param center - * - * @param data Data of the effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, data).sendTo(center, range); - } - - /** - * Displays a particle effect which requires additional data and is only visible for the specified players - * - * @param data Data of the effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), data).sendTo(center, players); - } - - /** - * Displays a particle effect which requires additional data and is only visible for the specified players - * - * @param data Data of the effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see #display(ParticleData, float, float, float, float, int, Location, List) - */ - public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException { - display(data, offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); - } - - /** - * Displays a single particle which requires additional data that flies into a determined direction and is only visible for all players within a certain range in the world of @param center - * - * @param data Data of the effect - * @param direction Direction of the particle - * @param speed Display speed of the particles - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(ParticleData data, Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, direction, speed, range > 256, data).sendTo(center, range); - } - - /** - * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players - * - * @param data Data of the effect - * @param direction Direction of the particle - * @param speed Display speed of the particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(ParticleData data, Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, direction, speed, isLongDistance(center, players), data).sendTo(center, players); - } - - /** - * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players - * - * @param data Data of the effect - * @param direction Direction of the particle - * @param speed Display speed of the particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see #display(ParticleData, Vector, float, Location, List) - */ - public void display(ParticleData data, Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException { - display(data, direction, speed, center, Arrays.asList(players)); - } - - /** - * Represents the property of a particle effect - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public enum ParticleProperty { - /** - * The particle effect requires water to be displayed - */ - REQUIRES_WATER, - /** - * The particle effect requires block or item data to be displayed - */ - REQUIRES_DATA, - /** - * The particle effect uses the offsets as direction values - */ - DIRECTIONAL, - /** - * The particle effect uses the offsets as color values - */ - COLORABLE - } - - /** - * Represents the particle data for effects like {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - public static abstract class ParticleData { - private final Material material; - private final byte data; - private final int[] packetData; - - /** - * Construct a new particle data - * - * @param material Material of the item/block - * @param data Data value of the item/block - */ - @SuppressWarnings("deprecation") - public ParticleData(Material material, byte data) { - this.material = material; - this.data = data; - this.packetData = new int[]{material.getId(), data}; - } - - /** - * Returns the material of this data - * - * @return The material - */ - public Material getMaterial() { - return material; - } - - /** - * Returns the data value of this data - * - * @return The data value - */ - public byte getData() { - return data; - } - - /** - * Returns the data as an int array for packet construction - * - * @return The data for the packet - */ - public int[] getPacketData() { - return packetData; - } - - /** - * Returns the data as a string for pre 1.8 versions - * - * @return The data string for the packet - */ - public String getPacketDataString() { - return "_" + packetData[0] + "_" + packetData[1]; - } - } - - /** - * Represents the item data for the {@link ParticleEffect#ITEM_CRACK} effect - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - public static final class ItemData extends ParticleData { - /** - * Construct a new item data - * - * @param material Material of the item - * @param data Data value of the item - * @see ParticleData#ParticleData(Material, byte) - */ - public ItemData(Material material, byte data) { - super(material, data); - } - } - - /** - * Represents the block data for the {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} effects - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - public static final class BlockData extends ParticleData { - /** - * Construct a new block data - * - * @param material Material of the block - * @param data Data value of the block - * @throws IllegalArgumentException If the material is not a block - * @see ParticleData#ParticleData(Material, byte) - */ - public BlockData(Material material, byte data) throws IllegalArgumentException { - super(material, data); - if (!material.isBlock()) { - throw new IllegalArgumentException("The material is not a block"); - } - } - } - - /** - * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT}, {@link ParticleEffect#REDSTONE} and {@link ParticleEffect#NOTE} - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public static abstract class ParticleColor { - /** - * Returns the value for the offsetX field - * - * @return The offsetX value - */ - public abstract float getValueX(); - - /** - * Returns the value for the offsetY field - * - * @return The offsetY value - */ - public abstract float getValueY(); - - /** - * Returns the value for the offsetZ field - * - * @return The offsetZ value - */ - public abstract float getValueZ(); - } - - /** - * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT} and {@link ParticleEffect#NOTE} - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public static final class OrdinaryColor extends ParticleColor { - private final int red; - private final int green; - private final int blue; - - /** - * Construct a new ordinary color - * - * @param red Red value of the RGB format - * @param green Green value of the RGB format - * @param blue Blue value of the RGB format - * @throws IllegalArgumentException If one of the values is lower than 0 or higher than 255 - */ - public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException { - if (red < 0) { - throw new IllegalArgumentException("The red value is lower than 0"); - } - if (red > 255) { - throw new IllegalArgumentException("The red value is higher than 255"); - } - this.red = red; - if (green < 0) { - throw new IllegalArgumentException("The green value is lower than 0"); - } - if (green > 255) { - throw new IllegalArgumentException("The green value is higher than 255"); - } - this.green = green; - if (blue < 0) { - throw new IllegalArgumentException("The blue value is lower than 0"); - } - if (blue > 255) { - throw new IllegalArgumentException("The blue value is higher than 255"); - } - this.blue = blue; - } - - /** - * Construct a new ordinary color - * - * @param color Bukkit color - */ - public OrdinaryColor(Color color) { - this(color.getRed(), color.getGreen(), color.getBlue()); - } - - /** - * Returns the red value of the RGB format - * - * @return The red value - */ - public int getRed() { - return red; - } - - /** - * Returns the green value of the RGB format - * - * @return The green value - */ - public int getGreen() { - return green; - } - - /** - * Returns the blue value of the RGB format - * - * @return The blue value - */ - public int getBlue() { - return blue; - } - - /** - * Returns the red value divided by 255 - * - * @return The offsetX value - */ - @Override - public float getValueX() { - return (float) red / 255F; - } - - /** - * Returns the green value divided by 255 - * - * @return The offsetY value - */ - @Override - public float getValueY() { - return (float) green / 255F; - } - - /** - * Returns the blue value divided by 255 - * - * @return The offsetZ value - */ - @Override - public float getValueZ() { - return (float) blue / 255F; - } - } - - /** - * Represents the color for the {@link ParticleEffect#NOTE} effect - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public static final class NoteColor extends ParticleColor { - private final int note; - - /** - * Construct a new note color - * - * @param note Note id which determines color - * @throws IllegalArgumentException If the note value is lower than 0 or higher than 24 - */ - public NoteColor(int note) throws IllegalArgumentException { - if (note < 0) { - throw new IllegalArgumentException("The note value is lower than 0"); - } - if (note > 24) { - throw new IllegalArgumentException("The note value is higher than 24"); - } - this.note = note; - } - - /** - * Returns the note value divided by 24 - * - * @return The offsetX value - */ - @Override - public float getValueX() { - return (float) note / 24F; - } - - /** - * Returns zero because the offsetY value is unused - * - * @return zero - */ - @Override - public float getValueY() { - return 0; - } - - /** - * Returns zero because the offsetZ value is unused - * - * @return zero - */ - @Override - public float getValueZ() { - return 0; - } - - } - - /** - * Represents a runtime exception that is thrown either if the displayed particle effect requires data and has none or vice-versa or if the data type is incorrect - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - private static final class ParticleDataException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new particle data exception - * - * @param message Message that will be logged - */ - public ParticleDataException(String message) { - super(message); - } - } - - /** - * Represents a runtime exception that is thrown either if the displayed particle effect is not colorable or if the particle color type is incorrect - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - private static final class ParticleColorException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new particle color exception - * - * @param message Message that will be logged - */ - public ParticleColorException(String message) { - super(message); - } - } - - /** - * Represents a runtime exception that is thrown if the displayed particle effect requires a newer version - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - private static final class ParticleVersionException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new particle version exception - * - * @param message Message that will be logged - */ - public ParticleVersionException(String message) { - super(message); - } - } - - /** - * Represents a particle effect packet with all attributes which is used for sending packets to the players - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.5 - */ - public static final class ParticlePacket { - private static int version; - private static Class enumParticle; - private static Constructor packetConstructor; - private static Method getHandle; - private static Field playerConnection; - private static Method sendPacket; - private static boolean initialized; - private final ParticleEffect effect; - private final float offsetY; - private final float offsetZ; - private final float speed; - private final int amount; - private final boolean longDistance; - private final ParticleData data; - private float offsetX; - private Object packet; - - /** - * Construct a new particle packet - * - * @param effect Particle effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 - * @param data Data of the effect - * @throws IllegalArgumentException If the speed or amount is lower than 0 - * @see #initialize() - */ - public ParticlePacket(ParticleEffect effect, float offsetX, float offsetY, float offsetZ, float speed, int amount, boolean longDistance, ParticleData data) throws IllegalArgumentException { - initialize(); - if (speed < 0) { - throw new IllegalArgumentException("The speed is lower than 0"); - } - if (amount < 0) { - throw new IllegalArgumentException("The amount is lower than 0"); - } - this.effect = effect; - this.offsetX = offsetX; - this.offsetY = offsetY; - this.offsetZ = offsetZ; - this.speed = speed; - this.amount = amount; - this.longDistance = longDistance; - this.data = data; - } - - /** - * Construct a new particle packet of a single particle flying into a determined direction - * - * @param effect Particle effect - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 - * @param data Data of the effect - * @throws IllegalArgumentException If the speed is lower than 0 - */ - public ParticlePacket(ParticleEffect effect, Vector direction, float speed, boolean longDistance, ParticleData data) throws IllegalArgumentException { - this(effect, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), speed, 0, longDistance, data); - } - - /** - * Construct a new particle packet of a single colored particle - * - * @param effect Particle effect - * @param color Color of the particle - * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 - */ - public ParticlePacket(ParticleEffect effect, ParticleColor color, boolean longDistance) { - this(effect, color.getValueX(), color.getValueY(), color.getValueZ(), 1, 0, longDistance, null); - if (effect == ParticleEffect.REDSTONE && color instanceof OrdinaryColor && ((OrdinaryColor) color).getRed() == 0) { - offsetX = Float.MIN_NORMAL; - } - } - - /** - * Initializes {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} and sets {@link #initialized} to true if it succeeds - * - * Note: These fields only have to be initialized once, so it will return if {@link #initialized} is already set to true - * - * @throws VersionIncompatibleException if your bukkit version is not supported by this library - */ - public static void initialize() throws VersionIncompatibleException { - if (initialized) { - return; - } - try { - version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); - if (version > 7) { - enumParticle = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("EnumParticle"); - } - - Class packetClass = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass(version < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles"); - - packetConstructor = ReflectionUtils.getConstructor(packetClass); - getHandle = ReflectionUtils.getMethod("CraftPlayer", ReflectionUtils.PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); - playerConnection = ReflectionUtils.getField("EntityPlayer", ReflectionUtils.PackageType.MINECRAFT_SERVER, false, "playerConnection"); - sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("Packet")); - } catch (Exception exception) { - throw new VersionIncompatibleException("Your current bukkit version seems to be incompatible with this library", exception); - } - initialized = true; - } - - /** - * Returns the version of your server (1.x) - * - * @return The version number - */ - public static int getVersion() { - if (!initialized) { - initialize(); - } - return version; - } - - /** - * Determine if {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} are initialized - * - * @return Whether these fields are initialized or not - * @see #initialize() - */ - public static boolean isInitialized() { - return initialized; - } - - /** - * Initializes {@link #packet} with all set values - * - * @param center Center location of the effect - * @throws PacketInstantiationException If instantion fails due to an unknown error - */ - private void initializePacket(Location center) throws PacketInstantiationException { - if (packet != null) { - return; - } - try { - packet = packetConstructor.newInstance(); - if (version < 8) { - String name = effect.getName(); - if (data != null) { - name += data.getPacketDataString(); - } - ReflectionUtils.setValue(packet, true, "a", name); - } else { - ReflectionUtils.setValue(packet, true, "a", enumParticle.getEnumConstants()[effect.getId()]); - ReflectionUtils.setValue(packet, true, "j", longDistance); - if (data != null) { - int[] packetData = data.getPacketData(); - ReflectionUtils.setValue(packet, true, "k", effect == ParticleEffect.ITEM_CRACK ? packetData : new int[]{packetData[0] | (packetData[1] << 12)}); - } - } - ReflectionUtils.setValue(packet, true, "b", (float) center.getX()); - ReflectionUtils.setValue(packet, true, "c", (float) center.getY()); - ReflectionUtils.setValue(packet, true, "d", (float) center.getZ()); - ReflectionUtils.setValue(packet, true, "e", offsetX); - ReflectionUtils.setValue(packet, true, "f", offsetY); - ReflectionUtils.setValue(packet, true, "g", offsetZ); - ReflectionUtils.setValue(packet, true, "h", speed); - ReflectionUtils.setValue(packet, true, "i", amount); - } catch (Exception exception) { - throw new PacketInstantiationException("Packet instantiation failed", exception); - } - } - - /** - * Sends the packet to a single player and caches it - * - * @param center Center location of the effect - * @param player Receiver of the packet - * @throws PacketInstantiationException If instantion fails due to an unknown error - * @throws PacketSendingException If sending fails due to an unknown error - * @see #initializePacket(Location) - */ - public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException { - initializePacket(center); - try { - sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), packet); - } catch (Exception exception) { - throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception); - } - } - - /** - * Sends the packet to all players in the list - * - * @param center Center location of the effect - * @param players Receivers of the packet - * @throws IllegalArgumentException If the player list is empty - * @see #sendTo(Location center, Player player) - */ - public void sendTo(Location center, List players) throws IllegalArgumentException { - if (players.isEmpty()) { - throw new IllegalArgumentException("The player list is empty"); - } - for (Player player : players) { - sendTo(center, player); - } - } - - /** - * Sends the packet to all players in a certain range - * - * @param center Center location of the effect - * @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types) - * @throws IllegalArgumentException If the range is lower than 1 - * @see #sendTo(Location center, Player player) - */ - public void sendTo(Location center, double range) throws IllegalArgumentException { - if (range < 1) { - throw new IllegalArgumentException("The range is lower than 1"); - } - String worldName = center.getWorld().getName(); - double squared = range * range; - for (Player player : Bukkit.getOnlinePlayers()) { - if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) { - continue; - } - sendTo(center, player); - } - } - - /** - * Represents a runtime exception that is thrown if a bukkit version is not compatible with this library - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.5 - */ - private static final class VersionIncompatibleException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new version incompatible exception - * - * @param message Message that will be logged - * @param cause Cause of the exception - */ - public VersionIncompatibleException(String message, Throwable cause) { - super(message, cause); - } - } - - /** - * Represents a runtime exception that is thrown if packet instantiation fails - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.4 - */ - private static final class PacketInstantiationException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new packet instantiation exception - * - * @param message Message that will be logged - * @param cause Cause of the exception - */ - public PacketInstantiationException(String message, Throwable cause) { - super(message, cause); - } - } - - /** - * Represents a runtime exception that is thrown if packet sending fails - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.4 - */ - private static final class PacketSendingException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new packet sending exception - * - * @param message Message that will be logged - * @param cause Cause of the exception - */ - public PacketSendingException(String message, Throwable cause) { - super(message, cause); - } - } - } + /** + * A particle effect which is displayed by exploding tnt and creepers: + *

      + *
    • It looks like a white cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + EXPLOSION_NORMAL("explode", 0, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by exploding ghast fireballs and wither skulls: + *
      + *
    • It looks like a gray ball which is fading away + *
    • The speed value slightly influences the size of this particle effect + *
    + */ + EXPLOSION_LARGE("largeexplode", 1, -1), + /** + * A particle effect which is displayed by exploding tnt and creepers: + *
      + *
    • It looks like a crowd of gray balls which are fading away + *
    • The speed value has no influence on this particle effect + *
    + */ + EXPLOSION_HUGE("hugeexplosion", 2, -1), + /** + * A particle effect which is displayed by launching fireworks: + *
      + *
    • It looks like a white star which is sparkling + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + FIREWORKS_SPARK("fireworksSpark", 3, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by swimming entities and arrows in water: + *
      + *
    • It looks like a bubble + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + WATER_BUBBLE("bubble", 4, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_WATER), + /** + * A particle effect which is displayed by swimming entities and shaking wolves: + *
      + *
    • It looks like a blue drop + *
    • The speed value has no influence on this particle effect + *
    + */ + WATER_SPLASH("splash", 5, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed on water when fishing: + *
      + *
    • It looks like a blue droplet + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + WATER_WAKE("wake", 6, 7, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by water: + *
      + *
    • It looks like a tiny blue square + *
    • The speed value has no influence on this particle effect + *
    + */ + SUSPENDED("suspended", 7, -1, ParticleProperty.REQUIRES_WATER), + /** + * A particle effect which is displayed by air when close to bedrock and the in the void: + *
      + *
    • It looks like a tiny gray square + *
    • The speed value has no influence on this particle effect + *
    + */ + SUSPENDED_DEPTH("depthSuspend", 8, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed when landing a critical hit and by arrows: + *
      + *
    • It looks like a light brown cross + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + CRIT("crit", 9, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed when landing a hit with an enchanted weapon: + *
      + *
    • It looks like a cyan star + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + CRIT_MAGIC("magicCrit", 10, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by primed tnt, torches, droppers, dispensers, end portals, brewing stands and monster spawners: + *
      + *
    • It looks like a little gray cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + SMOKE_NORMAL("smoke", 11, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by fire, minecarts with furnace and blazes: + *
      + *
    • It looks like a large gray cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + SMOKE_LARGE("largesmoke", 12, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed when splash potions or bottles o' enchanting hit something: + *
      + *
    • It looks like a white swirl + *
    • The speed value causes the particle to only move upwards when set to 0 + *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 + *
    + */ + SPELL("spell", 13, -1), + /** + * A particle effect which is displayed when instant splash potions hit something: + *
      + *
    • It looks like a white cross + *
    • The speed value causes the particle to only move upwards when set to 0 + *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 + *
    + */ + SPELL_INSTANT("instantSpell", 14, -1), + /** + * A particle effect which is displayed by entities with active potion effects: + *
      + *
    • It looks like a colored swirl + *
    • The speed value causes the particle to be colored black when set to 0 + *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed + *
    + */ + SPELL_MOB("mobSpell", 15, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed by entities with active potion effects applied through a beacon: + *
      + *
    • It looks like a transparent colored swirl + *
    • The speed value causes the particle to be always colored black when set to 0 + *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed + *
    + */ + SPELL_MOB_AMBIENT("mobSpellAmbient", 16, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed by witches: + *
      + *
    • It looks like a purple cross + *
    • The speed value causes the particle to only move upwards when set to 0 + *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 + *
    + */ + SPELL_WITCH("witchMagic", 17, -1), + /** + * A particle effect which is displayed by blocks beneath a water source: + *
      + *
    • It looks like a blue drip + *
    • The speed value has no influence on this particle effect + *
    + */ + DRIP_WATER("dripWater", 18, -1), + /** + * A particle effect which is displayed by blocks beneath a lava source: + *
      + *
    • It looks like an orange drip + *
    • The speed value has no influence on this particle effect + *
    + */ + DRIP_LAVA("dripLava", 19, -1), + /** + * A particle effect which is displayed when attacking a villager in a village: + *
      + *
    • It looks like a cracked gray heart + *
    • The speed value has no influence on this particle effect + *
    + */ + VILLAGER_ANGRY("angryVillager", 20, -1), + /** + * A particle effect which is displayed when using bone meal and trading with a villager in a village: + *
      + *
    • It looks like a green star + *
    • The speed value has no influence on this particle effect + *
    + */ + VILLAGER_HAPPY("happyVillager", 21, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by mycelium: + *
      + *
    • It looks like a tiny gray square + *
    • The speed value has no influence on this particle effect + *
    + */ + TOWN_AURA("townaura", 22, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by note blocks: + *
      + *
    • It looks like a colored note + *
    • The speed value causes the particle to be colored green when set to 0 + *
    + */ + NOTE("note", 23, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed by nether portals, endermen, ender pearls, eyes of ender, ender chests and dragon eggs: + *
      + *
    • It looks like a purple cloud + *
    • The speed value influences the spread of this particle effect + *
    + */ + PORTAL("portal", 24, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by enchantment tables which are nearby bookshelves: + *
      + *
    • It looks like a cryptic white letter + *
    • The speed value influences the spread of this particle effect + *
    + */ + ENCHANTMENT_TABLE("enchantmenttable", 25, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by torches, active furnaces, magma cubes and monster spawners: + *
      + *
    • It looks like a tiny flame + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + FLAME("flame", 26, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by lava: + *
      + *
    • It looks like a spark + *
    • The speed value has no influence on this particle effect + *
    + */ + LAVA("lava", 27, -1), + /** + * A particle effect which is currently unused: + *
      + *
    • It looks like a transparent gray square + *
    • The speed value has no influence on this particle effect + *
    + */ + FOOTSTEP("footstep", 28, -1), + /** + * A particle effect which is displayed when a mob dies: + *
      + *
    • It looks like a large white cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + CLOUD("cloud", 29, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by redstone ore, powered redstone, redstone torches and redstone repeaters: + *
      + *
    • It looks like a tiny colored cloud + *
    • The speed value causes the particle to be colored red when set to 0 + *
    + */ + REDSTONE("reddust", 30, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed when snowballs hit a block: + *
      + *
    • It looks like a little piece with the snowball texture + *
    • The speed value has no influence on this particle effect + *
    + */ + SNOWBALL("snowballpoof", 31, -1), + /** + * A particle effect which is currently unused: + *
      + *
    • It looks like a tiny white cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + SNOW_SHOVEL("snowshovel", 32, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by slimes: + *
      + *
    • It looks like a tiny part of the slimeball icon + *
    • The speed value has no influence on this particle effect + *
    + */ + SLIME("slime", 33, -1), + /** + * A particle effect which is displayed when breeding and taming animals: + *
      + *
    • It looks like a red heart + *
    • The speed value has no influence on this particle effect + *
    + */ + HEART("heart", 34, -1), + /** + * A particle effect which is displayed by barriers: + *
      + *
    • It looks like a red box with a slash through it + *
    • The speed value has no influence on this particle effect + *
    + */ + BARRIER("barrier", 35, 8), + /** + * A particle effect which is displayed when breaking a tool or eggs hit a block: + *
      + *
    • It looks like a little piece with an item texture + *
    + */ + ITEM_CRACK("iconcrack", 36, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), + /** + * A particle effect which is displayed when breaking blocks or sprinting: + *
      + *
    • It looks like a little piece with a block texture + *
    • The speed value has no influence on this particle effect + *
    + */ + BLOCK_CRACK("blockcrack", 37, -1, ParticleProperty.REQUIRES_DATA), + /** + * A particle effect which is displayed when falling: + *
      + *
    • It looks like a little piece with a block texture + *
    + */ + BLOCK_DUST("blockdust", 38, 7, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), + /** + * A particle effect which is displayed when rain hits the ground: + *
      + *
    • It looks like a blue droplet + *
    • The speed value has no influence on this particle effect + *
    + */ + WATER_DROP("droplet", 39, 8), + /** + * A particle effect which is currently unused: + *
      + *
    • It has no visual effect + *
    + */ + ITEM_TAKE("take", 40, 8), + /** + * A particle effect which is displayed by elder guardians: + *
      + *
    • It looks like the shape of the elder guardian + *
    • The speed value has no influence on this particle effect + *
    • The offset values have no influence on this particle effect + *
    + */ + MOB_APPEARANCE("mobappearance", 41, 8); + + private static final Map NAME_MAP = new HashMap(); + private static final Map ID_MAP = new HashMap(); + + // Initialize map for quick name and id lookup + static { + for (ParticleEffect effect : values()) { + NAME_MAP.put(effect.name, effect); + ID_MAP.put(effect.id, effect); + } + } + + private final String name; + private final int id; + private final int requiredVersion; + private final List properties; + + /** + * Construct a new particle effect + * + * @param name Name of this particle effect + * @param id Id of this particle effect + * @param requiredVersion Version which is required (1.x) + * @param properties Properties of this particle effect + */ + ParticleEffect(String name, int id, int requiredVersion, ParticleProperty... properties) { + this.name = name; + this.id = id; + this.requiredVersion = requiredVersion; + this.properties = Arrays.asList(properties); + } + + /** + * Returns the particle effect with the given name + * + * @param name Name of the particle effect + * @return The particle effect + */ + public static ParticleEffect fromName(String name) { + for (Entry entry : NAME_MAP.entrySet()) { + if (!entry.getKey().equalsIgnoreCase(name)) { + continue; + } + return entry.getValue(); + } + return null; + } + + /** + * Returns the particle effect with the given id + * + * @param id Id of the particle effect + * @return The particle effect + */ + public static ParticleEffect fromId(int id) { + for (Entry entry : ID_MAP.entrySet()) { + if (entry.getKey() != id) { + continue; + } + return entry.getValue(); + } + return null; + } + + /** + * Determine if water is at a certain location + * + * @param location Location to check + * @return Whether water is at this location or not + */ + private static boolean isWater(Location location) { + Material material = location.getBlock().getType(); + return material == Material.WATER || material == SavageFactions.plugin.STATIONARY_WATER; + } + + /** + * Determine if the distance between @param location and one of the players exceeds 256 + * + * @param location Location to check + * @return Whether the distance exceeds 256 or not + */ + private static boolean isLongDistance(Location location, List players) { + String world = location.getWorld().getName(); + for (Player player : players) { + Location playerLocation = player.getLocation(); + if (!world.equals(playerLocation.getWorld().getName()) || playerLocation.distanceSquared(location) < 65536) { + continue; + } + return true; + } + return false; + } + + /** + * Determine if the data type for a particle effect is correct + * + * @param effect Particle effect + * @param data Particle data + * @return Whether the data type is correct or not + */ + private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) { + return ((effect == BLOCK_CRACK || effect == BLOCK_DUST) && data instanceof BlockData) || (effect == ITEM_CRACK && data instanceof ItemData); + } + + /** + * Determine if the color type for a particle effect is correct + * + * @param effect Particle effect + * @param color Particle color + * @return Whether the color type is correct or not + */ + private static boolean isColorCorrect(ParticleEffect effect, ParticleColor color) { + return ((effect == SPELL_MOB || effect == SPELL_MOB_AMBIENT || effect == REDSTONE) && color instanceof OrdinaryColor) || (effect == NOTE && color instanceof NoteColor); + } + + /** + * Returns the name of this particle effect + * + * @return The name + */ + public String getName() { + return name; + } + + /** + * Returns the id of this particle effect + * + * @return The id + */ + public int getId() { + return id; + } + + /** + * Returns the required version for this particle effect (1.x) + * + * @return The required version + */ + public int getRequiredVersion() { + return requiredVersion; + } + + /** + * Determine if this particle effect has a specific property + * + * @param property - property to check. + * @return Whether it has the property or not + */ + public boolean hasProperty(ParticleProperty property) { + return properties.contains(property); + } + + /** + * Determine if this particle effect is supported by your current server version + * + * @return Whether the particle effect is supported or not + */ + public boolean isSupported() { + if (requiredVersion == -1) { + return true; + } + return ParticlePacket.getVersion() >= requiredVersion; + } + + /** + * Displays a particle effect which is only visible for all players within a certain range in the world of @param center + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, null).sendTo(center, range); + } + + /** + * Displays a particle effect which is only visible for the specified players + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), null).sendTo(center, players); + } + + /** + * Displays a particle effect which is only visible for the specified players + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see #display(float, float, float, float, int, Location, List) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + display(offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for all players within a certain range in the world of @param center + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location + * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (!hasProperty(ParticleProperty.DIRECTIONAL)) { + throw new IllegalArgumentException("This particle effect is not directional"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, direction, speed, range > 256, null).sendTo(center, range); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for the specified players + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location + * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (!hasProperty(ParticleProperty.DIRECTIONAL)) { + throw new IllegalArgumentException("This particle effect is not directional"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, direction, speed, isLongDistance(center, players), null).sendTo(center, players); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for the specified players + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location + * @see #display(Vector, float, Location, List) + */ + public void display(Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + display(direction, speed, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which is colored and only visible for all players within a certain range in the world of @param center + * + * @param color Color of the particle + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect + * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleColor color, Location center, double range) throws ParticleVersionException, ParticleColorException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.COLORABLE)) { + throw new ParticleColorException("This particle effect is not colorable"); + } + if (!isColorCorrect(this, color)) { + throw new ParticleColorException("The particle color type is incorrect"); + } + new ParticlePacket(this, color, range > 256).sendTo(center, range); + } + + /** + * Displays a single particle which is colored and only visible for the specified players + * + * @param color Color of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect + * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleColor color, Location center, List players) throws ParticleVersionException, ParticleColorException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.COLORABLE)) { + throw new ParticleColorException("This particle effect is not colorable"); + } + if (!isColorCorrect(this, color)) { + throw new ParticleColorException("The particle color type is incorrect"); + } + new ParticlePacket(this, color, isLongDistance(center, players)).sendTo(center, players); + } + + /** + * Displays a single particle which is colored and only visible for the specified players + * + * @param color Color of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect + * @see #display(ParticleColor, Location, List) + */ + public void display(ParticleColor color, Location center, Player... players) throws ParticleVersionException, ParticleColorException { + display(color, center, Arrays.asList(players)); + } + + /** + * Displays a particle effect which requires additional data and is only visible for all players within a certain range in the world of @param center + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, data).sendTo(center, range); + } + + /** + * Displays a particle effect which requires additional data and is only visible for the specified players + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), data).sendTo(center, players); + } + + /** + * Displays a particle effect which requires additional data and is only visible for the specified players + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see #display(ParticleData, float, float, float, float, int, Location, List) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException { + display(data, offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for all players within a certain range in the world of @param center + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, direction, speed, range > 256, data).sendTo(center, range); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, direction, speed, isLongDistance(center, players), data).sendTo(center, players); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see #display(ParticleData, Vector, float, Location, List) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException { + display(data, direction, speed, center, Arrays.asList(players)); + } + + /** + * Represents the property of a particle effect + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public enum ParticleProperty { + /** + * The particle effect requires water to be displayed + */ + REQUIRES_WATER, + /** + * The particle effect requires block or item data to be displayed + */ + REQUIRES_DATA, + /** + * The particle effect uses the offsets as direction values + */ + DIRECTIONAL, + /** + * The particle effect uses the offsets as color values + */ + COLORABLE + } + + /** + * Represents the particle data for effects like {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static abstract class ParticleData { + private final Material material; + private final byte data; + private final int[] packetData; + + /** + * Construct a new particle data + * + * @param material Material of the item/block + * @param data Data value of the item/block + */ + @SuppressWarnings("deprecation") + public ParticleData(Material material, byte data) { + this.material = material; + this.data = data; + this.packetData = new int[]{material.getId(), data}; + } + + /** + * Returns the material of this data + * + * @return The material + */ + public Material getMaterial() { + return material; + } + + /** + * Returns the data value of this data + * + * @return The data value + */ + public byte getData() { + return data; + } + + /** + * Returns the data as an int array for packet construction + * + * @return The data for the packet + */ + public int[] getPacketData() { + return packetData; + } + + /** + * Returns the data as a string for pre 1.8 versions + * + * @return The data string for the packet + */ + public String getPacketDataString() { + return "_" + packetData[0] + "_" + packetData[1]; + } + } + + /** + * Represents the item data for the {@link ParticleEffect#ITEM_CRACK} effect + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static final class ItemData extends ParticleData { + /** + * Construct a new item data + * + * @param material Material of the item + * @param data Data value of the item + * @see ParticleData#ParticleData(Material, byte) + */ + public ItemData(Material material, byte data) { + super(material, data); + } + } + + /** + * Represents the block data for the {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} effects + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static final class BlockData extends ParticleData { + /** + * Construct a new block data + * + * @param material Material of the block + * @param data Data value of the block + * @throws IllegalArgumentException If the material is not a block + * @see ParticleData#ParticleData(Material, byte) + */ + public BlockData(Material material, byte data) throws IllegalArgumentException { + super(material, data); + if (!material.isBlock()) { + throw new IllegalArgumentException("The material is not a block"); + } + } + } + + /** + * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT}, {@link ParticleEffect#REDSTONE} and {@link ParticleEffect#NOTE} + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public static abstract class ParticleColor { + /** + * Returns the value for the offsetX field + * + * @return The offsetX value + */ + public abstract float getValueX(); + + /** + * Returns the value for the offsetY field + * + * @return The offsetY value + */ + public abstract float getValueY(); + + /** + * Returns the value for the offsetZ field + * + * @return The offsetZ value + */ + public abstract float getValueZ(); + } + + /** + * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT} and {@link ParticleEffect#NOTE} + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public static final class OrdinaryColor extends ParticleColor { + private final int red; + private final int green; + private final int blue; + + /** + * Construct a new ordinary color + * + * @param red Red value of the RGB format + * @param green Green value of the RGB format + * @param blue Blue value of the RGB format + * @throws IllegalArgumentException If one of the values is lower than 0 or higher than 255 + */ + public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException { + if (red < 0) { + throw new IllegalArgumentException("The red value is lower than 0"); + } + if (red > 255) { + throw new IllegalArgumentException("The red value is higher than 255"); + } + this.red = red; + if (green < 0) { + throw new IllegalArgumentException("The green value is lower than 0"); + } + if (green > 255) { + throw new IllegalArgumentException("The green value is higher than 255"); + } + this.green = green; + if (blue < 0) { + throw new IllegalArgumentException("The blue value is lower than 0"); + } + if (blue > 255) { + throw new IllegalArgumentException("The blue value is higher than 255"); + } + this.blue = blue; + } + + /** + * Construct a new ordinary color + * + * @param color Bukkit color + */ + public OrdinaryColor(Color color) { + this(color.getRed(), color.getGreen(), color.getBlue()); + } + + /** + * Returns the red value of the RGB format + * + * @return The red value + */ + public int getRed() { + return red; + } + + /** + * Returns the green value of the RGB format + * + * @return The green value + */ + public int getGreen() { + return green; + } + + /** + * Returns the blue value of the RGB format + * + * @return The blue value + */ + public int getBlue() { + return blue; + } + + /** + * Returns the red value divided by 255 + * + * @return The offsetX value + */ + @Override + public float getValueX() { + return (float) red / 255F; + } + + /** + * Returns the green value divided by 255 + * + * @return The offsetY value + */ + @Override + public float getValueY() { + return (float) green / 255F; + } + + /** + * Returns the blue value divided by 255 + * + * @return The offsetZ value + */ + @Override + public float getValueZ() { + return (float) blue / 255F; + } + } + + /** + * Represents the color for the {@link ParticleEffect#NOTE} effect + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public static final class NoteColor extends ParticleColor { + private final int note; + + /** + * Construct a new note color + * + * @param note Note id which determines color + * @throws IllegalArgumentException If the note value is lower than 0 or higher than 24 + */ + public NoteColor(int note) throws IllegalArgumentException { + if (note < 0) { + throw new IllegalArgumentException("The note value is lower than 0"); + } + if (note > 24) { + throw new IllegalArgumentException("The note value is higher than 24"); + } + this.note = note; + } + + /** + * Returns the note value divided by 24 + * + * @return The offsetX value + */ + @Override + public float getValueX() { + return (float) note / 24F; + } + + /** + * Returns zero because the offsetY value is unused + * + * @return zero + */ + @Override + public float getValueY() { + return 0; + } + + /** + * Returns zero because the offsetZ value is unused + * + * @return zero + */ + @Override + public float getValueZ() { + return 0; + } + + } + + /** + * Represents a runtime exception that is thrown either if the displayed particle effect requires data and has none or vice-versa or if the data type is incorrect + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + private static final class ParticleDataException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle data exception + * + * @param message Message that will be logged + */ + public ParticleDataException(String message) { + super(message); + } + } + + /** + * Represents a runtime exception that is thrown either if the displayed particle effect is not colorable or if the particle color type is incorrect + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + private static final class ParticleColorException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle color exception + * + * @param message Message that will be logged + */ + public ParticleColorException(String message) { + super(message); + } + } + + /** + * Represents a runtime exception that is thrown if the displayed particle effect requires a newer version + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + private static final class ParticleVersionException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle version exception + * + * @param message Message that will be logged + */ + public ParticleVersionException(String message) { + super(message); + } + } + + /** + * Represents a particle effect packet with all attributes which is used for sending packets to the players + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.5 + */ + public static final class ParticlePacket { + private static int version; + private static Class enumParticle; + private static Constructor packetConstructor; + private static Method getHandle; + private static Field playerConnection; + private static Method sendPacket; + private static boolean initialized; + private final ParticleEffect effect; + private final float offsetY; + private final float offsetZ; + private final float speed; + private final int amount; + private final boolean longDistance; + private final ParticleData data; + private float offsetX; + private Object packet; + + /** + * Construct a new particle packet + * + * @param effect Particle effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + * @param data Data of the effect + * @throws IllegalArgumentException If the speed or amount is lower than 0 + * @see #initialize() + */ + public ParticlePacket(ParticleEffect effect, float offsetX, float offsetY, float offsetZ, float speed, int amount, boolean longDistance, ParticleData data) throws IllegalArgumentException { + initialize(); + if (speed < 0) { + throw new IllegalArgumentException("The speed is lower than 0"); + } + if (amount < 0) { + throw new IllegalArgumentException("The amount is lower than 0"); + } + this.effect = effect; + this.offsetX = offsetX; + this.offsetY = offsetY; + this.offsetZ = offsetZ; + this.speed = speed; + this.amount = amount; + this.longDistance = longDistance; + this.data = data; + } + + /** + * Construct a new particle packet of a single particle flying into a determined direction + * + * @param effect Particle effect + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + * @param data Data of the effect + * @throws IllegalArgumentException If the speed is lower than 0 + */ + public ParticlePacket(ParticleEffect effect, Vector direction, float speed, boolean longDistance, ParticleData data) throws IllegalArgumentException { + this(effect, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), speed, 0, longDistance, data); + } + + /** + * Construct a new particle packet of a single colored particle + * + * @param effect Particle effect + * @param color Color of the particle + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + */ + public ParticlePacket(ParticleEffect effect, ParticleColor color, boolean longDistance) { + this(effect, color.getValueX(), color.getValueY(), color.getValueZ(), 1, 0, longDistance, null); + if (effect == ParticleEffect.REDSTONE && color instanceof OrdinaryColor && ((OrdinaryColor) color).getRed() == 0) { + offsetX = Float.MIN_NORMAL; + } + } + + /** + * Initializes {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} and sets {@link #initialized} to true if it succeeds + * + * Note: These fields only have to be initialized once, so it will return if {@link #initialized} is already set to true + * + * @throws VersionIncompatibleException if your bukkit version is not supported by this library + */ + public static void initialize() throws VersionIncompatibleException { + if (initialized) { + return; + } + try { + version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); + if (version > 7) { + enumParticle = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("EnumParticle"); + } + + Class packetClass = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass(version < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles"); + + packetConstructor = ReflectionUtils.getConstructor(packetClass); + getHandle = ReflectionUtils.getMethod("CraftPlayer", ReflectionUtils.PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); + playerConnection = ReflectionUtils.getField("EntityPlayer", ReflectionUtils.PackageType.MINECRAFT_SERVER, false, "playerConnection"); + sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("Packet")); + } catch (Exception exception) { + throw new VersionIncompatibleException("Your current bukkit version seems to be incompatible with this library", exception); + } + initialized = true; + } + + /** + * Returns the version of your server (1.x) + * + * @return The version number + */ + public static int getVersion() { + if (!initialized) { + initialize(); + } + return version; + } + + /** + * Determine if {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} are initialized + * + * @return Whether these fields are initialized or not + * @see #initialize() + */ + public static boolean isInitialized() { + return initialized; + } + + /** + * Initializes {@link #packet} with all set values + * + * @param center Center location of the effect + * @throws PacketInstantiationException If instantion fails due to an unknown error + */ + private void initializePacket(Location center) throws PacketInstantiationException { + if (packet != null) { + return; + } + try { + packet = packetConstructor.newInstance(); + if (version < 8) { + String name = effect.getName(); + if (data != null) { + name += data.getPacketDataString(); + } + ReflectionUtils.setValue(packet, true, "a", name); + } else { + ReflectionUtils.setValue(packet, true, "a", enumParticle.getEnumConstants()[effect.getId()]); + ReflectionUtils.setValue(packet, true, "j", longDistance); + if (data != null) { + int[] packetData = data.getPacketData(); + ReflectionUtils.setValue(packet, true, "k", effect == ParticleEffect.ITEM_CRACK ? packetData : new int[]{packetData[0] | (packetData[1] << 12)}); + } + } + ReflectionUtils.setValue(packet, true, "b", (float) center.getX()); + ReflectionUtils.setValue(packet, true, "c", (float) center.getY()); + ReflectionUtils.setValue(packet, true, "d", (float) center.getZ()); + ReflectionUtils.setValue(packet, true, "e", offsetX); + ReflectionUtils.setValue(packet, true, "f", offsetY); + ReflectionUtils.setValue(packet, true, "g", offsetZ); + ReflectionUtils.setValue(packet, true, "h", speed); + ReflectionUtils.setValue(packet, true, "i", amount); + } catch (Exception exception) { + throw new PacketInstantiationException("Packet instantiation failed", exception); + } + } + + /** + * Sends the packet to a single player and caches it + * + * @param center Center location of the effect + * @param player Receiver of the packet + * @throws PacketInstantiationException If instantion fails due to an unknown error + * @throws PacketSendingException If sending fails due to an unknown error + * @see #initializePacket(Location) + */ + public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException { + initializePacket(center); + try { + sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), packet); + } catch (Exception exception) { + throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception); + } + } + + /** + * Sends the packet to all players in the list + * + * @param center Center location of the effect + * @param players Receivers of the packet + * @throws IllegalArgumentException If the player list is empty + * @see #sendTo(Location center, Player player) + */ + public void sendTo(Location center, List players) throws IllegalArgumentException { + if (players.isEmpty()) { + throw new IllegalArgumentException("The player list is empty"); + } + for (Player player : players) { + sendTo(center, player); + } + } + + /** + * Sends the packet to all players in a certain range + * + * @param center Center location of the effect + * @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types) + * @throws IllegalArgumentException If the range is lower than 1 + * @see #sendTo(Location center, Player player) + */ + public void sendTo(Location center, double range) throws IllegalArgumentException { + if (range < 1) { + throw new IllegalArgumentException("The range is lower than 1"); + } + String worldName = center.getWorld().getName(); + double squared = range * range; + for (Player player : Bukkit.getOnlinePlayers()) { + if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) { + continue; + } + sendTo(center, player); + } + } + + /** + * Represents a runtime exception that is thrown if a bukkit version is not compatible with this library + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.5 + */ + private static final class VersionIncompatibleException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new version incompatible exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public VersionIncompatibleException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Represents a runtime exception that is thrown if packet instantiation fails + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.4 + */ + private static final class PacketInstantiationException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new packet instantiation exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public PacketInstantiationException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Represents a runtime exception that is thrown if packet sending fails + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.4 + */ + private static final class PacketSendingException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new packet sending exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public PacketSendingException(String message, Throwable cause) { + super(message, cause); + } + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java b/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java index e3923367..4184eb08 100644 --- a/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java +++ b/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java @@ -26,583 +26,583 @@ import java.util.Map; * @version 1.1 */ public final class ReflectionUtils { - // Prevent accidental construction - private ReflectionUtils() { - } + // Prevent accidental construction + private ReflectionUtils() { + } - /** - * Returns the constructor of a given class with the given parameter types - * - * @param clazz Target class - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @see DataType - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Constructor constructor : clazz.getConstructors()) { - if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { - continue; - } - return constructor; - } - throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); - } + /** + * Returns the constructor of a given class with the given parameter types + * + * @param clazz Target class + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @see DataType + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Constructor constructor : clazz.getConstructors()) { + if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { + continue; + } + return constructor; + } + throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); + } - /** - * Returns the constructor of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the desired target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #getConstructor(Class, Class...) - */ - public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getConstructor(packageType.getClass(className), parameterTypes); - } + /** + * Returns the constructor of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the desired target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #getConstructor(Class, Class...) + */ + public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getConstructor(packageType.getClass(className), parameterTypes); + } - /** - * Returns an instance of a class with the given arguments - * - * @param clazz Target class - * @param arguments Arguments which are used to construct an object of the target class - * @return The instance of the target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - */ - public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); - } + /** + * Returns an instance of a class with the given arguments + * + * @param clazz Target class + * @param arguments Arguments which are used to construct an object of the target class + * @return The instance of the target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + */ + public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); + } - /** - * Returns an instance of a desired class with the given arguments - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param arguments Arguments which are used to construct an object of the desired target class - * @return The instance of the desired target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #instantiateObject(Class, Object...) - */ - public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return instantiateObject(packageType.getClass(className), arguments); - } + /** + * Returns an instance of a desired class with the given arguments + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param arguments Arguments which are used to construct an object of the desired target class + * @return The instance of the desired target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #instantiateObject(Class, Object...) + */ + public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return instantiateObject(packageType.getClass(className), arguments); + } - /** - * Returns a method of a class with the given parameter types - * - * @param clazz Target class - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Method method : clazz.getMethods()) { - if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { - continue; - } - return method; - } - throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); - } + /** + * Returns a method of a class with the given parameter types + * + * @param clazz Target class + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Method method : clazz.getMethods()) { + if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { + continue; + } + return method; + } + throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); + } - /** - * Returns a method of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the desired target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #getMethod(Class, String, Class...) - */ - public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getMethod(packageType.getClass(className), methodName, parameterTypes); - } + /** + * Returns a method of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the desired target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #getMethod(Class, String, Class...) + */ + public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getMethod(packageType.getClass(className), methodName, parameterTypes); + } - /** - * Invokes a method on an object with the given arguments - * - * @param instance Target object - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } + /** + * Invokes a method on an object with the given arguments + * + * @param instance Target object + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } - /** - * Invokes a method of the target class on an object with the given arguments - * - * @param instance Target object - * @param clazz Target class - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } + /** + * Invokes a method of the target class on an object with the given arguments + * + * @param instance Target object + * @param clazz Target class + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } - /** - * Invokes a method of a desired class on an object with the given arguments - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #invokeMethod(Object, Class, String, Object...) - */ - public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return invokeMethod(instance, packageType.getClass(className), methodName, arguments); - } + /** + * Invokes a method of a desired class on an object with the given arguments + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #invokeMethod(Object, Class, String, Object...) + */ + public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return invokeMethod(instance, packageType.getClass(className), methodName, arguments); + } - /** - * Returns a field of the target class with the given name - * - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the target class with the specified name - * @throws NoSuchFieldException If the desired field of the given class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - */ - public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { - Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); - field.setAccessible(true); - return field; - } + /** + * Returns a field of the target class with the given name + * + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the target class with the specified name + * @throws NoSuchFieldException If the desired field of the given class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + */ + public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { + Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); + field.setAccessible(true); + return field; + } - /** - * Returns a field of a desired class with the given name - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the desired target class with the specified name - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getField(Class, boolean, String) - */ - public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { - return getField(packageType.getClass(className), declared, fieldName); - } + /** + * Returns a field of a desired class with the given name + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the desired target class with the specified name + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getField(Class, boolean, String) + */ + public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { + return getField(packageType.getClass(className), declared, fieldName); + } - /** - * Returns the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getField(Class, boolean, String) - */ - public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getField(clazz, declared, fieldName).get(instance); - } + /** + * Returns the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getField(clazz, declared, fieldName).get(instance); + } - /** - * Returns the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - return getValue(instance, packageType.getClass(className), declared, fieldName); - } + /** + * Returns the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + return getValue(instance, packageType.getClass(className), declared, fieldName); + } - /** - * Returns the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getValue(instance, instance.getClass(), declared, fieldName); - } + /** + * Returns the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getValue(instance, instance.getClass(), declared, fieldName); + } - /** - * Sets the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getField(Class, boolean, String) - */ - public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - getField(clazz, declared, fieldName).set(instance, value); - } + /** + * Sets the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + getField(clazz, declared, fieldName).set(instance, value); + } - /** - * Sets the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - setValue(instance, packageType.getClass(className), declared, fieldName, value); - } + /** + * Sets the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + setValue(instance, packageType.getClass(className), declared, fieldName, value); + } - /** - * Sets the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - setValue(instance, instance.getClass(), declared, fieldName, value); - } + /** + * Sets the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + setValue(instance, instance.getClass(), declared, fieldName, value); + } - /** - * Represents an enumeration of dynamic packages of NMS and CraftBukkit - *

    - * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum PackageType { - MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), - CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), - CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), - CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), - CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), - CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), - CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), - CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), - CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), - CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), - CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), - CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), - CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), - CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), - CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), - CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), - CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), - CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), - CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), - CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); + /** + * Represents an enumeration of dynamic packages of NMS and CraftBukkit + *

    + * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum PackageType { + MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), + CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), + CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), + CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), + CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), + CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), + CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), + CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), + CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), + CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), + CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), + CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), + CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), + CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), + CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), + CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), + CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), + CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), + CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), + CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); - private final String path; + private final String path; - /** - * Construct a new package type - * - * @param path Path of the package - */ - PackageType(String path) { - this.path = path; - } + /** + * Construct a new package type + * + * @param path Path of the package + */ + PackageType(String path) { + this.path = path; + } - /** - * Construct a new package type - * - * @param parent Parent package of the package - * @param path Path of the package - */ - PackageType(PackageType parent, String path) { - this(parent + "." + path); - } + /** + * Construct a new package type + * + * @param parent Parent package of the package + * @param path Path of the package + */ + PackageType(PackageType parent, String path) { + this(parent + "." + path); + } - /** - * Returns the version of your server - * - * @return The server version - */ - public static String getServerVersion() { - return Bukkit.getServer().getClass().getName().split("\\.")[3]; - } + /** + * Returns the version of your server + * + * @return The server version + */ + public static String getServerVersion() { + return Bukkit.getServer().getClass().getName().split("\\.")[3]; + } - /** - * Returns the path of this package type - * - * @return The path - */ - public String getPath() { - return path; - } + /** + * Returns the path of this package type + * + * @return The path + */ + public String getPath() { + return path; + } - /** - * Returns the class with the given name - * - * @param className Name of the desired class - * @return The class with the specified name - * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found - */ - public Class getClass(String className) throws ClassNotFoundException { - return Class.forName(this + "." + className); - } + /** + * Returns the class with the given name + * + * @param className Name of the desired class + * @return The class with the specified name + * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found + */ + public Class getClass(String className) throws ClassNotFoundException { + return Class.forName(this + "." + className); + } - // Override for convenience - @Override - public String toString() { - return path; - } - } + // Override for convenience + @Override + public String toString() { + return path; + } + } - /** - * Represents an enumeration of Java data types with corresponding classes - *

    - * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum DataType { - BYTE(byte.class, Byte.class), - SHORT(short.class, Short.class), - INTEGER(int.class, Integer.class), - LONG(long.class, Long.class), - CHARACTER(char.class, Character.class), - FLOAT(float.class, Float.class), - DOUBLE(double.class, Double.class), - BOOLEAN(boolean.class, Boolean.class); + /** + * Represents an enumeration of Java data types with corresponding classes + *

    + * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum DataType { + BYTE(byte.class, Byte.class), + SHORT(short.class, Short.class), + INTEGER(int.class, Integer.class), + LONG(long.class, Long.class), + CHARACTER(char.class, Character.class), + FLOAT(float.class, Float.class), + DOUBLE(double.class, Double.class), + BOOLEAN(boolean.class, Boolean.class); - private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); + private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); - // Initialize map for quick class lookup - static { - for (DataType type : values()) { - CLASS_MAP.put(type.primitive, type); - CLASS_MAP.put(type.reference, type); - } - } + // Initialize map for quick class lookup + static { + for (DataType type : values()) { + CLASS_MAP.put(type.primitive, type); + CLASS_MAP.put(type.reference, type); + } + } - private final Class primitive; - private final Class reference; + private final Class primitive; + private final Class reference; - /** - * Construct a new data type - * - * @param primitive Primitive class of this data type - * @param reference Reference class of this data type - */ - DataType(Class primitive, Class reference) { - this.primitive = primitive; - this.reference = reference; - } + /** + * Construct a new data type + * + * @param primitive Primitive class of this data type + * @param reference Reference class of this data type + */ + DataType(Class primitive, Class reference) { + this.primitive = primitive; + this.reference = reference; + } - /** - * Returns the data type with the given primitive/reference class - * - * @param clazz Primitive/Reference class of the data type - * @return The data type - */ - public static DataType fromClass(Class clazz) { - return CLASS_MAP.get(clazz); - } + /** + * Returns the data type with the given primitive/reference class + * + * @param clazz Primitive/Reference class of the data type + * @return The data type + */ + public static DataType fromClass(Class clazz) { + return CLASS_MAP.get(clazz); + } - /** - * Returns the primitive class of the data type with the given reference class - * - * @param clazz Reference class of the data type - * @return The primitive class - */ - public static Class getPrimitive(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getPrimitive(); - } + /** + * Returns the primitive class of the data type with the given reference class + * + * @param clazz Reference class of the data type + * @return The primitive class + */ + public static Class getPrimitive(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getPrimitive(); + } - /** - * Returns the reference class of the data type with the given primitive class - * - * @param clazz Primitive class of the data type - * @return The reference class - */ - public static Class getReference(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getReference(); - } + /** + * Returns the reference class of the data type with the given primitive class + * + * @param clazz Primitive class of the data type + * @return The reference class + */ + public static Class getReference(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getReference(); + } - /** - * Returns the primitive class array of the given class array - * - * @param classes Given class array - * @return The primitive class array - */ - public static Class[] getPrimitive(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(classes[index]); - } - return types; - } + /** + * Returns the primitive class array of the given class array + * + * @param classes Given class array + * @return The primitive class array + */ + public static Class[] getPrimitive(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(classes[index]); + } + return types; + } - /** - * Returns the reference class array of the given class array - * - * @param classes Given class array - * @return The reference class array - */ - public static Class[] getReference(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(classes[index]); - } - return types; - } + /** + * Returns the reference class array of the given class array + * + * @param classes Given class array + * @return The reference class array + */ + public static Class[] getReference(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(classes[index]); + } + return types; + } - /** - * Returns the primitive class array of the given object array - * - * @param objects Given object array - * @return The primitive class array - */ - public static Class[] getPrimitive(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(objects[index].getClass()); - } - return types; - } + /** + * Returns the primitive class array of the given object array + * + * @param objects Given object array + * @return The primitive class array + */ + public static Class[] getPrimitive(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(objects[index].getClass()); + } + return types; + } - /** - * Returns the reference class array of the given object array - * - * @param objects Given object array - * @return The reference class array - */ - public static Class[] getReference(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(objects[index].getClass()); - } - return types; - } + /** + * Returns the reference class array of the given object array + * + * @param objects Given object array + * @return The reference class array + */ + public static Class[] getReference(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(objects[index].getClass()); + } + return types; + } - /** - * Compares two class arrays on equivalence - * - * @param primary Primary class array - * @param secondary Class array which is compared to the primary array - * @return Whether these arrays are equal or not - */ - public static boolean compare(Class[] primary, Class[] secondary) { - if (primary == null || secondary == null || primary.length != secondary.length) { - return false; - } - for (int index = 0; index < primary.length; index++) { - Class primaryClass = primary[index]; - Class secondaryClass = secondary[index]; - if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { - continue; - } - return false; - } - return true; - } + /** + * Compares two class arrays on equivalence + * + * @param primary Primary class array + * @param secondary Class array which is compared to the primary array + * @return Whether these arrays are equal or not + */ + public static boolean compare(Class[] primary, Class[] secondary) { + if (primary == null || secondary == null || primary.length != secondary.length) { + return false; + } + for (int index = 0; index < primary.length; index++) { + Class primaryClass = primary[index]; + Class secondaryClass = secondary[index]; + if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { + continue; + } + return false; + } + return true; + } - /** - * Returns the primitive class of this data type - * - * @return The primitive class - */ - public Class getPrimitive() { - return primitive; - } + /** + * Returns the primitive class of this data type + * + * @return The primitive class + */ + public Class getPrimitive() { + return primitive; + } - /** - * Returns the reference class of this data type - * - * @return The reference class - */ - public Class getReference() { - return reference; - } - } + /** + * Returns the reference class of this data type + * + * @return The reference class + */ + public Class getReference() { + return reference; + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java index aeb8de97..efd66b29 100644 --- a/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java @@ -17,82 +17,82 @@ import java.util.logging.Level; public class PermissionsMapTypeAdapter implements JsonDeserializer>> { - @Override - public Map> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { + @Override + public Map> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { - try { - JsonObject obj = json.getAsJsonObject(); - if (obj == null) { - return null; - } + try { + JsonObject obj = json.getAsJsonObject(); + if (obj == null) { + return null; + } - Map> permissionsMap = new ConcurrentHashMap<>(); + Map> permissionsMap = new ConcurrentHashMap<>(); - // Top level is Relation - for (Map.Entry entry : obj.entrySet()) { - Permissable permissable = getPermissable(entry.getKey()); + // Top level is Relation + for (Map.Entry entry : obj.entrySet()) { + Permissable permissable = getPermissable(entry.getKey()); - if (permissable == null) { - continue; - } + if (permissable == null) { + continue; + } - // Second level is the map between action -> access - Map accessMap = new HashMap<>(); - for (Map.Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { - PermissableAction permissableAction = PermissableAction.fromString(entry2.getKey()); - if (permissableAction == null) { - switch (entry2.getKey()) { - case "frostwalk": - permissableAction = PermissableAction.FROST_WALK; - break; - case "painbuild": - permissableAction = PermissableAction.PAIN_BUILD; - break; - case "items": - permissableAction = PermissableAction.ITEM; - break; - } - } - Access access = Access.fromString(entry2.getValue().getAsString()); - accessMap.put(permissableAction, access); - } - permissionsMap.put(permissable, accessMap); - } + // Second level is the map between action -> access + Map accessMap = new HashMap<>(); + for (Map.Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { + PermissableAction permissableAction = PermissableAction.fromString(entry2.getKey()); + if (permissableAction == null) { + switch (entry2.getKey()) { + case "frostwalk": + permissableAction = PermissableAction.FROST_WALK; + break; + case "painbuild": + permissableAction = PermissableAction.PAIN_BUILD; + break; + case "items": + permissableAction = PermissableAction.ITEM; + break; + } + } + Access access = Access.fromString(entry2.getValue().getAsString()); + accessMap.put(permissableAction, access); + } + permissionsMap.put(permissable, accessMap); + } - return permissionsMap; + return permissionsMap; - } catch (Exception ex) { - SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a PermissionsMap."); - ex.printStackTrace(); - return null; - } - } + } catch (Exception ex) { + SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a PermissionsMap."); + ex.printStackTrace(); + return null; + } + } - private Permissable getPermissable(String name) { - // If name is uppercase then it is (probably, no way to completely know) valid if not begin conversion - if (name.equals(name.toUpperCase())) { - if (Role.fromString(name.toUpperCase()) != null) { - return Role.fromString(name.toUpperCase()); - } else if (Relation.fromString(name.toUpperCase()) != null) { - return Relation.fromString(name.toUpperCase()); - } else { - return null; - } - } else { - if (name.equals(TL.ROLE_RECRUIT.toString())) { - return Role.RECRUIT; - } else if (name.equals(TL.ROLE_NORMAL.toString())) { - return Role.NORMAL; - } else if (name.equals(TL.ROLE_MODERATOR.toString())) { - return Role.MODERATOR; - } else { - // If it is explicitly member and its old data then it refers to relation member not role, skip it - if (name.equals("member")) { - return null; - } - return Relation.fromString(name); - } - } - } + private Permissable getPermissable(String name) { + // If name is uppercase then it is (probably, no way to completely know) valid if not begin conversion + if (name.equals(name.toUpperCase())) { + if (Role.fromString(name.toUpperCase()) != null) { + return Role.fromString(name.toUpperCase()); + } else if (Relation.fromString(name.toUpperCase()) != null) { + return Relation.fromString(name.toUpperCase()); + } else { + return null; + } + } else { + if (name.equals(TL.ROLE_RECRUIT.toString())) { + return Role.RECRUIT; + } else if (name.equals(TL.ROLE_NORMAL.toString())) { + return Role.NORMAL; + } else if (name.equals(TL.ROLE_MODERATOR.toString())) { + return Role.MODERATOR; + } else { + // If it is explicitly member and its old data then it refers to relation member not role, skip it + if (name.equals("member")) { + return null; + } + return Relation.fromString(name); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/RelationUtil.java b/src/main/java/com/massivecraft/factions/util/RelationUtil.java index 4c656f84..0912b81c 100644 --- a/src/main/java/com/massivecraft/factions/util/RelationUtil.java +++ b/src/main/java/com/massivecraft/factions/util/RelationUtil.java @@ -11,101 +11,101 @@ import org.bukkit.ChatColor; public class RelationUtil { - public static String describeThatToMe(RelationParticipator that, RelationParticipator me, boolean ucfirst) { - String ret = ""; + public static String describeThatToMe(RelationParticipator that, RelationParticipator me, boolean ucfirst) { + String ret = ""; - Faction thatFaction = getFaction(that); - if (thatFaction == null) { - return "ERROR"; // ERROR - } + Faction thatFaction = getFaction(that); + if (thatFaction == null) { + return "ERROR"; // ERROR + } - Faction myFaction = getFaction(me); + Faction myFaction = getFaction(me); // if (myFaction == null) return that.describeTo(null); // no relation, but can show basic name or tag - if (that instanceof Faction) { - if (me instanceof FPlayer && myFaction == thatFaction) { - ret = TL.GENERIC_YOURFACTION.toString(); - } else { - ret = thatFaction.getTag(); - } - } else if (that instanceof FPlayer) { - FPlayer fplayerthat = (FPlayer) that; - if (that == me) { - ret = TL.GENERIC_YOU.toString(); - } else if (thatFaction == myFaction) { - ret = fplayerthat.getNameAndTitle(); - } else { - ret = fplayerthat.getNameAndTag(); - } - } + if (that instanceof Faction) { + if (me instanceof FPlayer && myFaction == thatFaction) { + ret = TL.GENERIC_YOURFACTION.toString(); + } else { + ret = thatFaction.getTag(); + } + } else if (that instanceof FPlayer) { + FPlayer fplayerthat = (FPlayer) that; + if (that == me) { + ret = TL.GENERIC_YOU.toString(); + } else if (thatFaction == myFaction) { + ret = fplayerthat.getNameAndTitle(); + } else { + ret = fplayerthat.getNameAndTag(); + } + } - if (ucfirst) { - ret = TextUtil.upperCaseFirst(ret); - } + if (ucfirst) { + ret = TextUtil.upperCaseFirst(ret); + } - return "" + getColorOfThatToMe(that, me) + ret; - } + return "" + getColorOfThatToMe(that, me) + ret; + } - public static String describeThatToMe(RelationParticipator that, RelationParticipator me) { - return describeThatToMe(that, me, false); - } + public static String describeThatToMe(RelationParticipator that, RelationParticipator me) { + return describeThatToMe(that, me, false); + } - public static Relation getRelationTo(RelationParticipator me, RelationParticipator that) { - return getRelationTo(that, me, false); - } + public static Relation getRelationTo(RelationParticipator me, RelationParticipator that) { + return getRelationTo(that, me, false); + } - public static Relation getRelationTo(RelationParticipator me, RelationParticipator that, boolean ignorePeaceful) { - Faction fthat = getFaction(that); - Faction fme = getFaction(me); + public static Relation getRelationTo(RelationParticipator me, RelationParticipator that, boolean ignorePeaceful) { + Faction fthat = getFaction(that); + Faction fme = getFaction(me); - if (fthat == null || fme == null) { - return Relation.NEUTRAL; // ERROR - } + if (fthat == null || fme == null) { + return Relation.NEUTRAL; // ERROR + } - if (!fthat.isNormal() || !fme.isNormal()) { - return Relation.NEUTRAL; - } + if (!fthat.isNormal() || !fme.isNormal()) { + return Relation.NEUTRAL; + } - if (fthat.equals(fme)) { - return Relation.MEMBER; - } + if (fthat.equals(fme)) { + return Relation.MEMBER; + } - if (!ignorePeaceful && (fme.isPeaceful() || fthat.isPeaceful())) { - return Relation.NEUTRAL; - } + if (!ignorePeaceful && (fme.isPeaceful() || fthat.isPeaceful())) { + return Relation.NEUTRAL; + } - if (fme.getRelationWish(fthat).value >= fthat.getRelationWish(fme).value) { - return fthat.getRelationWish(fme); - } + if (fme.getRelationWish(fthat).value >= fthat.getRelationWish(fme).value) { + return fthat.getRelationWish(fme); + } - return fme.getRelationWish(fthat); - } + return fme.getRelationWish(fthat); + } - public static Faction getFaction(RelationParticipator rp) { - if (rp instanceof Faction) { - return (Faction) rp; - } + public static Faction getFaction(RelationParticipator rp) { + if (rp instanceof Faction) { + return (Faction) rp; + } - if (rp instanceof FPlayer) { - return ((FPlayer) rp).getFaction(); - } + if (rp instanceof FPlayer) { + return ((FPlayer) rp).getFaction(); + } - // ERROR - return null; - } + // ERROR + return null; + } - public static ChatColor getColorOfThatToMe(RelationParticipator that, RelationParticipator me) { - Faction thatFaction = getFaction(that); + public static ChatColor getColorOfThatToMe(RelationParticipator that, RelationParticipator me) { + Faction thatFaction = getFaction(that); - if (thatFaction != null && thatFaction != getFaction(me)) { - if (thatFaction.isPeaceful()) - return Conf.colorPeaceful; - else if (thatFaction.isSafeZone()) - return Conf.colorPeaceful; - else if (thatFaction.isWarZone()) - return Conf.colorWar; - } + if (thatFaction != null && thatFaction != getFaction(me)) { + if (thatFaction.isPeaceful()) + return Conf.colorPeaceful; + else if (thatFaction.isSafeZone()) + return Conf.colorPeaceful; + else if (thatFaction.isWarZone()) + return Conf.colorWar; + } - return getRelationTo(that, me).getColor(); - } + return getRelationTo(that, me).getColor(); + } } diff --git a/src/main/java/com/massivecraft/factions/util/SpiralTask.java b/src/main/java/com/massivecraft/factions/util/SpiralTask.java index 1124bf8b..1b209fd4 100644 --- a/src/main/java/com/massivecraft/factions/util/SpiralTask.java +++ b/src/main/java/com/massivecraft/factions/util/SpiralTask.java @@ -24,186 +24,186 @@ import java.util.logging.Level; public abstract class SpiralTask implements Runnable { - // general task-related reference data - private transient World world = null; - private transient boolean readyToGo = false; - private transient int taskID = -1; - private transient int limit = 0; + // general task-related reference data + private transient World world = null; + private transient boolean readyToGo = false; + private transient int taskID = -1; + private transient int limit = 0; - // values for the spiral pattern routine - private transient int x = 0; - private transient int z = 0; - private transient boolean isZLeg = false; - private transient boolean isNeg = false; - private transient int length = -1; - private transient int current = 0; + // values for the spiral pattern routine + private transient int x = 0; + private transient int z = 0; + private transient boolean isZLeg = false; + private transient boolean isNeg = false; + private transient int length = -1; + private transient int current = 0; - @SuppressWarnings("LeakingThisInConstructor") - public SpiralTask(FLocation fLocation, int radius) { - // limit is determined based on spiral leg length for given radius; see insideRadius() - this.limit = (radius - 1) * 2; + @SuppressWarnings("LeakingThisInConstructor") + public SpiralTask(FLocation fLocation, int radius) { + // limit is determined based on spiral leg length for given radius; see insideRadius() + this.limit = (radius - 1) * 2; - this.world = Bukkit.getWorld(fLocation.getWorldName()); - if (this.world == null) { - SavageFactions.plugin.log(Level.WARNING, "[SpiralTask] A valid world must be specified!"); - this.stop(); - return; - } + this.world = Bukkit.getWorld(fLocation.getWorldName()); + if (this.world == null) { + SavageFactions.plugin.log(Level.WARNING, "[SpiralTask] A valid world must be specified!"); + this.stop(); + return; + } - this.x = (int) fLocation.getX(); - this.z = (int) fLocation.getZ(); + this.x = (int) fLocation.getX(); + this.z = (int) fLocation.getZ(); - this.readyToGo = true; + this.readyToGo = true; - // get this party started - this.setTaskID(Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, this, 2, 2)); - } + // get this party started + this.setTaskID(Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, this, 2, 2)); + } - private static long now() { - return System.currentTimeMillis(); - } + private static long now() { + return System.currentTimeMillis(); + } - /* - * This is where the necessary work is done; you'll need to override this method with whatever you want - * done at each chunk in the spiral pattern. - * Return false if the entire task needs to be aborted, otherwise return true to continue. - */ - public abstract boolean work(); + /* + * This is where the necessary work is done; you'll need to override this method with whatever you want + * done at each chunk in the spiral pattern. + * Return false if the entire task needs to be aborted, otherwise return true to continue. + */ + public abstract boolean work(); - /* - * Returns an FLocation pointing at the current chunk X and Z values. - */ - public final FLocation currentFLocation() { - return new FLocation(world.getName(), x, z); - } + /* + * Returns an FLocation pointing at the current chunk X and Z values. + */ + public final FLocation currentFLocation() { + return new FLocation(world.getName(), x, z); + } - /* - * Returns a Location pointing at the current chunk X and Z values. - * note that the Location is at the corner of the chunk, not the center. - */ - public final Location currentLocation() { - return new Location(world, FLocation.chunkToBlock(x), 65.0, FLocation.chunkToBlock(z)); - } + /* + * Returns a Location pointing at the current chunk X and Z values. + * note that the Location is at the corner of the chunk, not the center. + */ + public final Location currentLocation() { + return new Location(world, FLocation.chunkToBlock(x), 65.0, FLocation.chunkToBlock(z)); + } - /* - * Returns current chunk X and Z values. - */ - public final int getX() { - return x; - } + /* + * Returns current chunk X and Z values. + */ + public final int getX() { + return x; + } - /* - * Below are the guts of the class, which you normally wouldn't need to mess with. - */ + /* + * Below are the guts of the class, which you normally wouldn't need to mess with. + */ - public final int getZ() { - return z; - } + public final int getZ() { + return z; + } - public final void setTaskID(int ID) { - if (ID == -1) { - this.stop(); - } - taskID = ID; - } + public final void setTaskID(int ID) { + if (ID == -1) { + this.stop(); + } + taskID = ID; + } - public final void run() { - if (!this.valid() || !readyToGo) { - return; - } + public final void run() { + if (!this.valid() || !readyToGo) { + return; + } - // this is set so it only does one iteration at a time, no matter how frequently the timer fires - readyToGo = false; + // this is set so it only does one iteration at a time, no matter how frequently the timer fires + readyToGo = false; - // make sure we're still inside the specified radius - if (!this.insideRadius()) { - return; - } + // make sure we're still inside the specified radius + if (!this.insideRadius()) { + return; + } - // track this to keep one iteration from dragging on too long and possibly choking the system - long loopStartTime = now(); + // track this to keep one iteration from dragging on too long and possibly choking the system + long loopStartTime = now(); - // keep going until the task has been running for 20ms or more, then stop to take a breather - while (now() < loopStartTime + 20) { - // run the primary task on the current X/Z coordinates - if (!this.work()) { - this.finish(); - return; - } + // keep going until the task has been running for 20ms or more, then stop to take a breather + while (now() < loopStartTime + 20) { + // run the primary task on the current X/Z coordinates + if (!this.work()) { + this.finish(); + return; + } - // move on to next chunk in spiral - if (!this.moveToNext()) { - return; - } - } + // move on to next chunk in spiral + if (!this.moveToNext()) { + return; + } + } - // ready for the next iteration to run - readyToGo = true; - } + // ready for the next iteration to run + readyToGo = true; + } - // step through chunks in spiral pattern from center; returns false if we're done, otherwise returns true - public final boolean moveToNext() { - if (!this.valid()) { - return false; - } + // step through chunks in spiral pattern from center; returns false if we're done, otherwise returns true + public final boolean moveToNext() { + if (!this.valid()) { + return false; + } - // make sure we don't need to turn down the next leg of the spiral - if (current < length) { - current++; + // make sure we don't need to turn down the next leg of the spiral + if (current < length) { + current++; - // if we're outside the radius, we're done - if (!this.insideRadius()) { - return false; - } - } else { // one leg/side of the spiral down... - current = 0; - isZLeg ^= true; - // every second leg (between X and Z legs, negative or positive), length increases - if (isZLeg) { - isNeg ^= true; - length++; - } - } + // if we're outside the radius, we're done + if (!this.insideRadius()) { + return false; + } + } else { // one leg/side of the spiral down... + current = 0; + isZLeg ^= true; + // every second leg (between X and Z legs, negative or positive), length increases + if (isZLeg) { + isNeg ^= true; + length++; + } + } - // move one chunk further in the appropriate direction - if (isZLeg) { - z += (isNeg) ? -1 : 1; - } else { - x += (isNeg) ? -1 : 1; - } + // move one chunk further in the appropriate direction + if (isZLeg) { + z += (isNeg) ? -1 : 1; + } else { + x += (isNeg) ? -1 : 1; + } - return true; - } + return true; + } - public final boolean insideRadius() { - boolean inside = current < limit; - if (!inside) { - this.finish(); - } - return inside; - } + public final boolean insideRadius() { + boolean inside = current < limit; + if (!inside) { + this.finish(); + } + return inside; + } - // for successful completion - public void finish() { + // for successful completion + public void finish() { // SavageFactions.plugin.log("SpiralTask successfully completed!"); - this.stop(); - } + this.stop(); + } - // we're done, whether finished or cancelled - public final void stop() { - if (!this.valid()) { - return; - } + // we're done, whether finished or cancelled + public final void stop() { + if (!this.valid()) { + return; + } - readyToGo = false; - Bukkit.getServer().getScheduler().cancelTask(taskID); - taskID = -1; - } + readyToGo = false; + Bukkit.getServer().getScheduler().cancelTask(taskID); + taskID = -1; + } - // is this task still valid/workable? - public final boolean valid() { - return taskID != -1; - } + // is this task still valid/workable? + public final boolean valid() { + return taskID != -1; + } } diff --git a/src/main/java/com/massivecraft/factions/util/UtilFly.java b/src/main/java/com/massivecraft/factions/util/UtilFly.java index 4a8a11f0..c8acf539 100644 --- a/src/main/java/com/massivecraft/factions/util/UtilFly.java +++ b/src/main/java/com/massivecraft/factions/util/UtilFly.java @@ -12,103 +12,103 @@ import java.util.Iterator; public class UtilFly { - public static ArrayList playersFlying; + public static ArrayList playersFlying; - static { - playersFlying = SavageFactions.playersFlying; - } + static { + playersFlying = SavageFactions.playersFlying; + } - public UtilFly() { - } + public UtilFly() { + } - public static void run() { - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - playersFlying.clear(); - Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - public void run() { - Iterator var2 = UtilFly.playersFlying.iterator(); + public static void run() { + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + playersFlying.clear(); + Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + public void run() { + Iterator var2 = UtilFly.playersFlying.iterator(); - while (var2.hasNext()) { - FPlayer fp = (FPlayer) var2.next(); - if (fp != null) { - fp.checkIfNearbyEnemies(); - } - } + while (var2.hasNext()) { + FPlayer fp = (FPlayer) var2.next(); + if (fp != null) { + fp.checkIfNearbyEnemies(); + } + } - } - }, 0L, (long) SavageFactions.plugin.getConfig().getInt("fly-task-interval", 10)); - } - } + } + }, 0L, (long) SavageFactions.plugin.getConfig().getInt("fly-task-interval", 10)); + } + } - public static void setFly(FPlayer fp, boolean fly, boolean silent, boolean damage) { - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - fp.getPlayer().setAllowFlight(fly); - fp.getPlayer().setFlying(fly); - fp.setFlying(fly); - if (fly) { - playersFlying.add(fp); - } else { - playersFlying.remove(fp); - } + public static void setFly(FPlayer fp, boolean fly, boolean silent, boolean damage) { + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + fp.getPlayer().setAllowFlight(fly); + fp.getPlayer().setFlying(fly); + fp.setFlying(fly); + if (fly) { + playersFlying.add(fp); + } else { + playersFlying.remove(fp); + } - if (!silent) { - if (!damage) { - fp.msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); - } else { - fp.msg(TL.COMMAND_FLY_DAMAGE); - } - } + if (!silent) { + if (!damage) { + fp.msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); + } else { + fp.msg(TL.COMMAND_FLY_DAMAGE); + } + } - setFallDamage(fp, fly, damage); - } - } + setFallDamage(fp, fly, damage); + } + } - public static void checkFly(FPlayer me, Faction factionTo) { - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - if (!me.isAdminBypassing() || !me.isFlying()) { - Relation relationTo; - if (!me.isFlying()) { - if (me.isAdminBypassing()) { - setFly(me, true, false, false); - return; - } + public static void checkFly(FPlayer me, Faction factionTo) { + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + if (!me.isAdminBypassing() || !me.isFlying()) { + Relation relationTo; + if (!me.isFlying()) { + if (me.isAdminBypassing()) { + setFly(me, true, false, false); + return; + } - if (factionTo == me.getFaction() && me.getPlayer().hasPermission("factions.fly")) { - setFly(me, true, false, false); - } else { - relationTo = factionTo.getRelationTo(me); - if (factionTo.isWilderness() && me.canflyinWilderness() || factionTo.isWarZone() && me.canflyinWarzone() || factionTo.isSafeZone() && me.canflyinSafezone() || relationTo == Relation.ENEMY && me.canflyinEnemy() || relationTo == Relation.ALLY && me.canflyinAlly() || relationTo == Relation.TRUCE && me.canflyinTruce() || relationTo == Relation.NEUTRAL && me.canflyinNeutral()) { - setFly(me, true, false, false); - } - } - } else { - relationTo = factionTo.getRelationTo(me); - if (factionTo.equals(me.getFaction()) && !me.getPlayer().hasPermission("factions.fly") || factionTo.isWilderness() && !me.canflyinWilderness() || factionTo.isWarZone() && !me.canflyinWarzone() || factionTo.isSafeZone() && !me.canflyinSafezone() || relationTo == Relation.ENEMY && !me.canflyinEnemy() || relationTo == Relation.ALLY && !me.canflyinAlly() || relationTo == Relation.TRUCE && !me.canflyinTruce() || relationTo == Relation.NEUTRAL && !me.canflyinNeutral()) { - setFly(me, false, false, false); - } - } + if (factionTo == me.getFaction() && me.getPlayer().hasPermission("factions.fly")) { + setFly(me, true, false, false); + } else { + relationTo = factionTo.getRelationTo(me); + if (factionTo.isWilderness() && me.canflyinWilderness() || factionTo.isWarZone() && me.canflyinWarzone() || factionTo.isSafeZone() && me.canflyinSafezone() || relationTo == Relation.ENEMY && me.canflyinEnemy() || relationTo == Relation.ALLY && me.canflyinAlly() || relationTo == Relation.TRUCE && me.canflyinTruce() || relationTo == Relation.NEUTRAL && me.canflyinNeutral()) { + setFly(me, true, false, false); + } + } + } else { + relationTo = factionTo.getRelationTo(me); + if (factionTo.equals(me.getFaction()) && !me.getPlayer().hasPermission("factions.fly") || factionTo.isWilderness() && !me.canflyinWilderness() || factionTo.isWarZone() && !me.canflyinWarzone() || factionTo.isSafeZone() && !me.canflyinSafezone() || relationTo == Relation.ENEMY && !me.canflyinEnemy() || relationTo == Relation.ALLY && !me.canflyinAlly() || relationTo == Relation.TRUCE && !me.canflyinTruce() || relationTo == Relation.NEUTRAL && !me.canflyinNeutral()) { + setFly(me, false, false, false); + } + } - } - } - } + } + } + } - public static void setFallDamage(final FPlayer fp, boolean fly, boolean damage) { - if (!fly) { - if (!damage) { - fp.sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", String.valueOf(SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3)))); - } + public static void setFallDamage(final FPlayer fp, boolean fly, boolean damage) { + if (!fly) { + if (!damage) { + fp.sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", String.valueOf(SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3)))); + } - int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); - if (cooldown > 0) { - fp.setTakeFallDamage(false); - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - public void run() { - fp.setTakeFallDamage(true); - } - }, 20L * (long) cooldown); - } - } + int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); + if (cooldown > 0) { + fp.setTakeFallDamage(false); + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + public void run() { + fp.setTakeFallDamage(true); + } + }, 20L * (long) cooldown); + } + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java b/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java index a817e166..f786900e 100644 --- a/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java +++ b/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java @@ -9,64 +9,64 @@ import java.util.*; public class VisualizeUtil { - protected static Map> playerLocations = new HashMap<>(); + protected static Map> playerLocations = new HashMap<>(); - public static Set getPlayerLocations(Player player) { - return getPlayerLocations(player.getUniqueId()); - } + public static Set getPlayerLocations(Player player) { + return getPlayerLocations(player.getUniqueId()); + } - public static Set getPlayerLocations(UUID uuid) { - Set ret = playerLocations.get(uuid); - if (ret == null) { - ret = new HashSet<>(); - playerLocations.put(uuid, ret); - } - return ret; - } + public static Set getPlayerLocations(UUID uuid) { + Set ret = playerLocations.get(uuid); + if (ret == null) { + ret = new HashSet<>(); + playerLocations.put(uuid, ret); + } + return ret; + } - @SuppressWarnings("deprecation") - public static void addLocation(Player player, Location location, Material type, byte data) { - getPlayerLocations(player).add(location); - player.sendBlockChange(location, type, data); - } + @SuppressWarnings("deprecation") + public static void addLocation(Player player, Location location, Material type, byte data) { + getPlayerLocations(player).add(location); + player.sendBlockChange(location, type, data); + } - @SuppressWarnings("deprecation") - public static void addLocation(Player player, Location location, Material material) { - getPlayerLocations(player).add(location); - player.sendBlockChange(location, material, (byte) 0); - } + @SuppressWarnings("deprecation") + public static void addLocation(Player player, Location location, Material material) { + getPlayerLocations(player).add(location); + player.sendBlockChange(location, material, (byte) 0); + } - @SuppressWarnings("deprecation") - public static void addLocations(Player player, Collection locations, Material material) { - Set ploc = getPlayerLocations(player); - for (Location location : locations) { - ploc.add(location); - player.sendBlockChange(location, material, (byte) 0); - } - } + @SuppressWarnings("deprecation") + public static void addLocations(Player player, Collection locations, Material material) { + Set ploc = getPlayerLocations(player); + for (Location location : locations) { + ploc.add(location); + player.sendBlockChange(location, material, (byte) 0); + } + } - @SuppressWarnings("deprecation") - public static void addBlocks(Player player, Collection blocks, Material material) { - Set ploc = getPlayerLocations(player); - for (Block block : blocks) { - Location location = block.getLocation(); - ploc.add(location); - player.sendBlockChange(location, material, (byte) 0); - } - } + @SuppressWarnings("deprecation") + public static void addBlocks(Player player, Collection blocks, Material material) { + Set ploc = getPlayerLocations(player); + for (Block block : blocks) { + Location location = block.getLocation(); + ploc.add(location); + player.sendBlockChange(location, material, (byte) 0); + } + } - @SuppressWarnings("deprecation") - public static void clear(Player player) { - Set locations = getPlayerLocations(player); - if (locations == null) { - return; - } - for (Location location : locations) { - Block block = location.getWorld().getBlockAt(location); - player.sendBlockChange(location, block.getType(), block.getData()); - } - locations.clear(); - } + @SuppressWarnings("deprecation") + public static void clear(Player player) { + Set locations = getPlayerLocations(player); + if (locations == null) { + return; + } + for (Location location : locations) { + Block block = location.getWorld().getBlockAt(location); + player.sendBlockChange(location, block.getType(), block.getData()); + } + locations.clear(); + } } diff --git a/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java b/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java index 8de53dff..bfd08ef6 100644 --- a/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java +++ b/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java @@ -6,37 +6,37 @@ import com.massivecraft.factions.zcore.util.TL; public class WarmUpUtil { - /** - * @param player The player to notify. - * @param translationKey The translation key used for notifying. - * @param action The action, inserted into the notification message. - * @param runnable The task to run after the delay. If the delay is 0, the task is instantly ran. - * @param delay The time used, in seconds, for the delay. - *

    - * note: for translations: %s = action, %d = delay - */ - public static void process(final FPlayer player, Warmup warmup, TL translationKey, String action, final Runnable runnable, long delay) { - if (delay > 0) { - if (player.isWarmingUp()) { - player.msg(TL.WARMUPS_ALREADY); - } else { - player.msg(translationKey.format(action, delay)); - int id = SavageFactions.plugin.getServer().getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - player.stopWarmup(); - runnable.run(); - } - }, delay * 20).getTaskId(); - player.addWarmup(warmup, id); - } - } else { - runnable.run(); - } - } + /** + * @param player The player to notify. + * @param translationKey The translation key used for notifying. + * @param action The action, inserted into the notification message. + * @param runnable The task to run after the delay. If the delay is 0, the task is instantly ran. + * @param delay The time used, in seconds, for the delay. + *

    "; - // Enable the %money% macro. Only do this if you know your economy manager is thread-safe. - public static boolean dynmapDescriptionMoney = false; - // Allow players in faction to see one another on Dynmap (only relevant if Dynmap has 'player-info-protected' enabled) - public static boolean dynmapVisibilityByFaction = true; - // Optional setting to limit which regions to show. - // If empty all regions are shown. - // Specify Faction either by name or UUID. - // To show all regions on a given world, add 'world:' to the list. - public static Set dynmapVisibleFactions = new HashSet<>(); - // Optional setting to hide specific Factions. - // Specify Faction either by name or UUID. - // To hide all regions on a given world, add 'world:' to the list. - public static Set dynmapHiddenFactions = new HashSet<>(); - public static DynmapStyle dynmapDefaultStyle = new DynmapStyle() - .setStrokeColor(DYNMAP_STYLE_LINE_COLOR) - .setLineOpacity(DYNMAP_STYLE_LINE_OPACITY) - .setLineWeight(DYNMAP_STYLE_LINE_WEIGHT) - .setFillColor(DYNMAP_STYLE_FILL_COLOR) - .setFillOpacity(DYNMAP_STYLE_FILL_OPACITY) - .setHomeMarker(DYNMAP_STYLE_HOME_MARKER) - .setBoost(DYNMAP_STYLE_BOOST); + // -------------------------------------------- // + // INTEGRATION: DYNMAP + // -------------------------------------------- // + public static double econCostStuck = 0.0; + public static double econCostOpen = 0.0; + public static double econCostAlly = 0.0; + public static double econCostTruce = 0.0; + public static double econCostEnemy = 0.0; + public static double econCostNeutral = 0.0; + public static double econCostNoBoom = 0.0; + // Should the dynmap intagration be used? + public static boolean dynmapUse = false; + // Name of the Factions layer + public static String dynmapLayerName = "Factions"; + // Should the layer be visible per default + public static boolean dynmapLayerVisible = true; + // Ordering priority in layer menu (low goes before high - default is 0) + public static int dynmapLayerPriority = 2; + // (optional) set minimum zoom level before layer is visible (0 = default, always visible) + public static int dynmapLayerMinimumZoom = 0; + // Format for popup - substitute values for macros + public static String dynmapDescription = + "
    \n" + + "%name%
    \n" + + "%description%
    " + + "
    \n" + + "Leader: %players.leader%
    \n" + + "Admins: %players.admins.count%
    \n" + + "Moderators: %players.moderators.count%
    \n" + + "Members: %players.normals.count%
    \n" + + "TOTAL: %players.count%
    \n" + + "
    \n" + + "Bank: %money%
    \n" + + "
    \n" + + "
    "; + // Enable the %money% macro. Only do this if you know your economy manager is thread-safe. + public static boolean dynmapDescriptionMoney = false; + // Allow players in faction to see one another on Dynmap (only relevant if Dynmap has 'player-info-protected' enabled) + public static boolean dynmapVisibilityByFaction = true; + // Optional setting to limit which regions to show. + // If empty all regions are shown. + // Specify Faction either by name or UUID. + // To show all regions on a given world, add 'world:' to the list. + public static Set dynmapVisibleFactions = new HashSet<>(); + // Optional setting to hide specific Factions. + // Specify Faction either by name or UUID. + // To hide all regions on a given world, add 'world:' to the list. + public static Set dynmapHiddenFactions = new HashSet<>(); + public static DynmapStyle dynmapDefaultStyle = new DynmapStyle() + .setStrokeColor(DYNMAP_STYLE_LINE_COLOR) + .setLineOpacity(DYNMAP_STYLE_LINE_OPACITY) + .setLineWeight(DYNMAP_STYLE_LINE_WEIGHT) + .setFillColor(DYNMAP_STYLE_FILL_COLOR) + .setFillOpacity(DYNMAP_STYLE_FILL_OPACITY) + .setHomeMarker(DYNMAP_STYLE_HOME_MARKER) + .setBoost(DYNMAP_STYLE_BOOST); - // Optional per Faction style overrides. Any defined replace those in dynmapDefaultStyle. - // Specify Faction either by name or UUID. - public static Map dynmapFactionStyles = ImmutableMap.of( - "SafeZone", new DynmapStyle().setStrokeColor("#FF00FF").setFillColor("#FF00FF").setBoost(false), - "WarZone", new DynmapStyle().setStrokeColor("#FF0000").setFillColor("#FF0000").setBoost(false) - ); + // Optional per Faction style overrides. Any defined replace those in dynmapDefaultStyle. + // Specify Faction either by name or UUID. + public static Map dynmapFactionStyles = ImmutableMap.of( + "SafeZone", new DynmapStyle().setStrokeColor("#FF00FF").setFillColor("#FF00FF").setBoost(false), + "WarZone", new DynmapStyle().setStrokeColor("#FF0000").setFillColor("#FF0000").setBoost(false) + ); - //Faction banks, to pay for land claiming and other costs instead of individuals paying for them - public static boolean bankEnabled = true; - public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction - public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome - public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs. + //Faction banks, to pay for land claiming and other costs instead of individuals paying for them + public static boolean bankEnabled = true; + public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction + public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome + public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs. - // mainly for other plugins/mods that use a fake player to take actions, which shouldn't be subject to our protections - public static Set playersWhoBypassAllProtection = new LinkedHashSet<>(); + // mainly for other plugins/mods that use a fake player to take actions, which shouldn't be subject to our protections + public static Set playersWhoBypassAllProtection = new LinkedHashSet<>(); - public static Set worldsNoClaiming = new LinkedHashSet<>(); - public static Set worldsNoPowerLoss = new LinkedHashSet<>(); - public static Set worldsIgnorePvP = new LinkedHashSet<>(); - public static Set worldsNoWildernessProtection = new LinkedHashSet<>(); + public static Set worldsNoClaiming = new LinkedHashSet<>(); + public static Set worldsNoPowerLoss = new LinkedHashSet<>(); + public static Set worldsIgnorePvP = new LinkedHashSet<>(); + public static Set worldsNoWildernessProtection = new LinkedHashSet<>(); - // faction- - public static String vaultPrefix = "faction-%s"; - public static int defaultMaxVaults = 0; + // faction- + public static String vaultPrefix = "faction-%s"; + public static int defaultMaxVaults = 0; - public static Backend backEnd = Backend.JSON; + public static Backend backEnd = Backend.JSON; - // Taller and wider for "bigger f map" - public static int mapHeight = 17; - public static int mapWidth = 49; - public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray(); + // Taller and wider for "bigger f map" + public static int mapHeight = 17; + public static int mapWidth = 49; + public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray(); - // Default Options - public static boolean useCustomDefaultPermissions = false; - public static boolean usePermissionHints = false; - public static HashMap defaultFactionPermissions; - // Custom Ranks - //public static boolean enableCustomRanks = false; // We will disable it by default to avoid any migration error - //public static int maxCustomRanks = 2; // Setting this to -1 will allow unlimited custom ranks - // -------------------------------------------- // - // Persistance - // -------------------------------------------- // - private static transient Conf i = new Conf(); + // Default Options + public static boolean useCustomDefaultPermissions = false; + public static boolean usePermissionHints = false; + public static HashMap defaultFactionPermissions; + // Custom Ranks + //public static boolean enableCustomRanks = false; // We will disable it by default to avoid any migration error + //public static int maxCustomRanks = 2; // Setting this to -1 will allow unlimited custom ranks + // -------------------------------------------- // + // Persistance + // -------------------------------------------- // + private static transient Conf i = new Conf(); - static { - baseCommandAliases.add("f"); + static { + baseCommandAliases.add("f"); - territoryEnemyDenyCommands.add("home"); - territoryEnemyDenyCommands.add("sethome"); - territoryEnemyDenyCommands.add("spawn"); - territoryEnemyDenyCommands.add("tpahere"); - territoryEnemyDenyCommands.add("tpaccept"); - territoryEnemyDenyCommands.add("tpa"); + territoryEnemyDenyCommands.add("home"); + territoryEnemyDenyCommands.add("sethome"); + territoryEnemyDenyCommands.add("spawn"); + territoryEnemyDenyCommands.add("tpahere"); + territoryEnemyDenyCommands.add("tpaccept"); + territoryEnemyDenyCommands.add("tpa"); - territoryProtectedMaterials.add(SavageFactions.plugin.WOODEN_DOOR); - territoryProtectedMaterials.add(SavageFactions.plugin.TRAP_DOOR); - territoryProtectedMaterials.add(SavageFactions.plugin.FENCE_GATE); - territoryProtectedMaterials.add(Material.DISPENSER); - territoryProtectedMaterials.add(Material.CHEST); - territoryProtectedMaterials.add(Material.FURNACE); - territoryProtectedMaterials.add(SavageFactions.plugin.BURNING_FURNACE); - territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_OFF); - territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_ON); - territoryProtectedMaterials.add(Material.JUKEBOX); - territoryProtectedMaterials.add(Material.BREWING_STAND); - territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); - territoryProtectedMaterials.add(Material.CAULDRON); - territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); - territoryProtectedMaterials.add(Material.BEACON); - territoryProtectedMaterials.add(Material.ANVIL); - territoryProtectedMaterials.add(Material.TRAPPED_CHEST); - territoryProtectedMaterials.add(Material.DROPPER); - territoryProtectedMaterials.add(Material.HOPPER); + territoryProtectedMaterials.add(SavageFactions.plugin.WOODEN_DOOR); + territoryProtectedMaterials.add(SavageFactions.plugin.TRAP_DOOR); + territoryProtectedMaterials.add(SavageFactions.plugin.FENCE_GATE); + territoryProtectedMaterials.add(Material.DISPENSER); + territoryProtectedMaterials.add(Material.CHEST); + territoryProtectedMaterials.add(Material.FURNACE); + territoryProtectedMaterials.add(SavageFactions.plugin.BURNING_FURNACE); + territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_OFF); + territoryProtectedMaterials.add(SavageFactions.plugin.DIODE_BLOCK_ON); + territoryProtectedMaterials.add(Material.JUKEBOX); + territoryProtectedMaterials.add(Material.BREWING_STAND); + territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); + territoryProtectedMaterials.add(Material.CAULDRON); + territoryProtectedMaterials.add(SavageFactions.plugin.ENCHANTMENT_TABLE); + territoryProtectedMaterials.add(Material.BEACON); + territoryProtectedMaterials.add(Material.ANVIL); + territoryProtectedMaterials.add(Material.TRAPPED_CHEST); + territoryProtectedMaterials.add(Material.DROPPER); + territoryProtectedMaterials.add(Material.HOPPER); - territoryDenyUseageMaterials.add(SavageFactions.plugin.FIREBALL); - territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL); - territoryDenyUseageMaterials.add(Material.BUCKET); - territoryDenyUseageMaterials.add(Material.WATER_BUCKET); - territoryDenyUseageMaterials.add(Material.LAVA_BUCKET); - territoryDenyUseageMaterials.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterials.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); - if (!SavageFactions.plugin.mc17) { - territoryDenyUseageMaterials.add(Material.ARMOR_STAND); - } + territoryDenyUseageMaterials.add(SavageFactions.plugin.FIREBALL); + territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL); + territoryDenyUseageMaterials.add(Material.BUCKET); + territoryDenyUseageMaterials.add(Material.WATER_BUCKET); + territoryDenyUseageMaterials.add(Material.LAVA_BUCKET); + territoryDenyUseageMaterials.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterials.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); + if (!SavageFactions.plugin.mc17) { + territoryDenyUseageMaterials.add(Material.ARMOR_STAND); + } - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.WOODEN_DOOR); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.TRAP_DOOR); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.FENCE_GATE); - territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER); - territoryProtectedMaterialsWhenOffline.add(Material.CHEST); - territoryProtectedMaterialsWhenOffline.add(Material.FURNACE); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.BURNING_FURNACE); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); - territoryProtectedMaterialsWhenOffline.add(Material.JUKEBOX); - territoryProtectedMaterialsWhenOffline.add(Material.BREWING_STAND); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.ENCHANTMENT_TABLE); - territoryProtectedMaterialsWhenOffline.add(Material.CAULDRON); - territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.SOIL); - territoryProtectedMaterialsWhenOffline.add(Material.BEACON); - territoryProtectedMaterialsWhenOffline.add(Material.ANVIL); - territoryProtectedMaterialsWhenOffline.add(Material.TRAPPED_CHEST); - territoryProtectedMaterialsWhenOffline.add(Material.DROPPER); - territoryProtectedMaterialsWhenOffline.add(Material.HOPPER); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.WOODEN_DOOR); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.TRAP_DOOR); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.FENCE_GATE); + territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER); + territoryProtectedMaterialsWhenOffline.add(Material.CHEST); + territoryProtectedMaterialsWhenOffline.add(Material.FURNACE); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.BURNING_FURNACE); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.DIODE_BLOCK_OFF); + territoryProtectedMaterialsWhenOffline.add(Material.JUKEBOX); + territoryProtectedMaterialsWhenOffline.add(Material.BREWING_STAND); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.ENCHANTMENT_TABLE); + territoryProtectedMaterialsWhenOffline.add(Material.CAULDRON); + territoryProtectedMaterialsWhenOffline.add(SavageFactions.plugin.SOIL); + territoryProtectedMaterialsWhenOffline.add(Material.BEACON); + territoryProtectedMaterialsWhenOffline.add(Material.ANVIL); + territoryProtectedMaterialsWhenOffline.add(Material.TRAPPED_CHEST); + territoryProtectedMaterialsWhenOffline.add(Material.DROPPER); + territoryProtectedMaterialsWhenOffline.add(Material.HOPPER); - territoryDenyUseageMaterialsWhenOffline.add(SavageFactions.plugin.FIREBALL); - territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL); - territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET); - territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET); - territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); - territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); - if (!SavageFactions.plugin.mc17) { - territoryDenyUseageMaterialsWhenOffline.add(Material.ARMOR_STAND); - } - safeZoneNerfedCreatureTypes.add(EntityType.BLAZE); - safeZoneNerfedCreatureTypes.add(EntityType.CAVE_SPIDER); - safeZoneNerfedCreatureTypes.add(EntityType.CREEPER); - safeZoneNerfedCreatureTypes.add(EntityType.ENDER_DRAGON); - safeZoneNerfedCreatureTypes.add(EntityType.ENDERMAN); - safeZoneNerfedCreatureTypes.add(EntityType.GHAST); - safeZoneNerfedCreatureTypes.add(EntityType.MAGMA_CUBE); - safeZoneNerfedCreatureTypes.add(EntityType.PIG_ZOMBIE); - safeZoneNerfedCreatureTypes.add(EntityType.SILVERFISH); - safeZoneNerfedCreatureTypes.add(EntityType.SKELETON); - safeZoneNerfedCreatureTypes.add(EntityType.SPIDER); - safeZoneNerfedCreatureTypes.add(EntityType.SLIME); - safeZoneNerfedCreatureTypes.add(EntityType.WITCH); - safeZoneNerfedCreatureTypes.add(EntityType.WITHER); - safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE); - // Is this called lazy load? - defaultFactionPermissions.put("LEADER", new DefaultPermissions(true)); - defaultFactionPermissions.put("COLEADER", new DefaultPermissions(true)); - defaultFactionPermissions.put("MODERATOR", new DefaultPermissions(true)); - defaultFactionPermissions.put("MEMBER", new DefaultPermissions(false)); - defaultFactionPermissions.put("RECRUIT", new DefaultPermissions(false)); - } + territoryDenyUseageMaterialsWhenOffline.add(SavageFactions.plugin.FIREBALL); + territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL); + territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET); + territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET); + territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.ACACIA_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.BIRCH_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.DARK_OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.JUNGLE_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.OAK_BUTTON.parseMaterial()); + territoryDenyUseageMaterialsWhenOffline.add(MultiversionMaterials.STONE_BUTTON.parseMaterial()); + if (!SavageFactions.plugin.mc17) { + territoryDenyUseageMaterialsWhenOffline.add(Material.ARMOR_STAND); + } + safeZoneNerfedCreatureTypes.add(EntityType.BLAZE); + safeZoneNerfedCreatureTypes.add(EntityType.CAVE_SPIDER); + safeZoneNerfedCreatureTypes.add(EntityType.CREEPER); + safeZoneNerfedCreatureTypes.add(EntityType.ENDER_DRAGON); + safeZoneNerfedCreatureTypes.add(EntityType.ENDERMAN); + safeZoneNerfedCreatureTypes.add(EntityType.GHAST); + safeZoneNerfedCreatureTypes.add(EntityType.MAGMA_CUBE); + safeZoneNerfedCreatureTypes.add(EntityType.PIG_ZOMBIE); + safeZoneNerfedCreatureTypes.add(EntityType.SILVERFISH); + safeZoneNerfedCreatureTypes.add(EntityType.SKELETON); + safeZoneNerfedCreatureTypes.add(EntityType.SPIDER); + safeZoneNerfedCreatureTypes.add(EntityType.SLIME); + safeZoneNerfedCreatureTypes.add(EntityType.WITCH); + safeZoneNerfedCreatureTypes.add(EntityType.WITHER); + safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE); + // Is this called lazy load? + defaultFactionPermissions.put("LEADER", new DefaultPermissions(true)); + defaultFactionPermissions.put("COLEADER", new DefaultPermissions(true)); + defaultFactionPermissions.put("MODERATOR", new DefaultPermissions(true)); + defaultFactionPermissions.put("MEMBER", new DefaultPermissions(false)); + defaultFactionPermissions.put("RECRUIT", new DefaultPermissions(false)); + } - public static void load() { - SavageFactions.plugin.persist.loadOrSaveDefault(i, Conf.class, "conf"); - } + public static void load() { + SavageFactions.plugin.persist.loadOrSaveDefault(i, Conf.class, "conf"); + } - public static void save() { - SavageFactions.plugin.persist.save(i); - } + public static void save() { + SavageFactions.plugin.persist.save(i); + } - public enum Backend { - JSON, - //MYSQL, TODO add MySQL storage - ; - } + public enum Backend { + JSON, + //MYSQL, TODO add MySQL storage + ; + } } diff --git a/src/main/java/com/massivecraft/factions/FLocation.java b/src/main/java/com/massivecraft/factions/FLocation.java index 1c684ce0..0f9c71fd 100644 --- a/src/main/java/com/massivecraft/factions/FLocation.java +++ b/src/main/java/com/massivecraft/factions/FLocation.java @@ -11,247 +11,247 @@ import java.util.LinkedHashSet; import java.util.Set; public class FLocation implements Serializable { - private static final long serialVersionUID = -8292915234027387983L; - private static final boolean worldBorderSupport; + private static final long serialVersionUID = -8292915234027387983L; + private static final boolean worldBorderSupport; - static { - boolean worldBorderClassPresent = false; - try { - Class.forName("org.bukkit.WorldBorder"); - worldBorderClassPresent = true; - } catch (ClassNotFoundException ignored) { - } + static { + boolean worldBorderClassPresent = false; + try { + Class.forName("org.bukkit.WorldBorder"); + worldBorderClassPresent = true; + } catch (ClassNotFoundException ignored) { + } - worldBorderSupport = worldBorderClassPresent; - } + worldBorderSupport = worldBorderClassPresent; + } - private String worldName = "world"; - private int x = 0; - private int z = 0; + private String worldName = "world"; + private int x = 0; + private int z = 0; - //----------------------------------------------// - // Constructors - //----------------------------------------------// + //----------------------------------------------// + // Constructors + //----------------------------------------------// - public FLocation() { + public FLocation() { - } + } - public FLocation(String worldName, int x, int z) { - this.worldName = worldName; - this.x = x; - this.z = z; - } + public FLocation(String worldName, int x, int z) { + this.worldName = worldName; + this.x = x; + this.z = z; + } - public FLocation(Location location) { - this(location.getWorld().getName(), blockToChunk(location.getBlockX()), blockToChunk(location.getBlockZ())); - } + public FLocation(Location location) { + this(location.getWorld().getName(), blockToChunk(location.getBlockX()), blockToChunk(location.getBlockZ())); + } - public FLocation(Player player) { - this(player.getLocation()); - } + public FLocation(Player player) { + this(player.getLocation()); + } - public FLocation(FPlayer fplayer) { - this(fplayer.getPlayer()); - } + public FLocation(FPlayer fplayer) { + this(fplayer.getPlayer()); + } - public FLocation(Block block) { - this(block.getLocation()); - } + public FLocation(Block block) { + this(block.getLocation()); + } - //----------------------------------------------// - // Getters and Setters - //----------------------------------------------// + //----------------------------------------------// + // Getters and Setters + //----------------------------------------------// - public static FLocation fromString(String string) { - int index = string.indexOf(","); - int start = 1; - String worldName = string.substring(start, index); - start = index + 1; - index = string.indexOf(",", start); - int x = Integer.valueOf(string.substring(start, index)); - int y = Integer.valueOf(string.substring(index + 1, string.length() - 1)); - return new FLocation(worldName, x, y); - } + public static FLocation fromString(String string) { + int index = string.indexOf(","); + int start = 1; + String worldName = string.substring(start, index); + start = index + 1; + index = string.indexOf(",", start); + int x = Integer.valueOf(string.substring(start, index)); + int y = Integer.valueOf(string.substring(index + 1, string.length() - 1)); + return new FLocation(worldName, x, y); + } - // bit-shifting is used because it's much faster than standard division and multiplication - public static int blockToChunk(int blockVal) { // 1 chunk is 16x16 blocks - return blockVal >> 4; // ">> 4" == "/ 16" - } + // bit-shifting is used because it's much faster than standard division and multiplication + public static int blockToChunk(int blockVal) { // 1 chunk is 16x16 blocks + return blockVal >> 4; // ">> 4" == "/ 16" + } - public static int blockToRegion(int blockVal) { // 1 region is 512x512 blocks - return blockVal >> 9; // ">> 9" == "/ 512" - } + public static int blockToRegion(int blockVal) { // 1 region is 512x512 blocks + return blockVal >> 9; // ">> 9" == "/ 512" + } - public static int chunkToRegion(int chunkVal) { // 1 region is 32x32 chunks - return chunkVal >> 5; // ">> 5" == "/ 32" - } + public static int chunkToRegion(int chunkVal) { // 1 region is 32x32 chunks + return chunkVal >> 5; // ">> 5" == "/ 32" + } - public static int chunkToBlock(int chunkVal) { - return chunkVal << 4; // "<< 4" == "* 16" - } + public static int chunkToBlock(int chunkVal) { + return chunkVal << 4; // "<< 4" == "* 16" + } - public static int regionToBlock(int regionVal) { - return regionVal << 9; // "<< 9" == "* 512" - } + public static int regionToBlock(int regionVal) { + return regionVal << 9; // "<< 9" == "* 512" + } - public static int regionToChunk(int regionVal) { - return regionVal << 5; // "<< 5" == "* 32" - } + public static int regionToChunk(int regionVal) { + return regionVal << 5; // "<< 5" == "* 32" + } - public static HashSet getArea(FLocation from, FLocation to) { - HashSet ret = new HashSet<>(); + public static HashSet getArea(FLocation from, FLocation to) { + HashSet ret = new HashSet<>(); - for (long x : MiscUtil.range(from.getX(), to.getX())) { - for (long z : MiscUtil.range(from.getZ(), to.getZ())) { - ret.add(new FLocation(from.getWorldName(), (int) x, (int) z)); - } - } + for (long x : MiscUtil.range(from.getX(), to.getX())) { + for (long z : MiscUtil.range(from.getZ(), to.getZ())) { + ret.add(new FLocation(from.getWorldName(), (int) x, (int) z)); + } + } - return ret; - } + return ret; + } - public Chunk getChunk() { - return Bukkit.getWorld(worldName).getChunkAt(x, z); - } + public Chunk getChunk() { + return Bukkit.getWorld(worldName).getChunkAt(x, z); + } - public String getWorldName() { - return worldName; - } + public String getWorldName() { + return worldName; + } - public void setWorldName(String worldName) { - this.worldName = worldName; - } + public void setWorldName(String worldName) { + this.worldName = worldName; + } - //----------------------------------------------// - // Block/Chunk/Region Value Transformation - //----------------------------------------------// + //----------------------------------------------// + // Block/Chunk/Region Value Transformation + //----------------------------------------------// - public World getWorld() { - return Bukkit.getWorld(worldName); - } + public World getWorld() { + return Bukkit.getWorld(worldName); + } - public long getX() { - return x; - } + public long getX() { + return x; + } - public void setX(int x) { - this.x = x; - } + public void setX(int x) { + this.x = x; + } - public long getZ() { - return z; - } + public long getZ() { + return z; + } - public void setZ(int z) { - this.z = z; - } + public void setZ(int z) { + this.z = z; + } - public String getCoordString() { - return "" + x + "," + z; - } + public String getCoordString() { + return "" + x + "," + z; + } - //----------------------------------------------// - // Misc Geometry - //----------------------------------------------// + //----------------------------------------------// + // Misc Geometry + //----------------------------------------------// - @Override - public String toString() { - return "[" + this.getWorldName() + "," + this.getCoordString() + "]"; - } + @Override + public String toString() { + return "[" + this.getWorldName() + "," + this.getCoordString() + "]"; + } - public FLocation getRelative(int dx, int dz) { - return new FLocation(this.worldName, this.x + dx, this.z + dz); - } + public FLocation getRelative(int dx, int dz) { + return new FLocation(this.worldName, this.x + dx, this.z + dz); + } - public double getDistanceTo(FLocation that) { - double dx = that.x - this.x; - double dz = that.z - this.z; - return Math.sqrt(dx * dx + dz * dz); - } + public double getDistanceTo(FLocation that) { + double dx = that.x - this.x; + double dz = that.z - this.z; + return Math.sqrt(dx * dx + dz * dz); + } - public double getDistanceSquaredTo(FLocation that) { - double dx = that.x - this.x; - double dz = that.z - this.z; - return dx * dx + dz * dz; - } + public double getDistanceSquaredTo(FLocation that) { + double dx = that.x - this.x; + double dz = that.z - this.z; + return dx * dx + dz * dz; + } - public boolean isInChunk(Location loc) { - if (loc == null) { - return false; - } - Chunk chunk = loc.getChunk(); - return loc.getWorld().getName().equalsIgnoreCase(getWorldName()) && chunk.getX() == x && chunk.getZ() == z; - } + public boolean isInChunk(Location loc) { + if (loc == null) { + return false; + } + Chunk chunk = loc.getChunk(); + return loc.getWorld().getName().equalsIgnoreCase(getWorldName()) && chunk.getX() == x && chunk.getZ() == z; + } - /** - * Checks if the chunk represented by this FLocation is outside the world border - * - * @param buffer the number of chunks from the border that will be treated as "outside" - * @return whether this location is outside of the border - */ - public boolean isOutsideWorldBorder(int buffer) { - if (!worldBorderSupport) { - return false; - } + /** + * Checks if the chunk represented by this FLocation is outside the world border + * + * @param buffer the number of chunks from the border that will be treated as "outside" + * @return whether this location is outside of the border + */ + public boolean isOutsideWorldBorder(int buffer) { + if (!worldBorderSupport) { + return false; + } - WorldBorder border = getWorld().getWorldBorder(); - Chunk chunk = border.getCenter().getChunk(); + WorldBorder border = getWorld().getWorldBorder(); + Chunk chunk = border.getCenter().getChunk(); - int lim = FLocation.chunkToRegion((int) border.getSize()) - buffer; - int diffX = chunk.getX() - x; - int diffZ = chunk.getZ() - z; - return diffX > lim || diffZ > lim || -diffX > lim - 1 || -diffZ > lim - 1; - } + int lim = FLocation.chunkToRegion((int) border.getSize()) - buffer; + int diffX = chunk.getX() - x; + int diffZ = chunk.getZ() - z; + return diffX > lim || diffZ > lim || -diffX > lim - 1 || -diffZ > lim - 1; + } - //----------------------------------------------// - // Some Geometry - //----------------------------------------------// - public Set getCircle(double radius) { - double radiusSquared = radius * radius; + //----------------------------------------------// + // Some Geometry + //----------------------------------------------// + public Set getCircle(double radius) { + double radiusSquared = radius * radius; - Set ret = new LinkedHashSet<>(); - if (radius <= 0) { - return ret; - } + Set ret = new LinkedHashSet<>(); + if (radius <= 0) { + return ret; + } - int xfrom = (int) Math.floor(this.x - radius); - int xto = (int) Math.ceil(this.x + radius); - int zfrom = (int) Math.floor(this.z - radius); - int zto = (int) Math.ceil(this.z + radius); + int xfrom = (int) Math.floor(this.x - radius); + int xto = (int) Math.ceil(this.x + radius); + int zfrom = (int) Math.floor(this.z - radius); + int zto = (int) Math.ceil(this.z + radius); - for (int x = xfrom; x <= xto; x++) { - for (int z = zfrom; z <= zto; z++) { - FLocation potential = new FLocation(this.worldName, x, z); - if (this.getDistanceSquaredTo(potential) <= radiusSquared) { - ret.add(potential); - } - } - } + for (int x = xfrom; x <= xto; x++) { + for (int z = zfrom; z <= zto; z++) { + FLocation potential = new FLocation(this.worldName, x, z); + if (this.getDistanceSquaredTo(potential) <= radiusSquared) { + ret.add(potential); + } + } + } - return ret; - } + return ret; + } - //----------------------------------------------// - // Comparison - //----------------------------------------------// + //----------------------------------------------// + // Comparison + //----------------------------------------------// - @Override - public int hashCode() { - // should be fast, with good range and few hash collisions: (x * 512) + z + worldName.hashCode - return (this.x << 9) + this.z + (this.worldName != null ? this.worldName.hashCode() : 0); - } + @Override + public int hashCode() { + // should be fast, with good range and few hash collisions: (x * 512) + z + worldName.hashCode + return (this.x << 9) + this.z + (this.worldName != null ? this.worldName.hashCode() : 0); + } - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof FLocation)) { - return false; - } + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof FLocation)) { + return false; + } - FLocation that = (FLocation) obj; - return this.x == that.x && this.z == that.z && (this.worldName == null ? that.worldName == null : this.worldName.equals(that.worldName)); - } + FLocation that = (FLocation) obj; + return this.x == that.x && this.z == that.z && (this.worldName == null ? that.worldName == null : this.worldName.equals(that.worldName)); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/FPlayer.java b/src/main/java/com/massivecraft/factions/FPlayer.java index 48d1a44a..359f09ba 100644 --- a/src/main/java/com/massivecraft/factions/FPlayer.java +++ b/src/main/java/com/massivecraft/factions/FPlayer.java @@ -26,354 +26,354 @@ import java.util.List; public interface FPlayer extends EconomyParticipator { - /** - * Used to know if stealth is toggled on or off - * - * @return if stealth mode is on or not. - */ - boolean isStealthEnabled(); + /** + * Used to know if stealth is toggled on or off + * + * @return if stealth mode is on or not. + */ + boolean isStealthEnabled(); - /** - * Toggles the stealth of the FPlayer depending on the parameter - * - * @param stealthToggle - toggles stealth - */ - void setStealth(boolean stealthToggle); + /** + * Toggles the stealth of the FPlayer depending on the parameter + * + * @param stealthToggle - toggles stealth + */ + void setStealth(boolean stealthToggle); - /** - * Sets the kills and deaths of a player. - */ - void login(); + /** + * Sets the kills and deaths of a player. + */ + void login(); - /** - * Caches the kills and deaths of a player. - */ - void logout(); + /** + * Caches the kills and deaths of a player. + */ + void logout(); - /** - * gets the faction of a FPlayer. - * - * @return Faction of the FPlayer. - */ - Faction getFaction(); + /** + * gets the faction of a FPlayer. + * + * @return Faction of the FPlayer. + */ + Faction getFaction(); - /** - * Sets the faction of the FPlayer - * - * @param faction faction to set. - */ - void setFaction(Faction faction); + /** + * Sets the faction of the FPlayer + * + * @param faction faction to set. + */ + void setFaction(Faction faction); - /** - * Gets the faction ID of the player. - * - * @return FactionsID string - */ - String getFactionId(); + /** + * Gets the faction ID of the player. + * + * @return FactionsID string + */ + String getFactionId(); - /** - * Check if a player has a faction - * - * @return boolean - */ - boolean hasFaction(); + /** + * Check if a player has a faction + * + * @return boolean + */ + boolean hasFaction(); - /** - * Gets autoleave status - * - * @return boolean of the autoleave - */ - boolean willAutoLeave(); + /** + * Gets autoleave status + * + * @return boolean of the autoleave + */ + boolean willAutoLeave(); - void setAutoLeave(boolean autoLeave); + void setAutoLeave(boolean autoLeave); - long getLastFrostwalkerMessage(); + long getLastFrostwalkerMessage(); - void setLastFrostwalkerMessage(); + void setLastFrostwalkerMessage(); - void setMonitorJoins(boolean monitor); + void setMonitorJoins(boolean monitor); - boolean isMonitoringJoins(); + boolean isMonitoringJoins(); - Role getRole(); + Role getRole(); - void setRole(Role role); + void setRole(Role role); - boolean shouldTakeFallDamage(); + boolean shouldTakeFallDamage(); - void setTakeFallDamage(boolean fallDamage); + void setTakeFallDamage(boolean fallDamage); - double getPowerBoost(); + double getPowerBoost(); - void setPowerBoost(double powerBoost); + void setPowerBoost(double powerBoost); - Faction getAutoClaimFor(); + Faction getAutoClaimFor(); - void setAutoClaimFor(Faction faction); + void setAutoClaimFor(Faction faction); - boolean isAutoSafeClaimEnabled(); + boolean isAutoSafeClaimEnabled(); - void setIsAutoSafeClaimEnabled(boolean enabled); + void setIsAutoSafeClaimEnabled(boolean enabled); - boolean isAutoWarClaimEnabled(); + boolean isAutoWarClaimEnabled(); - void setIsAutoWarClaimEnabled(boolean enabled); + void setIsAutoWarClaimEnabled(boolean enabled); - boolean isAdminBypassing(); + boolean isAdminBypassing(); - boolean isVanished(); + boolean isVanished(); - void setIsAdminBypassing(boolean val); + void setIsAdminBypassing(boolean val); - ChatMode getChatMode(); + ChatMode getChatMode(); - void setChatMode(ChatMode chatMode); + void setChatMode(ChatMode chatMode); - boolean isIgnoreAllianceChat(); + boolean isIgnoreAllianceChat(); - void setIgnoreAllianceChat(boolean ignore); + void setIgnoreAllianceChat(boolean ignore); - boolean isSpyingChat(); + boolean isSpyingChat(); - void setSpyingChat(boolean chatSpying); + void setSpyingChat(boolean chatSpying); - boolean showScoreboard(); + boolean showScoreboard(); - void setShowScoreboard(boolean show); + void setShowScoreboard(boolean show); - // FIELD: account - String getAccountId(); + // FIELD: account + String getAccountId(); - void resetFactionData(boolean doSpoutUpdate); + void resetFactionData(boolean doSpoutUpdate); - void resetFactionData(); + void resetFactionData(); - long getLastLoginTime(); + long getLastLoginTime(); - void setLastLoginTime(long lastLoginTime); + void setLastLoginTime(long lastLoginTime); - boolean isMapAutoUpdating(); + boolean isMapAutoUpdating(); - void setMapAutoUpdating(boolean mapAutoUpdating); + void setMapAutoUpdating(boolean mapAutoUpdating); - boolean hasLoginPvpDisabled(); + boolean hasLoginPvpDisabled(); - FLocation getLastStoodAt(); + FLocation getLastStoodAt(); - void setLastStoodAt(FLocation flocation); + void setLastStoodAt(FLocation flocation); - String getTitle(); + String getTitle(); - void setTitle(CommandSender sender, String title); + void setTitle(CommandSender sender, String title); - String getName(); + String getName(); - String getTag(); + String getTag(); - // Base concatenations: + // Base concatenations: - String getNameAndSomething(String something); + String getNameAndSomething(String something); - String getNameAndTitle(); + String getNameAndTitle(); - String getNameAndTag(); + String getNameAndTag(); - // Colored concatenations: - // These are used in information messages + // Colored concatenations: + // These are used in information messages - String getNameAndTitle(Faction faction); + String getNameAndTitle(Faction faction); - String getNameAndTitle(FPlayer fplayer); + String getNameAndTitle(FPlayer fplayer); - // Chat Tag: - // These are injected into the format of global chat messages. + // Chat Tag: + // These are injected into the format of global chat messages. - String getChatTag(); + String getChatTag(); - // Colored Chat Tag - String getChatTag(Faction faction); + // Colored Chat Tag + String getChatTag(Faction faction); - String getChatTag(FPlayer fplayer); + String getChatTag(FPlayer fplayer); - int getKills(); + int getKills(); - int getDeaths(); + int getDeaths(); - void takeMoney(int amt); + void takeMoney(int amt); - boolean hasMoney(int amt); + boolean hasMoney(int amt); - //inspect Stuff + //inspect Stuff - boolean isInspectMode(); + boolean isInspectMode(); - void setInspectMode(boolean status); + void setInspectMode(boolean status); - // Fly Checks + // Fly Checks - Boolean canflyinWilderness(); + Boolean canflyinWilderness(); - Boolean canflyinWarzone(); + Boolean canflyinWarzone(); - Boolean canflyinSafezone(); + Boolean canflyinSafezone(); - Boolean canflyinEnemy(); + Boolean canflyinEnemy(); - Boolean canflyinAlly(); + Boolean canflyinAlly(); - Boolean canflyinTruce(); + Boolean canflyinTruce(); - Boolean canflyinNeutral(); + Boolean canflyinNeutral(); - // ------------------------------- - // Relation and relation colors - // ------------------------------- + // ------------------------------- + // Relation and relation colors + // ------------------------------- - @Override - String describeTo(RelationParticipator that, boolean ucfirst); + @Override + String describeTo(RelationParticipator that, boolean ucfirst); - @Override - String describeTo(RelationParticipator that); + @Override + String describeTo(RelationParticipator that); - @Override - Relation getRelationTo(RelationParticipator rp); + @Override + Relation getRelationTo(RelationParticipator rp); - @Override - Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); + @Override + Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); - Relation getRelationToLocation(); + Relation getRelationToLocation(); - @Override - ChatColor getColorTo(RelationParticipator rp); + @Override + ChatColor getColorTo(RelationParticipator rp); - String getRolePrefix(); + String getRolePrefix(); - //----------------------------------------------// - // Health - //----------------------------------------------// - void heal(int amnt); + //----------------------------------------------// + // Health + //----------------------------------------------// + void heal(int amnt); - //----------------------------------------------// - // Power - //----------------------------------------------// - double getPower(); + //----------------------------------------------// + // Power + //----------------------------------------------// + double getPower(); - void alterPower(double delta); + void alterPower(double delta); - double getPowerMax(); + double getPowerMax(); - double getPowerMin(); + double getPowerMin(); - int getPowerRounded(); + int getPowerRounded(); - int getPowerMaxRounded(); + int getPowerMaxRounded(); - int getPowerMinRounded(); + int getPowerMinRounded(); - void updatePower(); + void updatePower(); - void losePowerFromBeingOffline(); + void losePowerFromBeingOffline(); - void onDeath(); + void onDeath(); - //----------------------------------------------// - // Territory - //----------------------------------------------// - boolean isInOwnTerritory(); + //----------------------------------------------// + // Territory + //----------------------------------------------// + boolean isInOwnTerritory(); - boolean isInOthersTerritory(); + boolean isInOthersTerritory(); - boolean isInAllyTerritory(); + boolean isInAllyTerritory(); - boolean isInNeutralTerritory(); + boolean isInNeutralTerritory(); - boolean isInEnemyTerritory(); + boolean isInEnemyTerritory(); - void sendFactionHereMessage(Faction from); + void sendFactionHereMessage(Faction from); - // ------------------------------- - // Actions - // ------------------------------- + // ------------------------------- + // Actions + // ------------------------------- - void leave(boolean makePay); + void leave(boolean makePay); - boolean canClaimForFaction(Faction forFaction); + boolean canClaimForFaction(Faction forFaction); - boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure); + boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure); - boolean canClaimForFactionAtLocation(Faction forFaction, FLocation location, boolean notifyFailure); + boolean canClaimForFactionAtLocation(Faction forFaction, FLocation location, boolean notifyFailure); - boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure); + boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure); - boolean attemptClaim(Faction forFaction, FLocation location, boolean notifyFailure); + boolean attemptClaim(Faction forFaction, FLocation location, boolean notifyFailure); - boolean isInVault(); + boolean isInVault(); - void setInVault(boolean status); + void setInVault(boolean status); - void msg(String str, Object... args); + void msg(String str, Object... args); - String getId(); + String getId(); - void setId(String id); + void setId(String id); - Player getPlayer(); + Player getPlayer(); - boolean isOnline(); + boolean isOnline(); - void sendMessage(String message); + void sendMessage(String message); - void sendMessage(List messages); + void sendMessage(List messages); - void sendFancyMessage(FancyMessage message); + void sendFancyMessage(FancyMessage message); - void sendFancyMessage(List message); + void sendFancyMessage(List message); - int getMapHeight(); + int getMapHeight(); - void setMapHeight(int height); + void setMapHeight(int height); - boolean isOnlineAndVisibleTo(Player me); + boolean isOnlineAndVisibleTo(Player me); - void remove(); + void remove(); - boolean isOffline(); + boolean isOffline(); - boolean isFlying(); + boolean isFlying(); - void setFlying(boolean fly); + void setFlying(boolean fly); - void setFFlying(boolean fly, boolean damage); + void setFFlying(boolean fly, boolean damage); - boolean canFlyAtLocation(); + boolean canFlyAtLocation(); - boolean canFlyAtLocation(FLocation location); + boolean canFlyAtLocation(FLocation location); - boolean isEnteringPassword(); + boolean isEnteringPassword(); - void setEnteringPassword(boolean toggle, String warp); + void setEnteringPassword(boolean toggle, String warp); - String getEnteringWarp(); + String getEnteringWarp(); - boolean checkIfNearbyEnemies(); + boolean checkIfNearbyEnemies(); - // ------------------------------- - // Warmups - // ------------------------------- + // ------------------------------- + // Warmups + // ------------------------------- - boolean isWarmingUp(); + boolean isWarmingUp(); - WarmUpUtil.Warmup getWarmupType(); + WarmUpUtil.Warmup getWarmupType(); - void addWarmup(WarmUpUtil.Warmup warmup, int taskId); + void addWarmup(WarmUpUtil.Warmup warmup, int taskId); - void stopWarmup(); + void stopWarmup(); - void clearWarmup(); + void clearWarmup(); } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/FPlayers.java b/src/main/java/com/massivecraft/factions/FPlayers.java index aca12183..a11917e7 100644 --- a/src/main/java/com/massivecraft/factions/FPlayers.java +++ b/src/main/java/com/massivecraft/factions/FPlayers.java @@ -1,41 +1,41 @@ -package com.massivecraft.factions; - -import com.massivecraft.factions.zcore.persist.json.JSONFPlayers; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.util.Collection; - -public abstract class FPlayers { - protected static FPlayers instance = getFPlayersImpl(); - - public static FPlayers getInstance() { - return instance; - } - - private static FPlayers getFPlayersImpl() { - switch (Conf.backEnd) { - case JSON: - return new JSONFPlayers(); - } - return null; - } - - public abstract void clean(); - - public abstract Collection getOnlinePlayers(); - - public abstract FPlayer getByPlayer(Player player); - - public abstract Collection getAllFPlayers(); - - public abstract void forceSave(); - - public abstract void forceSave(boolean sync); - - public abstract FPlayer getByOfflinePlayer(OfflinePlayer player); - - public abstract FPlayer getById(String string); - - public abstract void load(); -} +package com.massivecraft.factions; + +import com.massivecraft.factions.zcore.persist.json.JSONFPlayers; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public abstract class FPlayers { + protected static FPlayers instance = getFPlayersImpl(); + + public static FPlayers getInstance() { + return instance; + } + + private static FPlayers getFPlayersImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONFPlayers(); + } + return null; + } + + public abstract void clean(); + + public abstract Collection getOnlinePlayers(); + + public abstract FPlayer getByPlayer(Player player); + + public abstract Collection getAllFPlayers(); + + public abstract void forceSave(); + + public abstract void forceSave(boolean sync); + + public abstract FPlayer getByOfflinePlayer(OfflinePlayer player); + + public abstract FPlayer getById(String string); + + public abstract void load(); +} diff --git a/src/main/java/com/massivecraft/factions/Faction.java b/src/main/java/com/massivecraft/factions/Faction.java index be6412c6..5e97f012 100644 --- a/src/main/java/com/massivecraft/factions/Faction.java +++ b/src/main/java/com/massivecraft/factions/Faction.java @@ -21,327 +21,328 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; public interface Faction extends EconomyParticipator { - HashMap> getAnnouncements(); + HashMap> getAnnouncements(); - ConcurrentHashMap getWarps(); + ConcurrentHashMap getWarps(); - LazyLocation getWarp(String name); + LazyLocation getWarp(String name); - void setWarp(String name, LazyLocation loc); + void setWarp(String name, LazyLocation loc); - boolean isWarp(String name); + boolean isWarp(String name); - boolean hasWarpPassword(String warp); + boolean hasWarpPassword(String warp); - boolean isWarpPassword(String warp, String password); + boolean isWarpPassword(String warp, String password); - void setWarpPassword(String warp, String password); + void setWarpPassword(String warp, String password); - boolean removeWarp(String name); + boolean removeWarp(String name); - void clearWarps(); + void clearWarps(); - int getMaxVaults(); + int getMaxVaults(); - void setMaxVaults(int value); + void setMaxVaults(int value); - void addAnnouncement(FPlayer fPlayer, String msg); + void addAnnouncement(FPlayer fPlayer, String msg); - void sendUnreadAnnouncements(FPlayer fPlayer); + void sendUnreadAnnouncements(FPlayer fPlayer); - void removeAnnouncements(FPlayer fPlayer); + void removeAnnouncements(FPlayer fPlayer); - Set getInvites(); + Set getInvites(); - String getFocused(); + String getFocused(); - void setFocused(String setFocused); + void setFocused(String setFocused); - String getId(); + String getId(); - void setId(String id); + void setId(String id); - void invite(FPlayer fplayer); + void invite(FPlayer fplayer); - void deinvite(FPlayer fplayer); + void deinvite(FPlayer fplayer); - void setUpgrade(Upgrade upgrade, int level); + void setUpgrade(Upgrade upgrade, int level); - int getUpgrade(Upgrade upgrade); + int getUpgrade(Upgrade upgrade); - boolean isInvited(FPlayer fplayer); + boolean isInvited(FPlayer fplayer); - void ban(FPlayer target, FPlayer banner); + void ban(FPlayer target, FPlayer banner); - void unban(FPlayer player); + void unban(FPlayer player); - boolean isBanned(FPlayer player); + boolean isBanned(FPlayer player); - Set getBannedPlayers(); + Set getBannedPlayers(); - HashMap getRulesMap(); + HashMap getRulesMap(); - void setRule(int index, String rule); + void setRule(int index, String rule); - void addRule(String rule); + void addRule(String rule); - void removeRule(int index); + void removeRule(int index); - void clearRules(); + void clearRules(); - Location getCheckpoint(); + Location getCheckpoint(); - void setCheckpoint(Location location); + void setCheckpoint(Location location); - void addTnt(int amt); + void addTnt(int amt); - void takeTnt(int amt); + void takeTnt(int amt); - Location getVault(); + Location getVault(); - void setVault(Location vaultLocation); + void setVault(Location vaultLocation); - Inventory getChestInventory(); + Inventory getChestInventory(); - void setChestSize(int chestSize); + void setChestSize(int chestSize); - void setBannerPattern(ItemStack banner); + void setBannerPattern(ItemStack banner); - ItemStack getBanner(); + ItemStack getBanner(); - int getTnt(); + int getTnt(); - String getRule(int index); + String getRule(int index); - boolean getOpen(); + boolean getOpen(); - void setOpen(boolean isOpen); + void setOpen(boolean isOpen); - boolean isPeaceful(); + boolean isPeaceful(); - void setPeaceful(boolean isPeaceful); + void setPeaceful(boolean isPeaceful); - boolean getPeacefulExplosionsEnabled(); + boolean getPeacefulExplosionsEnabled(); - void setPeacefulExplosionsEnabled(boolean val); + void setPeacefulExplosionsEnabled(boolean val); - boolean noExplosionsInTerritory(); + boolean noExplosionsInTerritory(); - boolean isPermanent(); + boolean isPermanent(); - void setPermanent(boolean isPermanent); + void setPermanent(boolean isPermanent); - String getTag(); + String getTag(); - void setTag(String str); + void setTag(String str); - String getTag(String prefix); + String getTag(String prefix); - String getTag(Faction otherFaction); + String getTag(Faction otherFaction); - String getTag(FPlayer otherFplayer); + String getTag(FPlayer otherFplayer); - String getComparisonTag(); + String getComparisonTag(); - String getDescription(); + String getDescription(); - void setDescription(String value); + void setDescription(String value); - boolean hasHome(); + boolean hasHome(); - Location getHome(); + Location getHome(); - void setHome(Location home); + void setHome(Location home); - long getFoundedDate(); + long getFoundedDate(); - void setFoundedDate(long newDate); + void setFoundedDate(long newDate); - void confirmValidHome(); + void confirmValidHome(); - String getAccountId(); + String getAccountId(); - Integer getPermanentPower(); + Integer getPermanentPower(); - void setPermanentPower(Integer permanentPower); + void setPermanentPower(Integer permanentPower); - boolean hasPermanentPower(); + boolean hasPermanentPower(); - double getPowerBoost(); + double getPowerBoost(); - void setPowerBoost(double powerBoost); + void setPowerBoost(double powerBoost); - boolean noPvPInTerritory(); + boolean noPvPInTerritory(); - boolean noMonstersInTerritory(); + boolean noMonstersInTerritory(); - boolean isNormal(); + boolean isNormal(); - @Deprecated - boolean isNone(); + @Deprecated + boolean isNone(); - boolean isWilderness(); + boolean isWilderness(); - boolean isSafeZone(); + boolean isSafeZone(); - boolean isWarZone(); + boolean isWarZone(); - boolean isPlayerFreeType(); + boolean isPlayerFreeType(); - boolean isPowerFrozen(); + boolean isPowerFrozen(); - void setLastDeath(long time); + void setLastDeath(long time); - int getKills(); + int getKills(); - int getDeaths(); + int getDeaths(); - Access getAccess(Permissable permissable, PermissableAction permissableAction); + Access getAccess(Permissable permissable, PermissableAction permissableAction); - Access getAccess(FPlayer player, PermissableAction permissableAction); + Access getAccess(FPlayer player, PermissableAction permissableAction); - void setPermission(Permissable permissable, PermissableAction permissableAction, Access access); + void setPermission(Permissable permissable, PermissableAction permissableAction, Access access); - void resetPerms(); - void setDefaultPerms(); + void resetPerms(); - void disband(Player disbander); + void setDefaultPerms(); - void disband(Player disbander, PlayerDisbandReason reason); + void disband(Player disbander); - // ------------------------------- - // Relation and relation colors - // ------------------------------- + void disband(Player disbander, PlayerDisbandReason reason); - Map> getPermissions(); + // ------------------------------- + // Relation and relation colors + // ------------------------------- - @Override - String describeTo(RelationParticipator that, boolean ucfirst); + Map> getPermissions(); - @Override - String describeTo(RelationParticipator that); + @Override + String describeTo(RelationParticipator that, boolean ucfirst); - @Override - Relation getRelationTo(RelationParticipator rp); + @Override + String describeTo(RelationParticipator that); - @Override - Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); + @Override + Relation getRelationTo(RelationParticipator rp); - @Override - ChatColor getColorTo(RelationParticipator rp); + @Override + Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); - Relation getRelationWish(Faction otherFaction); + @Override + ChatColor getColorTo(RelationParticipator rp); - void setRelationWish(Faction otherFaction, Relation relation); + Relation getRelationWish(Faction otherFaction); - int getRelationCount(Relation relation); + void setRelationWish(Faction otherFaction, Relation relation); - // ----------------------------------------------// - // Power - // ----------------------------------------------// - double getPower(); + int getRelationCount(Relation relation); - double getPowerMax(); + // ----------------------------------------------// + // Power + // ----------------------------------------------// + double getPower(); - int getPowerRounded(); + double getPowerMax(); - int getPowerMaxRounded(); + int getPowerRounded(); - int getLandRounded(); + int getPowerMaxRounded(); - int getLandRoundedInWorld(String worldName); + int getLandRounded(); - // ------------------------------- - // FPlayers - // ------------------------------- + int getLandRoundedInWorld(String worldName); - boolean hasLandInflation(); + // ------------------------------- + // FPlayers + // ------------------------------- - // maintain the reference list of FPlayers in this faction - void refreshFPlayers(); + boolean hasLandInflation(); - boolean addFPlayer(FPlayer fplayer); + // maintain the reference list of FPlayers in this faction + void refreshFPlayers(); - boolean removeFPlayer(FPlayer fplayer); + boolean addFPlayer(FPlayer fplayer); - int getSize(); + boolean removeFPlayer(FPlayer fplayer); - Set getFPlayers(); + int getSize(); - Set getFPlayersWhereOnline(boolean online); + Set getFPlayers(); - Set getFPlayersWhereOnline(boolean online, FPlayer viewer); + Set getFPlayersWhereOnline(boolean online); - FPlayer getFPlayerAdmin(); + Set getFPlayersWhereOnline(boolean online, FPlayer viewer); - FPlayer getFPlayerLeader(); + FPlayer getFPlayerAdmin(); - ArrayList getFPlayersWhereRole(Role role); + FPlayer getFPlayerLeader(); - ArrayList getOnlinePlayers(); + ArrayList getFPlayersWhereRole(Role role); - // slightly faster check than getOnlinePlayers() if you just want to see if - // there are any players online - boolean hasPlayersOnline(); + ArrayList getOnlinePlayers(); - void memberLoggedOff(); + // slightly faster check than getOnlinePlayers() if you just want to see if + // there are any players online + boolean hasPlayersOnline(); - // used when current leader is about to be removed from the faction; - // promotes new leader, or disbands faction if no other members left - void promoteNewLeader(); + void memberLoggedOff(); - void promoteNewLeader(boolean autoLeave); + // used when current leader is about to be removed from the faction; + // promotes new leader, or disbands faction if no other members left + void promoteNewLeader(); - Role getDefaultRole(); + void promoteNewLeader(boolean autoLeave); - void setDefaultRole(Role role); + Role getDefaultRole(); - // ----------------------------------------------// - // Messages - // ----------------------------------------------// - void msg(String message, Object... args); + void setDefaultRole(Role role); - void sendMessage(String message); + // ----------------------------------------------// + // Messages + // ----------------------------------------------// + void msg(String message, Object... args); - // ----------------------------------------------// - // Ownership of specific claims - // ----------------------------------------------// + void sendMessage(String message); - void sendMessage(List messages); + // ----------------------------------------------// + // Ownership of specific claims + // ----------------------------------------------// - Map> getClaimOwnership(); + void sendMessage(List messages); - void clearAllClaimOwnership(); + Map> getClaimOwnership(); - void clearClaimOwnership(FLocation loc); + void clearAllClaimOwnership(); - void clearClaimOwnership(FPlayer player); + void clearClaimOwnership(FLocation loc); - int getCountOfClaimsWithOwners(); + void clearClaimOwnership(FPlayer player); - boolean doesLocationHaveOwnersSet(FLocation loc); + int getCountOfClaimsWithOwners(); - boolean isPlayerInOwnerList(FPlayer player, FLocation loc); + boolean doesLocationHaveOwnersSet(FLocation loc); - void setPlayerAsOwner(FPlayer player, FLocation loc); + boolean isPlayerInOwnerList(FPlayer player, FLocation loc); - void removePlayerAsOwner(FPlayer player, FLocation loc); + void setPlayerAsOwner(FPlayer player, FLocation loc); - Set getOwnerList(FLocation loc); + void removePlayerAsOwner(FPlayer player, FLocation loc); - String getOwnerListString(FLocation loc); + Set getOwnerList(FLocation loc); - boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc); + String getOwnerListString(FLocation loc); - // ----------------------------------------------// - // Persistance and entity management - // ----------------------------------------------// - void remove(); + boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc); - Set getAllClaims(); + // ----------------------------------------------// + // Persistance and entity management + // ----------------------------------------------// + void remove(); - String getPaypal(); + Set getAllClaims(); - void paypalSet(String paypal); + String getPaypal(); + + void paypalSet(String paypal); } diff --git a/src/main/java/com/massivecraft/factions/Factions.java b/src/main/java/com/massivecraft/factions/Factions.java index 285da06c..b573c3cf 100644 --- a/src/main/java/com/massivecraft/factions/Factions.java +++ b/src/main/java/com/massivecraft/factions/Factions.java @@ -1,55 +1,55 @@ -package com.massivecraft.factions; - -import com.massivecraft.factions.zcore.persist.json.JSONFactions; - -import java.util.ArrayList; -import java.util.Set; - -public abstract class Factions { - protected static Factions instance = getFactionsImpl(); - - public static Factions getInstance() { - return instance; - } - - private static Factions getFactionsImpl() { - switch (Conf.backEnd) { - case JSON: - return new JSONFactions(); - } - return null; - } - - public abstract Faction getFactionById(String id); - - public abstract Faction getByTag(String str); - - public abstract Faction getBestTagMatch(String start); - - public abstract boolean isTagTaken(String str); - - public abstract boolean isValidFactionId(String id); - - public abstract Faction createFaction(); - - public abstract void removeFaction(String id); - - public abstract Set getFactionTags(); - - public abstract ArrayList getAllFactions(); - - @Deprecated - public abstract Faction getNone(); - - public abstract Faction getWilderness(); - - public abstract Faction getSafeZone(); - - public abstract Faction getWarZone(); - - public abstract void forceSave(); - - public abstract void forceSave(boolean sync); - - public abstract void load(); -} +package com.massivecraft.factions; + +import com.massivecraft.factions.zcore.persist.json.JSONFactions; + +import java.util.ArrayList; +import java.util.Set; + +public abstract class Factions { + protected static Factions instance = getFactionsImpl(); + + public static Factions getInstance() { + return instance; + } + + private static Factions getFactionsImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONFactions(); + } + return null; + } + + public abstract Faction getFactionById(String id); + + public abstract Faction getByTag(String str); + + public abstract Faction getBestTagMatch(String start); + + public abstract boolean isTagTaken(String str); + + public abstract boolean isValidFactionId(String id); + + public abstract Faction createFaction(); + + public abstract void removeFaction(String id); + + public abstract Set getFactionTags(); + + public abstract ArrayList getAllFactions(); + + @Deprecated + public abstract Faction getNone(); + + public abstract Faction getWilderness(); + + public abstract Faction getSafeZone(); + + public abstract Faction getWarZone(); + + public abstract void forceSave(); + + public abstract void forceSave(boolean sync); + + public abstract void load(); +} diff --git a/src/main/java/com/massivecraft/factions/MassiveStats.java b/src/main/java/com/massivecraft/factions/MassiveStats.java index babb89a8..a1f01e56 100644 --- a/src/main/java/com/massivecraft/factions/MassiveStats.java +++ b/src/main/java/com/massivecraft/factions/MassiveStats.java @@ -34,464 +34,464 @@ import java.net.URL; @SuppressWarnings("all") public class MassiveStats implements Listener { - /* START: MASSIVESTATS SETTINGS */ - public static final int CLIENT_VERSION = 0; // v3.0 - public static final String API_URL = "https://report.massivestats.com/v2/"; + /* START: MASSIVESTATS SETTINGS */ + public static final int CLIENT_VERSION = 0; // v3.0 + public static final String API_URL = "https://report.massivestats.com/v2/"; - public static final String MASSIVE_UPDATE_PERMISSION = "massivestats.update"; - /* END: MASSIVESTATS SETTINGS */ - private final JavaPlugin plugin; - private MassiveStatsUpdateTask task = null; - private int pingInterval; - private MassiveStatsDataResponse lastResponse; - private boolean listenerDisabled; - private Class jsonElement; - private Class jsonParser; - private Class jsonObject; - private Class jsonPrimitive; + public static final String MASSIVE_UPDATE_PERMISSION = "massivestats.update"; + /* END: MASSIVESTATS SETTINGS */ + private final JavaPlugin plugin; + private MassiveStatsUpdateTask task = null; + private int pingInterval; + private MassiveStatsDataResponse lastResponse; + private boolean listenerDisabled; + private Class jsonElement; + private Class jsonParser; + private Class jsonObject; + private Class jsonPrimitive; - /** - * @param plugin The plugin you wish to collect data for. - * @author Sam Jakob Harker - */ - public MassiveStats(JavaPlugin plugin) { - this(plugin, 900); // default value: 900 seconds (= 15 minutes) - } + /** + * @param plugin The plugin you wish to collect data for. + * @author Sam Jakob Harker + */ + public MassiveStats(JavaPlugin plugin) { + this(plugin, 900); // default value: 900 seconds (= 15 minutes) + } - /** - * @param plugin The plugin you wish to collect data for. - * @param pingInterval Duration between requests. - * @author Sam Jakob Harker - */ - public MassiveStats(JavaPlugin plugin, int pingInterval) { - try { - jsonElement = Class.forName("com.google.gson.JsonElement"); - jsonParser = Class.forName("com.google.gson.JsonParser"); - jsonObject = Class.forName("com.google.gson.JsonObject"); - jsonPrimitive = Class.forName("com.google.gson.JsonPrimitive"); - } catch (ClassNotFoundException ex) { - // Gson not included in classpath (so use NMS version) - try { - jsonElement = Class.forName("net.minecraft.util.com.google.gson.JsonElement"); - jsonParser = Class.forName("net.minecraft.util.com.google.gson.JsonParser"); - jsonObject = Class.forName("net.minecraft.util.com.google.gson.JsonObject"); - jsonPrimitive = Class.forName("net.minecraft.util.com.google.gson.JsonPrimitive"); - } catch (ClassNotFoundException ignored) { - Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use."); - this.plugin = null; - return; - } - } + /** + * @param plugin The plugin you wish to collect data for. + * @param pingInterval Duration between requests. + * @author Sam Jakob Harker + */ + public MassiveStats(JavaPlugin plugin, int pingInterval) { + try { + jsonElement = Class.forName("com.google.gson.JsonElement"); + jsonParser = Class.forName("com.google.gson.JsonParser"); + jsonObject = Class.forName("com.google.gson.JsonObject"); + jsonPrimitive = Class.forName("com.google.gson.JsonPrimitive"); + } catch (ClassNotFoundException ex) { + // Gson not included in classpath (so use NMS version) + try { + jsonElement = Class.forName("net.minecraft.util.com.google.gson.JsonElement"); + jsonParser = Class.forName("net.minecraft.util.com.google.gson.JsonParser"); + jsonObject = Class.forName("net.minecraft.util.com.google.gson.JsonObject"); + jsonPrimitive = Class.forName("net.minecraft.util.com.google.gson.JsonPrimitive"); + } catch (ClassNotFoundException ignored) { + Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use."); + this.plugin = null; + return; + } + } - // Ensure the pingInterval that is set is reasonable. - if (pingInterval < 10 || pingInterval > 86400) { - pingInterval = 900; - } + // Ensure the pingInterval that is set is reasonable. + if (pingInterval < 10 || pingInterval > 86400) { + pingInterval = 900; + } - // Ensure that a plugin instance has been provided. - if (plugin == null) { - throw new IllegalArgumentException("You must provide a plugin for MassiveStats to collect data for!"); - } + // Ensure that a plugin instance has been provided. + if (plugin == null) { + throw new IllegalArgumentException("You must provide a plugin for MassiveStats to collect data for!"); + } - // Set the ping interval. - this.pingInterval = pingInterval; - // Set the plugin reference. - this.plugin = plugin; - // and start sending data to the MassiveStats server immediately. - start(); + // Set the ping interval. + this.pingInterval = pingInterval; + // Set the plugin reference. + this.plugin = plugin; + // and start sending data to the MassiveStats server immediately. + start(); - // Register join/leave events for the plugin - Bukkit.getServer().getPluginManager().registerEvents(this, plugin); - } + // Register join/leave events for the plugin + Bukkit.getServer().getPluginManager().registerEvents(this, plugin); + } - /** - * Gets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. - * - * @return Whether or not the MassiveStats listener is enabled. - */ - public boolean isListenerDisabled() { - return listenerDisabled; - } + /** + * Gets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. + * + * @return Whether or not the MassiveStats listener is enabled. + */ + public boolean isListenerDisabled() { + return listenerDisabled; + } - /** - * Sets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. - * - * @param listenerDisabled Whether or not the MassiveStats listener is enabled. - */ - public void setListenerDisabled(boolean listenerDisabled) { - this.listenerDisabled = listenerDisabled; - } + /** + * Sets whether or not the built-in MassiveStats {@link org.bukkit.event.player.PlayerJoinEvent} listener is enabled. + * + * @param listenerDisabled Whether or not the MassiveStats listener is enabled. + */ + public void setListenerDisabled(boolean listenerDisabled) { + this.listenerDisabled = listenerDisabled; + } - /** - * Start the MassiveStats reporting timer. - * If the timer is already running, this method will do nothing. - * - * @author Sam Jakob Harker - */ - public void start() { - if (this.plugin == null) { - Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use and thus cannot start."); - return; - } + /** + * Start the MassiveStats reporting timer. + * If the timer is already running, this method will do nothing. + * + * @author Sam Jakob Harker + */ + public void start() { + if (this.plugin == null) { + Bukkit.getLogger().severe("MassiveStats could not find an instance/version of Gson to use and thus cannot start."); + return; + } - if (task == null) { - // If the API endpoint URL is invalid, don't start a new task to prevent the user from being spammed. - try { - new URL(MassiveStats.API_URL); - } catch (MalformedURLException ex) { - getPlugin() - .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); - return; - } + if (task == null) { + // If the API endpoint URL is invalid, don't start a new task to prevent the user from being spammed. + try { + new URL(MassiveStats.API_URL); + } catch (MalformedURLException ex) { + getPlugin() + .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); + return; + } - task = new MassiveStatsUpdateTask(this); - task.runTaskTimerAsynchronously(plugin, 0L, pingInterval * 20L); - } - } + task = new MassiveStatsUpdateTask(this); + task.runTaskTimerAsynchronously(plugin, 0L, pingInterval * 20L); + } + } - /** - * Stop the MassiveStats reporting timer. - * Requests will no longer be sent to the server - or until {@link #start()} is invoked. - * - * @author Sam Jakob Harker - */ - public void stop() { - if (task == null) { - return; - } + /** + * Stop the MassiveStats reporting timer. + * Requests will no longer be sent to the server - or until {@link #start()} is invoked. + * + * @author Sam Jakob Harker + */ + public void stop() { + if (task == null) { + return; + } - task.cancel(); - task = null; - } + task.cancel(); + task = null; + } - /** - * Returns the duration, in seconds, that MassiveStats will wait before sending another request to the server. - * - * @return Duration between requests. - * @author Sam Jakob Harker - */ - public int getPingInterval() { - return pingInterval; - } + /** + * Returns the duration, in seconds, that MassiveStats will wait before sending another request to the server. + * + * @return Duration between requests. + * @author Sam Jakob Harker + */ + public int getPingInterval() { + return pingInterval; + } - /** - * Sets the duration, in seconds, that MassiveStats should wait before sending another request to the server. - * - * @param pingInterval Duration between requests. - * @author Sam Jakob Harker - */ - public void setPingInterval(int pingInterval) { - this.pingInterval = pingInterval; + /** + * Sets the duration, in seconds, that MassiveStats should wait before sending another request to the server. + * + * @param pingInterval Duration between requests. + * @author Sam Jakob Harker + */ + public void setPingInterval(int pingInterval) { + this.pingInterval = pingInterval; - stop(); - start(); - } + stop(); + start(); + } - /** - * Returns the plugin that this MassiveStats instance is collecting data for. - * - * @return MassiveStats instance plugin. - * @author Sam Jakob Harker - */ - public JavaPlugin getPlugin() { - return plugin; - } + /** + * Returns the plugin that this MassiveStats instance is collecting data for. + * + * @return MassiveStats instance plugin. + * @author Sam Jakob Harker + */ + public JavaPlugin getPlugin() { + return plugin; + } - /** - * Returns the contents of the last response from the MassiveStats server. - * - * @return MassiveStats server response. - * @author Sam Jakob Harker - */ - public MassiveStatsDataResponse getLastResponse() { - return lastResponse; - } + /** + * Returns the contents of the last response from the MassiveStats server. + * + * @return MassiveStats server response. + * @author Sam Jakob Harker + */ + public MassiveStatsDataResponse getLastResponse() { + return lastResponse; + } - void setLastResponse(MassiveStatsDataResponse lastResponse) { - this.lastResponse = lastResponse; - } + void setLastResponse(MassiveStatsDataResponse lastResponse) { + this.lastResponse = lastResponse; + } - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - // Ensure the listener should be active - if (lastResponse == null || listenerDisabled) { - return; - } + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + // Ensure the listener should be active + if (lastResponse == null || listenerDisabled) { + return; + } - // Of course, only notify the user if the plugin is not up to date. - if (lastResponse.isUpToDate()) { - return; - } + // Of course, only notify the user if the plugin is not up to date. + if (lastResponse.isUpToDate()) { + return; + } - // and only notify operators - or players with the correct permission. - if (!event.getPlayer().isOp() && !event.getPlayer().hasPermission(MassiveStats.MASSIVE_UPDATE_PERMISSION)) { - return; - } + // and only notify operators - or players with the correct permission. + if (!event.getPlayer().isOp() && !event.getPlayer().hasPermission(MassiveStats.MASSIVE_UPDATE_PERMISSION)) { + return; + } - event.getPlayer().sendMessage(lastResponse.getUpdateMessage()); - } + event.getPlayer().sendMessage(lastResponse.getUpdateMessage()); + } - Class getJsonElement() { - return jsonElement; - } + Class getJsonElement() { + return jsonElement; + } - Class getJsonParser() { - return jsonParser; - } + Class getJsonParser() { + return jsonParser; + } - Class getJsonObject() { - return jsonObject; - } + Class getJsonObject() { + return jsonObject; + } - Class getJsonPrimitive() { - return jsonPrimitive; - } + Class getJsonPrimitive() { + return jsonPrimitive; + } } class MassiveStatsUpdateTask extends BukkitRunnable { - private final MassiveStats instance; + private final MassiveStats instance; - MassiveStatsUpdateTask(MassiveStats requester) { - instance = requester; - } + MassiveStatsUpdateTask(MassiveStats requester) { + instance = requester; + } - @Override - @SuppressWarnings("all") - public void run() { - try { - // Generate the request payload and serialize it as JSON. - String payload = new MassiveStatsDataRequest(instance).serialize(); + @Override + @SuppressWarnings("all") + public void run() { + try { + // Generate the request payload and serialize it as JSON. + String payload = new MassiveStatsDataRequest(instance).serialize(); - // Then create a new HttpsUrlConnection to the API server and open it. - HttpsURLConnection connection = (HttpsURLConnection) new URL(MassiveStats.API_URL).openConnection(); + // Then create a new HttpsUrlConnection to the API server and open it. + HttpsURLConnection connection = (HttpsURLConnection) new URL(MassiveStats.API_URL).openConnection(); - // Ensure that we don't hang the server with our 'dang shenanigans'. - connection.setConnectTimeout(2500); - connection.setReadTimeout(3500); + // Ensure that we don't hang the server with our 'dang shenanigans'. + connection.setConnectTimeout(2500); + connection.setReadTimeout(3500); - // Set the all-important request headers before we begin POSTing... - connection.setRequestMethod("POST"); - connection.setRequestProperty("Accept", "application/json"); - connection.setRequestProperty("Content-Type", "application/json; charset=utf-8"); - connection.setRequestProperty("User-Agent", "Massive/" + MassiveStats.CLIENT_VERSION); + // Set the all-important request headers before we begin POSTing... + connection.setRequestMethod("POST"); + connection.setRequestProperty("Accept", "application/json"); + connection.setRequestProperty("Content-Type", "application/json; charset=utf-8"); + connection.setRequestProperty("User-Agent", "Massive/" + MassiveStats.CLIENT_VERSION); - // Open the output stream, write the payload, and then close the stream. - connection.setDoOutput(true); - DataOutputStream output = new DataOutputStream(connection.getOutputStream()); - output.writeBytes(payload); - output.flush(); - output.close(); + // Open the output stream, write the payload, and then close the stream. + connection.setDoOutput(true); + DataOutputStream output = new DataOutputStream(connection.getOutputStream()); + output.writeBytes(payload); + output.flush(); + output.close(); - // Ensure that the server was happy with our data. - int responseCode = connection.getResponseCode(); - if (responseCode != 200) { - throw new IOException(); - } + // Ensure that the server was happy with our data. + int responseCode = connection.getResponseCode(); + if (responseCode != 200) { + throw new IOException(); + } - // Now, read the server's response to our payload... - BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream())); - StringBuilder response = new StringBuilder(); + // Now, read the server's response to our payload... + BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder response = new StringBuilder(); - // ...line by line. - String line; - while ((line = input.readLine()) != null) { - response.append(line); - } - input.close(); + // ...line by line. + String line; + while ((line = input.readLine()) != null) { + response.append(line); + } + input.close(); - // Now, we parse the JSON object. - try { - if (response.toString().contains("ERR_DATA_MISSING")) { - Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " - + instance.getPlugin().getName()); - instance.stop(); - return; - } + // Now, we parse the JSON object. + try { + if (response.toString().contains("ERR_DATA_MISSING")) { + Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " + + instance.getPlugin().getName()); + instance.stop(); + return; + } - Object parser = instance.getJsonParser().newInstance(); + Object parser = instance.getJsonParser().newInstance(); - // JsonElement - Object serverResponseRaw = - parser.getClass().getMethod("parse", String.class).invoke(parser, response.toString()); + // JsonElement + Object serverResponseRaw = + parser.getClass().getMethod("parse", String.class).invoke(parser, response.toString()); - // JsonObject - Object serverResponse = serverResponseRaw.getClass().getMethod("getAsJsonObject", null) - .invoke(serverResponseRaw, null); + // JsonObject + Object serverResponse = serverResponseRaw.getClass().getMethod("getAsJsonObject", null) + .invoke(serverResponseRaw, null); - Method serverResponseGet = instance.getJsonObject().getMethod("get", String.class); + Method serverResponseGet = instance.getJsonObject().getMethod("get", String.class); - Method getAsBoolean = - instance.getJsonPrimitive().getMethod("getAsBoolean", null); - Method getAsString = - instance.getJsonPrimitive().getMethod("getAsString", null); + Method getAsBoolean = + instance.getJsonPrimitive().getMethod("getAsBoolean", null); + Method getAsString = + instance.getJsonPrimitive().getMethod("getAsString", null); - if (serverResponseGet.invoke(serverResponse, "upToDate") == null) { - Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " - + instance.getPlugin().getName()); - instance.stop(); - return; - } + if (serverResponseGet.invoke(serverResponse, "upToDate") == null) { + Bukkit.getLogger().severe("MassiveStats has encountered an error for the following plugin: " + + instance.getPlugin().getName()); + instance.stop(); + return; + } - if (serverResponseGet.invoke(serverResponse, "notice") != null) { - Bukkit.getLogger().severe( - (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "notice")) - ); - instance.stop(); - return; - } + if (serverResponseGet.invoke(serverResponse, "notice") != null) { + Bukkit.getLogger().severe( + (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "notice")) + ); + instance.stop(); + return; + } - boolean upToDate = (boolean) getAsBoolean.invoke(serverResponseGet.invoke(serverResponse, "upToDate"), null); - String latestVersion = (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "latestVersion"), null); - String updateMessage = ChatColor.translateAlternateColorCodes( - '&', (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "updateMessage"), null) - ); + boolean upToDate = (boolean) getAsBoolean.invoke(serverResponseGet.invoke(serverResponse, "upToDate"), null); + String latestVersion = (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "latestVersion"), null); + String updateMessage = ChatColor.translateAlternateColorCodes( + '&', (String) getAsString.invoke(serverResponseGet.invoke(serverResponse, "updateMessage"), null) + ); - instance.setLastResponse(new MassiveStatsDataResponse( - upToDate, latestVersion, updateMessage - )); + instance.setLastResponse(new MassiveStatsDataResponse( + upToDate, latestVersion, updateMessage + )); - } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { - instance.getPlugin() - .getLogger().warning("MassiveStats returned an invalid response for this plugin."); - } + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { + instance.getPlugin() + .getLogger().warning("MassiveStats returned an invalid response for this plugin."); + } - // Finally, call an event to mark the update. - } catch (MalformedURLException ex) { - instance.getPlugin() - .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); - } catch (IOException ex) { - instance.getPlugin() - .getLogger().warning("MassiveStats was unable to communicate with its API endpoint."); - } - } + // Finally, call an event to mark the update. + } catch (MalformedURLException ex) { + instance.getPlugin() + .getLogger().warning("You have specified an invalid API endpoint for MassiveStats."); + } catch (IOException ex) { + instance.getPlugin() + .getLogger().warning("MassiveStats was unable to communicate with its API endpoint."); + } + } } class MassiveStatsDataRequest { - private Object jsonObject; + private Object jsonObject; - MassiveStatsDataRequest(MassiveStats requester) { - try { - jsonObject = requester.getJsonObject().newInstance(); + MassiveStatsDataRequest(MassiveStats requester) { + try { + jsonObject = requester.getJsonObject().newInstance(); - Method add = - requester.getJsonObject().newInstance().getClass().getMethod("add", String.class, requester.getJsonElement()); - Method addPropertyString = - requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, String.class); - Method addPropertyNumber = - requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Number.class); - Method addPropertyBoolean = - requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Boolean.class); + Method add = + requester.getJsonObject().newInstance().getClass().getMethod("add", String.class, requester.getJsonElement()); + Method addPropertyString = + requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, String.class); + Method addPropertyNumber = + requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Number.class); + Method addPropertyBoolean = + requester.getJsonObject().newInstance().getClass().getMethod("addProperty", String.class, Boolean.class); - addPropertyNumber.invoke(jsonObject, "now", System.currentTimeMillis()); + addPropertyNumber.invoke(jsonObject, "now", System.currentTimeMillis()); - /* PLUGIN DATA */ - Object pluginObject = jsonObject.getClass().newInstance(); - addPropertyString.invoke(pluginObject, "name", requester.getPlugin().getDescription().getName()); - addPropertyString.invoke(pluginObject, "version", requester.getPlugin().getDescription().getVersion()); - add.invoke(jsonObject, "plugin", pluginObject); + /* PLUGIN DATA */ + Object pluginObject = jsonObject.getClass().newInstance(); + addPropertyString.invoke(pluginObject, "name", requester.getPlugin().getDescription().getName()); + addPropertyString.invoke(pluginObject, "version", requester.getPlugin().getDescription().getVersion()); + add.invoke(jsonObject, "plugin", pluginObject); - /* SERVER DATA */ - Object minecraftServerObject = jsonObject.getClass().newInstance(); - addPropertyNumber.invoke(minecraftServerObject, "players", Bukkit.getServer().getOnlinePlayers().size()); - addPropertyBoolean.invoke(minecraftServerObject, "onlineMode", Bukkit.getServer().getOnlineMode()); - addPropertyString.invoke(minecraftServerObject, "version", Bukkit.getServer().getVersion()); + /* SERVER DATA */ + Object minecraftServerObject = jsonObject.getClass().newInstance(); + addPropertyNumber.invoke(minecraftServerObject, "players", Bukkit.getServer().getOnlinePlayers().size()); + addPropertyBoolean.invoke(minecraftServerObject, "onlineMode", Bukkit.getServer().getOnlineMode()); + addPropertyString.invoke(minecraftServerObject, "version", Bukkit.getServer().getVersion()); - Object javaServerObject = jsonObject.getClass().newInstance(); - addPropertyString.invoke(javaServerObject, "version", System.getProperty("java.version")); + Object javaServerObject = jsonObject.getClass().newInstance(); + addPropertyString.invoke(javaServerObject, "version", System.getProperty("java.version")); - Object osServerObject = jsonObject.getClass().newInstance(); - addPropertyString.invoke(osServerObject, "name", System.getProperty("os.name")); - addPropertyString.invoke(osServerObject, "arch", System.getProperty("os.arch")); - addPropertyString.invoke(osServerObject, "version", System.getProperty("os.version")); + Object osServerObject = jsonObject.getClass().newInstance(); + addPropertyString.invoke(osServerObject, "name", System.getProperty("os.name")); + addPropertyString.invoke(osServerObject, "arch", System.getProperty("os.arch")); + addPropertyString.invoke(osServerObject, "version", System.getProperty("os.version")); - Object hardwareServerObject = jsonObject.getClass().newInstance(); - addPropertyNumber.invoke(hardwareServerObject, "cores", Runtime.getRuntime().availableProcessors()); + Object hardwareServerObject = jsonObject.getClass().newInstance(); + addPropertyNumber.invoke(hardwareServerObject, "cores", Runtime.getRuntime().availableProcessors()); - Object serverObject = jsonObject.getClass().newInstance(); - add.invoke(serverObject, "minecraft", minecraftServerObject); - add.invoke(serverObject, "java", javaServerObject); - add.invoke(serverObject, "os", osServerObject); - add.invoke(serverObject, "hardware", hardwareServerObject); + Object serverObject = jsonObject.getClass().newInstance(); + add.invoke(serverObject, "minecraft", minecraftServerObject); + add.invoke(serverObject, "java", javaServerObject); + add.invoke(serverObject, "os", osServerObject); + add.invoke(serverObject, "hardware", hardwareServerObject); - add.invoke(jsonObject, "server", serverObject); + add.invoke(jsonObject, "server", serverObject); - /* MASSIVE DATA */ - Object massiveObject = jsonObject.getClass().newInstance(); - addPropertyNumber.invoke(massiveObject, "version", MassiveStats.CLIENT_VERSION); - addPropertyNumber.invoke(massiveObject, "pingInterval", requester.getPingInterval()); + /* MASSIVE DATA */ + Object massiveObject = jsonObject.getClass().newInstance(); + addPropertyNumber.invoke(massiveObject, "version", MassiveStats.CLIENT_VERSION); + addPropertyNumber.invoke(massiveObject, "pingInterval", requester.getPingInterval()); - //object.add("Massive", massiveObject); - add.invoke(jsonObject, "Massive", massiveObject); - } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { - e.printStackTrace(); - } - } + //object.add("Massive", massiveObject); + add.invoke(jsonObject, "Massive", massiveObject); + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + } + } - @SuppressWarnings("all") - public String serialize() { - //return object.toString(); - try { - Method toString = jsonObject.getClass().getMethod("toString", null); - return (String) toString.invoke(jsonObject); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } + @SuppressWarnings("all") + public String serialize() { + //return object.toString(); + try { + Method toString = jsonObject.getClass().getMethod("toString", null); + return (String) toString.invoke(jsonObject); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } - return null; - } + return null; + } } final class MassiveStatsDataResponse { - private final boolean isUpToDate; - private final String newVersion; - private final String updateMessage; + private final boolean isUpToDate; + private final String newVersion; + private final String updateMessage; - MassiveStatsDataResponse(boolean isUpToDate, String newVersion, String updateMessage) { - this.isUpToDate = isUpToDate; + MassiveStatsDataResponse(boolean isUpToDate, String newVersion, String updateMessage) { + this.isUpToDate = isUpToDate; - if (!isUpToDate) { - this.newVersion = newVersion; - this.updateMessage = updateMessage; - return; - } + if (!isUpToDate) { + this.newVersion = newVersion; + this.updateMessage = updateMessage; + return; + } - this.newVersion = null; - this.updateMessage = null; - } + this.newVersion = null; + this.updateMessage = null; + } - /** - * Indicates whether or not this version of the plugin is the latest. - * True = This is the latest version of the plugin. - * False = There is an update available. - * - * @return Whether or not there is an update available. - */ - public boolean isUpToDate() { - return isUpToDate; - } + /** + * Indicates whether or not this version of the plugin is the latest. + * True = This is the latest version of the plugin. + * False = There is an update available. + * + * @return Whether or not there is an update available. + */ + public boolean isUpToDate() { + return isUpToDate; + } - /** - * Gets the name of the latest version. If this is the latest version, it returns null. - * - * @return The name of the latest version. - */ - public String getLatestVersion() { - return newVersion; - } + /** + * Gets the name of the latest version. If this is the latest version, it returns null. + * + * @return The name of the latest version. + */ + public String getLatestVersion() { + return newVersion; + } - /** - * Gets the message to display, convincing the user to update to the new version of the plugin. - * - * @return The update message to display. - */ - public String getUpdateMessage() { - return updateMessage; - } + /** + * Gets the message to display, convincing the user to update to the new version of the plugin. + * + * @return The update message to display. + */ + public String getUpdateMessage() { + return updateMessage; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/SavageFactions.java b/src/main/java/com/massivecraft/factions/SavageFactions.java index c580400f..bb7f7e2e 100644 --- a/src/main/java/com/massivecraft/factions/SavageFactions.java +++ b/src/main/java/com/massivecraft/factions/SavageFactions.java @@ -52,705 +52,705 @@ import java.util.stream.Collectors; public class SavageFactions extends MPlugin { - // Our single plugin instance. - // Single 4 life. - public static SavageFactions plugin; - public static Permission perms = null; - // Persistence related - public static ArrayList playersFlying = new ArrayList(); - public Essentials ess; - public boolean PlaceholderApi; - // Commands - public FCmdRoot cmdBase; - public CmdAutoHelp cmdAutoHelp; - public boolean mc17 = false; - public boolean mc18 = false; - public boolean mc113 = false; - public boolean useNonPacketParticles = false; - public boolean factionsFlight = false; - //multiversion material fields - public Material SUGAR_CANE_BLOCK, BANNER, CROPS, REDSTONE_LAMP_ON, - STAINED_GLASS, STATIONARY_WATER, STAINED_CLAY, WOOD_BUTTON, - SOIL, MOB_SPANWER, THIN_GLASS, IRON_FENCE, NETHER_FENCE, FENCE, - WOODEN_DOOR, TRAP_DOOR, FENCE_GATE, BURNING_FURNACE, DIODE_BLOCK_OFF, - DIODE_BLOCK_ON, ENCHANTMENT_TABLE, FIREBALL; - SkriptAddon skriptAddon; - private boolean locked = false; - private Integer AutoLeaveTask = null; - private boolean hookedPlayervaults; - private ClipPlaceholderAPIManager clipPlaceholderAPIManager; - private boolean mvdwPlaceholderAPIManager = false; - private Listener[] eventsListener; - - public SavageFactions() { - plugin = this; - } - - public boolean getLocked() { - return this.locked; - } - - public void setLocked(boolean val) { - this.locked = val; - this.setAutoSave(val); - } - - public void playSoundForAll(String sound) { - for (Player pl : Bukkit.getOnlinePlayers()) { - playSound(pl, sound); - } - } - - public void playSoundForAll(List sounds) { - for (Player pl : Bukkit.getOnlinePlayers()) { - playSound(pl, sounds); - } - } - - public void playSound(Player p, List sounds) { - for (String sound : sounds) { - playSound(p, sound); - } - } - - public void playSound(Player p, String sound) { - float pitch = Float.valueOf(sound.split(":")[1]); - sound = sound.split(":")[0]; - p.playSound(p.getLocation(), Sound.valueOf(sound), pitch, 5.0F); - } - - @Override - public void onEnable() { - log("==== Setup ===="); - - - // Vault dependency check. - if (getServer().getPluginManager().getPlugin("Vault") == null) { - log("Vault is not present, the plugin will not run properly."); - getServer().getPluginManager().disablePlugin(plugin); - return; - } - - int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); - if (version == 7) { - SavageFactions.plugin.log("Minecraft Version 1.7 found, disabling banners, itemflags inside GUIs, and Titles."); - mc17 = true; - } else if (version == 8) { - SavageFactions.plugin.log("Minecraft Version 1.8 found, Title Fadeouttime etc will not be configurable."); - mc18 = true; - } else if (version == 13) { - SavageFactions.plugin.log("Minecraft Version 1.13 found, New Items will be used."); - mc113 = true; - changeItemIDSInConfig(); - } - setupMultiversionMaterials(); - migrateFPlayerLeaders(); - log("==== End Setup ===="); - - if (!preEnable()) { - return; - } - this.loadSuccessful = false; - - saveDefaultConfig(); - - // Load Conf from disk - Conf.load(); - com.massivecraft.factions.integration.Essentials.setup(); - hookedPlayervaults = setupPlayervaults(); - FPlayers.getInstance().load(); - Factions.getInstance().load(); - - for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { - Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); - if (faction == null) { - log("Invalid faction id on " + fPlayer.getName() + ":" + fPlayer.getFactionId()); - fPlayer.resetFactionData(false); - continue; - } - faction.addFPlayer(fPlayer); - } - playersFlying.clear(); - for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { - playersFlying.add(fPlayer); - } - UtilFly.run(); - - Board.getInstance().load(); - Board.getInstance().clean(); - - // Add Base Commands - this.cmdBase = new FCmdRoot(); - this.cmdAutoHelp = new CmdAutoHelp(); - this.getBaseCommands().add(cmdBase); - - Econ.setup(); - setupPermissions(); - - if (Conf.worldGuardChecking || Conf.worldGuardBuildPriority) { - Worldguard.init(this); - } - - EngineDynmap.getInstance().init(); - - // start up task which runs the autoLeaveAfterDaysOfInactivity routine - startAutoLeaveTask(false); - - if (getConfig().getBoolean("MassiveStats")) { - // massive stats - new MassiveStats(this); - } - - if (version > 8) { - useNonPacketParticles = true; - log("Minecraft Version 1.9 or higher found, using non packet based particle API"); - } - - if (getConfig().getBoolean("enable-faction-flight")) { - factionsFlight = true; - } - - if (getServer().getPluginManager().getPlugin("Skript") != null) { - log("Skript was found! Registering SavageFactions Addon..."); - skriptAddon = Skript.registerAddon(this); - try { - skriptAddon.loadClasses("com.massivecraft.factions.skript", "expressions"); - } catch (IOException ex) { - ex.printStackTrace(); - } - log("Skript addon registered!"); - } - - - // Register Event Handlers - eventsListener = new Listener[]{ - new FactionsPlayerListener(), - new FactionsChatListener(), - new FactionsEntityListener(), - new FactionsExploitListener(), - new FactionsBlockListener(), - new FUpgradesGUI(), - new EXPUpgrade(), - new CropUpgrades(), - new SpawnerUpgrades(), - }; - - for (Listener eventListener : eventsListener) - getServer().getPluginManager().registerEvents(eventListener, this); - - // since some other plugins execute commands directly through this command interface, provide it - getCommand(this.refCommand).setExecutor(this); - getCommand(this.refCommand).setTabCompleter(this); - - setupEssentials(); - - if (getDescription().getFullName().contains("BETA")) { - divider(); - System.out.println("You are using a BETA version of the plugin!"); - System.out.println("This comes with risks of small bugs in newer features!"); - System.out.println("For support head to: https://github.com/ProSavage/SavageFactions/issues"); - divider(); - } - - this.setupPlaceholderAPI(); - this.postEnable(); - this.loadSuccessful = true; - } - - public SkriptAddon getSkriptAddon() { - return skriptAddon; - } - - private void setupMultiversionMaterials() { - if (mc113) { - BANNER = Material.valueOf("LEGACY_BANNER"); - CROPS = Material.valueOf("LEGACY_CROPS"); - SUGAR_CANE_BLOCK = Material.valueOf("LEGACY_SUGAR_CANE_BLOCK"); - REDSTONE_LAMP_ON = Material.valueOf("LEGACY_REDSTONE_LAMP_ON"); - STAINED_GLASS = Material.valueOf("LEGACY_STAINED_GLASS"); - STATIONARY_WATER = Material.valueOf("LEGACY_STATIONARY_WATER"); - STAINED_CLAY = Material.valueOf("LEGACY_STAINED_CLAY"); - WOOD_BUTTON = Material.valueOf("LEGACY_WOOD_BUTTON"); - SOIL = Material.valueOf("LEGACY_SOIL"); - MOB_SPANWER = Material.valueOf("LEGACY_MOB_SPAWNER"); - THIN_GLASS = Material.valueOf("LEGACY_THIN_GLASS"); - IRON_FENCE = Material.valueOf("LEGACY_IRON_FENCE"); - NETHER_FENCE = Material.valueOf("LEGACY_NETHER_FENCE"); - FENCE = Material.valueOf("LEGACY_FENCE"); - WOODEN_DOOR = Material.valueOf("LEGACY_WOODEN_DOOR"); - TRAP_DOOR = Material.valueOf("LEGACY_TRAP_DOOR"); - FENCE_GATE = Material.valueOf("LEGACY_FENCE_GATE"); - BURNING_FURNACE = Material.valueOf("LEGACY_BURNING_FURNACE"); - DIODE_BLOCK_OFF = Material.valueOf("LEGACY_DIODE_BLOCK_OFF"); - DIODE_BLOCK_ON = Material.valueOf("LEGACY_DIODE_BLOCK_ON"); - ENCHANTMENT_TABLE = Material.valueOf("LEGACY_ENCHANTMENT_TABLE"); - FIREBALL = Material.valueOf("LEGACY_FIREBALL"); - - } else { - if (!mc17) { - BANNER = Material.valueOf("BANNER"); - } - CROPS = Material.valueOf("CROPS"); - SUGAR_CANE_BLOCK = Material.valueOf("SUGAR_CANE_BLOCK"); - REDSTONE_LAMP_ON = Material.valueOf("REDSTONE_LAMP_ON"); - STAINED_GLASS = Material.valueOf("STAINED_GLASS"); - STATIONARY_WATER = Material.valueOf("STATIONARY_WATER"); - STAINED_CLAY = Material.valueOf("STAINED_CLAY"); - WOOD_BUTTON = Material.valueOf("WOOD_BUTTON"); - SOIL = Material.valueOf("SOIL"); - MOB_SPANWER = Material.valueOf("MOB_SPAWNER"); - THIN_GLASS = Material.valueOf("THIN_GLASS"); - IRON_FENCE = Material.valueOf("IRON_FENCE"); - NETHER_FENCE = Material.valueOf("NETHER_FENCE"); - FENCE = Material.valueOf("FENCE"); - WOODEN_DOOR = Material.valueOf("WOODEN_DOOR"); - TRAP_DOOR = Material.valueOf("TRAP_DOOR"); - FENCE_GATE = Material.valueOf("FENCE_GATE"); - BURNING_FURNACE = Material.valueOf("BURNING_FURNACE"); - DIODE_BLOCK_OFF = Material.valueOf("DIODE_BLOCK_OFF"); - DIODE_BLOCK_ON = Material.valueOf("DIODE_BLOCK_ON"); - ENCHANTMENT_TABLE = Material.valueOf("ENCHANTMENT_TABLE"); - FIREBALL = Material.valueOf("FIREBALL"); - } - - } - - private void setupPlaceholderAPI() { - Plugin clip = getServer().getPluginManager().getPlugin("PlaceholderAPI"); - if (clip != null && clip.isEnabled()) { - this.clipPlaceholderAPIManager = new ClipPlaceholderAPIManager(); - if (this.clipPlaceholderAPIManager.register()) { - PlaceholderApi = true; - log(Level.INFO, "Successfully registered placeholders with PlaceholderAPI."); - } else { - PlaceholderApi = false; - } - } else { - PlaceholderApi = false; - } - - Plugin mvdw = getServer().getPluginManager().getPlugin("MVdWPlaceholderAPI"); - if (mvdw != null && mvdw.isEnabled()) { - this.mvdwPlaceholderAPIManager = true; - log(Level.INFO, "Found MVdWPlaceholderAPI. Adding hooks."); - } - } - - private void migrateFPlayerLeaders() { - List lines = new ArrayList<>(); - File fplayerFile = new File("plugins\\Factions\\players.json"); - - try { - BufferedReader br = new BufferedReader(new FileReader(fplayerFile)); - System.out.println("Migrating old players.json file."); - - String line; - while ((line = br.readLine()) != null) { - if (line.contains("\"role\": \"ADMIN\"")) { - line = line.replace("\"role\": \"ADMIN\"", "\"role\": " + "\"LEADER\""); - } - lines.add(line); - } - br.close(); - BufferedWriter bw = new BufferedWriter(new FileWriter(fplayerFile)); - for (String newLine : lines) { - bw.write(newLine + "\n"); - } - bw.flush(); - bw.close(); - } catch (IOException ex) { - System.out.println("File was not found for players.json, assuming" - + " there is no need to migrate old players.json file."); - } - } - - public void changeItemIDSInConfig() { - log("Starting conversion of legacy material in config to 1.13 materials."); - - replaceStringInConfig("fperm-gui.relation.materials.recruit", "WOOD_SWORD", "WOODEN_SWORD"); - replaceStringInConfig("fperm-gui.relation.materials.normal", "GOLD_SWORD", "GOLDEN_SWORD"); - replaceStringInConfig("fperm-gui.relation.materials.ally", "GOLD_AXE", "GOLDEN_AXE"); - replaceStringInConfig("fperm-gui.relation.materials.neutral", "WOOD_AXE", "WOODEN_AXE"); - - ConfigurationSection actionMaterialsConfigSection = getConfig().getConfigurationSection("fperm-gui.action.materials"); - Set actionMaterialKeys = actionMaterialsConfigSection.getKeys(true); - - - for (String key : actionMaterialKeys) { - replaceStringInConfig("fperm-gui.action.materials." + key, "STAINED_GLASS", "GRAY_STAINED_GLASS"); - } - - replaceStringInConfig("fperm-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); - replaceStringInConfig("fwarp-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); - - replaceStringInConfig("fupgrades.MainMenu.DummyItem.Type", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); - replaceStringInConfig("fupgrades.MainMenu.EXP.EXPItem.Type", "EXP_BOTTLE", "EXPERIENCE_BOTTLE"); - replaceStringInConfig("fupgrades.MainMenu.Spawners.SpawnerItem.Type", "MOB_SPAWNER", "SPAWNER"); - - replaceStringInConfig("fperm-gui.action.access.allow", "LIME", "LIME_STAINED_GLASS"); - replaceStringInConfig("fperm-gui.action.access.deny", "RED", "RED_STAINED_GLASS"); - replaceStringInConfig("fperm-gui.action.access.undefined", "CYAN", "CYAN_STAINED_GLASS"); - } - - public void replaceStringInConfig(String path, String stringToReplace, String replacementString) { - if (getConfig().getString(path).equals(stringToReplace)) { - // SavageFactions.plugin.log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); - // log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); - - getConfig().set(path, replacementString); - } - } - - public boolean isClipPlaceholderAPIHooked() { - return this.clipPlaceholderAPIManager != null; - } - - public boolean isMVdWPlaceholderAPIHooked() { - return this.mvdwPlaceholderAPIManager; - } - - private boolean setupPermissions() { - try { - RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Permission.class); - if (rsp != null) { - perms = rsp.getProvider(); - } - } catch (NoClassDefFoundError ex) { - return false; - } - return perms != null; - } - - private boolean setupPlayervaults() { - Plugin plugin = getServer().getPluginManager().getPlugin("PlayerVaults"); - return plugin != null && plugin.isEnabled(); - } - - @Override - public GsonBuilder getGsonBuilder() { - Type mapFLocToStringSetType = new TypeToken>>() { - }.getType(); - - Type accessTypeAdatper = new TypeToken>>() { - }.getType(); - - return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().enableComplexMapKeySerialization().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) - .registerTypeAdapter(accessTypeAdatper, new PermissionsMapTypeAdapter()) - .registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter()) - .registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()) - .registerTypeAdapter(Inventory.class, new InventoryTypeAdapter()) - .registerTypeAdapter(Location.class, new LocationTypeAdapter()) - .registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY); - } - - private void divider() { - System.out.println(" .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-"); - System.out.println(" / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\"); - System.out.println("`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'"); - } - - @Override - public void onDisable() { - // only save data if plugin actually completely loaded successfully - if (this.loadSuccessful) { - // Dont save, as this is kind of pointless, as the /f config command manually saves. - // So any edits done are saved, this way manual edits to json can go through. - - // Conf.save(); - } - - if (AutoLeaveTask != null) { - this.getServer().getScheduler().cancelTask(AutoLeaveTask); - AutoLeaveTask = null; - } - - super.onDisable(); - } - - public void startAutoLeaveTask(boolean restartIfRunning) { - if (AutoLeaveTask != null) { - if (!restartIfRunning) { - return; - } - this.getServer().getScheduler().cancelTask(AutoLeaveTask); - } - - if (Conf.autoLeaveRoutineRunsEveryXMinutes > 0.0) { - long ticks = (long) (20 * 60 * Conf.autoLeaveRoutineRunsEveryXMinutes); - AutoLeaveTask = getServer().getScheduler().scheduleSyncRepeatingTask(this, new AutoLeaveTask(), ticks, ticks); - } - } - - @Override - public void postAutoSave() { - //Board.getInstance().forceSave(); Not sure why this was there as it's called after the board is already saved. - Conf.save(); - } - - public ItemStack createItem(Material material, int amount, short datavalue, String name, List lore) { - ItemStack item = new ItemStack(material, amount, datavalue); - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(color(name)); - meta.setLore(colorList(lore)); - item.setItemMeta(meta); - return item; - } - - public ItemStack createLazyItem(Material material, int amount, short datavalue, String name, String lore) { - ItemStack item = new ItemStack(material, amount, datavalue); - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(color(SavageFactions.plugin.getConfig().getString(name))); - meta.setLore(colorList(SavageFactions.plugin.getConfig().getStringList(lore))); - item.setItemMeta(meta); - return item; - } - - public Economy getEcon() { - RegisteredServiceProvider rsp = SavageFactions.plugin.getServer().getServicesManager().getRegistration(Economy.class); - Economy econ = rsp.getProvider(); - return econ; - } - - private boolean setupEssentials() { - SavageFactions.plugin.ess = (Essentials) this.getServer().getPluginManager().getPlugin("Essentials"); - return SavageFactions.plugin.ess == null; - } - - @Override - public boolean logPlayerCommands() { - return Conf.logPlayerCommands; - } - - @Override - public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { - return sender instanceof Player && FactionsPlayerListener.preventCommand(commandString, (Player) sender) || super.handleCommand(sender, commandString, testOnly); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] split) { - if (split.length == 0) { - return handleCommand(sender, "/f help", false); - } - - // otherwise, needs to be handled; presumably another plugin directly ran the command - String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); - return handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false); - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer((Player) sender); - List completions = new ArrayList<>(); - String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); - List argsList = new ArrayList<>(Arrays.asList(args)); - argsList.remove(argsList.size() - 1); - String cmdValid = (cmd + " " + TextUtil.implode(argsList, " ")).trim(); - MCommand commandEx = cmdBase; - List> commandsList = cmdBase.subCommands; - - if (Board.getInstance().getFactionAt(new FLocation(fPlayer.getPlayer().getLocation())) == Factions.getInstance().getWarZone()) { - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou cannot use autocomplete in warzone.")); - return new ArrayList<>(); - } - - for (; !commandsList.isEmpty() && !argsList.isEmpty(); argsList.remove(0)) { - String cmdName = argsList.get(0).toLowerCase(); - MCommand commandFounded = commandsList.stream() - .filter(c -> c.aliases.contains(cmdName)) - .findFirst().orElse(null); - - if (commandFounded != null) { - commandEx = commandFounded; - commandsList = commandFounded.subCommands; - } else break; - } - - if (argsList.isEmpty()) { - for (MCommand subCommand : commandEx.subCommands) { - subCommand.setCommandSender(sender); - if (handleCommand(sender, cmdValid + " " + subCommand.aliases.get(0), true) - && subCommand.visibility != CommandVisibility.INVISIBLE - && subCommand.validSenderType(sender, false) - && subCommand.validSenderPermissions(sender, false)) - completions.addAll(subCommand.aliases); - } - } - - String lastArg = args[args.length - 1].toLowerCase(); - - completions = completions.stream() - .filter(m -> m.toLowerCase().startsWith(lastArg)) - .collect(Collectors.toList()); - - return completions; - } - - public void createTimedHologram(final Location location, String text, Long timeout) { - ArmorStand as = (ArmorStand) location.add(0.5, 1, 0.5).getWorld().spawnEntity(location, EntityType.ARMOR_STAND); //Spawn the ArmorStand - as.setVisible(false); //Makes the ArmorStand invisible - as.setGravity(false); //Make sure it doesn't fall - as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it - as.setCustomName(SavageFactions.plugin.color(text)); //Set this to the text you want - as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not - final ArmorStand armorStand = as; - - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, () -> { - armorStand.remove(); - getLogger().info("Removing Hologram."); - } - , timeout * 20); - } - - - // -------------------------------------------- // - // Functions for other plugins to hook into - // -------------------------------------------- // - - // This value will be updated whenever new hooks are added - public int hookSupportVersion() { - return 3; - } - - // If another plugin is handling insertion of chat tags, this should be used to notify Factions - public void handleFactionTagExternally(boolean notByFactions) { - Conf.chatTagHandledByAnotherPlugin = notByFactions; - } - - // Simply put, should this chat event be left for Factions to handle? For now, that means players with Faction Chat - // enabled or use of the Factions f command without a slash; combination of isPlayerFactionChatting() and isFactionsCommand() - - public boolean shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent event) { - return event != null && (isPlayerFactionChatting(event.getPlayer()) || isFactionsCommand(event.getMessage())); - } - - - // Does player have Faction Chat enabled? If so, chat plugins should preferably not do channels, - // local chat, or anything else which targets individual recipients, so Faction Chat can be done - public boolean isPlayerFactionChatting(Player player) { - if (player == null) { - return false; - } - FPlayer me = FPlayers.getInstance().getByPlayer(player); - - return me != null && me.getChatMode().isAtLeast(ChatMode.ALLIANCE); - } - - // Is this chat message actually a Factions command, and thus should be left alone by other plugins? - - // TODO: GET THIS BACK AND WORKING - - public boolean isFactionsCommand(String check) { - return !(check == null || check.isEmpty()) && this.handleCommand(null, check, true); - } - - // Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat - public String getPlayerFactionTag(Player player) { - return getPlayerFactionTagRelation(player, null); - } - - // Same as above, but with relation (enemy/neutral/ally) coloring potentially added to the tag - public String getPlayerFactionTagRelation(Player speaker, Player listener) { - String tag = "~"; - - if (speaker == null) { - return tag; - } - - FPlayer me = FPlayers.getInstance().getByPlayer(speaker); - if (me == null) { - return tag; - } - - // if listener isn't set, or config option is disabled, give back uncolored tag - if (listener == null || !Conf.chatTagRelationColored) { - tag = me.getChatTag().trim(); - } else { - FPlayer you = FPlayers.getInstance().getByPlayer(listener); - if (you == null) { - tag = me.getChatTag().trim(); - } else // everything checks out, give the colored tag - { - tag = me.getChatTag(you).trim(); - } - } - if (tag.isEmpty()) { - tag = "~"; - } - - return tag; - } - - // Get a player's title within their faction, mainly for usage by chat plugins for local/channel chat - public String getPlayerTitle(Player player) { - if (player == null) { - return ""; - } - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - if (me == null) { - return ""; - } - - return me.getTitle().trim(); - } - - public String color(String line) { - line = ChatColor.translateAlternateColorCodes('&', line); - return line; - } - - //colors a string list - public List colorList(List lore) { - for (int i = 0; i <= lore.size() - 1; i++) { - lore.set(i, color(lore.get(i))); - } - return lore; - } - - // Get a list of all faction tags (names) - public Set getFactionTags() { - return Factions.getInstance().getFactionTags(); - } - - // Get a list of all players in the specified faction - public Set getPlayersInFaction(String factionTag) { - Set players = new HashSet<>(); - Faction faction = Factions.getInstance().getByTag(factionTag); - if (faction != null) { - for (FPlayer fplayer : faction.getFPlayers()) { - players.add(fplayer.getName()); - } - } - return players; - } - - // Get a list of all online players in the specified faction - public Set getOnlinePlayersInFaction(String factionTag) { - Set players = new HashSet<>(); - Faction faction = Factions.getInstance().getByTag(factionTag); - if (faction != null) { - for (FPlayer fplayer : faction.getFPlayersWhereOnline(true)) { - players.add(fplayer.getName()); - } - } - return players; - } - - public boolean isHookedPlayervaults() { - return hookedPlayervaults; - } - - public String getPrimaryGroup(OfflinePlayer player) { - return perms == null || !perms.hasGroupSupport() ? " " : perms.getPrimaryGroup(Bukkit.getWorlds().get(0).toString(), player); - } - - public void debug(Level level, String s) { - if (getConfig().getBoolean("debug", false)) { - getLogger().log(level, s); - } - } - - public void debug(String s) { - debug(Level.INFO, s); - } + // Our single plugin instance. + // Single 4 life. + public static SavageFactions plugin; + public static Permission perms = null; + // Persistence related + public static ArrayList playersFlying = new ArrayList(); + public Essentials ess; + public boolean PlaceholderApi; + // Commands + public FCmdRoot cmdBase; + public CmdAutoHelp cmdAutoHelp; + public boolean mc17 = false; + public boolean mc18 = false; + public boolean mc113 = false; + public boolean useNonPacketParticles = false; + public boolean factionsFlight = false; + //multiversion material fields + public Material SUGAR_CANE_BLOCK, BANNER, CROPS, REDSTONE_LAMP_ON, + STAINED_GLASS, STATIONARY_WATER, STAINED_CLAY, WOOD_BUTTON, + SOIL, MOB_SPANWER, THIN_GLASS, IRON_FENCE, NETHER_FENCE, FENCE, + WOODEN_DOOR, TRAP_DOOR, FENCE_GATE, BURNING_FURNACE, DIODE_BLOCK_OFF, + DIODE_BLOCK_ON, ENCHANTMENT_TABLE, FIREBALL; + SkriptAddon skriptAddon; + private boolean locked = false; + private Integer AutoLeaveTask = null; + private boolean hookedPlayervaults; + private ClipPlaceholderAPIManager clipPlaceholderAPIManager; + private boolean mvdwPlaceholderAPIManager = false; + private Listener[] eventsListener; + + public SavageFactions() { + plugin = this; + } + + public boolean getLocked() { + return this.locked; + } + + public void setLocked(boolean val) { + this.locked = val; + this.setAutoSave(val); + } + + public void playSoundForAll(String sound) { + for (Player pl : Bukkit.getOnlinePlayers()) { + playSound(pl, sound); + } + } + + public void playSoundForAll(List sounds) { + for (Player pl : Bukkit.getOnlinePlayers()) { + playSound(pl, sounds); + } + } + + public void playSound(Player p, List sounds) { + for (String sound : sounds) { + playSound(p, sound); + } + } + + public void playSound(Player p, String sound) { + float pitch = Float.valueOf(sound.split(":")[1]); + sound = sound.split(":")[0]; + p.playSound(p.getLocation(), Sound.valueOf(sound), pitch, 5.0F); + } + + @Override + public void onEnable() { + log("==== Setup ===="); + + + // Vault dependency check. + if (getServer().getPluginManager().getPlugin("Vault") == null) { + log("Vault is not present, the plugin will not run properly."); + getServer().getPluginManager().disablePlugin(plugin); + return; + } + + int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); + if (version == 7) { + SavageFactions.plugin.log("Minecraft Version 1.7 found, disabling banners, itemflags inside GUIs, and Titles."); + mc17 = true; + } else if (version == 8) { + SavageFactions.plugin.log("Minecraft Version 1.8 found, Title Fadeouttime etc will not be configurable."); + mc18 = true; + } else if (version == 13) { + SavageFactions.plugin.log("Minecraft Version 1.13 found, New Items will be used."); + mc113 = true; + changeItemIDSInConfig(); + } + setupMultiversionMaterials(); + migrateFPlayerLeaders(); + log("==== End Setup ===="); + + if (!preEnable()) { + return; + } + this.loadSuccessful = false; + + saveDefaultConfig(); + + // Load Conf from disk + Conf.load(); + com.massivecraft.factions.integration.Essentials.setup(); + hookedPlayervaults = setupPlayervaults(); + FPlayers.getInstance().load(); + Factions.getInstance().load(); + + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); + if (faction == null) { + log("Invalid faction id on " + fPlayer.getName() + ":" + fPlayer.getFactionId()); + fPlayer.resetFactionData(false); + continue; + } + faction.addFPlayer(fPlayer); + } + playersFlying.clear(); + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + playersFlying.add(fPlayer); + } + UtilFly.run(); + + Board.getInstance().load(); + Board.getInstance().clean(); + + // Add Base Commands + this.cmdBase = new FCmdRoot(); + this.cmdAutoHelp = new CmdAutoHelp(); + this.getBaseCommands().add(cmdBase); + + Econ.setup(); + setupPermissions(); + + if (Conf.worldGuardChecking || Conf.worldGuardBuildPriority) { + Worldguard.init(this); + } + + EngineDynmap.getInstance().init(); + + // start up task which runs the autoLeaveAfterDaysOfInactivity routine + startAutoLeaveTask(false); + + if (getConfig().getBoolean("MassiveStats")) { + // massive stats + new MassiveStats(this); + } + + if (version > 8) { + useNonPacketParticles = true; + log("Minecraft Version 1.9 or higher found, using non packet based particle API"); + } + + if (getConfig().getBoolean("enable-faction-flight")) { + factionsFlight = true; + } + + if (getServer().getPluginManager().getPlugin("Skript") != null) { + log("Skript was found! Registering SavageFactions Addon..."); + skriptAddon = Skript.registerAddon(this); + try { + skriptAddon.loadClasses("com.massivecraft.factions.skript", "expressions"); + } catch (IOException ex) { + ex.printStackTrace(); + } + log("Skript addon registered!"); + } + + + // Register Event Handlers + eventsListener = new Listener[]{ + new FactionsPlayerListener(), + new FactionsChatListener(), + new FactionsEntityListener(), + new FactionsExploitListener(), + new FactionsBlockListener(), + new FUpgradesGUI(), + new EXPUpgrade(), + new CropUpgrades(), + new SpawnerUpgrades(), + }; + + for (Listener eventListener : eventsListener) + getServer().getPluginManager().registerEvents(eventListener, this); + + // since some other plugins execute commands directly through this command interface, provide it + getCommand(this.refCommand).setExecutor(this); + getCommand(this.refCommand).setTabCompleter(this); + + setupEssentials(); + + if (getDescription().getFullName().contains("BETA")) { + divider(); + System.out.println("You are using a BETA version of the plugin!"); + System.out.println("This comes with risks of small bugs in newer features!"); + System.out.println("For support head to: https://github.com/ProSavage/SavageFactions/issues"); + divider(); + } + + this.setupPlaceholderAPI(); + this.postEnable(); + this.loadSuccessful = true; + } + + public SkriptAddon getSkriptAddon() { + return skriptAddon; + } + + private void setupMultiversionMaterials() { + if (mc113) { + BANNER = Material.valueOf("LEGACY_BANNER"); + CROPS = Material.valueOf("LEGACY_CROPS"); + SUGAR_CANE_BLOCK = Material.valueOf("LEGACY_SUGAR_CANE_BLOCK"); + REDSTONE_LAMP_ON = Material.valueOf("LEGACY_REDSTONE_LAMP_ON"); + STAINED_GLASS = Material.valueOf("LEGACY_STAINED_GLASS"); + STATIONARY_WATER = Material.valueOf("LEGACY_STATIONARY_WATER"); + STAINED_CLAY = Material.valueOf("LEGACY_STAINED_CLAY"); + WOOD_BUTTON = Material.valueOf("LEGACY_WOOD_BUTTON"); + SOIL = Material.valueOf("LEGACY_SOIL"); + MOB_SPANWER = Material.valueOf("LEGACY_MOB_SPAWNER"); + THIN_GLASS = Material.valueOf("LEGACY_THIN_GLASS"); + IRON_FENCE = Material.valueOf("LEGACY_IRON_FENCE"); + NETHER_FENCE = Material.valueOf("LEGACY_NETHER_FENCE"); + FENCE = Material.valueOf("LEGACY_FENCE"); + WOODEN_DOOR = Material.valueOf("LEGACY_WOODEN_DOOR"); + TRAP_DOOR = Material.valueOf("LEGACY_TRAP_DOOR"); + FENCE_GATE = Material.valueOf("LEGACY_FENCE_GATE"); + BURNING_FURNACE = Material.valueOf("LEGACY_BURNING_FURNACE"); + DIODE_BLOCK_OFF = Material.valueOf("LEGACY_DIODE_BLOCK_OFF"); + DIODE_BLOCK_ON = Material.valueOf("LEGACY_DIODE_BLOCK_ON"); + ENCHANTMENT_TABLE = Material.valueOf("LEGACY_ENCHANTMENT_TABLE"); + FIREBALL = Material.valueOf("LEGACY_FIREBALL"); + + } else { + if (!mc17) { + BANNER = Material.valueOf("BANNER"); + } + CROPS = Material.valueOf("CROPS"); + SUGAR_CANE_BLOCK = Material.valueOf("SUGAR_CANE_BLOCK"); + REDSTONE_LAMP_ON = Material.valueOf("REDSTONE_LAMP_ON"); + STAINED_GLASS = Material.valueOf("STAINED_GLASS"); + STATIONARY_WATER = Material.valueOf("STATIONARY_WATER"); + STAINED_CLAY = Material.valueOf("STAINED_CLAY"); + WOOD_BUTTON = Material.valueOf("WOOD_BUTTON"); + SOIL = Material.valueOf("SOIL"); + MOB_SPANWER = Material.valueOf("MOB_SPAWNER"); + THIN_GLASS = Material.valueOf("THIN_GLASS"); + IRON_FENCE = Material.valueOf("IRON_FENCE"); + NETHER_FENCE = Material.valueOf("NETHER_FENCE"); + FENCE = Material.valueOf("FENCE"); + WOODEN_DOOR = Material.valueOf("WOODEN_DOOR"); + TRAP_DOOR = Material.valueOf("TRAP_DOOR"); + FENCE_GATE = Material.valueOf("FENCE_GATE"); + BURNING_FURNACE = Material.valueOf("BURNING_FURNACE"); + DIODE_BLOCK_OFF = Material.valueOf("DIODE_BLOCK_OFF"); + DIODE_BLOCK_ON = Material.valueOf("DIODE_BLOCK_ON"); + ENCHANTMENT_TABLE = Material.valueOf("ENCHANTMENT_TABLE"); + FIREBALL = Material.valueOf("FIREBALL"); + } + + } + + private void setupPlaceholderAPI() { + Plugin clip = getServer().getPluginManager().getPlugin("PlaceholderAPI"); + if (clip != null && clip.isEnabled()) { + this.clipPlaceholderAPIManager = new ClipPlaceholderAPIManager(); + if (this.clipPlaceholderAPIManager.register()) { + PlaceholderApi = true; + log(Level.INFO, "Successfully registered placeholders with PlaceholderAPI."); + } else { + PlaceholderApi = false; + } + } else { + PlaceholderApi = false; + } + + Plugin mvdw = getServer().getPluginManager().getPlugin("MVdWPlaceholderAPI"); + if (mvdw != null && mvdw.isEnabled()) { + this.mvdwPlaceholderAPIManager = true; + log(Level.INFO, "Found MVdWPlaceholderAPI. Adding hooks."); + } + } + + private void migrateFPlayerLeaders() { + List lines = new ArrayList<>(); + File fplayerFile = new File("plugins\\Factions\\players.json"); + + try { + BufferedReader br = new BufferedReader(new FileReader(fplayerFile)); + System.out.println("Migrating old players.json file."); + + String line; + while ((line = br.readLine()) != null) { + if (line.contains("\"role\": \"ADMIN\"")) { + line = line.replace("\"role\": \"ADMIN\"", "\"role\": " + "\"LEADER\""); + } + lines.add(line); + } + br.close(); + BufferedWriter bw = new BufferedWriter(new FileWriter(fplayerFile)); + for (String newLine : lines) { + bw.write(newLine + "\n"); + } + bw.flush(); + bw.close(); + } catch (IOException ex) { + System.out.println("File was not found for players.json, assuming" + + " there is no need to migrate old players.json file."); + } + } + + public void changeItemIDSInConfig() { + log("Starting conversion of legacy material in config to 1.13 materials."); + + replaceStringInConfig("fperm-gui.relation.materials.recruit", "WOOD_SWORD", "WOODEN_SWORD"); + replaceStringInConfig("fperm-gui.relation.materials.normal", "GOLD_SWORD", "GOLDEN_SWORD"); + replaceStringInConfig("fperm-gui.relation.materials.ally", "GOLD_AXE", "GOLDEN_AXE"); + replaceStringInConfig("fperm-gui.relation.materials.neutral", "WOOD_AXE", "WOODEN_AXE"); + + ConfigurationSection actionMaterialsConfigSection = getConfig().getConfigurationSection("fperm-gui.action.materials"); + Set actionMaterialKeys = actionMaterialsConfigSection.getKeys(true); + + + for (String key : actionMaterialKeys) { + replaceStringInConfig("fperm-gui.action.materials." + key, "STAINED_GLASS", "GRAY_STAINED_GLASS"); + } + + replaceStringInConfig("fperm-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); + replaceStringInConfig("fwarp-gui.dummy-items.0.material", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); + + replaceStringInConfig("fupgrades.MainMenu.DummyItem.Type", "STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE"); + replaceStringInConfig("fupgrades.MainMenu.EXP.EXPItem.Type", "EXP_BOTTLE", "EXPERIENCE_BOTTLE"); + replaceStringInConfig("fupgrades.MainMenu.Spawners.SpawnerItem.Type", "MOB_SPAWNER", "SPAWNER"); + + replaceStringInConfig("fperm-gui.action.access.allow", "LIME", "LIME_STAINED_GLASS"); + replaceStringInConfig("fperm-gui.action.access.deny", "RED", "RED_STAINED_GLASS"); + replaceStringInConfig("fperm-gui.action.access.undefined", "CYAN", "CYAN_STAINED_GLASS"); + } + + public void replaceStringInConfig(String path, String stringToReplace, String replacementString) { + if (getConfig().getString(path).equals(stringToReplace)) { + // SavageFactions.plugin.log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); + // log("Replacing legacy material '" + stringToReplace + "' with '" + replacementString + "' for config node '" + path + "'."); + + getConfig().set(path, replacementString); + } + } + + public boolean isClipPlaceholderAPIHooked() { + return this.clipPlaceholderAPIManager != null; + } + + public boolean isMVdWPlaceholderAPIHooked() { + return this.mvdwPlaceholderAPIManager; + } + + private boolean setupPermissions() { + try { + RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Permission.class); + if (rsp != null) { + perms = rsp.getProvider(); + } + } catch (NoClassDefFoundError ex) { + return false; + } + return perms != null; + } + + private boolean setupPlayervaults() { + Plugin plugin = getServer().getPluginManager().getPlugin("PlayerVaults"); + return plugin != null && plugin.isEnabled(); + } + + @Override + public GsonBuilder getGsonBuilder() { + Type mapFLocToStringSetType = new TypeToken>>() { + }.getType(); + + Type accessTypeAdatper = new TypeToken>>() { + }.getType(); + + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().enableComplexMapKeySerialization().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) + .registerTypeAdapter(accessTypeAdatper, new PermissionsMapTypeAdapter()) + .registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter()) + .registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()) + .registerTypeAdapter(Inventory.class, new InventoryTypeAdapter()) + .registerTypeAdapter(Location.class, new LocationTypeAdapter()) + .registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY); + } + + private void divider() { + System.out.println(" .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-"); + System.out.println(" / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\ \\ / / \\"); + System.out.println("`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'"); + } + + @Override + public void onDisable() { + // only save data if plugin actually completely loaded successfully + if (this.loadSuccessful) { + // Dont save, as this is kind of pointless, as the /f config command manually saves. + // So any edits done are saved, this way manual edits to json can go through. + + // Conf.save(); + } + + if (AutoLeaveTask != null) { + this.getServer().getScheduler().cancelTask(AutoLeaveTask); + AutoLeaveTask = null; + } + + super.onDisable(); + } + + public void startAutoLeaveTask(boolean restartIfRunning) { + if (AutoLeaveTask != null) { + if (!restartIfRunning) { + return; + } + this.getServer().getScheduler().cancelTask(AutoLeaveTask); + } + + if (Conf.autoLeaveRoutineRunsEveryXMinutes > 0.0) { + long ticks = (long) (20 * 60 * Conf.autoLeaveRoutineRunsEveryXMinutes); + AutoLeaveTask = getServer().getScheduler().scheduleSyncRepeatingTask(this, new AutoLeaveTask(), ticks, ticks); + } + } + + @Override + public void postAutoSave() { + //Board.getInstance().forceSave(); Not sure why this was there as it's called after the board is already saved. + Conf.save(); + } + + public ItemStack createItem(Material material, int amount, short datavalue, String name, List lore) { + ItemStack item = new ItemStack(material, amount, datavalue); + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(color(name)); + meta.setLore(colorList(lore)); + item.setItemMeta(meta); + return item; + } + + public ItemStack createLazyItem(Material material, int amount, short datavalue, String name, String lore) { + ItemStack item = new ItemStack(material, amount, datavalue); + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(color(SavageFactions.plugin.getConfig().getString(name))); + meta.setLore(colorList(SavageFactions.plugin.getConfig().getStringList(lore))); + item.setItemMeta(meta); + return item; + } + + public Economy getEcon() { + RegisteredServiceProvider rsp = SavageFactions.plugin.getServer().getServicesManager().getRegistration(Economy.class); + Economy econ = rsp.getProvider(); + return econ; + } + + private boolean setupEssentials() { + SavageFactions.plugin.ess = (Essentials) this.getServer().getPluginManager().getPlugin("Essentials"); + return SavageFactions.plugin.ess == null; + } + + @Override + public boolean logPlayerCommands() { + return Conf.logPlayerCommands; + } + + @Override + public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { + return sender instanceof Player && FactionsPlayerListener.preventCommand(commandString, (Player) sender) || super.handleCommand(sender, commandString, testOnly); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] split) { + if (split.length == 0) { + return handleCommand(sender, "/f help", false); + } + + // otherwise, needs to be handled; presumably another plugin directly ran the command + String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); + return handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false); + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer((Player) sender); + List completions = new ArrayList<>(); + String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0); + List argsList = new ArrayList<>(Arrays.asList(args)); + argsList.remove(argsList.size() - 1); + String cmdValid = (cmd + " " + TextUtil.implode(argsList, " ")).trim(); + MCommand commandEx = cmdBase; + List> commandsList = cmdBase.subCommands; + + if (Board.getInstance().getFactionAt(new FLocation(fPlayer.getPlayer().getLocation())) == Factions.getInstance().getWarZone()) { + sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou cannot use autocomplete in warzone.")); + return new ArrayList<>(); + } + + for (; !commandsList.isEmpty() && !argsList.isEmpty(); argsList.remove(0)) { + String cmdName = argsList.get(0).toLowerCase(); + MCommand commandFounded = commandsList.stream() + .filter(c -> c.aliases.contains(cmdName)) + .findFirst().orElse(null); + + if (commandFounded != null) { + commandEx = commandFounded; + commandsList = commandFounded.subCommands; + } else break; + } + + if (argsList.isEmpty()) { + for (MCommand subCommand : commandEx.subCommands) { + subCommand.setCommandSender(sender); + if (handleCommand(sender, cmdValid + " " + subCommand.aliases.get(0), true) + && subCommand.visibility != CommandVisibility.INVISIBLE + && subCommand.validSenderType(sender, false) + && subCommand.validSenderPermissions(sender, false)) + completions.addAll(subCommand.aliases); + } + } + + String lastArg = args[args.length - 1].toLowerCase(); + + completions = completions.stream() + .filter(m -> m.toLowerCase().startsWith(lastArg)) + .collect(Collectors.toList()); + + return completions; + } + + public void createTimedHologram(final Location location, String text, Long timeout) { + ArmorStand as = (ArmorStand) location.add(0.5, 1, 0.5).getWorld().spawnEntity(location, EntityType.ARMOR_STAND); //Spawn the ArmorStand + as.setVisible(false); //Makes the ArmorStand invisible + as.setGravity(false); //Make sure it doesn't fall + as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it + as.setCustomName(SavageFactions.plugin.color(text)); //Set this to the text you want + as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not + final ArmorStand armorStand = as; + + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, () -> { + armorStand.remove(); + getLogger().info("Removing Hologram."); + } + , timeout * 20); + } + + + // -------------------------------------------- // + // Functions for other plugins to hook into + // -------------------------------------------- // + + // This value will be updated whenever new hooks are added + public int hookSupportVersion() { + return 3; + } + + // If another plugin is handling insertion of chat tags, this should be used to notify Factions + public void handleFactionTagExternally(boolean notByFactions) { + Conf.chatTagHandledByAnotherPlugin = notByFactions; + } + + // Simply put, should this chat event be left for Factions to handle? For now, that means players with Faction Chat + // enabled or use of the Factions f command without a slash; combination of isPlayerFactionChatting() and isFactionsCommand() + + public boolean shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent event) { + return event != null && (isPlayerFactionChatting(event.getPlayer()) || isFactionsCommand(event.getMessage())); + } + + + // Does player have Faction Chat enabled? If so, chat plugins should preferably not do channels, + // local chat, or anything else which targets individual recipients, so Faction Chat can be done + public boolean isPlayerFactionChatting(Player player) { + if (player == null) { + return false; + } + FPlayer me = FPlayers.getInstance().getByPlayer(player); + + return me != null && me.getChatMode().isAtLeast(ChatMode.ALLIANCE); + } + + // Is this chat message actually a Factions command, and thus should be left alone by other plugins? + + // TODO: GET THIS BACK AND WORKING + + public boolean isFactionsCommand(String check) { + return !(check == null || check.isEmpty()) && this.handleCommand(null, check, true); + } + + // Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat + public String getPlayerFactionTag(Player player) { + return getPlayerFactionTagRelation(player, null); + } + + // Same as above, but with relation (enemy/neutral/ally) coloring potentially added to the tag + public String getPlayerFactionTagRelation(Player speaker, Player listener) { + String tag = "~"; + + if (speaker == null) { + return tag; + } + + FPlayer me = FPlayers.getInstance().getByPlayer(speaker); + if (me == null) { + return tag; + } + + // if listener isn't set, or config option is disabled, give back uncolored tag + if (listener == null || !Conf.chatTagRelationColored) { + tag = me.getChatTag().trim(); + } else { + FPlayer you = FPlayers.getInstance().getByPlayer(listener); + if (you == null) { + tag = me.getChatTag().trim(); + } else // everything checks out, give the colored tag + { + tag = me.getChatTag(you).trim(); + } + } + if (tag.isEmpty()) { + tag = "~"; + } + + return tag; + } + + // Get a player's title within their faction, mainly for usage by chat plugins for local/channel chat + public String getPlayerTitle(Player player) { + if (player == null) { + return ""; + } + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + if (me == null) { + return ""; + } + + return me.getTitle().trim(); + } + + public String color(String line) { + line = ChatColor.translateAlternateColorCodes('&', line); + return line; + } + + //colors a string list + public List colorList(List lore) { + for (int i = 0; i <= lore.size() - 1; i++) { + lore.set(i, color(lore.get(i))); + } + return lore; + } + + // Get a list of all faction tags (names) + public Set getFactionTags() { + return Factions.getInstance().getFactionTags(); + } + + // Get a list of all players in the specified faction + public Set getPlayersInFaction(String factionTag) { + Set players = new HashSet<>(); + Faction faction = Factions.getInstance().getByTag(factionTag); + if (faction != null) { + for (FPlayer fplayer : faction.getFPlayers()) { + players.add(fplayer.getName()); + } + } + return players; + } + + // Get a list of all online players in the specified faction + public Set getOnlinePlayersInFaction(String factionTag) { + Set players = new HashSet<>(); + Faction faction = Factions.getInstance().getByTag(factionTag); + if (faction != null) { + for (FPlayer fplayer : faction.getFPlayersWhereOnline(true)) { + players.add(fplayer.getName()); + } + } + return players; + } + + public boolean isHookedPlayervaults() { + return hookedPlayervaults; + } + + public String getPrimaryGroup(OfflinePlayer player) { + return perms == null || !perms.hasGroupSupport() ? " " : perms.getPrimaryGroup(Bukkit.getWorlds().get(0).toString(), player); + } + + public void debug(Level level, String s) { + if (getConfig().getBoolean("debug", false)) { + getLogger().log(level, s); + } + } + + public void debug(String s) { + debug(Level.INFO, s); + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java b/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java index f9a2bdc1..ba413640 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAHome.java @@ -8,45 +8,45 @@ import org.bukkit.event.player.PlayerTeleportEvent; public class CmdAHome extends FCommand { - public CmdAHome() { - super(); - this.aliases.add("ahome"); + public CmdAHome() { + super(); + this.aliases.add("ahome"); - this.requiredArgs.add("player name"); + this.requiredArgs.add("player name"); - this.permission = Permission.AHOME.node; - this.disableOnLock = false; + this.permission = Permission.AHOME.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer target = argAsBestFPlayerMatch(0); - if (target == null) { - msg(TL.GENERIC_NOPLAYERMATCH, argAsString(0)); - return; - } + @Override + public void perform() { + FPlayer target = argAsBestFPlayerMatch(0); + if (target == null) { + msg(TL.GENERIC_NOPLAYERMATCH, argAsString(0)); + return; + } - if (target.isOnline()) { - Faction faction = target.getFaction(); - if (faction.hasHome()) { - target.getPlayer().teleport(faction.getHome(), PlayerTeleportEvent.TeleportCause.PLUGIN); - msg(TL.COMMAND_AHOME_SUCCESS, target.getName()); - target.msg(TL.COMMAND_AHOME_TARGET); - } else { - msg(TL.COMMAND_AHOME_NOHOME, target.getName()); - } - } else { - msg(TL.COMMAND_AHOME_OFFLINE, target.getName()); - } - } + if (target.isOnline()) { + Faction faction = target.getFaction(); + if (faction.hasHome()) { + target.getPlayer().teleport(faction.getHome(), PlayerTeleportEvent.TeleportCause.PLUGIN); + msg(TL.COMMAND_AHOME_SUCCESS, target.getName()); + target.msg(TL.COMMAND_AHOME_TARGET); + } else { + msg(TL.COMMAND_AHOME_NOHOME, target.getName()); + } + } else { + msg(TL.COMMAND_AHOME_OFFLINE, target.getName()); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_AHOME_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_AHOME_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java b/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java index ed21beb0..5c03529f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java @@ -11,90 +11,90 @@ import org.bukkit.Bukkit; public class CmdAdmin extends FCommand { - public CmdAdmin() { - super(); - this.aliases.add("admin"); - this.aliases.add("setadmin"); - this.aliases.add("leader"); - this.aliases.add("setleader"); + public CmdAdmin() { + super(); + this.aliases.add("admin"); + this.aliases.add("setadmin"); + this.aliases.add("leader"); + this.aliases.add("setleader"); - this.requiredArgs.add("player name"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("player name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.ADMIN.node; - this.disableOnLock = true; + this.permission = Permission.ADMIN.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer fyou = this.argAsBestFPlayerMatch(0); - if (fyou == null) { - return; - } + @Override + public void perform() { + FPlayer fyou = this.argAsBestFPlayerMatch(0); + if (fyou == null) { + return; + } - boolean permAny = Permission.ADMIN_ANY.has(sender, false); - Faction targetFaction = fyou.getFaction(); + boolean permAny = Permission.ADMIN_ANY.has(sender, false); + Faction targetFaction = fyou.getFaction(); - if (targetFaction != myFaction && !permAny) { - msg(TL.COMMAND_ADMIN_NOTMEMBER, fyou.describeTo(fme, true)); - return; - } + if (targetFaction != myFaction && !permAny) { + msg(TL.COMMAND_ADMIN_NOTMEMBER, fyou.describeTo(fme, true)); + return; + } - if (fme != null && fme.getRole() != Role.LEADER && !permAny) { - msg(TL.COMMAND_ADMIN_NOTADMIN); - return; - } + if (fme != null && fme.getRole() != Role.LEADER && !permAny) { + msg(TL.COMMAND_ADMIN_NOTADMIN); + return; + } - if (fyou == fme && !permAny) { - msg(TL.COMMAND_ADMIN_TARGETSELF); - return; - } + if (fyou == fme && !permAny) { + msg(TL.COMMAND_ADMIN_TARGETSELF); + return; + } - // only perform a FPlayerJoinEvent when newLeader isn't actually in the faction - if (fyou.getFaction() != targetFaction) { - FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER); - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - } + // only perform a FPlayerJoinEvent when newLeader isn't actually in the faction + if (fyou.getFaction() != targetFaction) { + FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } - FPlayer admin = targetFaction.getFPlayerAdmin(); + FPlayer admin = targetFaction.getFPlayerAdmin(); - if (fyou == admin && fyou.getFaction().getSize() == 1) { - msg(TL.COMMAND_ADMIN_NOMEMBERS); - return; - } + if (fyou == admin && fyou.getFaction().getSize() == 1) { + msg(TL.COMMAND_ADMIN_NOMEMBERS); + return; + } - // if target player is currently admin, demote and replace him - if (fyou == admin) { - targetFaction.promoteNewLeader(); - msg(TL.COMMAND_ADMIN_DEMOTES, fyou.describeTo(fme, true)); - fyou.msg(TL.COMMAND_ADMIN_DEMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fyou, true)); - return; - } + // if target player is currently admin, demote and replace him + if (fyou == admin) { + targetFaction.promoteNewLeader(); + msg(TL.COMMAND_ADMIN_DEMOTES, fyou.describeTo(fme, true)); + fyou.msg(TL.COMMAND_ADMIN_DEMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fyou, true)); + return; + } - // promote target player, and demote existing admin if one exists - if (admin != null) { - admin.setRole(Role.COLEADER); - } - fyou.setRole(Role.LEADER); - msg(TL.COMMAND_ADMIN_PROMOTES, fyou.describeTo(fme, true)); + // promote target player, and demote existing admin if one exists + if (admin != null) { + admin.setRole(Role.COLEADER); + } + fyou.setRole(Role.LEADER); + msg(TL.COMMAND_ADMIN_PROMOTES, fyou.describeTo(fme, true)); - // Inform all players - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg(TL.COMMAND_ADMIN_PROMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true), fyou.describeTo(fplayer), targetFaction.describeTo(fplayer)); - } - } + // Inform all players + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg(TL.COMMAND_ADMIN_PROMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true), fyou.describeTo(fplayer), targetFaction.describeTo(fplayer)); + } + } - public TL getUsageTranslation() { - return TL.COMMAND_ADMIN_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_ADMIN_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java b/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java index 296891d7..952d9d38 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAnnounce.java @@ -9,41 +9,41 @@ import org.bukkit.entity.Player; public class CmdAnnounce extends FCommand { - public CmdAnnounce() { - super(); - this.aliases.add("ann"); - this.aliases.add("announce"); + public CmdAnnounce() { + super(); + this.aliases.add("ann"); + this.aliases.add("announce"); - this.requiredArgs.add("message"); - this.errorOnToManyArgs = false; + this.requiredArgs.add("message"); + this.errorOnToManyArgs = false; - this.permission = Permission.ANNOUNCE.node; - this.disableOnLock = false; + this.permission = Permission.ANNOUNCE.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + } - @Override - public void perform() { - String prefix = ChatColor.GREEN + myFaction.getTag() + ChatColor.YELLOW + " [" + ChatColor.GRAY + me.getName() + ChatColor.YELLOW + "] " + ChatColor.RESET; - String message = StringUtils.join(args, " "); + @Override + public void perform() { + String prefix = ChatColor.GREEN + myFaction.getTag() + ChatColor.YELLOW + " [" + ChatColor.GRAY + me.getName() + ChatColor.YELLOW + "] " + ChatColor.RESET; + String message = StringUtils.join(args, " "); - for (Player player : myFaction.getOnlinePlayers()) { - player.sendMessage(prefix + message); - } + for (Player player : myFaction.getOnlinePlayers()) { + player.sendMessage(prefix + message); + } - // Add for offline players. - for (FPlayer fp : myFaction.getFPlayersWhereOnline(false)) { - myFaction.addAnnouncement(fp, prefix + message); - } - } + // Add for offline players. + for (FPlayer fp : myFaction.getFPlayersWhereOnline(false)) { + myFaction.addAnnouncement(fp, prefix + message); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_ANNOUNCE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_ANNOUNCE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java index 5aa47e72..61742f98 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAutoClaim.java @@ -7,50 +7,50 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdAutoClaim extends FCommand { - public CmdAutoClaim() { - super(); - this.aliases.add("autoclaim"); + public CmdAutoClaim() { + super(); + this.aliases.add("autoclaim"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction", "your"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction", "your"); - this.permission = Permission.AUTOCLAIM.node; - this.disableOnLock = true; + this.permission = Permission.AUTOCLAIM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction forFaction = this.argAsFaction(0, myFaction); - if (forFaction == null || forFaction == fme.getAutoClaimFor()) { - fme.setAutoClaimFor(null); - msg(TL.COMMAND_AUTOCLAIM_DISABLED); - return; - } + @Override + public void perform() { + Faction forFaction = this.argAsFaction(0, myFaction); + if (forFaction == null || forFaction == fme.getAutoClaimFor()) { + fme.setAutoClaimFor(null); + msg(TL.COMMAND_AUTOCLAIM_DISABLED); + return; + } - if (!fme.canClaimForFaction(forFaction)) { - if (myFaction == forFaction) { - msg(TL.COMMAND_AUTOCLAIM_REQUIREDRANK, Role.MODERATOR.getTranslation()); - } else { - msg(TL.COMMAND_AUTOCLAIM_OTHERFACTION, forFaction.describeTo(fme)); - } + if (!fme.canClaimForFaction(forFaction)) { + if (myFaction == forFaction) { + msg(TL.COMMAND_AUTOCLAIM_REQUIREDRANK, Role.MODERATOR.getTranslation()); + } else { + msg(TL.COMMAND_AUTOCLAIM_OTHERFACTION, forFaction.describeTo(fme)); + } - return; - } + return; + } - fme.setAutoClaimFor(forFaction); + fme.setAutoClaimFor(forFaction); - msg(TL.COMMAND_AUTOCLAIM_ENABLED, forFaction.describeTo(fme)); - fme.attemptClaim(forFaction, me.getLocation(), true); - } + msg(TL.COMMAND_AUTOCLAIM_ENABLED, forFaction.describeTo(fme)); + fme.attemptClaim(forFaction, me.getLocation(), true); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_AUTOCLAIM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_AUTOCLAIM_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java b/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java index 798914d3..78ba49c9 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAutoHelp.java @@ -1,48 +1,48 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.zcore.CommandVisibility; -import com.massivecraft.factions.zcore.MCommand; -import com.massivecraft.factions.zcore.util.TL; - -import java.util.ArrayList; - -public class CmdAutoHelp extends MCommand { - - public CmdAutoHelp() { - super(SavageFactions.plugin); - this.aliases.add("?"); - this.aliases.add("h"); - this.aliases.add("help"); - - this.setHelpShort(""); - - this.optionalArgs.put("page", "1"); - } - - @Override - public void perform() { - - if (this.commandChain.size() == 0) { - return; - } - MCommand pcmd = this.commandChain.get(this.commandChain.size() - 1); - - ArrayList lines = new ArrayList<>(); - - lines.addAll(pcmd.helpLong); - - for (MCommand scmd : pcmd.subCommands) { - if (scmd.visibility == CommandVisibility.VISIBLE || (scmd.visibility == CommandVisibility.SECRET && scmd.validSenderPermissions(sender, false))) { - lines.add(scmd.getUseageTemplate(this.commandChain, true)); - } - } - - sendMessage(p.txt.getPage(lines, this.argAsInt(0, 1), TL.COMMAND_AUTOHELP_HELPFOR.toString() + pcmd.aliases.get(0) + "\"")); - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_HELP_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.zcore.CommandVisibility; +import com.massivecraft.factions.zcore.MCommand; +import com.massivecraft.factions.zcore.util.TL; + +import java.util.ArrayList; + +public class CmdAutoHelp extends MCommand { + + public CmdAutoHelp() { + super(SavageFactions.plugin); + this.aliases.add("?"); + this.aliases.add("h"); + this.aliases.add("help"); + + this.setHelpShort(""); + + this.optionalArgs.put("page", "1"); + } + + @Override + public void perform() { + + if (this.commandChain.size() == 0) { + return; + } + MCommand pcmd = this.commandChain.get(this.commandChain.size() - 1); + + ArrayList lines = new ArrayList<>(); + + lines.addAll(pcmd.helpLong); + + for (MCommand scmd : pcmd.subCommands) { + if (scmd.visibility == CommandVisibility.VISIBLE || (scmd.visibility == CommandVisibility.SECRET && scmd.validSenderPermissions(sender, false))) { + lines.add(scmd.getUseageTemplate(this.commandChain, true)); + } + } + + sendMessage(p.txt.getPage(lines, this.argAsInt(0, 1), TL.COMMAND_AUTOHELP_HELPFOR.toString() + pcmd.aliases.get(0) + "\"")); + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_HELP_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBan.java b/src/main/java/com/massivecraft/factions/cmd/CmdBan.java index 64551254..2bbe9f33 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBan.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBan.java @@ -15,87 +15,87 @@ import java.util.logging.Level; public class CmdBan extends FCommand { - public CmdBan() { - super(); - this.aliases.add("ban"); + public CmdBan() { + super(); + this.aliases.add("ban"); - this.requiredArgs.add("target"); + this.requiredArgs.add("target"); - this.permission = Permission.BAN.node; - this.disableOnLock = true; + this.permission = Permission.BAN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { + @Override + public void perform() { - // Adds bypass to admins and clean permission check - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.BAN); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "ban"); - return; - } - } + // Adds bypass to admins and clean permission check + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.BAN); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "ban"); + return; + } + } - // Good on permission checks. Now lets just ban the player. - FPlayer target = argAsFPlayer(0); - if (target == null) { - return; // the above method sends a message if fails to find someone. - } + // Good on permission checks. Now lets just ban the player. + FPlayer target = argAsFPlayer(0); + if (target == null) { + return; // the above method sends a message if fails to find someone. + } - if (fme == target) { - // You may not ban yourself - fme.msg(TL.COMMAND_BAN_SELF); - return; - } else if (target.getFaction() == myFaction && target.getRole().value >= fme.getRole().value) { - // You may not ban someone that has same or higher faction rank - fme.msg(TL.COMMAND_BAN_INSUFFICIENTRANK, target.getName()); - return; - } + if (fme == target) { + // You may not ban yourself + fme.msg(TL.COMMAND_BAN_SELF); + return; + } else if (target.getFaction() == myFaction && target.getRole().value >= fme.getRole().value) { + // You may not ban someone that has same or higher faction rank + fme.msg(TL.COMMAND_BAN_INSUFFICIENTRANK, target.getName()); + return; + } - for (BanInfo banInfo : myFaction.getBannedPlayers()) { - if (banInfo.getBanned().equals(target.getId())) { - msg(TL.COMMAND_BAN_ALREADYBANNED); - return; - } - } + for (BanInfo banInfo : myFaction.getBannedPlayers()) { + if (banInfo.getBanned().equals(target.getId())) { + msg(TL.COMMAND_BAN_ALREADYBANNED); + return; + } + } - // Ban the user. - myFaction.ban(target, fme); - myFaction.deinvite(target); // can't hurt + // Ban the user. + myFaction.ban(target, fme); + myFaction.deinvite(target); // can't hurt - // If in same Faction, lets make sure to kick them and throw an event. - if (target.getFaction() == myFaction) { + // If in same Faction, lets make sure to kick them and throw an event. + if (target.getFaction() == myFaction) { - FPlayerLeaveEvent event = new FPlayerLeaveEvent(target, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.BANNED); - Bukkit.getServer().getPluginManager().callEvent(event); + FPlayerLeaveEvent event = new FPlayerLeaveEvent(target, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.BANNED); + Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - // if someone cancels a ban, we'll get people complaining here. So lets log it. - SavageFactions.plugin.log(Level.WARNING, "Attempted to ban {0} but someone cancelled the kick event. This isn't good.", target.getName()); - return; - } + if (event.isCancelled()) { + // if someone cancels a ban, we'll get people complaining here. So lets log it. + SavageFactions.plugin.log(Level.WARNING, "Attempted to ban {0} but someone cancelled the kick event. This isn't good.", target.getName()); + return; + } - // Didn't get cancelled so remove them and reset their invite. - myFaction.removeFPlayer(target); - target.resetFactionData(); - } + // Didn't get cancelled so remove them and reset their invite. + myFaction.removeFPlayer(target); + target.resetFactionData(); + } - // Lets inform the people! - target.msg(TL.COMMAND_BAN_TARGET, myFaction.getTag(target.getFaction())); - myFaction.msg(TL.COMMAND_BAN_BANNED, fme.getName(), target.getName()); - } + // Lets inform the people! + target.msg(TL.COMMAND_BAN_TARGET, myFaction.getTag(target.getFaction())); + myFaction.msg(TL.COMMAND_BAN_BANNED, fme.getName(), target.getName()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BAN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BAN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java b/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java index 42d8c7e5..87154386 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBanlist.java @@ -13,60 +13,60 @@ import java.util.List; public class CmdBanlist extends FCommand { - public CmdBanlist() { - super(); - this.aliases.add("banlist"); - this.aliases.add("bans"); - this.aliases.add("banl"); + public CmdBanlist() { + super(); + this.aliases.add("banlist"); + this.aliases.add("bans"); + this.aliases.add("banl"); - this.optionalArgs.put("faction", "faction"); + this.optionalArgs.put("faction", "faction"); - this.permission = Permission.BAN.node; - this.disableOnLock = true; + this.permission = Permission.BAN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction target = myFaction; - if (!args.isEmpty()) { - target = argAsFaction(0); - } + @Override + public void perform() { + Faction target = myFaction; + if (!args.isEmpty()) { + target = argAsFaction(0); + } - if (target == Factions.getInstance().getWilderness()) { - sender.sendMessage(TL.COMMAND_BANLIST_NOFACTION.toString()); - return; - } + if (target == Factions.getInstance().getWilderness()) { + sender.sendMessage(TL.COMMAND_BANLIST_NOFACTION.toString()); + return; + } - if (target == null) { - sender.sendMessage(TL.COMMAND_BANLIST_INVALID.format(argAsString(0))); - return; - } + if (target == null) { + sender.sendMessage(TL.COMMAND_BANLIST_INVALID.format(argAsString(0))); + return; + } - List lines = new ArrayList<>(); - lines.add(TL.COMMAND_BANLIST_HEADER.format(target.getBannedPlayers().size(), target.getTag(myFaction))); - int i = 1; + List lines = new ArrayList<>(); + lines.add(TL.COMMAND_BANLIST_HEADER.format(target.getBannedPlayers().size(), target.getTag(myFaction))); + int i = 1; - for (BanInfo info : target.getBannedPlayers()) { - FPlayer banned = FPlayers.getInstance().getById(info.getBanned()); - FPlayer banner = FPlayers.getInstance().getById(info.getBanner()); - String timestamp = TL.sdf.format(info.getTime()); + for (BanInfo info : target.getBannedPlayers()) { + FPlayer banned = FPlayers.getInstance().getById(info.getBanned()); + FPlayer banner = FPlayers.getInstance().getById(info.getBanner()); + String timestamp = TL.sdf.format(info.getTime()); - lines.add(TL.COMMAND_BANLIST_ENTRY.format(i, banned.getName(), banner.getName(), timestamp)); - i++; - } + lines.add(TL.COMMAND_BANLIST_ENTRY.format(i, banned.getName(), banner.getName(), timestamp)); + i++; + } - for (String s : lines) { - fme.sendMessage(s); - } - } + for (String s : lines) { + fme.sendMessage(s); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BANLIST_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BANLIST_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java b/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java index 7f8e6fa6..46960073 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBanner.java @@ -13,123 +13,123 @@ import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; public class CmdBanner extends FCommand { - public CmdBanner() { - super(); + public CmdBanner() { + super(); - this.aliases.add("banner"); - this.aliases.add("warbanner"); + this.aliases.add("banner"); + this.aliases.add("warbanner"); - this.permission = Permission.BANNER.node; - this.disableOnLock = false; + this.permission = Permission.BANNER.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { - msg(TL.COMMAND_BANNER_DISABLED); - return; - } - if (!fme.hasMoney(SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000))) { - msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); - return; - } - takeMoney(fme, SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000)); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { + msg(TL.COMMAND_BANNER_DISABLED); + return; + } + if (!fme.hasMoney(SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000))) { + msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); + return; + } + takeMoney(fme, SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Cost", 5000)); - //ItemStack warBanner = SavageFactions.plugin.createItem(Material.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); - //BannerMeta bannerMeta = (BannerMeta) warBanner.getItemMeta(); - ItemStack warBanner = fme.getFaction().getBanner(); - if (warBanner != null) { - ItemMeta warmeta = warBanner.getItemMeta(); - warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); - warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); - warBanner.setItemMeta(warmeta); + //ItemStack warBanner = SavageFactions.plugin.createItem(Material.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); + //BannerMeta bannerMeta = (BannerMeta) warBanner.getItemMeta(); + ItemStack warBanner = fme.getFaction().getBanner(); + if (warBanner != null) { + ItemMeta warmeta = warBanner.getItemMeta(); + warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); + warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); + warBanner.setItemMeta(warmeta); - } else { + } else { - warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); - } - fme.msg(TL.COMMAND_BANNER_SUCCESS); - warBanner.setAmount(1); - me.getInventory().addItem(warBanner); - } + warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); + } + fme.msg(TL.COMMAND_BANNER_SUCCESS); + warBanner.setAmount(1); + me.getInventory().addItem(warBanner); + } - public boolean hasMoney(FPlayer fme, int amt) { - Economy econ = SavageFactions.plugin.getEcon(); - if (econ.getBalance(fme.getPlayer()) >= amt) { - return true; - } else { - fme.msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); - return false; - } - } + public boolean hasMoney(FPlayer fme, int amt) { + Economy econ = SavageFactions.plugin.getEcon(); + if (econ.getBalance(fme.getPlayer()) >= amt) { + return true; + } else { + fme.msg(TL.COMMAND_BANNER_NOTENOUGHMONEY); + return false; + } + } - public void takeMoney(FPlayer fme, int amt) { - if (hasMoney(fme, amt)) { - Economy econ = SavageFactions.plugin.getEcon(); - econ.withdrawPlayer(fme.getPlayer(), amt); - fme.sendMessage(TL.COMMAND_BANNER_MONEYTAKE.toString().replace("{amount}", amt + "")); - } - } + public void takeMoney(FPlayer fme, int amt) { + if (hasMoney(fme, amt)) { + Economy econ = SavageFactions.plugin.getEcon(); + econ.withdrawPlayer(fme.getPlayer(), amt); + fme.sendMessage(TL.COMMAND_BANNER_MONEYTAKE.toString().replace("{amount}", amt + "")); + } + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - public void removeFromInventory(Inventory inventory, ItemStack item) { - int amt = item.getAmount(); - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - if (items[i].getAmount() > amt) { - items[i].setAmount(items[i].getAmount() - amt); - break; - } else if (items[i].getAmount() == amt) { - items[i] = null; - break; - } else { - amt -= items[i].getAmount(); - items[i] = null; - } - } - } - inventory.setContents(items); - } + public void removeFromInventory(Inventory inventory, ItemStack item) { + int amt = item.getAmount(); + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + if (items[i].getAmount() > amt) { + items[i].setAmount(items[i].getAmount() - amt); + break; + } else if (items[i].getAmount() == amt) { + items[i] = null; + break; + } else { + amt -= items[i].getAmount(); + items[i] = null; + } + } + } + inventory.setContents(items); + } - public int getEmptySlots(Player p) { - PlayerInventory inventory = p.getInventory(); - ItemStack[] cont = inventory.getContents(); - int i = 0; - for (ItemStack item : cont) - if (item != null && item.getType() != Material.AIR) { - i++; - } - return 36 - i; - } + public int getEmptySlots(Player p) { + PlayerInventory inventory = p.getInventory(); + ItemStack[] cont = inventory.getContents(); + int i = 0; + for (ItemStack item : cont) + if (item != null && item.getType() != Material.AIR) { + i++; + } + return 36 - i; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BANNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BANNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java b/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java index fcbe859f..514a5c67 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBoom.java @@ -6,47 +6,47 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdBoom extends FCommand { - public CmdBoom() { - super(); - this.aliases.add("noboom"); - this.aliases.add("explosions"); - this.aliases.add("toggleexplosions"); + public CmdBoom() { + super(); + this.aliases.add("noboom"); + this.aliases.add("explosions"); + this.aliases.add("toggleexplosions"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.NO_BOOM.node; - this.disableOnLock = true; + this.permission = Permission.NO_BOOM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!myFaction.isPeaceful()) { - fme.msg(TL.COMMAND_BOOM_PEACEFULONLY); - return; - } + @Override + public void perform() { + if (!myFaction.isPeaceful()) { + fme.msg(TL.COMMAND_BOOM_PEACEFULONLY); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostNoBoom, TL.COMMAND_BOOM_TOTOGGLE, TL.COMMAND_BOOM_FORTOGGLE)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostNoBoom, TL.COMMAND_BOOM_TOTOGGLE, TL.COMMAND_BOOM_FORTOGGLE)) { + return; + } - myFaction.setPeacefulExplosionsEnabled(this.argAsBool(0, !myFaction.getPeacefulExplosionsEnabled())); + myFaction.setPeacefulExplosionsEnabled(this.argAsBool(0, !myFaction.getPeacefulExplosionsEnabled())); - String enabled = myFaction.noExplosionsInTerritory() ? TL.GENERIC_DISABLED.toString() : TL.GENERIC_ENABLED.toString(); + String enabled = myFaction.noExplosionsInTerritory() ? TL.GENERIC_DISABLED.toString() : TL.GENERIC_ENABLED.toString(); - // Inform - myFaction.msg(TL.COMMAND_BOOM_ENABLED, fme.describeTo(myFaction), enabled); - } + // Inform + myFaction.msg(TL.COMMAND_BOOM_ENABLED, fme.describeTo(myFaction), enabled); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BOOM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BOOM_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java b/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java index 3dd55678..410d1865 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdBypass.java @@ -6,39 +6,39 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdBypass extends FCommand { - public CmdBypass() { - super(); - this.aliases.add("bypass"); + public CmdBypass() { + super(); + this.aliases.add("bypass"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.BYPASS.node; - this.disableOnLock = false; + this.permission = Permission.BYPASS.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - fme.setIsAdminBypassing(this.argAsBool(0, !fme.isAdminBypassing())); + @Override + public void perform() { + fme.setIsAdminBypassing(this.argAsBool(0, !fme.isAdminBypassing())); - // TODO: Move this to a transient field in the model?? - if (fme.isAdminBypassing()) { - fme.msg(TL.COMMAND_BYPASS_ENABLE.toString()); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_ENABLELOG.toString()); - } else { - fme.msg(TL.COMMAND_BYPASS_DISABLE.toString()); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_DISABLELOG.toString()); - } - } + // TODO: Move this to a transient field in the model?? + if (fme.isAdminBypassing()) { + fme.msg(TL.COMMAND_BYPASS_ENABLE.toString()); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_ENABLELOG.toString()); + } else { + fme.msg(TL.COMMAND_BYPASS_DISABLE.toString()); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_BYPASS_DISABLELOG.toString()); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_BYPASS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_BYPASS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdChat.java b/src/main/java/com/massivecraft/factions/cmd/CmdChat.java index 983868c0..ffda5965 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdChat.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdChat.java @@ -8,80 +8,80 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdChat extends FCommand { - public CmdChat() { - super(); - this.aliases.add("c"); - this.aliases.add("chat"); + public CmdChat() { + super(); + this.aliases.add("c"); + this.aliases.add("chat"); - //this.requiredArgs.add(""); - this.optionalArgs.put("mode", "next"); + //this.requiredArgs.add(""); + this.optionalArgs.put("mode", "next"); - this.permission = Permission.CHAT.node; - this.disableOnLock = false; + this.permission = Permission.CHAT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!Conf.factionOnlyChat) { - msg(TL.COMMAND_CHAT_DISABLED.toString()); - return; - } + @Override + public void perform() { + if (!Conf.factionOnlyChat) { + msg(TL.COMMAND_CHAT_DISABLED.toString()); + return; + } - String modeString = this.argAsString(0); - ChatMode modeTarget = fme.getChatMode().getNext(); + String modeString = this.argAsString(0); + ChatMode modeTarget = fme.getChatMode().getNext(); - if (modeString != null) { - modeString = modeString.toLowerCase(); - // Only allow Mods and higher rank to switch to this channel. - if (modeString.startsWith("m")) { - if (!fme.getRole().isAtLeast(Role.MODERATOR)) { - msg(TL.COMMAND_CHAT_MOD_ONLY); - return; - } else modeTarget = ChatMode.MOD; - } else if (modeString.startsWith("p")) { - modeTarget = ChatMode.PUBLIC; - } else if (modeString.startsWith("a")) { - modeTarget = ChatMode.ALLIANCE; - } else if (modeString.startsWith("f")) { - modeTarget = ChatMode.FACTION; - } else if (modeString.startsWith("t")) { - modeTarget = ChatMode.TRUCE; - } else { - msg(TL.COMMAND_CHAT_INVALIDMODE); - return; - } - } + if (modeString != null) { + modeString = modeString.toLowerCase(); + // Only allow Mods and higher rank to switch to this channel. + if (modeString.startsWith("m")) { + if (!fme.getRole().isAtLeast(Role.MODERATOR)) { + msg(TL.COMMAND_CHAT_MOD_ONLY); + return; + } else modeTarget = ChatMode.MOD; + } else if (modeString.startsWith("p")) { + modeTarget = ChatMode.PUBLIC; + } else if (modeString.startsWith("a")) { + modeTarget = ChatMode.ALLIANCE; + } else if (modeString.startsWith("f")) { + modeTarget = ChatMode.FACTION; + } else if (modeString.startsWith("t")) { + modeTarget = ChatMode.TRUCE; + } else { + msg(TL.COMMAND_CHAT_INVALIDMODE); + return; + } + } - fme.setChatMode(modeTarget); + fme.setChatMode(modeTarget); - switch (fme.getChatMode()) { - case MOD: - msg(TL.COMMAND_CHAT_MODE_MOD); - break; - case PUBLIC: - msg(TL.COMMAND_CHAT_MODE_PUBLIC); - break; - case ALLIANCE: - msg(TL.COMMAND_CHAT_MODE_ALLIANCE); - break; - case TRUCE: - msg(TL.COMMAND_CHAT_MODE_TRUCE); - break; - default: - msg(TL.COMMAND_CHAT_MODE_FACTION); - break; - } - } + switch (fme.getChatMode()) { + case MOD: + msg(TL.COMMAND_CHAT_MODE_MOD); + break; + case PUBLIC: + msg(TL.COMMAND_CHAT_MODE_PUBLIC); + break; + case ALLIANCE: + msg(TL.COMMAND_CHAT_MODE_ALLIANCE); + break; + case TRUCE: + msg(TL.COMMAND_CHAT_MODE_TRUCE); + break; + default: + msg(TL.COMMAND_CHAT_MODE_FACTION); + break; + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CHAT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CHAT_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java b/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java index f6cd198f..d8d1b4e3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdChatSpy.java @@ -6,37 +6,37 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdChatSpy extends FCommand { - public CmdChatSpy() { - super(); - this.aliases.add("chatspy"); + public CmdChatSpy() { + super(); + this.aliases.add("chatspy"); - this.optionalArgs.put("on/off", "flip"); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.CHATSPY.node; - this.disableOnLock = false; + this.permission = Permission.CHATSPY.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - fme.setSpyingChat(this.argAsBool(0, !fme.isSpyingChat())); + @Override + public void perform() { + fme.setSpyingChat(this.argAsBool(0, !fme.isSpyingChat())); - if (fme.isSpyingChat()) { - fme.msg(TL.COMMAND_CHATSPY_ENABLE); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_ENABLELOG.toString()); - } else { - fme.msg(TL.COMMAND_CHATSPY_DISABLE); - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_DISABLELOG.toString()); - } - } + if (fme.isSpyingChat()) { + fme.msg(TL.COMMAND_CHATSPY_ENABLE); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_ENABLELOG.toString()); + } else { + fme.msg(TL.COMMAND_CHATSPY_DISABLE); + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CHATSPY_DISABLELOG.toString()); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CHATSPY_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CHATSPY_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java b/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java index 01021f8d..fe153b0a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCheckpoint.java @@ -6,66 +6,66 @@ import com.massivecraft.factions.util.WarmUpUtil; import com.massivecraft.factions.zcore.util.TL; public class CmdCheckpoint extends FCommand { - public CmdCheckpoint() { - super(); - this.aliases.add("checkp"); - this.aliases.add("checkpoint"); - this.aliases.add("cpoint"); + public CmdCheckpoint() { + super(); + this.aliases.add("checkp"); + this.aliases.add("checkpoint"); + this.aliases.add("cpoint"); - this.optionalArgs.put("set", ""); + this.optionalArgs.put("set", ""); - this.permission = Permission.CHECKPOINT.node; - this.disableOnLock = false; + this.permission = Permission.CHECKPOINT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("checkpoints.Enabled")) { - fme.msg(TL.COMMAND_CHECKPOINT_DISABLED); - return; - } - if (args.size() == 1) { - FLocation myLocation = new FLocation(fme.getPlayer().getLocation()); - Faction myLocFaction = Board.getInstance().getFactionAt(myLocation); - if (myLocFaction == Factions.getInstance().getWilderness() || myLocFaction == fme.getFaction()) { - fme.getFaction().setCheckpoint(fme.getPlayer().getLocation()); - fme.msg(TL.COMMAND_CHECKPOINT_SET); - return; - } else { - fme.msg(TL.COMMAND_CHECKPOINT_INVALIDLOCATION); - return; - } - } - if (fme.getFaction().getCheckpoint() == null) { - fme.msg(TL.COMMAND_CHECKPOINT_NOT_SET); - return; - } - FLocation checkLocation = new FLocation(fme.getFaction().getCheckpoint()); - Faction checkfaction = Board.getInstance().getFactionAt(checkLocation); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("checkpoints.Enabled")) { + fme.msg(TL.COMMAND_CHECKPOINT_DISABLED); + return; + } + if (args.size() == 1) { + FLocation myLocation = new FLocation(fme.getPlayer().getLocation()); + Faction myLocFaction = Board.getInstance().getFactionAt(myLocation); + if (myLocFaction == Factions.getInstance().getWilderness() || myLocFaction == fme.getFaction()) { + fme.getFaction().setCheckpoint(fme.getPlayer().getLocation()); + fme.msg(TL.COMMAND_CHECKPOINT_SET); + return; + } else { + fme.msg(TL.COMMAND_CHECKPOINT_INVALIDLOCATION); + return; + } + } + if (fme.getFaction().getCheckpoint() == null) { + fme.msg(TL.COMMAND_CHECKPOINT_NOT_SET); + return; + } + FLocation checkLocation = new FLocation(fme.getFaction().getCheckpoint()); + Faction checkfaction = Board.getInstance().getFactionAt(checkLocation); - if (checkfaction.getId().equals(Factions.getInstance().getWilderness().getId()) || checkfaction.getId().equals(fme.getFaction().getId())) { - fme.msg(TL.COMMAND_CHECKPOINT_GO); - this.doWarmUp(WarmUpUtil.Warmup.CHECKPOINT, TL.WARMUPS_NOTIFY_TELEPORT, "Checkpoint", new Runnable() { - @Override - public void run() { - fme.getPlayer().teleport(fme.getFaction().getCheckpoint()); - } - }, this.p.getConfig().getLong("warmups.f-checkpoint", 0)); - } else { - fme.msg(TL.COMMAND_CHECKPOINT_CLAIMED); - } + if (checkfaction.getId().equals(Factions.getInstance().getWilderness().getId()) || checkfaction.getId().equals(fme.getFaction().getId())) { + fme.msg(TL.COMMAND_CHECKPOINT_GO); + this.doWarmUp(WarmUpUtil.Warmup.CHECKPOINT, TL.WARMUPS_NOTIFY_TELEPORT, "Checkpoint", new Runnable() { + @Override + public void run() { + fme.getPlayer().teleport(fme.getFaction().getCheckpoint()); + } + }, this.p.getConfig().getLong("warmups.f-checkpoint", 0)); + } else { + fme.msg(TL.COMMAND_CHECKPOINT_CLAIMED); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CHECKPOINT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CHECKPOINT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdChest.java b/src/main/java/com/massivecraft/factions/cmd/CmdChest.java index f007b99b..8fcb0d7a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdChest.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdChest.java @@ -9,47 +9,47 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdChest extends FCommand { - public CmdChest() { - this.aliases.add("chest"); - this.aliases.add("pv"); + public CmdChest() { + this.aliases.add("chest"); + this.aliases.add("pv"); - //this.requiredArgs.add(""); + //this.requiredArgs.add(""); - this.permission = Permission.CHEST.node; - this.disableOnLock = false; + this.permission = Permission.CHEST.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { + @Override + public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fchest.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - // This permission check is way too explicit but it's clean - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.CHEST); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "access chest"); - return; - } - } + if (!SavageFactions.plugin.getConfig().getBoolean("fchest.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + // This permission check is way too explicit but it's clean + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.CHEST); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "access chest"); + return; + } + } - me.openInventory(fme.getFaction().getChestInventory()); + me.openInventory(fme.getFaction().getChestInventory()); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_VAULT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_VAULT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java index f0e4077d..9fa20093 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdClaim.java @@ -14,82 +14,82 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdClaim extends FCommand { - public CmdClaim() { - super(); - this.aliases.add("claim"); + public CmdClaim() { + super(); + this.aliases.add("claim"); - //this.requiredArgs.add(""); - this.optionalArgs.put("radius", "1"); - this.optionalArgs.put("faction", "your"); + //this.requiredArgs.add(""); + this.optionalArgs.put("radius", "1"); + this.optionalArgs.put("faction", "your"); - this.permission = Permission.CLAIM.node; - this.disableOnLock = true; + this.permission = Permission.CLAIM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // Read and validate input - int radius = this.argAsInt(0, 1); // Default to 1 - final Faction forFaction = this.argAsFaction(1, myFaction); // Default to own + @Override + public void perform() { + // Read and validate input + int radius = this.argAsInt(0, 1); // Default to 1 + final Faction forFaction = this.argAsFaction(1, myFaction); // Default to own - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "change faction territory"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "change faction territory"); + return; + } + } - if (forFaction.isWilderness()) { - CmdUnclaim cmdUnclaim = SavageFactions.plugin.cmdBase.cmdUnclaim; - cmdUnclaim.execute(sender, args.size() > 1 ? args.subList(0, 1) : args); - return; - } + if (forFaction.isWilderness()) { + CmdUnclaim cmdUnclaim = SavageFactions.plugin.cmdBase.cmdUnclaim; + cmdUnclaim.execute(sender, args.size() > 1 ? args.subList(0, 1) : args); + return; + } - if (radius < 1) { - msg(TL.COMMAND_CLAIM_INVALIDRADIUS); - return; - } + if (radius < 1) { + msg(TL.COMMAND_CLAIM_INVALIDRADIUS); + return; + } - if (radius < 2) { - // single chunk - fme.attemptClaim(forFaction, me.getLocation(), true); - } else { - // radius claim - if (!Permission.CLAIM_RADIUS.has(sender, false)) { - msg(TL.COMMAND_CLAIM_DENIED); - return; - } + if (radius < 2) { + // single chunk + fme.attemptClaim(forFaction, me.getLocation(), true); + } else { + // radius claim + if (!Permission.CLAIM_RADIUS.has(sender, false)) { + msg(TL.COMMAND_CLAIM_DENIED); + return; + } - new SpiralTask(new FLocation(me), radius) { - private final int limit = Conf.radiusClaimFailureLimit - 1; - private int failCount = 0; + new SpiralTask(new FLocation(me), radius) { + private final int limit = Conf.radiusClaimFailureLimit - 1; + private int failCount = 0; - @Override - public boolean work() { - boolean success = fme.attemptClaim(forFaction, this.currentLocation(), true); - if (success) { - failCount = 0; - } else if (failCount++ >= limit) { - this.stop(); - return false; - } + @Override + public boolean work() { + boolean success = fme.attemptClaim(forFaction, this.currentLocation(), true); + if (success) { + failCount = 0; + } else if (failCount++ >= limit) { + this.stop(); + return false; + } - return true; - } - }; - } - } + return true; + } + }; + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CLAIM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CLAIM_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java b/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java index feee8c76..2b2bf2b3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdClaimAt.java @@ -6,35 +6,35 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdClaimAt extends FCommand { - public CmdClaimAt() { - super(); - this.aliases.add("claimat"); + public CmdClaimAt() { + super(); + this.aliases.add("claimat"); - this.requiredArgs.add("world"); - this.requiredArgs.add("x"); - this.requiredArgs.add("z"); + this.requiredArgs.add("world"); + this.requiredArgs.add("x"); + this.requiredArgs.add("z"); - this.permission = Permission.CLAIMAT.node; - this.disableOnLock = true; + this.permission = Permission.CLAIMAT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - int x = argAsInt(1); - int z = argAsInt(2); - FLocation location = new FLocation(argAsString(0), x, z); - fme.attemptClaim(myFaction, location, true); - } + @Override + public void perform() { + int x = argAsInt(1); + int z = argAsInt(2); + FLocation location = new FLocation(argAsString(0), x, z); + fme.attemptClaim(myFaction, location, true); + } - @Override - public TL getUsageTranslation() { - return null; - } + @Override + public TL getUsageTranslation() { + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java b/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java index e3507db5..fad5124f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdClaimLine.java @@ -9,70 +9,70 @@ import org.bukkit.block.BlockFace; public class CmdClaimLine extends FCommand { - public static final BlockFace[] axis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST}; + public static final BlockFace[] axis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST}; - public CmdClaimLine() { + public CmdClaimLine() { - // Aliases - this.aliases.add("claimline"); - this.aliases.add("cl"); + // Aliases + this.aliases.add("claimline"); + this.aliases.add("cl"); - // Args - this.optionalArgs.put("amount", "1"); - this.optionalArgs.put("direction", "facing"); - this.optionalArgs.put("faction", "you"); + // Args + this.optionalArgs.put("amount", "1"); + this.optionalArgs.put("direction", "facing"); + this.optionalArgs.put("faction", "you"); - this.permission = Permission.CLAIM_LINE.node; - this.disableOnLock = true; + this.permission = Permission.CLAIM_LINE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // Args - Integer amount = this.argAsInt(0, 1); // Default to 1 + @Override + public void perform() { + // Args + Integer amount = this.argAsInt(0, 1); // Default to 1 - if (amount > Conf.lineClaimLimit) { - fme.msg(TL.COMMAND_CLAIMLINE_ABOVEMAX, Conf.lineClaimLimit); - return; - } + if (amount > Conf.lineClaimLimit) { + fme.msg(TL.COMMAND_CLAIMLINE_ABOVEMAX, Conf.lineClaimLimit); + return; + } - String direction = this.argAsString(1); - BlockFace blockFace; + String direction = this.argAsString(1); + BlockFace blockFace; - if (direction == null) { - blockFace = axis[Math.round(me.getLocation().getYaw() / 90f) & 0x3]; - } else if (direction.equalsIgnoreCase("north")) { - blockFace = BlockFace.NORTH; - } else if (direction.equalsIgnoreCase("east")) { - blockFace = BlockFace.EAST; - } else if (direction.equalsIgnoreCase("south")) { - blockFace = BlockFace.SOUTH; - } else if (direction.equalsIgnoreCase("west")) { - blockFace = BlockFace.WEST; - } else { - fme.msg(TL.COMMAND_CLAIMLINE_NOTVALID, direction); - return; - } + if (direction == null) { + blockFace = axis[Math.round(me.getLocation().getYaw() / 90f) & 0x3]; + } else if (direction.equalsIgnoreCase("north")) { + blockFace = BlockFace.NORTH; + } else if (direction.equalsIgnoreCase("east")) { + blockFace = BlockFace.EAST; + } else if (direction.equalsIgnoreCase("south")) { + blockFace = BlockFace.SOUTH; + } else if (direction.equalsIgnoreCase("west")) { + blockFace = BlockFace.WEST; + } else { + fme.msg(TL.COMMAND_CLAIMLINE_NOTVALID, direction); + return; + } - final Faction forFaction = this.argAsFaction(2, myFaction); - Location location = me.getLocation(); + final Faction forFaction = this.argAsFaction(2, myFaction); + Location location = me.getLocation(); - // TODO: make this a task like claiming a radius? - for (int i = 0; i < amount; i++) { - fme.attemptClaim(forFaction, location, true); - location = location.add(blockFace.getModX() * 16, 0, blockFace.getModZ() * 16); - } - } + // TODO: make this a task like claiming a radius? + for (int i = 0; i < amount; i++) { + fme.attemptClaim(forFaction, location, true); + location = location.add(blockFace.getModX() * 16, 0, blockFace.getModZ() * 16); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CLAIMLINE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CLAIMLINE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java b/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java index f1aaefca..926df953 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdColeader.java @@ -10,82 +10,82 @@ import mkremins.fanciful.FancyMessage; import org.bukkit.ChatColor; public class CmdColeader extends FCommand { - public CmdColeader() { - super(); - this.aliases.add("co"); - this.aliases.add("setcoleader"); - this.aliases.add("coleader"); - this.aliases.add("setco"); + public CmdColeader() { + super(); + this.aliases.add("co"); + this.aliases.add("setcoleader"); + this.aliases.add("coleader"); + this.aliases.add("setco"); - this.optionalArgs.put("player name", "name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.COLEADER.node; - this.disableOnLock = true; + this.permission = Permission.COLEADER.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = true; - } + senderMustBePlayer = false; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = true; + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (you == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_COLEADER_CANDIDATES.toString()).color(ChatColor.GOLD); - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); - } - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (you == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_COLEADER_CANDIDATES.toString()).color(ChatColor.GOLD); + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); + } + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " coleader " + s); + } - sendFancyMessage(msg); - return; - } + sendFancyMessage(msg); + return; + } - boolean permAny = Permission.COLEADER_ANY.has(sender, false); - Faction targetFaction = you.getFaction(); + boolean permAny = Permission.COLEADER_ANY.has(sender, false); + Faction targetFaction = you.getFaction(); - if (targetFaction != myFaction && !permAny) { - msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); - return; - } + if (targetFaction != myFaction && !permAny) { + msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); + return; + } - if (fme != null && fme.getRole() != Role.LEADER && !permAny) { - msg(TL.COMMAND_COLEADER_NOTADMIN); - return; - } + if (fme != null && fme.getRole() != Role.LEADER && !permAny) { + msg(TL.COMMAND_COLEADER_NOTADMIN); + return; + } - if (you == fme && !permAny) { - msg(TL.COMMAND_COLEADER_SELF); - return; - } + if (you == fme && !permAny) { + msg(TL.COMMAND_COLEADER_SELF); + return; + } - if (you.getRole() == Role.LEADER) { - msg(TL.COMMAND_COLEADER_TARGETISADMIN); - return; - } + if (you.getRole() == Role.LEADER) { + msg(TL.COMMAND_COLEADER_TARGETISADMIN); + return; + } - if (you.getRole() == Role.COLEADER) { - // Revoke - you.setRole(Role.MODERATOR); - targetFaction.msg(TL.COMMAND_COLEADER_REVOKED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_COLEADER_REVOKES, you.describeTo(fme, true)); - } else { - // Give - you.setRole(Role.COLEADER); - targetFaction.msg(TL.COMMAND_COLEADER_PROMOTED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_COLEADER_PROMOTES, you.describeTo(fme, true)); - } - } + if (you.getRole() == Role.COLEADER) { + // Revoke + you.setRole(Role.MODERATOR); + targetFaction.msg(TL.COMMAND_COLEADER_REVOKED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_COLEADER_REVOKES, you.describeTo(fme, true)); + } else { + // Give + you.setRole(Role.COLEADER); + targetFaction.msg(TL.COMMAND_COLEADER_PROMOTED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_COLEADER_PROMOTES, you.describeTo(fme, true)); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_COLEADER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_COLEADER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java b/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java index 6717b53e..3d65283e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdConfig.java @@ -16,234 +16,234 @@ import java.util.Set; public class CmdConfig extends FCommand { - private static HashMap properFieldNames = new HashMap<>(); + private static HashMap properFieldNames = new HashMap<>(); - public CmdConfig() { - super(); - this.aliases.add("config"); + public CmdConfig() { + super(); + this.aliases.add("config"); - this.requiredArgs.add("setting"); - this.requiredArgs.add("value"); - this.errorOnToManyArgs = false; + this.requiredArgs.add("setting"); + this.requiredArgs.add("value"); + this.errorOnToManyArgs = false; - this.permission = Permission.CONFIG.node; - this.disableOnLock = true; + this.permission = Permission.CONFIG.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // store a lookup map of lowercase field names paired with proper capitalization field names - // that way, if the person using this command messes up the capitalization, we can fix that - if (properFieldNames.isEmpty()) { - Field[] fields = Conf.class.getDeclaredFields(); - for (Field field : fields) { - properFieldNames.put(field.getName().toLowerCase(), field.getName()); - } - } + @Override + public void perform() { + // store a lookup map of lowercase field names paired with proper capitalization field names + // that way, if the person using this command messes up the capitalization, we can fix that + if (properFieldNames.isEmpty()) { + Field[] fields = Conf.class.getDeclaredFields(); + for (Field field : fields) { + properFieldNames.put(field.getName().toLowerCase(), field.getName()); + } + } - String field = this.argAsString(0).toLowerCase(); - if (field.startsWith("\"") && field.endsWith("\"")) { - field = field.substring(1, field.length() - 1); - } - String fieldName = properFieldNames.get(field); + String field = this.argAsString(0).toLowerCase(); + if (field.startsWith("\"") && field.endsWith("\"")) { + field = field.substring(1, field.length() - 1); + } + String fieldName = properFieldNames.get(field); - if (fieldName == null || fieldName.isEmpty()) { - msg(TL.COMMAND_CONFIG_NOEXIST, field); - return; - } + if (fieldName == null || fieldName.isEmpty()) { + msg(TL.COMMAND_CONFIG_NOEXIST, field); + return; + } - String success; + String success; - StringBuilder value = new StringBuilder(args.get(1)); - for (int i = 2; i < args.size(); i++) { - value.append(' ').append(args.get(i)); - } + StringBuilder value = new StringBuilder(args.get(1)); + for (int i = 2; i < args.size(); i++) { + value.append(' ').append(args.get(i)); + } - try { - Field target = Conf.class.getField(fieldName); + try { + Field target = Conf.class.getField(fieldName); - // boolean - if (target.getType() == boolean.class) { - boolean targetValue = this.strAsBool(value.toString()); - target.setBoolean(null, targetValue); + // boolean + if (target.getType() == boolean.class) { + boolean targetValue = this.strAsBool(value.toString()); + target.setBoolean(null, targetValue); - if (targetValue) { - success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_TRUE.toString(); - } else { - success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_FALSE.toString(); - } - } + if (targetValue) { + success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_TRUE.toString(); + } else { + success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_FALSE.toString(); + } + } - // int - else if (target.getType() == int.class) { - try { - int intVal = Integer.parseInt(value.toString()); - target.setInt(null, intVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + intVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_INTREQUIRED.format(fieldName)); - return; - } - } + // int + else if (target.getType() == int.class) { + try { + int intVal = Integer.parseInt(value.toString()); + target.setInt(null, intVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + intVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_INTREQUIRED.format(fieldName)); + return; + } + } - // long - else if (target.getType() == long.class) { - try { - long longVal = Long.parseLong(value.toString()); - target.setLong(null, longVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + longVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_LONGREQUIRED.format(fieldName)); - return; - } - } + // long + else if (target.getType() == long.class) { + try { + long longVal = Long.parseLong(value.toString()); + target.setLong(null, longVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + longVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_LONGREQUIRED.format(fieldName)); + return; + } + } - // double - else if (target.getType() == double.class) { - try { - double doubleVal = Double.parseDouble(value.toString()); - target.setDouble(null, doubleVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + doubleVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_DOUBLEREQUIRED.format(fieldName)); - return; - } - } + // double + else if (target.getType() == double.class) { + try { + double doubleVal = Double.parseDouble(value.toString()); + target.setDouble(null, doubleVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + doubleVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_DOUBLEREQUIRED.format(fieldName)); + return; + } + } - // float - else if (target.getType() == float.class) { - try { - float floatVal = Float.parseFloat(value.toString()); - target.setFloat(null, floatVal); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + floatVal + "."; - } catch (NumberFormatException ex) { - sendMessage(TL.COMMAND_CONFIG_FLOATREQUIRED.format(fieldName)); - return; - } - } + // float + else if (target.getType() == float.class) { + try { + float floatVal = Float.parseFloat(value.toString()); + target.setFloat(null, floatVal); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + floatVal + "."; + } catch (NumberFormatException ex) { + sendMessage(TL.COMMAND_CONFIG_FLOATREQUIRED.format(fieldName)); + return; + } + } - // String - else if (target.getType() == String.class) { - target.set(null, value.toString()); - success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + value + "\"."; - } + // String + else if (target.getType() == String.class) { + target.set(null, value.toString()); + success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + value + "\"."; + } - // ChatColor - else if (target.getType() == ChatColor.class) { - ChatColor newColor = null; - try { - newColor = ChatColor.valueOf(value.toString().toUpperCase()); - } catch (IllegalArgumentException ex) { + // ChatColor + else if (target.getType() == ChatColor.class) { + ChatColor newColor = null; + try { + newColor = ChatColor.valueOf(value.toString().toUpperCase()); + } catch (IllegalArgumentException ex) { - } - if (newColor == null) { - sendMessage(TL.COMMAND_CONFIG_INVALID_COLOUR.format(fieldName, value.toString().toUpperCase())); - return; - } - target.set(null, newColor); - success = "\"" + fieldName + TL.COMMAND_CONFIG_COLOURSET.toString() + value.toString().toUpperCase() + "\"."; - } + } + if (newColor == null) { + sendMessage(TL.COMMAND_CONFIG_INVALID_COLOUR.format(fieldName, value.toString().toUpperCase())); + return; + } + target.set(null, newColor); + success = "\"" + fieldName + TL.COMMAND_CONFIG_COLOURSET.toString() + value.toString().toUpperCase() + "\"."; + } - // Set or other parameterized collection - else if (target.getGenericType() instanceof ParameterizedType) { - ParameterizedType targSet = (ParameterizedType) target.getGenericType(); - Type innerType = targSet.getActualTypeArguments()[0]; + // Set or other parameterized collection + else if (target.getGenericType() instanceof ParameterizedType) { + ParameterizedType targSet = (ParameterizedType) target.getGenericType(); + Type innerType = targSet.getActualTypeArguments()[0]; - // not a Set, somehow, and that should be the only collection we're using in Conf.java - if (targSet.getRawType() != Set.class) { - sendMessage(TL.COMMAND_CONFIG_INVALID_COLLECTION.format(fieldName)); - return; - } + // not a Set, somehow, and that should be the only collection we're using in Conf.java + if (targSet.getRawType() != Set.class) { + sendMessage(TL.COMMAND_CONFIG_INVALID_COLLECTION.format(fieldName)); + return; + } - // Set - else if (innerType == Material.class) { - Material newMat = null; - try { - newMat = Material.valueOf(value.toString().toUpperCase()); - } catch (IllegalArgumentException ex) { + // Set + else if (innerType == Material.class) { + Material newMat = null; + try { + newMat = Material.valueOf(value.toString().toUpperCase()); + } catch (IllegalArgumentException ex) { - } - if (newMat == null) { - sendMessage(TL.COMMAND_CONFIG_INVALID_MATERIAL.format(fieldName, value.toString().toUpperCase())); - return; - } + } + if (newMat == null) { + sendMessage(TL.COMMAND_CONFIG_INVALID_MATERIAL.format(fieldName, value.toString().toUpperCase())); + return; + } - @SuppressWarnings("unchecked") Set matSet = (Set) target.get(null); + @SuppressWarnings("unchecked") Set matSet = (Set) target.get(null); - // Material already present, so remove it - if (matSet.contains(newMat)) { - matSet.remove(newMat); - target.set(null, matSet); - success = TL.COMMAND_CONFIG_MATERIAL_REMOVED.format(fieldName, value.toString().toUpperCase()); - } - // Material not present yet, add it - else { - matSet.add(newMat); - target.set(null, matSet); - success = TL.COMMAND_CONFIG_MATERIAL_ADDED.format(fieldName, value.toString().toUpperCase()); - } - } + // Material already present, so remove it + if (matSet.contains(newMat)) { + matSet.remove(newMat); + target.set(null, matSet); + success = TL.COMMAND_CONFIG_MATERIAL_REMOVED.format(fieldName, value.toString().toUpperCase()); + } + // Material not present yet, add it + else { + matSet.add(newMat); + target.set(null, matSet); + success = TL.COMMAND_CONFIG_MATERIAL_ADDED.format(fieldName, value.toString().toUpperCase()); + } + } - // Set - else if (innerType == String.class) { - @SuppressWarnings("unchecked") Set stringSet = (Set) target.get(null); + // Set + else if (innerType == String.class) { + @SuppressWarnings("unchecked") Set stringSet = (Set) target.get(null); - // String already present, so remove it - if (stringSet.contains(value.toString())) { - stringSet.remove(value.toString()); - target.set(null, stringSet); - success = TL.COMMAND_CONFIG_SET_REMOVED.format(fieldName, value.toString()); - } - // String not present yet, add it - else { - stringSet.add(value.toString()); - target.set(null, stringSet); - success = TL.COMMAND_CONFIG_SET_ADDED.format(fieldName, value.toString()); - } - } + // String already present, so remove it + if (stringSet.contains(value.toString())) { + stringSet.remove(value.toString()); + target.set(null, stringSet); + success = TL.COMMAND_CONFIG_SET_REMOVED.format(fieldName, value.toString()); + } + // String not present yet, add it + else { + stringSet.add(value.toString()); + target.set(null, stringSet); + success = TL.COMMAND_CONFIG_SET_ADDED.format(fieldName, value.toString()); + } + } - // Set of unknown type - else { - sendMessage(TL.COMMAND_CONFIG_INVALID_TYPESET.format(fieldName)); - return; - } - } + // Set of unknown type + else { + sendMessage(TL.COMMAND_CONFIG_INVALID_TYPESET.format(fieldName)); + return; + } + } - // unknown type - else { - sendMessage(TL.COMMAND_CONFIG_ERROR_TYPE.format(fieldName, target.getClass().getName())); - return; - } - } catch (NoSuchFieldException ex) { - sendMessage(TL.COMMAND_CONFIG_ERROR_MATCHING.format(fieldName)); - return; - } catch (IllegalAccessException ex) { - sendMessage(TL.COMMAND_CONFIG_ERROR_SETTING.format(fieldName, value.toString())); - return; - } + // unknown type + else { + sendMessage(TL.COMMAND_CONFIG_ERROR_TYPE.format(fieldName, target.getClass().getName())); + return; + } + } catch (NoSuchFieldException ex) { + sendMessage(TL.COMMAND_CONFIG_ERROR_MATCHING.format(fieldName)); + return; + } catch (IllegalAccessException ex) { + sendMessage(TL.COMMAND_CONFIG_ERROR_SETTING.format(fieldName, value.toString())); + return; + } - if (!success.isEmpty()) { - if (sender instanceof Player) { - sendMessage(success); - SavageFactions.plugin.log(success + TL.COMMAND_CONFIG_LOG.format((Player) sender)); - } else // using SavageFactions.plugin.log() instead of sendMessage if run from server console so that "[Factions v#.#.#]" is prepended in server log - { - SavageFactions.plugin.log(success); - } - } - // save change to disk - Conf.save(); - } + if (!success.isEmpty()) { + if (sender instanceof Player) { + sendMessage(success); + SavageFactions.plugin.log(success + TL.COMMAND_CONFIG_LOG.format((Player) sender)); + } else // using SavageFactions.plugin.log() instead of sendMessage if run from server console so that "[Factions v#.#.#]" is prepended in server log + { + SavageFactions.plugin.log(success); + } + } + // save change to disk + Conf.save(); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CONFIG_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CONFIG_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java b/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java index bc923ec6..caf90c96 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java @@ -9,39 +9,39 @@ import org.bukkit.command.ConsoleCommandSender; public class CmdConvert extends FCommand { - public CmdConvert() { - this.aliases.add("convert"); + public CmdConvert() { + this.aliases.add("convert"); - this.permission = Permission.CONVERT.node; + this.permission = Permission.CONVERT.node; - this.requiredArgs.add("[MYSQL|JSON]"); - } + this.requiredArgs.add("[MYSQL|JSON]"); + } - @Override - public void perform() { - if (!(this.sender instanceof ConsoleCommandSender)) { - this.sender.sendMessage(TL.GENERIC_CONSOLEONLY.toString()); - } - Backend nb = Backend.valueOf(this.argAsString(0).toUpperCase()); - if (nb == Conf.backEnd) { - this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_RUNNING.toString()); - return; - } - switch (nb) { - case JSON: - FactionsJSON.convertTo(); - break; - default: - this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_INVALID.toString()); - return; + @Override + public void perform() { + if (!(this.sender instanceof ConsoleCommandSender)) { + this.sender.sendMessage(TL.GENERIC_CONSOLEONLY.toString()); + } + Backend nb = Backend.valueOf(this.argAsString(0).toUpperCase()); + if (nb == Conf.backEnd) { + this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_RUNNING.toString()); + return; + } + switch (nb) { + case JSON: + FactionsJSON.convertTo(); + break; + default: + this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_INVALID.toString()); + return; - } - Conf.backEnd = nb; - } + } + Conf.backEnd = nb; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CONVERT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CONVERT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java b/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java index e6b3bad3..506ad1b0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCoords.java @@ -7,36 +7,36 @@ import org.bukkit.Location; public class CmdCoords extends FCommand { - public CmdCoords() { - super(); - this.aliases.add("coords"); - this.aliases.add("coord"); + public CmdCoords() { + super(); + this.aliases.add("coords"); + this.aliases.add("coord"); - this.permission = Permission.COORD.node; - this.disableOnLock = true; + this.permission = Permission.COORD.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Location location = fme.getPlayer().getLocation(); - String message = TL.COMMAND_COORDS_MESSAGE.toString().replace("{player}", fme.getPlayer().getDisplayName()).replace("{x}", (int) location.getX() + "") - .replace("{y}", (int) location.getY() + "").replace("{z}", (int) location.getZ() + "").replace("{world}", location.getWorld().getName()); - for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { - fPlayer.sendMessage(message); - } - } + @Override + public void perform() { + Location location = fme.getPlayer().getLocation(); + String message = TL.COMMAND_COORDS_MESSAGE.toString().replace("{player}", fme.getPlayer().getDisplayName()).replace("{x}", (int) location.getX() + "") + .replace("{y}", (int) location.getY() + "").replace("{z}", (int) location.getZ() + "").replace("{world}", location.getWorld().getName()); + for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { + fPlayer.sendMessage(message); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_COORDS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_COORDS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java index ad7455b1..48140931 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java @@ -14,105 +14,105 @@ import java.util.ArrayList; public class CmdCreate extends FCommand { - public CmdCreate() { - super(); - this.aliases.add("create"); + public CmdCreate() { + super(); + this.aliases.add("create"); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); - this.permission = Permission.CREATE.node; - this.disableOnLock = true; + this.permission = Permission.CREATE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - String tag = this.argAsString(0); + @Override + public void perform() { + String tag = this.argAsString(0); - if (fme.hasFaction()) { - msg(TL.COMMAND_CREATE_MUSTLEAVE); - return; - } + if (fme.hasFaction()) { + msg(TL.COMMAND_CREATE_MUSTLEAVE); + return; + } - if (Factions.getInstance().isTagTaken(tag)) { - msg(TL.COMMAND_CREATE_INUSE); - return; - } + if (Factions.getInstance().isTagTaken(tag)) { + msg(TL.COMMAND_CREATE_INUSE); + return; + } - ArrayList tagValidationErrors = MiscUtil.validateTag(tag); - if (tagValidationErrors.size() > 0) { - sendMessage(tagValidationErrors); - return; - } + ArrayList tagValidationErrors = MiscUtil.validateTag(tag); + if (tagValidationErrors.size() > 0) { + sendMessage(tagValidationErrors); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (!canAffordCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (!canAffordCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE.toString())) { + return; + } - // trigger the faction creation event (cancellable) - FactionCreateEvent createEvent = new FactionCreateEvent(me, tag); - Bukkit.getServer().getPluginManager().callEvent(createEvent); - if (createEvent.isCancelled()) { - return; - } + // trigger the faction creation event (cancellable) + FactionCreateEvent createEvent = new FactionCreateEvent(me, tag); + Bukkit.getServer().getPluginManager().callEvent(createEvent); + if (createEvent.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (!payForCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE, TL.COMMAND_CREATE_FORCREATE)) { - return; - } + // then make 'em pay (if applicable) + if (!payForCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE, TL.COMMAND_CREATE_FORCREATE)) { + return; + } - Faction faction = Factions.getInstance().createFaction(); + Faction faction = Factions.getInstance().createFaction(); - // TODO: Why would this even happen??? Auto increment clash?? - if (faction == null) { - msg(TL.COMMAND_CREATE_ERROR); - return; - } + // TODO: Why would this even happen??? Auto increment clash?? + if (faction == null) { + msg(TL.COMMAND_CREATE_ERROR); + return; + } - // finish setting up the Faction - faction.setTag(tag); + // finish setting up the Faction + faction.setTag(tag); - // trigger the faction join event for the creator - FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE); - Bukkit.getServer().getPluginManager().callEvent(joinEvent); - // join event cannot be cancelled or you'll have an empty faction + // trigger the faction join event for the creator + FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE); + Bukkit.getServer().getPluginManager().callEvent(joinEvent); + // join event cannot be cancelled or you'll have an empty faction - // finish setting up the FPlayer - fme.setFaction(faction); - // We should consider adding the role just AFTER joining the faction. - // That way we don't have to mess up deleting more stuff. - // And prevent the user from being returned to NORMAL after deleting his old faction. - fme.setRole(Role.LEADER); - if (SavageFactions.plugin.getConfig().getBoolean("faction-creation-broadcast", true)) { - for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { - follower.msg(TL.COMMAND_CREATE_CREATED, fme.describeTo(follower, true), faction.getTag(follower)); - } - } - msg(TL.COMMAND_CREATE_YOUSHOULD, p.cmdBase.cmdDescription.getUseageTemplate()); + // finish setting up the FPlayer + fme.setFaction(faction); + // We should consider adding the role just AFTER joining the faction. + // That way we don't have to mess up deleting more stuff. + // And prevent the user from being returned to NORMAL after deleting his old faction. + fme.setRole(Role.LEADER); + if (SavageFactions.plugin.getConfig().getBoolean("faction-creation-broadcast", true)) { + for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { + follower.msg(TL.COMMAND_CREATE_CREATED, fme.describeTo(follower, true), faction.getTag(follower)); + } + } + msg(TL.COMMAND_CREATE_YOUSHOULD, p.cmdBase.cmdDescription.getUseageTemplate()); - if (Conf.logFactionCreate) { - SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CREATE_CREATEDLOG.toString() + tag); - } - if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - this.fme.msg(TL.COMMAND_PAYPALSET_CREATED); - } - if (Conf.useCustomDefaultPermissions) { - faction.setDefaultPerms(); - if (Conf.usePermissionHints) - this.fme.msg(TL.COMMAND_HINT_PERMISSION); - } - } + if (Conf.logFactionCreate) { + SavageFactions.plugin.log(fme.getName() + TL.COMMAND_CREATE_CREATEDLOG.toString() + tag); + } + if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + this.fme.msg(TL.COMMAND_PAYPALSET_CREATED); + } + if (Conf.useCustomDefaultPermissions) { + faction.setDefaultPerms(); + if (Conf.usePermissionHints) + this.fme.msg(TL.COMMAND_HINT_PERMISSION); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_CREATE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_CREATE_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java b/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java index 62c2b72e..51948c2c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDeinvite.java @@ -13,62 +13,62 @@ import org.bukkit.ChatColor; public class CmdDeinvite extends FCommand { - public CmdDeinvite() { - super(); - this.aliases.add("deinvite"); - this.aliases.add("deinv"); + public CmdDeinvite() { + super(); + this.aliases.add("deinvite"); + this.aliases.add("deinv"); - this.optionalArgs.put("player name", "name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.DEINVITE.node; - this.disableOnLock = true; + this.permission = Permission.DEINVITE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.INVITE); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); - return; - } - } - if (you == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_DEINVITE_CANDEINVITE.toString()).color(ChatColor.GOLD); - for (String id : myFaction.getInvites()) { - FPlayer fp = FPlayers.getInstance().getById(id); - String name = fp != null ? fp.getName() : id; - msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_DEINVITE_CLICKTODEINVITE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); - } - sendFancyMessage(msg); - return; - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.INVITE); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); + return; + } + } + if (you == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_DEINVITE_CANDEINVITE.toString()).color(ChatColor.GOLD); + for (String id : myFaction.getInvites()) { + FPlayer fp = FPlayers.getInstance().getById(id); + String name = fp != null ? fp.getName() : id; + msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_DEINVITE_CLICKTODEINVITE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); + } + sendFancyMessage(msg); + return; + } - if (you.getFaction() == myFaction) { - msg(TL.COMMAND_DEINVITE_ALREADYMEMBER, you.getName(), myFaction.getTag()); - msg(TL.COMMAND_DEINVITE_MIGHTWANT, p.cmdBase.cmdKick.getUseageTemplate(false)); - return; - } + if (you.getFaction() == myFaction) { + msg(TL.COMMAND_DEINVITE_ALREADYMEMBER, you.getName(), myFaction.getTag()); + msg(TL.COMMAND_DEINVITE_MIGHTWANT, p.cmdBase.cmdKick.getUseageTemplate(false)); + return; + } - myFaction.deinvite(you); + myFaction.deinvite(you); - you.msg(TL.COMMAND_DEINVITE_REVOKED, fme.describeTo(you), myFaction.describeTo(you)); + you.msg(TL.COMMAND_DEINVITE_REVOKED, fme.describeTo(you), myFaction.describeTo(you)); - myFaction.msg(TL.COMMAND_DEINVITE_REVOKES, fme.describeTo(myFaction), you.describeTo(myFaction)); - } + myFaction.msg(TL.COMMAND_DEINVITE_REVOKES, fme.describeTo(myFaction), you.describeTo(myFaction)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DEINVITE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DEINVITE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java b/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java index 6f592b3f..1249266f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDelFWarp.java @@ -7,39 +7,39 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdDelFWarp extends FCommand { - public CmdDelFWarp() { - super(); - this.aliases.add("delwarp"); - this.aliases.add("dw"); - this.aliases.add("deletewarp"); - this.requiredArgs.add("warp name"); - this.senderMustBeMember = true; - this.senderMustBeModerator = true; - this.senderMustBePlayer = true; - this.permission = Permission.SETWARP.node; + public CmdDelFWarp() { + super(); + this.aliases.add("delwarp"); + this.aliases.add("dw"); + this.aliases.add("deletewarp"); + this.requiredArgs.add("warp name"); + this.senderMustBeMember = true; + this.senderMustBeModerator = true; + this.senderMustBePlayer = true; + this.permission = Permission.SETWARP.node; - } + } - @Override - public void perform() { - String warp = argAsString(0); - if (myFaction.isWarp(warp)) { - if (!transact(fme)) { - return; - } - myFaction.removeWarp(warp); - fme.msg(TL.COMMAND_DELFWARP_DELETED, warp); - } else { - fme.msg(TL.COMMAND_DELFWARP_INVALID, warp); - } - } + @Override + public void perform() { + String warp = argAsString(0); + if (myFaction.isWarp(warp)) { + if (!transact(fme)) { + return; + } + myFaction.removeWarp(warp); + fme.msg(TL.COMMAND_DELFWARP_DELETED, warp); + } else { + fme.msg(TL.COMMAND_DELFWARP_INVALID, warp); + } + } - private boolean transact(FPlayer player) { - return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.delwarp", 5), TL.COMMAND_DELFWARP_TODELETE.toString(), TL.COMMAND_DELFWARP_FORDELETE.toString()); - } + private boolean transact(FPlayer player) { + return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.delwarp", 5), TL.COMMAND_DELFWARP_TODELETE.toString(), TL.COMMAND_DELFWARP_FORDELETE.toString()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DELFWARP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DELFWARP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java b/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java index 2890d2f5..0378de1c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDemote.java @@ -2,8 +2,8 @@ package com.massivecraft.factions.cmd; public class CmdDemote extends FPromoteCommand { - public CmdDemote() { - aliases.add("demote"); - this.relative = -1; - } + public CmdDemote() { + aliases.add("demote"); + this.relative = -1; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java b/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java index a0e6d00a..fe272298 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java @@ -9,53 +9,53 @@ import com.massivecraft.factions.zcore.util.TextUtil; public class CmdDescription extends FCommand { - public CmdDescription() { - super(); - this.aliases.add("desc"); - this.aliases.add("description"); + public CmdDescription() { + super(); + this.aliases.add("desc"); + this.aliases.add("description"); - this.requiredArgs.add("desc"); - this.errorOnToManyArgs = false; - //this.optionalArgs + this.requiredArgs.add("desc"); + this.errorOnToManyArgs = false; + //this.optionalArgs - this.permission = Permission.DESCRIPTION.node; - this.disableOnLock = true; + this.permission = Permission.DESCRIPTION.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostDesc, TL.COMMAND_DESCRIPTION_TOCHANGE, TL.COMMAND_DESCRIPTION_FORCHANGE)) { - return; - } + @Override + public void perform() { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostDesc, TL.COMMAND_DESCRIPTION_TOCHANGE, TL.COMMAND_DESCRIPTION_FORCHANGE)) { + return; + } - // since "&" color tags seem to work even through plain old FPlayer.sendMessage() for some reason, we need to break those up - // And replace all the % because it messes with string formatting and this is easy way around that. - myFaction.setDescription(TextUtil.implode(args, " ").replaceAll("%", "").replaceAll("(&([a-f0-9klmnor]))", "& $2")); + // since "&" color tags seem to work even through plain old FPlayer.sendMessage() for some reason, we need to break those up + // And replace all the % because it messes with string formatting and this is easy way around that. + myFaction.setDescription(TextUtil.implode(args, " ").replaceAll("%", "").replaceAll("(&([a-f0-9klmnor]))", "& $2")); - if (!Conf.broadcastDescriptionChanges) { - fme.msg(TL.COMMAND_DESCRIPTION_CHANGED, myFaction.describeTo(fme)); - fme.sendMessage(myFaction.getDescription()); - return; - } + if (!Conf.broadcastDescriptionChanges) { + fme.msg(TL.COMMAND_DESCRIPTION_CHANGED, myFaction.describeTo(fme)); + fme.sendMessage(myFaction.getDescription()); + return; + } - // Broadcast the description to everyone - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg(TL.COMMAND_DESCRIPTION_CHANGES, myFaction.describeTo(fplayer)); - fplayer.sendMessage(myFaction.getDescription()); // players can inject "&" or "`" or "" or whatever in their description; &k is particularly interesting looking - } - } + // Broadcast the description to everyone + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg(TL.COMMAND_DESCRIPTION_CHANGES, myFaction.describeTo(fplayer)); + fplayer.sendMessage(myFaction.getDescription()); // players can inject "&" or "`" or "" or whatever in their description; &k is particularly interesting looking + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DESCRIPTION_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DESCRIPTION_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java b/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java index 2ad00c4d..2f806816 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java @@ -16,99 +16,99 @@ import java.util.HashMap; public class CmdDisband extends FCommand { - private static HashMap disbandMap = new HashMap<>(); + private static HashMap disbandMap = new HashMap<>(); - public CmdDisband() { - super(); - this.aliases.add("disband"); + public CmdDisband() { + super(); + this.aliases.add("disband"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction tag", "yours"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction tag", "yours"); - this.permission = Permission.DISBAND.node; - this.disableOnLock = true; + this.permission = Permission.DISBAND.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - // The faction, default to your own.. but null if console sender. - Faction faction = this.argAsFaction(0, fme == null ? null : myFaction); - if (faction == null) { - return; - } + @Override + public void perform() { + // The faction, default to your own.. but null if console sender. + Faction faction = this.argAsFaction(0, fme == null ? null : myFaction); + if (faction == null) { + return; + } - boolean isMyFaction = fme != null && faction == myFaction; + boolean isMyFaction = fme != null && faction == myFaction; - if (isMyFaction) { - if (!assertMinRole(Role.LEADER)) { - return; - } - } else { - if (!Permission.DISBAND_ANY.has(sender, true)) { - return; - } - } + if (isMyFaction) { + if (!assertMinRole(Role.LEADER)) { + return; + } + } else { + if (!Permission.DISBAND_ANY.has(sender, true)) { + return; + } + } - if (!fme.isAdminBypassing()) { - Access access = faction.getAccess(fme, PermissableAction.DISBAND); - if (fme.getRole() != Role.LEADER && faction.getFPlayerLeader() != fme && access != Access.ALLOW) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "disband " + faction.getTag()); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = faction.getAccess(fme, PermissableAction.DISBAND); + if (fme.getRole() != Role.LEADER && faction.getFPlayerLeader() != fme && access != Access.ALLOW) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "disband " + faction.getTag()); + return; + } + } - if (!faction.isNormal()) { - msg(TL.COMMAND_DISBAND_IMMUTABLE.toString()); - return; - } - if (faction.isPermanent()) { - msg(TL.COMMAND_DISBAND_MARKEDPERMANENT.toString()); - return; - } + if (!faction.isNormal()) { + msg(TL.COMMAND_DISBAND_IMMUTABLE.toString()); + return; + } + if (faction.isPermanent()) { + msg(TL.COMMAND_DISBAND_MARKEDPERMANENT.toString()); + return; + } - // check for tnt before disbanding. + // check for tnt before disbanding. - if (!disbandMap.containsKey(me.getUniqueId().toString()) && faction.getTnt() > 0) { - msg(TL.COMMAND_DISBAND_CONFIRM.toString().replace("{tnt}", faction.getTnt() + "")); - disbandMap.put(me.getUniqueId().toString(), faction.getId()); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - disbandMap.remove(me.getUniqueId().toString()); - } - }, 200L); - } else if (faction.getId().equals(disbandMap.get(me.getUniqueId().toString())) || faction.getTnt() == 0) { - if (SavageFactions.plugin.getConfig().getBoolean("faction-disband-broadcast", true)) { - for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { - String amountString = senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(follower); - UtilFly.checkFly(this.fme, Board.getInstance().getFactionAt(new FLocation(follower))); - if (follower.getFaction() == faction) { - follower.msg(TL.COMMAND_DISBAND_BROADCAST_YOURS, amountString); - } else { - follower.msg(TL.COMMAND_DISBAND_BROADCAST_NOTYOURS, amountString, faction.getTag(follower)); - } - } - faction.disband(me, PlayerDisbandReason.COMMAND); - } else { - faction.disband(me, PlayerDisbandReason.COMMAND); - me.sendMessage(String.valueOf(TL.COMMAND_DISBAND_PLAYER)); - } - } - } + if (!disbandMap.containsKey(me.getUniqueId().toString()) && faction.getTnt() > 0) { + msg(TL.COMMAND_DISBAND_CONFIRM.toString().replace("{tnt}", faction.getTnt() + "")); + disbandMap.put(me.getUniqueId().toString(), faction.getId()); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + disbandMap.remove(me.getUniqueId().toString()); + } + }, 200L); + } else if (faction.getId().equals(disbandMap.get(me.getUniqueId().toString())) || faction.getTnt() == 0) { + if (SavageFactions.plugin.getConfig().getBoolean("faction-disband-broadcast", true)) { + for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { + String amountString = senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(follower); + UtilFly.checkFly(this.fme, Board.getInstance().getFactionAt(new FLocation(follower))); + if (follower.getFaction() == faction) { + follower.msg(TL.COMMAND_DISBAND_BROADCAST_YOURS, amountString); + } else { + follower.msg(TL.COMMAND_DISBAND_BROADCAST_NOTYOURS, amountString, faction.getTag(follower)); + } + } + faction.disband(me, PlayerDisbandReason.COMMAND); + } else { + faction.disband(me, PlayerDisbandReason.COMMAND); + me.sendMessage(String.valueOf(TL.COMMAND_DISBAND_PLAYER)); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_DISBAND_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_DISBAND_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java b/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java index 21a4bac4..de8c13cc 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdFWarp.java @@ -16,78 +16,78 @@ import java.util.UUID; public class CmdFWarp extends FCommand { - public CmdFWarp() { - super(); - this.aliases.add("warp"); - this.aliases.add("warps"); - this.optionalArgs.put("warpname", "warpname"); - this.optionalArgs.put("password", "password"); + public CmdFWarp() { + super(); + this.aliases.add("warp"); + this.aliases.add("warps"); + this.optionalArgs.put("warpname", "warpname"); + this.optionalArgs.put("password", "password"); - this.permission = Permission.WARP.node; - this.senderMustBeMember = true; - this.senderMustBeModerator = false; - } + this.permission = Permission.WARP.node; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; + } - @Override - public void perform() { - //TODO: check if in combat. - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.WARP); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use warps"); - return; - } - } + @Override + public void perform() { + //TODO: check if in combat. + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.WARP); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use warps"); + return; + } + } - if (args.size() == 0) { - WarpGUI warpGUI = new WarpGUI(fme); - warpGUI.build(); + if (args.size() == 0) { + WarpGUI warpGUI = new WarpGUI(fme); + warpGUI.build(); - me.openInventory(warpGUI.getInventory()); - } else if (args.size() > 2) { - fme.msg(TL.COMMAND_FWARP_COMMANDFORMAT); - } else { - final String warpName = argAsString(0); - final String passwordAttempt = argAsString(1); + me.openInventory(warpGUI.getInventory()); + } else if (args.size() > 2) { + fme.msg(TL.COMMAND_FWARP_COMMANDFORMAT); + } else { + final String warpName = argAsString(0); + final String passwordAttempt = argAsString(1); - if (myFaction.isWarp(argAsString(0))) { + if (myFaction.isWarp(argAsString(0))) { - // Check if requires password and if so, check if valid. CASE SENSITIVE - if (myFaction.hasWarpPassword(warpName) && !myFaction.isWarpPassword(warpName, passwordAttempt)) { - fme.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); - return; - } + // Check if requires password and if so, check if valid. CASE SENSITIVE + if (myFaction.hasWarpPassword(warpName) && !myFaction.isWarpPassword(warpName, passwordAttempt)) { + fme.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); + return; + } - // Check transaction AFTER password check. - if (!transact(fme)) { - return; - } - final FPlayer fPlayer = fme; - final UUID uuid = fme.getPlayer().getUniqueId(); - this.doWarmUp(WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warpName, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(uuid); - if (player != null) { - player.teleport(fPlayer.getFaction().getWarp(warpName).getLocation()); - fPlayer.msg(TL.COMMAND_FWARP_WARPED, warpName); - } - } - }, this.p.getConfig().getLong("warmups.f-warp", 0)); - } else { - fme.msg(TL.COMMAND_FWARP_INVALID_WARP, warpName); - } - } - } + // Check transaction AFTER password check. + if (!transact(fme)) { + return; + } + final FPlayer fPlayer = fme; + final UUID uuid = fme.getPlayer().getUniqueId(); + this.doWarmUp(WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warpName, new Runnable() { + @Override + public void run() { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + player.teleport(fPlayer.getFaction().getWarp(warpName).getLocation()); + fPlayer.msg(TL.COMMAND_FWARP_WARPED, warpName); + } + } + }, this.p.getConfig().getLong("warmups.f-warp", 0)); + } else { + fme.msg(TL.COMMAND_FWARP_INVALID_WARP, warpName); + } + } + } - private boolean transact(FPlayer player) { - return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5), TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); - } + private boolean transact(FPlayer player) { + return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5), TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_FWARP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_FWARP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdFly.java b/src/main/java/com/massivecraft/factions/cmd/CmdFly.java index b9f737b6..d5072e82 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdFly.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdFly.java @@ -22,230 +22,230 @@ import java.util.concurrent.ConcurrentHashMap; public class CmdFly extends FCommand { - public static ConcurrentHashMap flyMap = new ConcurrentHashMap(); - public static int id = -1; - public static int flyid = -1; + public static ConcurrentHashMap flyMap = new ConcurrentHashMap(); + public static int id = -1; + public static int flyid = -1; - public CmdFly() { - super(); - this.aliases.add("fly"); + public CmdFly() { + super(); + this.aliases.add("fly"); - this.optionalArgs.put("on/off", "flip"); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.FLY.node; - this.senderMustBeMember = true; - this.senderMustBeModerator = false; - } + this.permission = Permission.FLY.node; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; + } - public static void startParticles() { - // Just a secondary check. - if (!SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { - return; - } + public static void startParticles() { + // Just a secondary check. + if (!SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { + return; + } - id = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - for (String name : flyMap.keySet()) { - Player player = Bukkit.getPlayer(name); - if (player == null) { - continue; - } - if (!player.isFlying()) { - continue; - } - if (!SavageFactions.plugin.mc17) { - if (player.getGameMode() == GameMode.SPECTATOR) { - continue; - } - } + id = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + for (String name : flyMap.keySet()) { + Player player = Bukkit.getPlayer(name); + if (player == null) { + continue; + } + if (!player.isFlying()) { + continue; + } + if (!SavageFactions.plugin.mc17) { + if (player.getGameMode() == GameMode.SPECTATOR) { + continue; + } + } - if (FPlayers.getInstance().getByPlayer(player).isVanished()) { - // Actually, vanished players (such as admins) should not display particles to prevent others from knowing their vanished assistance for moderation. - // But we can keep it as a config. - if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enable-While-Vanished")) { - return; - } - continue; - } - if (SavageFactions.plugin.useNonPacketParticles) { - // 1.9+ based servers will use the built in particleAPI instead of packet based. - // any particle amount higher than 0 made them go everywhere, and the offset at 0 was not working. - // So setting the amount to 0 spawns 1 in the precise location - player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation().add(0, -0.35, 0), 0); - } else { - ParticleEffect.CLOUD.display((float) 0, (float) 0, (float) 0, (float) 0, 3, player.getLocation().add(0, -0.35, 0), 16); - } + if (FPlayers.getInstance().getByPlayer(player).isVanished()) { + // Actually, vanished players (such as admins) should not display particles to prevent others from knowing their vanished assistance for moderation. + // But we can keep it as a config. + if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enable-While-Vanished")) { + return; + } + continue; + } + if (SavageFactions.plugin.useNonPacketParticles) { + // 1.9+ based servers will use the built in particleAPI instead of packet based. + // any particle amount higher than 0 made them go everywhere, and the offset at 0 was not working. + // So setting the amount to 0 spawns 1 in the precise location + player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation().add(0, -0.35, 0), 0); + } else { + ParticleEffect.CLOUD.display((float) 0, (float) 0, (float) 0, (float) 0, 3, player.getLocation().add(0, -0.35, 0), 16); + } - } - if (flyMap.keySet().size() == 0) { - Bukkit.getScheduler().cancelTask(id); - id = -1; - } - } - }, 10L, 3L); - } + } + if (flyMap.keySet().size() == 0) { + Bukkit.getScheduler().cancelTask(id); + id = -1; + } + } + }, 10L, 3L); + } - public static void startFlyCheck() { - flyid = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() throws ConcurrentModificationException { //threw the exception for now, until I recode fly :( Cringe. - checkTaskState(); - if (flyMap.keySet().size() != 0) { - for (String name : flyMap.keySet()) { - if (name == null) { - continue; - } - Player player = Bukkit.getPlayer(name); - if (player == null) { - continue; - } - if (!player.isFlying()) { - continue; - } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer == null) { - continue; - } - if (player.getGameMode() == GameMode.CREATIVE) { - continue; - } - if (!SavageFactions.plugin.mc17 && player.getGameMode() == GameMode.SPECTATOR) { - continue; - } - Faction myFaction = fPlayer.getFaction(); - if (myFaction.isWilderness()) { - fPlayer.setFlying(false); - flyMap.remove(name); - continue; - } - if (fPlayer.checkIfNearbyEnemies()) { - continue; - } - FLocation myFloc = new FLocation(player.getLocation()); - Faction toFac = Board.getInstance().getFactionAt(myFloc); - if (Board.getInstance().getFactionAt(myFloc) != myFaction) { - if (!checkBypassPerms(fPlayer, player, toFac)) { - fPlayer.setFlying(false); - flyMap.remove(name); - continue; - } - } + public static void startFlyCheck() { + flyid = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() throws ConcurrentModificationException { //threw the exception for now, until I recode fly :( Cringe. + checkTaskState(); + if (flyMap.keySet().size() != 0) { + for (String name : flyMap.keySet()) { + if (name == null) { + continue; + } + Player player = Bukkit.getPlayer(name); + if (player == null) { + continue; + } + if (!player.isFlying()) { + continue; + } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer == null) { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE) { + continue; + } + if (!SavageFactions.plugin.mc17 && player.getGameMode() == GameMode.SPECTATOR) { + continue; + } + Faction myFaction = fPlayer.getFaction(); + if (myFaction.isWilderness()) { + fPlayer.setFlying(false); + flyMap.remove(name); + continue; + } + if (fPlayer.checkIfNearbyEnemies()) { + continue; + } + FLocation myFloc = new FLocation(player.getLocation()); + Faction toFac = Board.getInstance().getFactionAt(myFloc); + if (Board.getInstance().getFactionAt(myFloc) != myFaction) { + if (!checkBypassPerms(fPlayer, player, toFac)) { + fPlayer.setFlying(false); + flyMap.remove(name); + continue; + } + } - } - } + } + } - } - }, 20L, 20L); - } + } + }, 20L, 20L); + } - private static boolean checkBypassPerms(FPlayer fme, Player me, Faction toFac) { - if (toFac != fme.getFaction()) { - if (!me.hasPermission("factions.fly.wilderness") && toFac.isWilderness() || !me.hasPermission("factions.fly.safezone") && toFac.isSafeZone() || !me.hasPermission("factions.fly.warzone") && toFac.isWarZone()) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - Access access = toFac.getAccess(fme, PermissableAction.FLY); - if ((!(me.hasPermission("factions.fly.enemy") || access == Access.ALLOW)) && toFac.getRelationTo(fme.getFaction()) == Relation.ENEMY) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - if (!(me.hasPermission("factions.fly.ally") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.ALLY) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - if (!(me.hasPermission("factions.fly.truce") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.TRUCE) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } + private static boolean checkBypassPerms(FPlayer fme, Player me, Faction toFac) { + if (toFac != fme.getFaction()) { + if (!me.hasPermission("factions.fly.wilderness") && toFac.isWilderness() || !me.hasPermission("factions.fly.safezone") && toFac.isSafeZone() || !me.hasPermission("factions.fly.warzone") && toFac.isWarZone()) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + Access access = toFac.getAccess(fme, PermissableAction.FLY); + if ((!(me.hasPermission("factions.fly.enemy") || access == Access.ALLOW)) && toFac.getRelationTo(fme.getFaction()) == Relation.ENEMY) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + if (!(me.hasPermission("factions.fly.ally") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.ALLY) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + if (!(me.hasPermission("factions.fly.truce") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.TRUCE) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } - if (!(me.hasPermission("factions.fly.neutral") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.NEUTRAL && !isSystemFaction(toFac)) { - fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); - return false; - } - return me.hasPermission("factions.fly") && access != Access.DENY; - } - return true; - } + if (!(me.hasPermission("factions.fly.neutral") || access == Access.ALLOW) && toFac.getRelationTo(fme.getFaction()) == Relation.NEUTRAL && !isSystemFaction(toFac)) { + fme.msg(TL.COMMAND_FLY_NO_ACCESS, toFac.getTag(fme)); + return false; + } + return me.hasPermission("factions.fly") && access != Access.DENY; + } + return true; + } - public static Boolean isSystemFaction(Faction faction) { - return faction.isSafeZone() || - faction.isWarZone() || - faction.isWilderness(); - } + public static Boolean isSystemFaction(Faction faction) { + return faction.isSafeZone() || + faction.isWarZone() || + faction.isWilderness(); + } - public static void checkTaskState() { - if (flyMap.keySet().size() == 0) { - Bukkit.getScheduler().cancelTask(flyid); - flyid = -1; - } - } + public static void checkTaskState() { + if (flyMap.keySet().size() == 0) { + Bukkit.getScheduler().cancelTask(flyid); + flyid = -1; + } + } - public boolean isInFlightChecker(Player player) { - return flyMap.containsKey(player.getName()); - } + public boolean isInFlightChecker(Player player) { + return flyMap.containsKey(player.getName()); + } - @Override - public void perform() { - // Disabled by default. - if (!SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { - fme.msg(TL.COMMAND_FLY_DISABLED); - return; - } + @Override + public void perform() { + // Disabled by default. + if (!SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { + fme.msg(TL.COMMAND_FLY_DISABLED); + return; + } - FLocation myfloc = new FLocation(me.getLocation()); - Faction toFac = Board.getInstance().getFactionAt(myfloc); - if (!checkBypassPerms(fme, me, toFac)) return; - List entities = this.me.getNearbyEntities(16.0D, 256.0D, 16.0D); + FLocation myfloc = new FLocation(me.getLocation()); + Faction toFac = Board.getInstance().getFactionAt(myfloc); + if (!checkBypassPerms(fme, me, toFac)) return; + List entities = this.me.getNearbyEntities(16.0D, 256.0D, 16.0D); - for (int i = 0; i <= entities.size() - 1; ++i) { - if (entities.get(i) instanceof Player) { - Player eplayer = (Player) entities.get(i); - FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); - if (efplayer.getRelationTo(this.fme) == Relation.ENEMY && !efplayer.isStealthEnabled()) { - this.fme.msg(TL.COMMAND_FLY_CHECK_ENEMY); - return; - } - } - } + for (int i = 0; i <= entities.size() - 1; ++i) { + if (entities.get(i) instanceof Player) { + Player eplayer = (Player) entities.get(i); + FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); + if (efplayer.getRelationTo(this.fme) == Relation.ENEMY && !efplayer.isStealthEnabled()) { + this.fme.msg(TL.COMMAND_FLY_CHECK_ENEMY); + return; + } + } + } - if (args.size() == 0) { - toggleFlight(!fme.isFlying(), me); - } else if (args.size() == 1) { - toggleFlight(argAsBool(0), me); - } - } + if (args.size() == 0) { + toggleFlight(!fme.isFlying(), me); + } else if (args.size() == 1) { + toggleFlight(argAsBool(0), me); + } + } - private void toggleFlight(final boolean toggle, final Player player) { - if (!toggle) { - fme.setFlying(false); - flyMap.remove(player.getName()); - return; - } + private void toggleFlight(final boolean toggle, final Player player) { + if (!toggle) { + fme.setFlying(false); + flyMap.remove(player.getName()); + return; + } - if (fme.canFlyAtLocation()) + if (fme.canFlyAtLocation()) - this.doWarmUp(WarmUpUtil.Warmup.FLIGHT, TL.WARMUPS_NOTIFY_FLIGHT, "Fly", new Runnable() { - @Override - public void run() { - fme.setFlying(true); - flyMap.put(player.getName(), true); - if (id == -1) { - if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { - startParticles(); - } - } - if (flyid == -1) { - startFlyCheck(); - } - } - }, this.p.getConfig().getLong("warmups.f-fly", 0)); - } + this.doWarmUp(WarmUpUtil.Warmup.FLIGHT, TL.WARMUPS_NOTIFY_FLIGHT, "Fly", new Runnable() { + @Override + public void run() { + fme.setFlying(true); + flyMap.put(player.getName(), true); + if (id == -1) { + if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { + startParticles(); + } + } + if (flyid == -1) { + startFlyCheck(); + } + } + }, this.p.getConfig().getLong("warmups.f-fly", 0)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_FLY_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_FLY_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java b/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java index b01ceb6e..09d8e105 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdFocus.java @@ -7,48 +7,48 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdFocus - extends FCommand { - public CmdFocus() { - aliases.add("focus"); + extends FCommand { + public CmdFocus() { + aliases.add("focus"); - requiredArgs.add("player"); + requiredArgs.add("player"); - permission = Permission.FOCUS.node; + permission = Permission.FOCUS.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { - fme.msg(TL.GENERIC_DISABLED); - return; - } - FPlayer target = argAsFPlayer(0); - if (target == null) { - return; - } - if (target.getFaction().getId().equalsIgnoreCase(myFaction.getId())) { - fme.msg(TL.COMMAND_FOCUS_SAMEFACTION); - return; - } - if ((myFaction.getFocused() != null) && (myFaction.getFocused().equalsIgnoreCase(target.getName()))) { - myFaction.setFocused(null); - myFaction.msg(TL.COMMAND_FOCUS_NO_LONGER, target.getName()); - FTeamWrapper.updatePrefixes(target.getFaction()); - return; - } - myFaction.msg(TL.COMMAND_FOCUS_FOCUSING, target.getName()); - myFaction.setFocused(target.getName()); - FTeamWrapper.updatePrefixes(target.getFaction()); - } + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { + fme.msg(TL.GENERIC_DISABLED); + return; + } + FPlayer target = argAsFPlayer(0); + if (target == null) { + return; + } + if (target.getFaction().getId().equalsIgnoreCase(myFaction.getId())) { + fme.msg(TL.COMMAND_FOCUS_SAMEFACTION); + return; + } + if ((myFaction.getFocused() != null) && (myFaction.getFocused().equalsIgnoreCase(target.getName()))) { + myFaction.setFocused(null); + myFaction.msg(TL.COMMAND_FOCUS_NO_LONGER, target.getName()); + FTeamWrapper.updatePrefixes(target.getFaction()); + return; + } + myFaction.msg(TL.COMMAND_FOCUS_FOCUSING, target.getName()); + myFaction.setFocused(target.getName()); + FTeamWrapper.updatePrefixes(target.getFaction()); + } - public TL getUsageTranslation() { - return TL.COMMAND_FOCUS_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_FOCUS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java b/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java index a2029688..a1a73848 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdGetVault.java @@ -9,70 +9,70 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; public class CmdGetVault extends FCommand { - public CmdGetVault() { - super(); + public CmdGetVault() { + super(); - this.aliases.add("getvault"); + this.aliases.add("getvault"); - this.permission = Permission.GETVAULT.node; - this.disableOnLock = true; + this.permission = Permission.GETVAULT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - Location vaultLocation = fme.getFaction().getVault(); - ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + Location vaultLocation = fme.getFaction().getVault(); + ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); - //check if vault is set - if (vaultLocation != null) { - fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); - return; - } + //check if vault is set + if (vaultLocation != null) { + fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); + return; + } - //has enough money? - int amount = SavageFactions.plugin.getConfig().getInt("fvault.Price"); - if (!fme.hasMoney(amount)) { - return; - } + //has enough money? + int amount = SavageFactions.plugin.getConfig().getInt("fvault.Price"); + if (!fme.hasMoney(amount)) { + return; + } - //success :) - fme.takeMoney(amount); - me.getInventory().addItem(vault); - fme.msg(TL.COMMAND_GETVAULT_RECEIVE); + //success :) + fme.takeMoney(amount); + me.getInventory().addItem(vault); + fme.msg(TL.COMMAND_GETVAULT_RECEIVE); - } + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_GETVAULT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_GETVAULT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java b/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java index e46084f5..5b7bd34b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdHelp.java @@ -13,207 +13,207 @@ import java.util.List; public class CmdHelp extends FCommand { - public ArrayList> helpPages; + public ArrayList> helpPages; - public CmdHelp() { - super(); - this.aliases.add("help"); - this.aliases.add("h"); - this.aliases.add("?"); + public CmdHelp() { + super(); + this.aliases.add("help"); + this.aliases.add("h"); + this.aliases.add("?"); - //this.requiredArgs.add(""); - this.optionalArgs.put("page", "1"); + //this.requiredArgs.add(""); + this.optionalArgs.put("page", "1"); - this.permission = Permission.HELP.node; - this.disableOnLock = false; + this.permission = Permission.HELP.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - //----------------------------------------------// - // Build the help pages - //----------------------------------------------// + //----------------------------------------------// + // Build the help pages + //----------------------------------------------// - @Override - public void perform() { - if (SavageFactions.plugin.getConfig().getBoolean("use-old-help", true)) { - if (helpPages == null) { - updateHelp(); - } + @Override + public void perform() { + if (SavageFactions.plugin.getConfig().getBoolean("use-old-help", true)) { + if (helpPages == null) { + updateHelp(); + } - int page = this.argAsInt(0, 1); - sendMessage(p.txt.titleize("Factions Help (" + page + "/" + helpPages.size() + ")")); + int page = this.argAsInt(0, 1); + sendMessage(p.txt.titleize("Factions Help (" + page + "/" + helpPages.size() + ")")); - page -= 1; + page -= 1; - if (page < 0 || page >= helpPages.size()) { - msg(TL.COMMAND_HELP_404.format(String.valueOf(page))); - return; - } - sendMessage(helpPages.get(page)); - return; - } - ConfigurationSection help = SavageFactions.plugin.getConfig().getConfigurationSection("help"); - if (help == null) { - help = SavageFactions.plugin.getConfig().createSection("help"); // create new help section - List error = new ArrayList<>(); - error.add("&cUpdate help messages in config.yml!"); - error.add("&cSet use-old-help for legacy help messages"); - help.set("'1'", error); // add default error messages - } - String pageArg = this.argAsString(0, "1"); - List page = help.getStringList(pageArg); - if (page == null || page.isEmpty()) { - msg(TL.COMMAND_HELP_404.format(pageArg)); - return; - } - for (String helpLine : page) { - sendMessage(SavageFactions.plugin.txt.parse(helpLine)); - } - } + if (page < 0 || page >= helpPages.size()) { + msg(TL.COMMAND_HELP_404.format(String.valueOf(page))); + return; + } + sendMessage(helpPages.get(page)); + return; + } + ConfigurationSection help = SavageFactions.plugin.getConfig().getConfigurationSection("help"); + if (help == null) { + help = SavageFactions.plugin.getConfig().createSection("help"); // create new help section + List error = new ArrayList<>(); + error.add("&cUpdate help messages in config.yml!"); + error.add("&cSet use-old-help for legacy help messages"); + help.set("'1'", error); // add default error messages + } + String pageArg = this.argAsString(0, "1"); + List page = help.getStringList(pageArg); + if (page == null || page.isEmpty()) { + msg(TL.COMMAND_HELP_404.format(pageArg)); + return; + } + for (String helpLine : page) { + sendMessage(SavageFactions.plugin.txt.parse(helpLine)); + } + } - public void updateHelp() { - helpPages = new ArrayList<>(); - ArrayList pageLines; + public void updateHelp() { + helpPages = new ArrayList<>(); + ArrayList pageLines; - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdHelp.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdList.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdShow.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPower.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdJoin.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdLeave.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdChat.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdToggleAllianceChat.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdHome.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_NEXTCREATE.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdHelp.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdList.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdShow.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPower.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdJoin.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdLeave.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdChat.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdToggleAllianceChat.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdHome.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_NEXTCREATE.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdCreate.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdDescription.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdTag.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_INVITATIONS.toString())); - pageLines.add(p.cmdBase.cmdOpen.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdInvite.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdDeinvite.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_HOME.toString())); - pageLines.add(p.cmdBase.cmdSethome.getUseageTemplate(true)); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdCreate.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdDescription.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdTag.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_INVITATIONS.toString())); + pageLines.add(p.cmdBase.cmdOpen.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdInvite.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdDeinvite.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_HOME.toString())); + pageLines.add(p.cmdBase.cmdSethome.getUseageTemplate(true)); + helpPages.add(pageLines); - if (Econ.isSetup() && Conf.econEnabled && Conf.bankEnabled) { - pageLines = new ArrayList<>(); - pageLines.add(""); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_3.toString())); - pageLines.add(""); - pageLines.add(p.cmdBase.cmdMoney.getUseageTemplate(true)); - pageLines.add(""); - pageLines.add(""); - pageLines.add(""); - helpPages.add(pageLines); - } + if (Econ.isSetup() && Conf.econEnabled && Conf.bankEnabled) { + pageLines = new ArrayList<>(); + pageLines.add(""); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_3.toString())); + pageLines.add(""); + pageLines.add(p.cmdBase.cmdMoney.getUseageTemplate(true)); + pageLines.add(""); + pageLines.add(""); + pageLines.add(""); + helpPages.add(pageLines); + } - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdClaim.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdAutoClaim.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdUnclaim.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdUnclaimall.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdKick.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdMod.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdAdmin.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdTitle.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdSB.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdSeeChunk.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdStatus.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PLAYERTITLES.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdClaim.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdAutoClaim.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdUnclaim.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdUnclaimall.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdKick.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdMod.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdAdmin.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdTitle.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdSB.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdSeeChunk.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdStatus.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PLAYERTITLES.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdMap.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdBoom.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdOwner.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdOwnerList.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_3.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdMap.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdBoom.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdOwner.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdOwnerList.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_3.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.cmdBase.cmdDisband.getUseageTemplate(true)); - pageLines.add(""); - pageLines.add(p.cmdBase.cmdRelationAlly.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdRelationNeutral.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdRelationEnemy.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_3.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_4.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.cmdBase.cmdDisband.getUseageTemplate(true)); + pageLines.add(""); + pageLines.add(p.cmdBase.cmdRelationAlly.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdRelationNeutral.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdRelationEnemy.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_3.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_4.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_5.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_6.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_7.toString())); - pageLines.add(TL.COMMAND_HELP_RELATIONS_8.toString()); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_9.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_10.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_11.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_12.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_13.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_5.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_6.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_7.toString())); + pageLines.add(TL.COMMAND_HELP_RELATIONS_8.toString()); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_9.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_10.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_11.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_12.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_13.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_3.toString())); - pageLines.add(TL.COMMAND_HELP_PERMISSIONS_4.toString()); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_5.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_6.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_7.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_8.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_9.toString())); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_3.toString())); + pageLines.add(TL.COMMAND_HELP_PERMISSIONS_4.toString()); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_5.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_6.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_7.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_8.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_9.toString())); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(TL.COMMAND_HELP_MOAR_1.toString()); - pageLines.add(p.cmdBase.cmdBypass.getUseageTemplate(true)); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_1.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_2.toString())); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_3.toString())); - pageLines.add(p.cmdBase.cmdSafeunclaimall.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdWarunclaimall.getUseageTemplate(true)); - //TODO:TL - pageLines.add(p.txt.parse("Note: " + p.cmdBase.cmdUnclaim.getUseageTemplate(false) + SavageFactions.plugin.txt.parse("") + " works on safe/war zones as well.")); - pageLines.add(p.cmdBase.cmdPeaceful.getUseageTemplate(true)); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(TL.COMMAND_HELP_MOAR_1.toString()); + pageLines.add(p.cmdBase.cmdBypass.getUseageTemplate(true)); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_1.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_2.toString())); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_3.toString())); + pageLines.add(p.cmdBase.cmdSafeunclaimall.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdWarunclaimall.getUseageTemplate(true)); + //TODO:TL + pageLines.add(p.txt.parse("Note: " + p.cmdBase.cmdUnclaim.getUseageTemplate(false) + SavageFactions.plugin.txt.parse("") + " works on safe/war zones as well.")); + pageLines.add(p.cmdBase.cmdPeaceful.getUseageTemplate(true)); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_2.toString())); - pageLines.add(p.cmdBase.cmdChatSpy.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPermanent.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPermanentPower.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdPowerBoost.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdConfig.getUseageTemplate(true)); - helpPages.add(pageLines); + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_2.toString())); + pageLines.add(p.cmdBase.cmdChatSpy.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPermanent.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPermanentPower.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdPowerBoost.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdConfig.getUseageTemplate(true)); + helpPages.add(pageLines); - pageLines = new ArrayList<>(); - pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_3.toString())); - pageLines.add(p.cmdBase.cmdLock.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdReload.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdSaveAll.getUseageTemplate(true)); - pageLines.add(p.cmdBase.cmdVersion.getUseageTemplate(true)); - helpPages.add(pageLines); - } + pageLines = new ArrayList<>(); + pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_3.toString())); + pageLines.add(p.cmdBase.cmdLock.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdReload.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdSaveAll.getUseageTemplate(true)); + pageLines.add(p.cmdBase.cmdVersion.getUseageTemplate(true)); + helpPages.add(pageLines); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_HELP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_HELP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdHome.java b/src/main/java/com/massivecraft/factions/cmd/CmdHome.java index 1ec5fed7..e680f552 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdHome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdHome.java @@ -20,130 +20,130 @@ import java.util.List; public class CmdHome extends FCommand { - public CmdHome() { - super(); - this.aliases.add("home"); + public CmdHome() { + super(); + this.aliases.add("home"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.HOME.node; - this.disableOnLock = false; + this.permission = Permission.HOME.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // TODO: Hide this command on help also. - if (!Conf.homesEnabled) { - fme.msg(TL.COMMAND_HOME_DISABLED); - return; - } + @Override + public void perform() { + // TODO: Hide this command on help also. + if (!Conf.homesEnabled) { + fme.msg(TL.COMMAND_HOME_DISABLED); + return; + } - if (!Conf.homesTeleportCommandEnabled) { - fme.msg(TL.COMMAND_HOME_TELEPORTDISABLED); - return; - } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.HOME); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "teleport home"); - return; - } - } + if (!Conf.homesTeleportCommandEnabled) { + fme.msg(TL.COMMAND_HOME_TELEPORTDISABLED); + return; + } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.HOME); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "teleport home"); + return; + } + } - if (!myFaction.hasHome()) { - fme.msg(TL.COMMAND_HOME_NOHOME.toString() + (fme.getRole().value < Role.MODERATOR.value ? TL.GENERIC_ASKYOURLEADER.toString() : TL.GENERIC_YOUSHOULD.toString())); - fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate()); - return; - } + if (!myFaction.hasHome()) { + fme.msg(TL.COMMAND_HOME_NOHOME.toString() + (fme.getRole().value < Role.MODERATOR.value ? TL.GENERIC_ASKYOURLEADER.toString() : TL.GENERIC_YOUSHOULD.toString())); + fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate()); + return; + } - if (!Conf.homesTeleportAllowedFromEnemyTerritory && fme.isInEnemyTerritory()) { - fme.msg(TL.COMMAND_HOME_INENEMY); - return; - } + if (!Conf.homesTeleportAllowedFromEnemyTerritory && fme.isInEnemyTerritory()) { + fme.msg(TL.COMMAND_HOME_INENEMY); + return; + } - if (!Conf.homesTeleportAllowedFromDifferentWorld && me.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) { - fme.msg(TL.COMMAND_HOME_WRONGWORLD); - return; - } + if (!Conf.homesTeleportAllowedFromDifferentWorld && me.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) { + fme.msg(TL.COMMAND_HOME_WRONGWORLD); + return; + } - Faction faction = Board.getInstance().getFactionAt(new FLocation(me.getLocation())); - final Location loc = me.getLocation().clone(); + Faction faction = Board.getInstance().getFactionAt(new FLocation(me.getLocation())); + final Location loc = me.getLocation().clone(); - // if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby - if (Conf.homesTeleportAllowedEnemyDistance > 0 && - !faction.isSafeZone() && - (!fme.isInOwnTerritory() || (fme.isInOwnTerritory() && !Conf.homesTeleportIgnoreEnemiesIfInOwnTerritory))) { - World w = loc.getWorld(); - double x = loc.getX(); - double y = loc.getY(); - double z = loc.getZ(); + // if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby + if (Conf.homesTeleportAllowedEnemyDistance > 0 && + !faction.isSafeZone() && + (!fme.isInOwnTerritory() || (fme.isInOwnTerritory() && !Conf.homesTeleportIgnoreEnemiesIfInOwnTerritory))) { + World w = loc.getWorld(); + double x = loc.getX(); + double y = loc.getY(); + double z = loc.getZ(); - for (Player p : me.getServer().getOnlinePlayers()) { - if (p == null || !p.isOnline() || p.isDead() || p == me || p.getWorld() != w) { - continue; - } + for (Player p : me.getServer().getOnlinePlayers()) { + if (p == null || !p.isOnline() || p.isDead() || p == me || p.getWorld() != w) { + continue; + } - FPlayer fp = FPlayers.getInstance().getByPlayer(p); - if (fme.getRelationTo(fp) != Relation.ENEMY || fp.isVanished()) { - continue; - } + FPlayer fp = FPlayers.getInstance().getByPlayer(p); + if (fme.getRelationTo(fp) != Relation.ENEMY || fp.isVanished()) { + continue; + } - Location l = p.getLocation(); - double dx = Math.abs(x - l.getX()); - double dy = Math.abs(y - l.getY()); - double dz = Math.abs(z - l.getZ()); - double max = Conf.homesTeleportAllowedEnemyDistance; + Location l = p.getLocation(); + double dx = Math.abs(x - l.getX()); + double dy = Math.abs(y - l.getY()); + double dz = Math.abs(z - l.getZ()); + double max = Conf.homesTeleportAllowedEnemyDistance; - // box-shaped distance check - if (dx > max || dy > max || dz > max) { - continue; - } + // box-shaped distance check + if (dx > max || dy > max || dz > max) { + continue; + } - fme.msg(TL.COMMAND_HOME_ENEMYNEAR, String.valueOf(Conf.homesTeleportAllowedEnemyDistance)); - return; - } - } + fme.msg(TL.COMMAND_HOME_ENEMYNEAR, String.valueOf(Conf.homesTeleportAllowedEnemyDistance)); + return; + } + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostHome, TL.COMMAND_HOME_TOTELEPORT.toString(), TL.COMMAND_HOME_FORTELEPORT.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostHome, TL.COMMAND_HOME_TOTELEPORT.toString(), TL.COMMAND_HOME_FORTELEPORT.toString())) { + return; + } - // if Essentials teleport handling is enabled and available, pass the teleport off to it (for delay and cooldown) - if (Essentials.handleTeleport(me, myFaction.getHome())) { - return; - } + // if Essentials teleport handling is enabled and available, pass the teleport off to it (for delay and cooldown) + if (Essentials.handleTeleport(me, myFaction.getHome())) { + return; + } - this.doWarmUp(WarmUpUtil.Warmup.HOME, TL.WARMUPS_NOTIFY_TELEPORT, "Home", new Runnable() { - @Override - public void run() { - // Create a smoke effect - if (Conf.homesTeleportCommandSmokeEffectEnabled) { - List smokeLocations = new ArrayList<>(); - smokeLocations.add(loc); - smokeLocations.add(loc.add(0, 1, 0)); - smokeLocations.add(CmdHome.this.myFaction.getHome()); - smokeLocations.add(CmdHome.this.myFaction.getHome().clone().add(0, 1, 0)); - SmokeUtil.spawnCloudRandom(smokeLocations, Conf.homesTeleportCommandSmokeEffectThickness); - } + this.doWarmUp(WarmUpUtil.Warmup.HOME, TL.WARMUPS_NOTIFY_TELEPORT, "Home", new Runnable() { + @Override + public void run() { + // Create a smoke effect + if (Conf.homesTeleportCommandSmokeEffectEnabled) { + List smokeLocations = new ArrayList<>(); + smokeLocations.add(loc); + smokeLocations.add(loc.add(0, 1, 0)); + smokeLocations.add(CmdHome.this.myFaction.getHome()); + smokeLocations.add(CmdHome.this.myFaction.getHome().clone().add(0, 1, 0)); + SmokeUtil.spawnCloudRandom(smokeLocations, Conf.homesTeleportCommandSmokeEffectThickness); + } - CmdHome.this.me.teleport(CmdHome.this.myFaction.getHome()); - } - }, this.p.getConfig().getLong("warmups.f-home", 0)); - } + CmdHome.this.me.teleport(CmdHome.this.myFaction.getHome()); + } + }, this.p.getConfig().getLong("warmups.f-home", 0)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_HOME_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_HOME_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java b/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java index 5e465e4a..4660844f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdInspect.java @@ -4,37 +4,37 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdInspect extends FCommand { - public CmdInspect() { - super(); - this.aliases.add("inspect"); - this.aliases.add("ins"); + public CmdInspect() { + super(); + this.aliases.add("inspect"); + this.aliases.add("ins"); - this.permission = Permission.INSPECT.node; - this.disableOnLock = true; + this.permission = Permission.INSPECT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (fme.isInspectMode()) { - fme.setInspectMode(false); - msg(TL.COMMAND_INSPECT_DISABLED_MSG); - } else { - fme.setInspectMode(true); - msg(TL.COMMAND_INSPECT_ENABLED); - } + @Override + public void perform() { + if (fme.isInspectMode()) { + fme.setInspectMode(false); + msg(TL.COMMAND_INSPECT_DISABLED_MSG); + } else { + fme.setInspectMode(true); + msg(TL.COMMAND_INSPECT_ENABLED); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_INSPECT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_INSPECT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java b/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java index a177d8f7..00a9197e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdInvite.java @@ -12,83 +12,83 @@ import org.bukkit.ChatColor; public class CmdInvite extends FCommand { - public CmdInvite() { - super(); - this.aliases.add("invite"); - this.aliases.add("inv"); + public CmdInvite() { + super(); + this.aliases.add("invite"); + this.aliases.add("inv"); - this.requiredArgs.add("player name"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("player name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.INVITE.node; - this.disableOnLock = true; + this.permission = Permission.INVITE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer target = this.argAsBestFPlayerMatch(0); - if (target == null) { - return; - } + @Override + public void perform() { + FPlayer target = this.argAsBestFPlayerMatch(0); + if (target == null) { + return; + } - if (target.getFaction() == myFaction) { - msg(TL.COMMAND_INVITE_ALREADYMEMBER, target.getName(), myFaction.getTag()); - msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdKick.getUseageTemplate(false)); - return; - } + if (target.getFaction() == myFaction) { + msg(TL.COMMAND_INVITE_ALREADYMEMBER, target.getName(), myFaction.getTag()); + msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdKick.getUseageTemplate(false)); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostInvite, TL.COMMAND_INVITE_TOINVITE.toString(), TL.COMMAND_INVITE_FORINVITE.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostInvite, TL.COMMAND_INVITE_TOINVITE.toString(), TL.COMMAND_INVITE_FORINVITE.toString())) { + return; + } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.INVITE); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.INVITE); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage invites"); + return; + } + } - if (myFaction.isInvited(target)) { - fme.msg(TL.COMMAND_INVITE_ALREADYINVITED, target.getName()); - return; - } - if (myFaction.isBanned(target)) { - fme.msg(TL.COMMAND_INVITE_BANNED, target.getName()); - return; - } + if (myFaction.isInvited(target)) { + fme.msg(TL.COMMAND_INVITE_ALREADYINVITED, target.getName()); + return; + } + if (myFaction.isBanned(target)) { + fme.msg(TL.COMMAND_INVITE_BANNED, target.getName()); + return; + } - myFaction.invite(target); - // Send the invitation to the target player when online, otherwise just ignore - if (target.isOnline()) { - // Tooltips, colors, and commands only apply to the string immediately before it. - FancyMessage message = new FancyMessage(fme.describeTo(target, true)) - .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) - .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) - .then(TL.COMMAND_INVITE_INVITEDYOU.toString()) - .color(ChatColor.YELLOW) - .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) - .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) - .then(myFaction.describeTo(target)).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) - .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()); + myFaction.invite(target); + // Send the invitation to the target player when online, otherwise just ignore + if (target.isOnline()) { + // Tooltips, colors, and commands only apply to the string immediately before it. + FancyMessage message = new FancyMessage(fme.describeTo(target, true)) + .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) + .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) + .then(TL.COMMAND_INVITE_INVITEDYOU.toString()) + .color(ChatColor.YELLOW) + .tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) + .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()) + .then(myFaction.describeTo(target)).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()) + .command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()); - message.send(target.getPlayer()); - } + message.send(target.getPlayer()); + } - myFaction.msg(TL.COMMAND_INVITE_INVITED, fme.describeTo(myFaction, true), target.describeTo(myFaction)); - } + myFaction.msg(TL.COMMAND_INVITE_INVITED, fme.describeTo(myFaction, true), target.describeTo(myFaction)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_INVITE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_INVITE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java b/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java index f34a2bf2..3688b2b4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java @@ -8,120 +8,120 @@ import org.bukkit.Bukkit; public class CmdJoin extends FCommand { - public CmdJoin() { - super(); - this.aliases.add("join"); + public CmdJoin() { + super(); + this.aliases.add("join"); - this.requiredArgs.add("faction name"); - this.optionalArgs.put("player", "you"); + this.requiredArgs.add("faction name"); + this.optionalArgs.put("player", "you"); - this.permission = Permission.JOIN.node; - this.disableOnLock = true; + this.permission = Permission.JOIN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction faction = this.argAsFaction(0); - if (faction == null) { - return; - } + @Override + public void perform() { + Faction faction = this.argAsFaction(0); + if (faction == null) { + return; + } - FPlayer fplayer = this.argAsBestFPlayerMatch(1, fme, false); - boolean samePlayer = fplayer == fme; + FPlayer fplayer = this.argAsBestFPlayerMatch(1, fme, false); + boolean samePlayer = fplayer == fme; - if (!samePlayer && !Permission.JOIN_OTHERS.has(sender, false)) { - msg(TL.COMMAND_JOIN_CANNOTFORCE); - return; - } + if (!samePlayer && !Permission.JOIN_OTHERS.has(sender, false)) { + msg(TL.COMMAND_JOIN_CANNOTFORCE); + return; + } - if (!faction.isNormal()) { - msg(TL.COMMAND_JOIN_SYSTEMFACTION); - return; - } + if (!faction.isNormal()) { + msg(TL.COMMAND_JOIN_SYSTEMFACTION); + return; + } - if (faction == fplayer.getFaction()) { - //TODO:TL - msg(TL.COMMAND_JOIN_ALREADYMEMBER, fplayer.describeTo(fme, true), (samePlayer ? "are" : "is"), faction.getTag(fme)); - return; - } + if (faction == fplayer.getFaction()) { + //TODO:TL + msg(TL.COMMAND_JOIN_ALREADYMEMBER, fplayer.describeTo(fme, true), (samePlayer ? "are" : "is"), faction.getTag(fme)); + return; + } - if (Conf.factionMemberLimit > 0 && faction.getFPlayers().size() >= Conf.factionMemberLimit) { - msg(TL.COMMAND_JOIN_ATLIMIT, faction.getTag(fme), Conf.factionMemberLimit, fplayer.describeTo(fme, false)); - return; - } + if (Conf.factionMemberLimit > 0 && faction.getFPlayers().size() >= Conf.factionMemberLimit) { + msg(TL.COMMAND_JOIN_ATLIMIT, faction.getTag(fme), Conf.factionMemberLimit, fplayer.describeTo(fme, false)); + return; + } - if (fplayer.hasFaction()) { - //TODO:TL - msg(TL.COMMAND_JOIN_INOTHERFACTION, fplayer.describeTo(fme, true), (samePlayer ? "your" : "their")); - return; - } + if (fplayer.hasFaction()) { + //TODO:TL + msg(TL.COMMAND_JOIN_INOTHERFACTION, fplayer.describeTo(fme, true), (samePlayer ? "your" : "their")); + return; + } - if (!Conf.canLeaveWithNegativePower && fplayer.getPower() < 0) { - msg(TL.COMMAND_JOIN_NEGATIVEPOWER, fplayer.describeTo(fme, true)); - return; - } + if (!Conf.canLeaveWithNegativePower && fplayer.getPower() < 0) { + msg(TL.COMMAND_JOIN_NEGATIVEPOWER, fplayer.describeTo(fme, true)); + return; + } - if (!(faction.getOpen() || faction.isInvited(fplayer) || fme.isAdminBypassing() || Permission.JOIN_ANY.has(sender, false))) { - msg(TL.COMMAND_JOIN_REQUIRESINVITATION); - if (samePlayer) { - faction.msg(TL.COMMAND_JOIN_ATTEMPTEDJOIN, fplayer.describeTo(faction, true)); - } - return; - } + if (!(faction.getOpen() || faction.isInvited(fplayer) || fme.isAdminBypassing() || Permission.JOIN_ANY.has(sender, false))) { + msg(TL.COMMAND_JOIN_REQUIRESINVITATION); + if (samePlayer) { + faction.msg(TL.COMMAND_JOIN_ATTEMPTEDJOIN, fplayer.describeTo(faction, true)); + } + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (samePlayer && !canAffordCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (samePlayer && !canAffordCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString())) { + return; + } - // Check for ban - if (!fme.isAdminBypassing() && faction.isBanned(fme)) { - fme.msg(TL.COMMAND_JOIN_BANNED, faction.getTag(fme)); - return; - } + // Check for ban + if (!fme.isAdminBypassing() && faction.isBanned(fme)) { + fme.msg(TL.COMMAND_JOIN_BANNED, faction.getTag(fme)); + return; + } - // trigger the join event (cancellable) - FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND); - Bukkit.getServer().getPluginManager().callEvent(joinEvent); - if (joinEvent.isCancelled()) { - return; - } + // trigger the join event (cancellable) + FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND); + Bukkit.getServer().getPluginManager().callEvent(joinEvent); + if (joinEvent.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (samePlayer && !payForCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString(), TL.COMMAND_JOIN_FORJOIN.toString())) { - return; - } + // then make 'em pay (if applicable) + if (samePlayer && !payForCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString(), TL.COMMAND_JOIN_FORJOIN.toString())) { + return; + } - fme.msg(TL.COMMAND_JOIN_SUCCESS, fplayer.describeTo(fme, true), faction.getTag(fme)); + fme.msg(TL.COMMAND_JOIN_SUCCESS, fplayer.describeTo(fme, true), faction.getTag(fme)); - if (!samePlayer) { - fplayer.msg(TL.COMMAND_JOIN_MOVED, fme.describeTo(fplayer, true), faction.getTag(fplayer)); - } - faction.msg(TL.COMMAND_JOIN_JOINED, fplayer.describeTo(faction, true)); + if (!samePlayer) { + fplayer.msg(TL.COMMAND_JOIN_MOVED, fme.describeTo(fplayer, true), faction.getTag(fplayer)); + } + faction.msg(TL.COMMAND_JOIN_JOINED, fplayer.describeTo(faction, true)); - fplayer.resetFactionData(); - fplayer.setFaction(faction); - faction.deinvite(fplayer); - fme.setRole(faction.getDefaultRole()); + fplayer.resetFactionData(); + fplayer.setFaction(faction); + faction.deinvite(fplayer); + fme.setRole(faction.getDefaultRole()); - if (Conf.logFactionJoin) { - if (samePlayer) { - SavageFactions.plugin.log(TL.COMMAND_JOIN_JOINEDLOG.toString(), fplayer.getName(), faction.getTag()); - } else { - SavageFactions.plugin.log(TL.COMMAND_JOIN_MOVEDLOG.toString(), fme.getName(), fplayer.getName(), faction.getTag()); - } - } - } + if (Conf.logFactionJoin) { + if (samePlayer) { + SavageFactions.plugin.log(TL.COMMAND_JOIN_JOINEDLOG.toString(), fplayer.getName(), faction.getTag()); + } else { + SavageFactions.plugin.log(TL.COMMAND_JOIN_MOVEDLOG.toString(), fme.getName(), fplayer.getName(), faction.getTag()); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_JOIN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_JOIN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdKick.java b/src/main/java/com/massivecraft/factions/cmd/CmdKick.java index dcdb74ff..0cb144bb 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdKick.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdKick.java @@ -16,125 +16,125 @@ import org.bukkit.ChatColor; public class CmdKick extends FCommand { - public CmdKick() { - super(); - this.aliases.add("kick"); + public CmdKick() { + super(); + this.aliases.add("kick"); - this.optionalArgs.put("player name", "player name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "player name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.KICK.node; - this.disableOnLock = false; + this.permission = Permission.KICK.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer toKick = this.argIsSet(0) ? this.argAsBestFPlayerMatch(0) : null; - if (toKick == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_KICK_CANDIDATES.toString()).color(ChatColor.GOLD); - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); - } - if (fme.getRole().isAtLeast(Role.COLEADER)) { - // For both coleader and admin, add mods. - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.GRAY).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); - } - if (fme.getRole() == Role.LEADER) { - // Only add coleader to this for the leader. - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.COLEADER)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.RED).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); - } - } - } + @Override + public void perform() { + FPlayer toKick = this.argIsSet(0) ? this.argAsBestFPlayerMatch(0) : null; + if (toKick == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_KICK_CANDIDATES.toString()).color(ChatColor.GOLD); + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); + } + if (fme.getRole().isAtLeast(Role.COLEADER)) { + // For both coleader and admin, add mods. + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.GRAY).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); + } + if (fme.getRole() == Role.LEADER) { + // Only add coleader to this for the leader. + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.COLEADER)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.RED).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s); + } + } + } - sendFancyMessage(msg); - return; - } + sendFancyMessage(msg); + return; + } - if (fme == toKick) { - msg(TL.COMMAND_KICK_SELF); - msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdLeave.getUseageTemplate(false)); - return; - } + if (fme == toKick) { + msg(TL.COMMAND_KICK_SELF); + msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdLeave.getUseageTemplate(false)); + return; + } - Faction toKickFaction = toKick.getFaction(); + Faction toKickFaction = toKick.getFaction(); - if (toKickFaction.isWilderness()) { - sender.sendMessage(TL.COMMAND_KICK_NONE.toString()); - return; - } + if (toKickFaction.isWilderness()) { + sender.sendMessage(TL.COMMAND_KICK_NONE.toString()); + return; + } - // This permission check has been cleaned to be more understandable and logical - // Unless is admin, - // - Check for the kick permission. - // - Make sure the player is in the faction. - // - Make sure the kicked player has lower rank than the kicker. - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.KICK); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_NOPERMISSION, "kick"); - return; - } - if (toKickFaction != myFaction) { - msg(TL.COMMAND_KICK_NOTMEMBER, toKick.describeTo(fme, true), myFaction.describeTo(fme)); - return; - } - if (toKick.getRole().value >= fme.getRole().value) { - msg(TL.COMMAND_KICK_INSUFFICIENTRANK); - return; - } - if (!Conf.canLeaveWithNegativePower && toKick.getPower() < 0) { - msg(TL.COMMAND_KICK_NEGATIVEPOWER); - return; - } - } + // This permission check has been cleaned to be more understandable and logical + // Unless is admin, + // - Check for the kick permission. + // - Make sure the player is in the faction. + // - Make sure the kicked player has lower rank than the kicker. + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.KICK); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_NOPERMISSION, "kick"); + return; + } + if (toKickFaction != myFaction) { + msg(TL.COMMAND_KICK_NOTMEMBER, toKick.describeTo(fme, true), myFaction.describeTo(fme)); + return; + } + if (toKick.getRole().value >= fme.getRole().value) { + msg(TL.COMMAND_KICK_INSUFFICIENTRANK); + return; + } + if (!Conf.canLeaveWithNegativePower && toKick.getPower() < 0) { + msg(TL.COMMAND_KICK_NEGATIVEPOWER); + return; + } + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (!canAffordCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (!canAffordCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString())) { + return; + } - // trigger the leave event (cancellable) [reason:kicked] - FPlayerLeaveEvent event = new FPlayerLeaveEvent(toKick, toKick.getFaction(), FPlayerLeaveEvent.PlayerLeaveReason.KICKED); - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } + // trigger the leave event (cancellable) [reason:kicked] + FPlayerLeaveEvent event = new FPlayerLeaveEvent(toKick, toKick.getFaction(), FPlayerLeaveEvent.PlayerLeaveReason.KICKED); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (!payForCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString(), TL.COMMAND_KICK_FORKICK.toString())) { - return; - } + // then make 'em pay (if applicable) + if (!payForCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString(), TL.COMMAND_KICK_FORKICK.toString())) { + return; + } - toKickFaction.msg(TL.COMMAND_KICK_FACTION, fme.describeTo(toKickFaction, true), toKick.describeTo(toKickFaction, true)); + toKickFaction.msg(TL.COMMAND_KICK_FACTION, fme.describeTo(toKickFaction, true), toKick.describeTo(toKickFaction, true)); - toKick.msg(TL.COMMAND_KICK_KICKED, fme.describeTo(toKick, true), toKickFaction.describeTo(toKick)); - if (toKickFaction != myFaction) { - fme.msg(TL.COMMAND_KICK_KICKS, toKick.describeTo(fme), toKickFaction.describeTo(fme)); - } - if (Conf.logFactionKick) { - SavageFactions.plugin.log((senderIsConsole ? "A console command" : fme.getName()) + " kicked " + toKick.getName() + " from the faction: " + toKickFaction.getTag()); - } - if (toKick.getRole() == Role.LEADER) { - toKickFaction.promoteNewLeader(); - } - toKickFaction.deinvite(toKick); - toKick.resetFactionData(); - } + toKick.msg(TL.COMMAND_KICK_KICKED, fme.describeTo(toKick, true), toKickFaction.describeTo(toKick)); + if (toKickFaction != myFaction) { + fme.msg(TL.COMMAND_KICK_KICKS, toKick.describeTo(fme), toKickFaction.describeTo(fme)); + } + if (Conf.logFactionKick) { + SavageFactions.plugin.log((senderIsConsole ? "A console command" : fme.getName()) + " kicked " + toKick.getName() + " from the faction: " + toKickFaction.getTag()); + } + if (toKick.getRole() == Role.LEADER) { + toKickFaction.promoteNewLeader(); + } + toKickFaction.deinvite(toKick); + toKick.resetFactionData(); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_KICK_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_KICK_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java b/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java index 0ee95a2b..4c3ec562 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdKillHolograms.java @@ -4,32 +4,32 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdKillHolograms extends FCommand { - public CmdKillHolograms() { - super(); + public CmdKillHolograms() { + super(); - this.aliases.add("killholos"); + this.aliases.add("killholos"); - this.requiredArgs.add("radius"); + this.requiredArgs.add("radius"); - this.permission = Permission.KILLHOLOS.node; - this.disableOnLock = true; + this.permission = Permission.KILLHOLOS.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - me.sendMessage("Killing Invisible Armor Stands.."); - me.chat("/minecraft:kill @e[type=ArmorStand,r=" + argAsInt(0) + "]"); + @Override + public void perform() { + me.sendMessage("Killing Invisible Armor Stands.."); + me.chat("/minecraft:kill @e[type=ArmorStand,r=" + argAsInt(0) + "]"); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_KILLHOLOGRAMS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_KILLHOLOGRAMS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java b/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java index b28f4ab6..8d9c5634 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLeave.java @@ -5,32 +5,32 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLeave extends FCommand { - public CmdLeave() { - super(); - this.aliases.add("leave"); + public CmdLeave() { + super(); + this.aliases.add("leave"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.LEAVE.node; - this.disableOnLock = true; + this.permission = Permission.LEAVE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - fme.leave(true); - } + @Override + public void perform() { + fme.leave(true); + } - @Override - public TL getUsageTranslation() { - return TL.LEAVE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.LEAVE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdList.java b/src/main/java/com/massivecraft/factions/cmd/CmdList.java index 7c6793e1..46f75b2b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdList.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdList.java @@ -13,119 +13,119 @@ import java.util.*; public class CmdList extends FCommand { - private String[] defaults = new String[3]; + private String[] defaults = new String[3]; - public CmdList() { - super(); - this.aliases.add("list"); - this.aliases.add("ls"); + public CmdList() { + super(); + this.aliases.add("list"); + this.aliases.add("ls"); - // default values in case user has old config - defaults[0] = "&e&m----------&r&e[ &2Faction List &9{pagenumber}&e/&9{pagecount} &e]&m----------"; - defaults[1] = "Factionless {factionless} online"; - defaults[2] = "
    {faction} {online} / {members} online, Land / Power / Maxpower: {chunks}/{power}/{maxPower}"; + // default values in case user has old config + defaults[0] = "&e&m----------&r&e[ &2Faction List &9{pagenumber}&e/&9{pagecount} &e]&m----------"; + defaults[1] = "Factionless {factionless} online"; + defaults[2] = "{faction} {online} / {members} online, Land / Power / Maxpower: {chunks}/{power}/{maxPower}"; - //this.requiredArgs.add(""); - this.optionalArgs.put("page", "1"); + //this.requiredArgs.add(""); + this.optionalArgs.put("page", "1"); - this.permission = Permission.LIST.node; - this.disableOnLock = false; + this.permission = Permission.LIST.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostList, "to list the factions", "for listing the factions")) - return; + @Override + public void perform() { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostList, "to list the factions", "for listing the factions")) + return; - ArrayList factionList = Factions.getInstance().getAllFactions(); - factionList.remove(Factions.getInstance().getWilderness()); - factionList.remove(Factions.getInstance().getSafeZone()); - factionList.remove(Factions.getInstance().getWarZone()); + ArrayList factionList = Factions.getInstance().getAllFactions(); + factionList.remove(Factions.getInstance().getWilderness()); + factionList.remove(Factions.getInstance().getSafeZone()); + factionList.remove(Factions.getInstance().getWarZone()); - // remove exempt factions - if (fme != null && fme.getPlayer() != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt")) { - List exemptFactions = SavageFactions.plugin.getConfig().getStringList("show-exempt"); - Iterator factionIterator = factionList.iterator(); + // remove exempt factions + if (fme != null && fme.getPlayer() != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt")) { + List exemptFactions = SavageFactions.plugin.getConfig().getStringList("show-exempt"); + Iterator factionIterator = factionList.iterator(); - while (factionIterator.hasNext()) { - Faction next = factionIterator.next(); - if (exemptFactions.contains(next.getTag())) - factionIterator.remove(); - } - } + while (factionIterator.hasNext()) { + Faction next = factionIterator.next(); + if (exemptFactions.contains(next.getTag())) + factionIterator.remove(); + } + } - // Sort by total followers first - Collections.sort(factionList, new Comparator() { - @Override - public int compare(Faction f1, Faction f2) { - int f1Size = f1.getFPlayers().size(); - int f2Size = f2.getFPlayers().size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - } - }); + // Sort by total followers first + Collections.sort(factionList, new Comparator() { + @Override + public int compare(Faction f1, Faction f2) { + int f1Size = f1.getFPlayers().size(); + int f2Size = f2.getFPlayers().size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + } + }); - // Then sort by how many members are online now - Collections.sort(factionList, new Comparator() { - @Override - public int compare(Faction f1, Faction f2) { - int f1Size = f1.getFPlayersWhereOnline(true).size(); - int f2Size = f2.getFPlayersWhereOnline(true).size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - } - }); + // Then sort by how many members are online now + Collections.sort(factionList, new Comparator() { + @Override + public int compare(Faction f1, Faction f2) { + int f1Size = f1.getFPlayersWhereOnline(true).size(); + int f2Size = f2.getFPlayersWhereOnline(true).size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + } + }); - ArrayList lines = new ArrayList<>(); + ArrayList lines = new ArrayList<>(); - factionList.add(0, Factions.getInstance().getWilderness()); + factionList.add(0, Factions.getInstance().getWilderness()); - final int pageheight = 9; - int pagenumber = this.argAsInt(0, 1); - int pagecount = (factionList.size() / pageheight) + 1; - if (pagenumber > pagecount) { - pagenumber = pagecount; - } else if (pagenumber < 1) { - pagenumber = 1; - } - int start = (pagenumber - 1) * pageheight; - int end = start + pageheight; - if (end > factionList.size()) { - end = factionList.size(); - } + final int pageheight = 9; + int pagenumber = this.argAsInt(0, 1); + int pagecount = (factionList.size() / pageheight) + 1; + if (pagenumber > pagecount) { + pagenumber = pagecount; + } else if (pagenumber < 1) { + pagenumber = 1; + } + int start = (pagenumber - 1) * pageheight; + int end = start + pageheight; + if (end > factionList.size()) { + end = factionList.size(); + } - String header = p.getConfig().getString("list.header", defaults[0]); - header = header.replace("{pagenumber}", String.valueOf(pagenumber)).replace("{pagecount}", String.valueOf(pagecount)); - lines.add(p.txt.parse(header)); + String header = p.getConfig().getString("list.header", defaults[0]); + header = header.replace("{pagenumber}", String.valueOf(pagenumber)).replace("{pagecount}", String.valueOf(pagecount)); + lines.add(p.txt.parse(header)); - for (Faction faction : factionList.subList(start, end)) { - if (faction.isWilderness()) { - lines.add(p.txt.parse(TagUtil.parsePlain(faction, p.getConfig().getString("list.factionless", defaults[1])))); - continue; - } - lines.add(p.txt.parse(TagUtil.parsePlain(faction, fme, p.getConfig().getString("list.entry", defaults[2])))); - } - sendMessage(lines); - } + for (Faction faction : factionList.subList(start, end)) { + if (faction.isWilderness()) { + lines.add(p.txt.parse(TagUtil.parsePlain(faction, p.getConfig().getString("list.factionless", defaults[1])))); + continue; + } + lines.add(p.txt.parse(TagUtil.parsePlain(faction, fme, p.getConfig().getString("list.entry", defaults[2])))); + } + sendMessage(lines); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LIST_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LIST_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLock.java b/src/main/java/com/massivecraft/factions/cmd/CmdLock.java index 37c1bdac..e8872473 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLock.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLock.java @@ -5,40 +5,40 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLock extends FCommand { - // TODO: This solution needs refactoring. + // TODO: This solution needs refactoring. /* factions.lock: description: use the /f lock [on/off] command to temporarily lock the data files from being overwritten default: op */ - public CmdLock() { - super(); - this.aliases.add("lock"); + public CmdLock() { + super(); + this.aliases.add("lock"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "flip"); - this.permission = Permission.LOCK.node; - this.disableOnLock = false; + this.permission = Permission.LOCK.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - p.setLocked(this.argAsBool(0, !p.getLocked())); - msg(p.getLocked() ? TL.COMMAND_LOCK_LOCKED : TL.COMMAND_LOCK_UNLOCKED); - } + @Override + public void perform() { + p.setLocked(this.argAsBool(0, !p.getLocked())); + msg(p.getLocked() ? TL.COMMAND_LOCK_LOCKED : TL.COMMAND_LOCK_UNLOCKED); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LOCK_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LOCK_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java b/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java index b310cbd0..ca0917cb 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLogins.java @@ -5,27 +5,27 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLogins extends FCommand { - public CmdLogins() { - super(); - this.aliases.add("login"); - this.aliases.add("logins"); - this.aliases.add("logout"); - this.aliases.add("logouts"); - this.senderMustBePlayer = true; + public CmdLogins() { + super(); + this.aliases.add("login"); + this.aliases.add("logins"); + this.aliases.add("logout"); + this.aliases.add("logouts"); + this.senderMustBePlayer = true; - this.senderMustBeMember = true; - this.permission = Permission.MONITOR_LOGINS.node; - } + this.senderMustBeMember = true; + this.permission = Permission.MONITOR_LOGINS.node; + } - @Override - public void perform() { - boolean monitor = fme.isMonitoringJoins(); - fme.msg(TL.COMMAND_LOGINS_TOGGLE, String.valueOf(!monitor)); - fme.setMonitorJoins(!monitor); - } + @Override + public void perform() { + boolean monitor = fme.isMonitoringJoins(); + fme.msg(TL.COMMAND_LOGINS_TOGGLE, String.valueOf(!monitor)); + fme.setMonitorJoins(!monitor); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LOGINS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LOGINS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java index 9d40fbe6..ac02a91f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdLowPower.java @@ -6,38 +6,38 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdLowPower extends FCommand { - public CmdLowPower() { - super(); - this.aliases.add("lowpower"); + public CmdLowPower() { + super(); + this.aliases.add("lowpower"); - this.disableOnLock = false; + this.disableOnLock = false; - senderMustBePlayer = true; + senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double maxPower = Conf.powerPlayerMax; - String format = TL.COMMAND_LOWPOWER_FORMAT.toString(); - msg(TL.COMMAND_LOWPOWER_HEADER.toString().replace("{maxpower}", (int) maxPower + "")); - for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { - if (fPlayer.getPower() < maxPower) { - sendMessage(format.replace("{player}", fPlayer.getName()).replace("{player_power}", (int) fPlayer.getPower() + "").replace("{maxpower}", (int) maxPower + "")); - } - } - } + @Override + public void perform() { + double maxPower = Conf.powerPlayerMax; + String format = TL.COMMAND_LOWPOWER_FORMAT.toString(); + msg(TL.COMMAND_LOWPOWER_HEADER.toString().replace("{maxpower}", (int) maxPower + "")); + for (FPlayer fPlayer : fme.getFaction().getFPlayers()) { + if (fPlayer.getPower() < maxPower) { + sendMessage(format.replace("{player}", fPlayer.getName()).replace("{player_power}", (int) fPlayer.getPower() + "").replace("{maxpower}", (int) maxPower + "")); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_LOWPOWER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_LOWPOWER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMap.java b/src/main/java/com/massivecraft/factions/cmd/CmdMap.java index 14ec1fce..ccbaffbd 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMap.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMap.java @@ -9,62 +9,62 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMap extends FCommand { - public CmdMap() { - super(); - this.aliases.add("map"); + public CmdMap() { + super(); + this.aliases.add("map"); - //this.requiredArgs.add(""); - this.optionalArgs.put("on/off", "once"); + //this.requiredArgs.add(""); + this.optionalArgs.put("on/off", "once"); - this.permission = Permission.MAP.node; - this.disableOnLock = false; + this.permission = Permission.MAP.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (this.argIsSet(0)) { - if (this.argAsBool(0, !fme.isMapAutoUpdating())) { - // Turn on + @Override + public void perform() { + if (this.argIsSet(0)) { + if (this.argAsBool(0, !fme.isMapAutoUpdating())) { + // Turn on - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostMap, "to show the map", "for showing the map")) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostMap, "to show the map", "for showing the map")) { + return; + } - fme.setMapAutoUpdating(true); - msg(TL.COMMAND_MAP_UPDATE_ENABLED); + fme.setMapAutoUpdating(true); + msg(TL.COMMAND_MAP_UPDATE_ENABLED); - // And show the map once - showMap(); - } else { - // Turn off - fme.setMapAutoUpdating(false); - msg(TL.COMMAND_MAP_UPDATE_DISABLED); - } - } else { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostMap, TL.COMMAND_MAP_TOSHOW, TL.COMMAND_MAP_FORSHOW)) { - return; - } + // And show the map once + showMap(); + } else { + // Turn off + fme.setMapAutoUpdating(false); + msg(TL.COMMAND_MAP_UPDATE_DISABLED); + } + } else { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostMap, TL.COMMAND_MAP_TOSHOW, TL.COMMAND_MAP_FORSHOW)) { + return; + } - showMap(); - } - } + showMap(); + } + } - public void showMap() { - sendFancyMessage(Board.getInstance().getMap(fme, new FLocation(fme), fme.getPlayer().getLocation().getYaw())); - } + public void showMap() { + sendFancyMessage(Board.getInstance().getMap(fme, new FLocation(fme), fme.getPlayer().getLocation().getYaw())); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MAP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MAP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java b/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java index eac2f9b2..5588f828 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMapHeight.java @@ -5,36 +5,36 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMapHeight extends FCommand { - public CmdMapHeight() { - super(); + public CmdMapHeight() { + super(); - this.aliases.add("mapheight"); - this.aliases.add("mh"); + this.aliases.add("mapheight"); + this.aliases.add("mh"); - this.optionalArgs.put("height", "height"); + this.optionalArgs.put("height", "height"); - this.permission = Permission.MAPHEIGHT.node; + this.permission = Permission.MAPHEIGHT.node; - this.senderMustBePlayer = true; - } + this.senderMustBePlayer = true; + } - @Override - public void perform() { - if (args.size() == 0) { - fme.sendMessage(TL.COMMAND_MAPHEIGHT_CURRENT.format(fme.getMapHeight())); - return; - } + @Override + public void perform() { + if (args.size() == 0) { + fme.sendMessage(TL.COMMAND_MAPHEIGHT_CURRENT.format(fme.getMapHeight())); + return; + } - int height = argAsInt(0); + int height = argAsInt(0); - fme.setMapHeight(height); - fme.sendMessage(TL.COMMAND_MAPHEIGHT_SET.format(fme.getMapHeight())); - } + fme.setMapHeight(height); + fme.sendMessage(TL.COMMAND_MAPHEIGHT_SET.format(fme.getMapHeight())); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MAPHEIGHT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MAPHEIGHT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMod.java b/src/main/java/com/massivecraft/factions/cmd/CmdMod.java index 978d4428..56ab092b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMod.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMod.java @@ -11,79 +11,79 @@ import org.bukkit.ChatColor; public class CmdMod extends FCommand { - public CmdMod() { - super(); - this.aliases.add("mod"); - this.aliases.add("setmod"); - this.aliases.add("officer"); - this.aliases.add("setofficer"); + public CmdMod() { + super(); + this.aliases.add("mod"); + this.aliases.add("setmod"); + this.aliases.add("officer"); + this.aliases.add("setofficer"); - this.optionalArgs.put("player name", "name"); - //this.optionalArgs.put("", ""); + this.optionalArgs.put("player name", "name"); + //this.optionalArgs.put("", ""); - this.permission = Permission.MOD.node; - this.disableOnLock = true; + this.permission = Permission.MOD.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (you == null) { - FancyMessage msg = new FancyMessage(TL.COMMAND_MOD_CANDIDATES.toString()).color(ChatColor.GOLD); - for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { - String s = player.getName(); - msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " mod " + s); - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (you == null) { + FancyMessage msg = new FancyMessage(TL.COMMAND_MOD_CANDIDATES.toString()).color(ChatColor.GOLD); + for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) { + String s = player.getName(); + msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " mod " + s); + } - sendFancyMessage(msg); - return; - } + sendFancyMessage(msg); + return; + } - boolean permAny = Permission.MOD_ANY.has(sender, false); - Faction targetFaction = you.getFaction(); - if (targetFaction != myFaction && !permAny) { - msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); - return; - } + boolean permAny = Permission.MOD_ANY.has(sender, false); + Faction targetFaction = you.getFaction(); + if (targetFaction != myFaction && !permAny) { + msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true)); + return; + } - if (fme != null && fme.getRole() != Role.LEADER && !permAny) { - msg(TL.COMMAND_MOD_NOTADMIN); - return; - } + if (fme != null && fme.getRole() != Role.LEADER && !permAny) { + msg(TL.COMMAND_MOD_NOTADMIN); + return; + } - if (you == fme && !permAny) { - msg(TL.COMMAND_MOD_SELF); - return; - } + if (you == fme && !permAny) { + msg(TL.COMMAND_MOD_SELF); + return; + } - if (you.getRole() == Role.LEADER) { - msg(TL.COMMAND_MOD_TARGETISADMIN); - return; - } + if (you.getRole() == Role.LEADER) { + msg(TL.COMMAND_MOD_TARGETISADMIN); + return; + } - if (you.getRole() == Role.MODERATOR) { - // Revoke - you.setRole(Role.NORMAL); - targetFaction.msg(TL.COMMAND_MOD_REVOKED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_MOD_REVOKES, you.describeTo(fme, true)); - } else { - // Give - you.setRole(Role.MODERATOR); - targetFaction.msg(TL.COMMAND_MOD_PROMOTED, you.describeTo(targetFaction, true)); - msg(TL.COMMAND_MOD_PROMOTES, you.describeTo(fme, true)); - } - } + if (you.getRole() == Role.MODERATOR) { + // Revoke + you.setRole(Role.NORMAL); + targetFaction.msg(TL.COMMAND_MOD_REVOKED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_MOD_REVOKES, you.describeTo(fme, true)); + } else { + // Give + you.setRole(Role.MODERATOR); + targetFaction.msg(TL.COMMAND_MOD_PROMOTED, you.describeTo(targetFaction, true)); + msg(TL.COMMAND_MOD_PROMOTES, you.describeTo(fme, true)); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MOD_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MOD_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java index 361e632f..1720bd91 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdModifyPower.java @@ -6,45 +6,45 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdModifyPower extends FCommand { - public CmdModifyPower() { - super(); + public CmdModifyPower() { + super(); - this.aliases.add("pm"); - this.aliases.add("mp"); - this.aliases.add("modifypower"); - this.aliases.add("modpower"); + this.aliases.add("pm"); + this.aliases.add("mp"); + this.aliases.add("modifypower"); + this.aliases.add("modpower"); - this.requiredArgs.add("name"); - this.requiredArgs.add("power"); + this.requiredArgs.add("name"); + this.requiredArgs.add("power"); - this.permission = Permission.MODIFY_POWER.node; // admin only perm. + this.permission = Permission.MODIFY_POWER.node; // admin only perm. - // Let's not require anything and let console modify this as well. - this.senderMustBeAdmin = false; - this.senderMustBePlayer = false; - this.senderMustBeMember = false; - senderMustBeColeader = false; - this.senderMustBeModerator = false; - } + // Let's not require anything and let console modify this as well. + this.senderMustBeAdmin = false; + this.senderMustBePlayer = false; + this.senderMustBeMember = false; + senderMustBeColeader = false; + this.senderMustBeModerator = false; + } - @Override - public void perform() { - // /f modify # - FPlayer player = argAsBestFPlayerMatch(0); - Double number = argAsDouble(1); // returns null if not a Double. + @Override + public void perform() { + // /f modify # + FPlayer player = argAsBestFPlayerMatch(0); + Double number = argAsDouble(1); // returns null if not a Double. - if (player == null || number == null) { - sender.sendMessage(getHelpShort()); - return; - } + if (player == null || number == null) { + sender.sendMessage(getHelpShort()); + return; + } - player.alterPower(number); - int newPower = player.getPowerRounded(); // int so we don't have super long doubles. - msg(TL.COMMAND_MODIFYPOWER_ADDED, number, player.getName(), newPower); - } + player.alterPower(number); + int newPower = player.getPowerRounded(); // int so we don't have super long doubles. + msg(TL.COMMAND_MODIFYPOWER_ADDED, number, player.getName(), newPower); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MODIFYPOWER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MODIFYPOWER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java index b1cd4e19..dbce6182 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoney.java @@ -5,48 +5,48 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMoney extends FCommand { - public CmdMoneyBalance cmdMoneyBalance = new CmdMoneyBalance(); - public CmdMoneyDeposit cmdMoneyDeposit = new CmdMoneyDeposit(); - public CmdMoneyWithdraw cmdMoneyWithdraw = new CmdMoneyWithdraw(); - public CmdMoneyTransferFf cmdMoneyTransferFf = new CmdMoneyTransferFf(); - public CmdMoneyTransferFp cmdMoneyTransferFp = new CmdMoneyTransferFp(); - public CmdMoneyTransferPf cmdMoneyTransferPf = new CmdMoneyTransferPf(); + public CmdMoneyBalance cmdMoneyBalance = new CmdMoneyBalance(); + public CmdMoneyDeposit cmdMoneyDeposit = new CmdMoneyDeposit(); + public CmdMoneyWithdraw cmdMoneyWithdraw = new CmdMoneyWithdraw(); + public CmdMoneyTransferFf cmdMoneyTransferFf = new CmdMoneyTransferFf(); + public CmdMoneyTransferFp cmdMoneyTransferFp = new CmdMoneyTransferFp(); + public CmdMoneyTransferPf cmdMoneyTransferPf = new CmdMoneyTransferPf(); - public CmdMoney() { - super(); - this.aliases.add("money"); + public CmdMoney() { + super(); + this.aliases.add("money"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("","") + //this.requiredArgs.add(""); + //this.optionalArgs.put("","") - this.isMoneyCommand = true; + this.isMoneyCommand = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - this.helpLong.add(p.txt.parseTags(TL.COMMAND_MONEY_LONG.toString())); + this.helpLong.add(p.txt.parseTags(TL.COMMAND_MONEY_LONG.toString())); - this.addSubCommand(this.cmdMoneyBalance); - this.addSubCommand(this.cmdMoneyDeposit); - this.addSubCommand(this.cmdMoneyWithdraw); - this.addSubCommand(this.cmdMoneyTransferFf); - this.addSubCommand(this.cmdMoneyTransferFp); - this.addSubCommand(this.cmdMoneyTransferPf); + this.addSubCommand(this.cmdMoneyBalance); + this.addSubCommand(this.cmdMoneyDeposit); + this.addSubCommand(this.cmdMoneyWithdraw); + this.addSubCommand(this.cmdMoneyTransferFf); + this.addSubCommand(this.cmdMoneyTransferFp); + this.addSubCommand(this.cmdMoneyTransferPf); - } + } - @Override - public void perform() { - this.commandChain.add(this); - SavageFactions.plugin.cmdAutoHelp.execute(this.sender, this.args, this.commandChain); - } + @Override + public void perform() { + this.commandChain.add(this); + SavageFactions.plugin.cmdAutoHelp.execute(this.sender, this.args, this.commandChain); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEY_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEY_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java index bce68b8a..83699a5e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyBalance.java @@ -7,46 +7,46 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdMoneyBalance extends FCommand { - public CmdMoneyBalance() { - super(); - this.aliases.add("b"); - this.aliases.add("balance"); + public CmdMoneyBalance() { + super(); + this.aliases.add("b"); + this.aliases.add("balance"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction", "yours"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction", "yours"); - this.permission = Permission.MONEY_BALANCE.node; - this.setHelpShort(TL.COMMAND_MONEYBALANCE_SHORT.toString()); + this.permission = Permission.MONEY_BALANCE.node; + this.setHelpShort(TL.COMMAND_MONEYBALANCE_SHORT.toString()); - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction faction = myFaction; - if (this.argIsSet(0)) { - faction = this.argAsFaction(0); - } + @Override + public void perform() { + Faction faction = myFaction; + if (this.argIsSet(0)) { + faction = this.argAsFaction(0); + } - if (faction == null) { - return; - } - if (faction != myFaction && !Permission.MONEY_BALANCE_ANY.has(sender, true)) { - return; - } + if (faction == null) { + return; + } + if (faction != myFaction && !Permission.MONEY_BALANCE_ANY.has(sender, true)) { + return; + } - if (fme != null) { - Econ.sendBalanceInfo(fme, faction); - } - } + if (fme != null) { + Econ.sendBalanceInfo(fme, faction); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYBALANCE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYBALANCE_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java index cdf79595..331161b6 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyDeposit.java @@ -11,41 +11,41 @@ import org.bukkit.ChatColor; public class CmdMoneyDeposit extends FCommand { - public CmdMoneyDeposit() { - super(); - this.aliases.add("d"); - this.aliases.add("deposit"); + public CmdMoneyDeposit() { + super(); + this.aliases.add("d"); + this.aliases.add("deposit"); - this.requiredArgs.add("amount"); - this.optionalArgs.put("faction", "yours"); + this.requiredArgs.add("amount"); + this.optionalArgs.put("faction", "yours"); - this.permission = Permission.MONEY_DEPOSIT.node; + this.permission = Permission.MONEY_DEPOSIT.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator faction = this.argAsFaction(1, myFaction); - if (faction == null) { - return; - } - boolean success = Econ.transferMoney(fme, fme, faction, amount); + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator faction = this.argAsFaction(1, myFaction); + if (faction == null) { + return; + } + boolean success = Econ.transferMoney(fme, fme, faction, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYDEPOSIT_DEPOSITED.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYDEPOSIT_DEPOSITED.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYDEPOSIT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYDEPOSIT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java index 75d5884d..27274da4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFf.java @@ -12,47 +12,47 @@ import org.bukkit.entity.Player; public class CmdMoneyTransferFf extends FCommand { - public CmdMoneyTransferFf() { - this.aliases.add("ff"); + public CmdMoneyTransferFf() { + this.aliases.add("ff"); - this.requiredArgs.add("amount"); - this.requiredArgs.add("faction"); - this.requiredArgs.add("faction"); + this.requiredArgs.add("amount"); + this.requiredArgs.add("faction"); + this.requiredArgs.add("faction"); - //this.optionalArgs.put("", ""); + //this.optionalArgs.put("", ""); - this.permission = Permission.MONEY_F2F.node; + this.permission = Permission.MONEY_F2F.node; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator from = this.argAsFaction(1); - if (from == null) { - return; - } - EconomyParticipator to = this.argAsFaction(2); - if (to == null) { - return; - } + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator from = this.argAsFaction(1); + if (from == null) { + return; + } + EconomyParticipator to = this.argAsFaction(2); + if (to == null) { + return; + } - boolean success = Econ.transferMoney(fme, from, to, amount); + boolean success = Econ.transferMoney(fme, from, to, amount); - if (success && Conf.logMoneyTransactions) { - String name = sender instanceof Player ? fme.getName() : sender.getName(); - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFF_TRANSFER.toString(), name, Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + String name = sender instanceof Player ? fme.getName() : sender.getName(); + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFF_TRANSFER.toString(), name, Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYTRANSFERFF_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYTRANSFERFF_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java index 17eb50bb..e743ea9e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferFp.java @@ -11,46 +11,46 @@ import org.bukkit.ChatColor; public class CmdMoneyTransferFp extends FCommand { - public CmdMoneyTransferFp() { - this.aliases.add("fp"); + public CmdMoneyTransferFp() { + this.aliases.add("fp"); - this.requiredArgs.add("amount"); - this.requiredArgs.add("faction"); - this.requiredArgs.add("player"); + this.requiredArgs.add("amount"); + this.requiredArgs.add("faction"); + this.requiredArgs.add("player"); - //this.optionalArgs.put("", ""); + //this.optionalArgs.put("", ""); - this.permission = Permission.MONEY_F2P.node; + this.permission = Permission.MONEY_F2P.node; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator from = this.argAsFaction(1); - if (from == null) { - return; - } - EconomyParticipator to = this.argAsBestFPlayerMatch(2); - if (to == null) { - return; - } + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator from = this.argAsFaction(1); + if (from == null) { + return; + } + EconomyParticipator to = this.argAsBestFPlayerMatch(2); + if (to == null) { + return; + } - boolean success = Econ.transferMoney(fme, from, to, amount); + boolean success = Econ.transferMoney(fme, from, to, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFP_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERFP_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYTRANSFERFP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYTRANSFERFP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java index 474cb70e..f245e4d5 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyTransferPf.java @@ -11,46 +11,46 @@ import org.bukkit.ChatColor; public class CmdMoneyTransferPf extends FCommand { - public CmdMoneyTransferPf() { - this.aliases.add("pf"); + public CmdMoneyTransferPf() { + this.aliases.add("pf"); - this.requiredArgs.add("amount"); - this.requiredArgs.add("player"); - this.requiredArgs.add("faction"); + this.requiredArgs.add("amount"); + this.requiredArgs.add("player"); + this.requiredArgs.add("faction"); - //this.optionalArgs.put("", ""); + //this.optionalArgs.put("", ""); - this.permission = Permission.MONEY_P2F.node; + this.permission = Permission.MONEY_P2F.node; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator from = this.argAsBestFPlayerMatch(1); - if (from == null) { - return; - } - EconomyParticipator to = this.argAsFaction(2); - if (to == null) { - return; - } + @Override + public void perform() { + double amount = this.argAsDouble(0, 0d); + EconomyParticipator from = this.argAsBestFPlayerMatch(1); + if (from == null) { + return; + } + EconomyParticipator to = this.argAsFaction(2); + if (to == null) { + return; + } - boolean success = Econ.transferMoney(fme, from, to, amount); + boolean success = Econ.transferMoney(fme, from, to, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERPF_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYTRANSFERPF_TRANSFER.toString(), fme.getName(), Econ.moneyString(amount), from.describeTo(null), to.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYTRANSFERPF_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYTRANSFERPF_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java index 32f4e07e..e08791d7 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMoneyWithdraw.java @@ -13,47 +13,47 @@ import org.bukkit.ChatColor; public class CmdMoneyWithdraw extends FCommand { - public CmdMoneyWithdraw() { - this.aliases.add("w"); - this.aliases.add("withdraw"); + public CmdMoneyWithdraw() { + this.aliases.add("w"); + this.aliases.add("withdraw"); - this.requiredArgs.add("amount"); - this.optionalArgs.put("faction", "yours"); + this.requiredArgs.add("amount"); + this.optionalArgs.put("faction", "yours"); - this.permission = Permission.MONEY_WITHDRAW.node; + this.permission = Permission.MONEY_WITHDRAW.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { + @Override + public void perform() { - double amount = this.argAsDouble(0, 0d); - EconomyParticipator faction = this.argAsFaction(1, myFaction); - if (faction == null) { - return; - } + double amount = this.argAsDouble(0, 0d); + EconomyParticipator faction = this.argAsFaction(1, myFaction); + if (faction == null) { + return; + } - Access access = myFaction.getAccess(fme, PermissableAction.WITHDRAW); - if (access == Access.DENY) { - fme.msg(TL.GENERIC_NOPERMISSION, "withdraw"); - return; - } + Access access = myFaction.getAccess(fme, PermissableAction.WITHDRAW); + if (access == Access.DENY) { + fme.msg(TL.GENERIC_NOPERMISSION, "withdraw"); + return; + } - boolean success = Econ.transferMoney(fme, faction, fme, amount); + boolean success = Econ.transferMoney(fme, faction, fme, amount); - if (success && Conf.logMoneyTransactions) { - SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYWITHDRAW_WITHDRAW.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); - } - } + if (success && Conf.logMoneyTransactions) { + SavageFactions.plugin.log(ChatColor.stripColor(SavageFactions.plugin.txt.parse(TL.COMMAND_MONEYWITHDRAW_WITHDRAW.toString(), fme.getName(), Econ.moneyString(amount), faction.describeTo(null)))); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_MONEYWITHDRAW_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_MONEYWITHDRAW_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdNear.java b/src/main/java/com/massivecraft/factions/cmd/CmdNear.java index 0a6208c8..eeae4895 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdNear.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdNear.java @@ -8,47 +8,47 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; public class CmdNear extends FCommand { - public CmdNear() { - super(); + public CmdNear() { + super(); - this.aliases.add("near"); - this.aliases.add("nearby"); + this.aliases.add("near"); + this.aliases.add("nearby"); - this.disableOnLock = true; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fnear.Enabled")) { - fme.msg(TL.COMMAND_NEAR_DISABLED_MSG); - return; - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fnear.Enabled")) { + fme.msg(TL.COMMAND_NEAR_DISABLED_MSG); + return; + } - double range = SavageFactions.plugin.getConfig().getInt("fnear.Radius"); - String format = TL.COMMAND_NEAR_FORMAT.toString(); - fme.msg(TL.COMMAND_NEAR_USE_MSG); - for (Entity e : me.getNearbyEntities(range, 255, range)) { - if (e instanceof Player) { - Player player = (((Player) e).getPlayer()); - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fme.getFaction() == fplayer.getFaction()) { - double distance = me.getLocation().distance(player.getLocation()); - fme.sendMessage(format.replace("{playername}", player.getDisplayName()).replace("{distance}", (int) distance + "")); - } - } + double range = SavageFactions.plugin.getConfig().getInt("fnear.Radius"); + String format = TL.COMMAND_NEAR_FORMAT.toString(); + fme.msg(TL.COMMAND_NEAR_USE_MSG); + for (Entity e : me.getNearbyEntities(range, 255, range)) { + if (e instanceof Player) { + Player player = (((Player) e).getPlayer()); + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fme.getFaction() == fplayer.getFaction()) { + double distance = me.getLocation().distance(player.getLocation()); + fme.sendMessage(format.replace("{playername}", player.getDisplayName()).replace("{distance}", (int) distance + "")); + } + } - } - } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_NEAR_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_NEAR_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java b/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java index 0d3dabe3..ba0c8f6b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java @@ -8,48 +8,48 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdOpen extends FCommand { - public CmdOpen() { - super(); - this.aliases.add("open"); + public CmdOpen() { + super(); + this.aliases.add("open"); - //this.requiredArgs.add(""); - this.optionalArgs.put("yes/no", "flip"); + //this.requiredArgs.add(""); + this.optionalArgs.put("yes/no", "flip"); - this.permission = Permission.OPEN.node; - this.disableOnLock = false; + this.permission = Permission.OPEN.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostOpen, TL.COMMAND_OPEN_TOOPEN, TL.COMMAND_OPEN_FOROPEN)) { - return; - } + @Override + public void perform() { + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostOpen, TL.COMMAND_OPEN_TOOPEN, TL.COMMAND_OPEN_FOROPEN)) { + return; + } - myFaction.setOpen(this.argAsBool(0, !myFaction.getOpen())); + myFaction.setOpen(this.argAsBool(0, !myFaction.getOpen())); - String open = myFaction.getOpen() ? TL.COMMAND_OPEN_OPEN.toString() : TL.COMMAND_OPEN_CLOSED.toString(); + String open = myFaction.getOpen() ? TL.COMMAND_OPEN_OPEN.toString() : TL.COMMAND_OPEN_CLOSED.toString(); - // Inform - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (fplayer.getFactionId().equals(myFaction.getId())) { - fplayer.msg(TL.COMMAND_OPEN_CHANGES, fme.getName(), open); - continue; - } - fplayer.msg(TL.COMMAND_OPEN_CHANGED, myFaction.getTag(fplayer.getFaction()), open); - } - } + // Inform + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.getFactionId().equals(myFaction.getId())) { + fplayer.msg(TL.COMMAND_OPEN_CHANGES, fme.getName(), open); + continue; + } + fplayer.msg(TL.COMMAND_OPEN_CHANGED, myFaction.getTag(fplayer.getFaction()), open); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_OPEN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_OPEN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java b/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java index 9811f02c..beb69334 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java @@ -8,100 +8,100 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdOwner extends FCommand { - public CmdOwner() { - super(); - this.aliases.add("owner"); + public CmdOwner() { + super(); + this.aliases.add("owner"); - //this.requiredArgs.add(""); - this.optionalArgs.put("player name", "you"); + //this.requiredArgs.add(""); + this.optionalArgs.put("player name", "you"); - this.permission = Permission.OWNER.node; - this.disableOnLock = true; + this.permission = Permission.OWNER.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - // TODO: Fix colors! + // TODO: Fix colors! - @Override - public void perform() { - boolean hasBypass = fme.isAdminBypassing(); + @Override + public void perform() { + boolean hasBypass = fme.isAdminBypassing(); - if (!hasBypass && !assertHasFaction()) { - return; - } + if (!hasBypass && !assertHasFaction()) { + return; + } - if (!Conf.ownedAreasEnabled) { - fme.msg(TL.COMMAND_OWNER_DISABLED); - return; - } + if (!Conf.ownedAreasEnabled) { + fme.msg(TL.COMMAND_OWNER_DISABLED); + return; + } - if (!hasBypass && Conf.ownedAreasLimitPerFaction > 0 && myFaction.getCountOfClaimsWithOwners() >= Conf.ownedAreasLimitPerFaction) { - fme.msg(TL.COMMAND_OWNER_LIMIT, Conf.ownedAreasLimitPerFaction); - return; - } + if (!hasBypass && Conf.ownedAreasLimitPerFaction > 0 && myFaction.getCountOfClaimsWithOwners() >= Conf.ownedAreasLimitPerFaction) { + fme.msg(TL.COMMAND_OWNER_LIMIT, Conf.ownedAreasLimitPerFaction); + return; + } - if (!hasBypass && !assertMinRole(Conf.ownedAreasModeratorsCanSet ? Role.MODERATOR : Role.LEADER)) { - return; - } + if (!hasBypass && !assertMinRole(Conf.ownedAreasModeratorsCanSet ? Role.MODERATOR : Role.LEADER)) { + return; + } - FLocation flocation = new FLocation(fme); + FLocation flocation = new FLocation(fme); - Faction factionHere = Board.getInstance().getFactionAt(flocation); - if (factionHere != myFaction) { - if (!factionHere.isNormal()) { - fme.msg(TL.COMMAND_OWNER_NOTCLAIMED); - return; - } + Faction factionHere = Board.getInstance().getFactionAt(flocation); + if (factionHere != myFaction) { + if (!factionHere.isNormal()) { + fme.msg(TL.COMMAND_OWNER_NOTCLAIMED); + return; + } - if (!hasBypass) { - fme.msg(TL.COMMAND_OWNER_WRONGFACTION); - return; - } - } + if (!hasBypass) { + fme.msg(TL.COMMAND_OWNER_WRONGFACTION); + return; + } + } - FPlayer target = this.argAsBestFPlayerMatch(0, fme); - if (target == null) { - return; - } + FPlayer target = this.argAsBestFPlayerMatch(0, fme); + if (target == null) { + return; + } - String playerName = target.getName(); + String playerName = target.getName(); - if (target.getFaction() != myFaction) { - fme.msg(TL.COMMAND_OWNER_NOTMEMBER, playerName); - return; - } + if (target.getFaction() != myFaction) { + fme.msg(TL.COMMAND_OWNER_NOTMEMBER, playerName); + return; + } - // if no player name was passed, and this claim does already have owners set, clear them - if (args.isEmpty() && myFaction.doesLocationHaveOwnersSet(flocation)) { - myFaction.clearClaimOwnership(flocation); - fme.msg(TL.COMMAND_OWNER_CLEARED); - return; - } + // if no player name was passed, and this claim does already have owners set, clear them + if (args.isEmpty() && myFaction.doesLocationHaveOwnersSet(flocation)) { + myFaction.clearClaimOwnership(flocation); + fme.msg(TL.COMMAND_OWNER_CLEARED); + return; + } - if (myFaction.isPlayerInOwnerList(target, flocation)) { - myFaction.removePlayerAsOwner(target, flocation); - fme.msg(TL.COMMAND_OWNER_REMOVED, playerName); - return; - } + if (myFaction.isPlayerInOwnerList(target, flocation)) { + myFaction.removePlayerAsOwner(target, flocation); + fme.msg(TL.COMMAND_OWNER_REMOVED, playerName); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostOwner, TL.COMMAND_OWNER_TOSET, TL.COMMAND_OWNER_FORSET)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostOwner, TL.COMMAND_OWNER_TOSET, TL.COMMAND_OWNER_FORSET)) { + return; + } - myFaction.setPlayerAsOwner(target, flocation); + myFaction.setPlayerAsOwner(target, flocation); - fme.msg(TL.COMMAND_OWNER_ADDED, playerName); - } + fme.msg(TL.COMMAND_OWNER_ADDED, playerName); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_OWNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_OWNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java b/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java index ee49571e..4d0f77d1 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java @@ -9,64 +9,64 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdOwnerList extends FCommand { - public CmdOwnerList() { - super(); - this.aliases.add("ownerlist"); + public CmdOwnerList() { + super(); + this.aliases.add("ownerlist"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.OWNERLIST.node; - this.disableOnLock = false; + this.permission = Permission.OWNERLIST.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - boolean hasBypass = fme.isAdminBypassing(); + @Override + public void perform() { + boolean hasBypass = fme.isAdminBypassing(); - if (!hasBypass && !assertHasFaction()) { - return; - } + if (!hasBypass && !assertHasFaction()) { + return; + } - if (!Conf.ownedAreasEnabled) { - fme.msg(TL.COMMAND_OWNERLIST_DISABLED); - return; - } + if (!Conf.ownedAreasEnabled) { + fme.msg(TL.COMMAND_OWNERLIST_DISABLED); + return; + } - FLocation flocation = new FLocation(fme); + FLocation flocation = new FLocation(fme); - if (Board.getInstance().getFactionAt(flocation) != myFaction) { - if (!hasBypass) { - fme.msg(TL.COMMAND_OWNERLIST_WRONGFACTION); - return; - } - //TODO: This code won't ever be called. - myFaction = Board.getInstance().getFactionAt(flocation); - if (!myFaction.isNormal()) { - fme.msg(TL.COMMAND_OWNERLIST_NOTCLAIMED); - return; - } - } + if (Board.getInstance().getFactionAt(flocation) != myFaction) { + if (!hasBypass) { + fme.msg(TL.COMMAND_OWNERLIST_WRONGFACTION); + return; + } + //TODO: This code won't ever be called. + myFaction = Board.getInstance().getFactionAt(flocation); + if (!myFaction.isNormal()) { + fme.msg(TL.COMMAND_OWNERLIST_NOTCLAIMED); + return; + } + } - String owners = myFaction.getOwnerListString(flocation); + String owners = myFaction.getOwnerListString(flocation); - if (owners == null || owners.isEmpty()) { - fme.msg(TL.COMMAND_OWNERLIST_NONE); - return; - } + if (owners == null || owners.isEmpty()) { + fme.msg(TL.COMMAND_OWNERLIST_NONE); + return; + } - fme.msg(TL.COMMAND_OWNERLIST_OWNERS, owners); - } + fme.msg(TL.COMMAND_OWNERLIST_OWNERS, owners); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_OWNERLIST_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_OWNERLIST_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java index ade8d076..29a789fe 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSee.java @@ -6,44 +6,44 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdPaypalSee extends FCommand { - public CmdPaypalSee() { - aliases.add("seepaypal"); - aliases.add("getpaypal"); - requiredArgs.add("faction"); - permission = Permission.ADMIN.node; - disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + public CmdPaypalSee() { + aliases.add("seepaypal"); + aliases.add("getpaypal"); + requiredArgs.add("faction"); + permission = Permission.ADMIN.node; + disableOnLock = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - fme.msg(TL.GENERIC_DISABLED); - } else { - Faction faction = argAsFaction(0); + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + fme.msg(TL.GENERIC_DISABLED); + } else { + Faction faction = argAsFaction(0); - if (faction != null) { - if (!faction.isWilderness() && !faction.isSafeZone() && !faction.isWarZone()) { - if (faction.getPaypal() != null) { - fme.msg(TL.COMMAND_PAYPALSEE_FACTION_PAYPAL.toString(), faction.getTag(), faction.getPaypal()); - } else { - fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOTSET.toString(), faction.getTag(), faction.getPaypal()); - } + if (faction != null) { + if (!faction.isWilderness() && !faction.isSafeZone() && !faction.isWarZone()) { + if (faction.getPaypal() != null) { + fme.msg(TL.COMMAND_PAYPALSEE_FACTION_PAYPAL.toString(), faction.getTag(), faction.getPaypal()); + } else { + fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOTSET.toString(), faction.getTag(), faction.getPaypal()); + } - } else { - fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOFACTION.toString(), me.getName()); - } - } - } - } + } else { + fme.msg(TL.COMMAND_PAYPALSEE_FACTION_NOFACTION.toString(), me.getName()); + } + } + } + } - public TL getUsageTranslation() { - return TL.COMMAND_PAYPALSEE_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_PAYPALSEE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java index 35456fbd..02b1b3a4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPaypalSet.java @@ -6,34 +6,34 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdPaypalSet extends FCommand { - public CmdPaypalSet() { - this.aliases.add("setpaypal"); - this.aliases.add("paypal"); - this.requiredArgs.add("email"); - this.permission = Permission.PAYPALSET.node; - this.disableOnLock = false; - this.senderMustBePlayer = true; - this.senderMustBeMember = false; - this.senderMustBeModerator = false; - this.senderMustBeColeader = true; - this.senderMustBeAdmin = false; + public CmdPaypalSet() { + this.aliases.add("setpaypal"); + this.aliases.add("paypal"); + this.requiredArgs.add("email"); + this.permission = Permission.PAYPALSET.node; + this.disableOnLock = false; + this.senderMustBePlayer = true; + this.senderMustBeMember = false; + this.senderMustBeModerator = false; + this.senderMustBeColeader = true; + this.senderMustBeAdmin = false; - } + } - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - fme.msg(TL.GENERIC_DISABLED); - } else { - String paypal = argAsString(0); - if (paypal != null) { - myFaction.paypalSet(paypal); - fme.msg(TL.COMMAND_PAYPALSET_SUCCESSFUL, paypal); - } - } - } + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + fme.msg(TL.GENERIC_DISABLED); + } else { + String paypal = argAsString(0); + if (paypal != null) { + myFaction.paypalSet(paypal); + fme.msg(TL.COMMAND_PAYPALSET_SUCCESSFUL, paypal); + } + } + } - public TL getUsageTranslation() { - return TL.COMMAND_PAYPALSET_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_PAYPALSET_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java b/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java index 02f6bb29..58151f98 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java @@ -8,55 +8,55 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdPeaceful extends FCommand { - public CmdPeaceful() { - super(); - this.aliases.add("peaceful"); + public CmdPeaceful() { + super(); + this.aliases.add("peaceful"); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); - this.permission = Permission.SET_PEACEFUL.node; - this.disableOnLock = true; + this.permission = Permission.SET_PEACEFUL.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - Faction faction = this.argAsFaction(0); - if (faction == null) { - return; - } + @Override + public void perform() { + Faction faction = this.argAsFaction(0); + if (faction == null) { + return; + } - String change; - if (faction.isPeaceful()) { - change = TL.COMMAND_PEACEFUL_REVOKE.toString(); - faction.setPeaceful(false); - } else { - change = TL.COMMAND_PEACEFUL_GRANT.toString(); - faction.setPeaceful(true); - } + String change; + if (faction.isPeaceful()) { + change = TL.COMMAND_PEACEFUL_REVOKE.toString(); + faction.setPeaceful(false); + } else { + change = TL.COMMAND_PEACEFUL_GRANT.toString(); + faction.setPeaceful(true); + } - // Inform all players - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); - if (fplayer.getFaction() == faction) { - fplayer.msg(TL.COMMAND_PEACEFUL_YOURS, blame, change); - } else { - fplayer.msg(TL.COMMAND_PEACEFUL_OTHER, blame, change, faction.getTag(fplayer)); - } - } + // Inform all players + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); + if (fplayer.getFaction() == faction) { + fplayer.msg(TL.COMMAND_PEACEFUL_YOURS, blame, change); + } else { + fplayer.msg(TL.COMMAND_PEACEFUL_OTHER, blame, change, faction.getTag(fplayer)); + } + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PEACEFUL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PEACEFUL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java b/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java index 6c942012..6c3f6541 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java @@ -16,111 +16,111 @@ import java.util.Set; public class CmdPerm extends FCommand { - public CmdPerm() { - super(); - this.aliases.add("perm"); - this.aliases.add("perms"); - this.aliases.add("permission"); - this.aliases.add("permissions"); + public CmdPerm() { + super(); + this.aliases.add("perm"); + this.aliases.add("perms"); + this.aliases.add("permission"); + this.aliases.add("permissions"); - this.optionalArgs.put("relation", "relation"); - this.optionalArgs.put("action", "action"); - this.optionalArgs.put("access", "access"); + this.optionalArgs.put("relation", "relation"); + this.optionalArgs.put("action", "action"); + this.optionalArgs.put("access", "access"); - this.disableOnLock = true; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = true; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = true; - } + } - @Override - public void perform() { - if (args.size() == 0) { - PermissableRelationGUI gui = new PermissableRelationGUI(fme); - gui.build(); + @Override + public void perform() { + if (args.size() == 0) { + PermissableRelationGUI gui = new PermissableRelationGUI(fme); + gui.build(); - me.openInventory(gui.getInventory()); - return; - } else if (args.size() == 1 && getPermissable(argAsString(0)) != null) { - PermissableActionGUI gui = new PermissableActionGUI(fme, getPermissable(argAsString(0))); - gui.build(); + me.openInventory(gui.getInventory()); + return; + } else if (args.size() == 1 && getPermissable(argAsString(0)) != null) { + PermissableActionGUI gui = new PermissableActionGUI(fme, getPermissable(argAsString(0))); + gui.build(); - me.openInventory(gui.getInventory()); - return; - } + me.openInventory(gui.getInventory()); + return; + } - // If not opening GUI, then setting the permission manually. - if (args.size() != 3) { - fme.msg(TL.COMMAND_PERM_DESCRIPTION); - return; - } + // If not opening GUI, then setting the permission manually. + if (args.size() != 3) { + fme.msg(TL.COMMAND_PERM_DESCRIPTION); + return; + } - Set permissables = new HashSet<>(); - Set permissableActions = new HashSet<>(); + Set permissables = new HashSet<>(); + Set permissableActions = new HashSet<>(); - boolean allRelations = argAsString(0).equalsIgnoreCase("all"); - boolean allActions = argAsString(1).equalsIgnoreCase("all"); + boolean allRelations = argAsString(0).equalsIgnoreCase("all"); + boolean allActions = argAsString(1).equalsIgnoreCase("all"); - if (allRelations) { - permissables.addAll(myFaction.getPermissions().keySet()); - } else { - Permissable permissable = getPermissable(argAsString(0)); + if (allRelations) { + permissables.addAll(myFaction.getPermissions().keySet()); + } else { + Permissable permissable = getPermissable(argAsString(0)); - if (permissable == null) { - fme.msg(TL.COMMAND_PERM_INVALID_RELATION); - return; - } + if (permissable == null) { + fme.msg(TL.COMMAND_PERM_INVALID_RELATION); + return; + } - permissables.add(permissable); - } + permissables.add(permissable); + } - if (allActions) { - permissableActions.addAll(Arrays.asList(PermissableAction.values())); - } else { - PermissableAction permissableAction = PermissableAction.fromString(argAsString(1)); - if (permissableAction == null) { - fme.msg(TL.COMMAND_PERM_INVALID_ACTION); - return; - } + if (allActions) { + permissableActions.addAll(Arrays.asList(PermissableAction.values())); + } else { + PermissableAction permissableAction = PermissableAction.fromString(argAsString(1)); + if (permissableAction == null) { + fme.msg(TL.COMMAND_PERM_INVALID_ACTION); + return; + } - permissableActions.add(permissableAction); - } + permissableActions.add(permissableAction); + } - Access access = Access.fromString(argAsString(2)); + Access access = Access.fromString(argAsString(2)); - if (access == null) { - fme.msg(TL.COMMAND_PERM_INVALID_ACCESS); - return; - } + if (access == null) { + fme.msg(TL.COMMAND_PERM_INVALID_ACCESS); + return; + } - for (Permissable permissable : permissables) { - for (PermissableAction permissableAction : permissableActions) { - fme.getFaction().setPermission(permissable, permissableAction, access); - } - } + for (Permissable permissable : permissables) { + for (PermissableAction permissableAction : permissableActions) { + fme.getFaction().setPermission(permissable, permissableAction, access); + } + } - fme.msg(TL.COMMAND_PERM_SET, argAsString(1), access.name(), argAsString(0)); - SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), argAsString(1), access.name(), argAsString(0)) + " for faction " + fme.getTag()); - } + fme.msg(TL.COMMAND_PERM_SET, argAsString(1), access.name(), argAsString(0)); + SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), argAsString(1), access.name(), argAsString(0)) + " for faction " + fme.getTag()); + } - private Permissable getPermissable(String name) { - if (Role.fromString(name.toUpperCase()) != null) { - return Role.fromString(name.toUpperCase()); - } else if (Relation.fromString(name.toUpperCase()) != null) { - return Relation.fromString(name.toUpperCase()); - } else { - return null; - } - } + private Permissable getPermissable(String name) { + if (Role.fromString(name.toUpperCase()) != null) { + return Role.fromString(name.toUpperCase()); + } else if (Relation.fromString(name.toUpperCase()) != null) { + return Relation.fromString(name.toUpperCase()); + } else { + return null; + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PERM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PERM_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java b/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java index 369b8415..54e71cd0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java @@ -1,63 +1,63 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.FPlayers; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - - -public class CmdPermanent extends FCommand { - - public CmdPermanent() { - super(); - this.aliases.add("permanent"); - - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); - - this.permission = Permission.SET_PERMANENT.node; - this.disableOnLock = true; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - Faction faction = this.argAsFaction(0); - if (faction == null) { - return; - } - - String change; - if (faction.isPermanent()) { - change = TL.COMMAND_PERMANENT_REVOKE.toString(); - faction.setPermanent(false); - } else { - change = TL.COMMAND_PERMANENT_GRANT.toString(); - faction.setPermanent(true); - } - - SavageFactions.plugin.log((fme == null ? "A server admin" : fme.getName()) + " " + change + " the faction \"" + faction.getTag() + "\"."); - - // Inform all players - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); - if (fplayer.getFaction() == faction) { - fplayer.msg(TL.COMMAND_PERMANENT_YOURS, blame, change); - } else { - fplayer.msg(TL.COMMAND_PERMANENT_OTHER, blame, change, faction.getTag(fplayer)); - } - } - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PERMANENT_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + + +public class CmdPermanent extends FCommand { + + public CmdPermanent() { + super(); + this.aliases.add("permanent"); + + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); + + this.permission = Permission.SET_PERMANENT.node; + this.disableOnLock = true; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + Faction faction = this.argAsFaction(0); + if (faction == null) { + return; + } + + String change; + if (faction.isPermanent()) { + change = TL.COMMAND_PERMANENT_REVOKE.toString(); + faction.setPermanent(false); + } else { + change = TL.COMMAND_PERMANENT_GRANT.toString(); + faction.setPermanent(true); + } + + SavageFactions.plugin.log((fme == null ? "A server admin" : fme.getName()) + " " + change + " the faction \"" + faction.getTag() + "\"."); + + // Inform all players + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); + if (fplayer.getFaction() == faction) { + fplayer.msg(TL.COMMAND_PERMANENT_YOURS, blame, change); + } else { + fplayer.msg(TL.COMMAND_PERMANENT_OTHER, blame, change, faction.getTag(fplayer)); + } + } + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PERMANENT_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java index 5e0018d5..5e985ea1 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPermanentPower.java @@ -1,59 +1,59 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - -public class CmdPermanentPower extends FCommand { - public CmdPermanentPower() { - super(); - this.aliases.add("permanentpower"); - - this.requiredArgs.add("faction"); - this.requiredArgs.add("power"); - - this.permission = Permission.SET_PERMANENTPOWER.node; - this.disableOnLock = true; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - Faction targetFaction = this.argAsFaction(0); - if (targetFaction == null) { - return; - } - - Integer targetPower = this.argAsInt(1); - - targetFaction.setPermanentPower(targetPower); - - String change = TL.COMMAND_PERMANENTPOWER_REVOKE.toString(); - if (targetFaction.hasPermanentPower()) { - change = TL.COMMAND_PERMANENTPOWER_GRANT.toString(); - } - - // Inform sender - msg(TL.COMMAND_PERMANENTPOWER_SUCCESS, change, targetFaction.describeTo(fme)); - - // Inform all other players - for (FPlayer fplayer : targetFaction.getFPlayersWhereOnline(true)) { - if (fplayer == fme) { - continue; - } - String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); - fplayer.msg(TL.COMMAND_PERMANENTPOWER_FACTION, blame, change); - } - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PERMANENTPOWER_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + +public class CmdPermanentPower extends FCommand { + public CmdPermanentPower() { + super(); + this.aliases.add("permanentpower"); + + this.requiredArgs.add("faction"); + this.requiredArgs.add("power"); + + this.permission = Permission.SET_PERMANENTPOWER.node; + this.disableOnLock = true; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + Faction targetFaction = this.argAsFaction(0); + if (targetFaction == null) { + return; + } + + Integer targetPower = this.argAsInt(1); + + targetFaction.setPermanentPower(targetPower); + + String change = TL.COMMAND_PERMANENTPOWER_REVOKE.toString(); + if (targetFaction.hasPermanentPower()) { + change = TL.COMMAND_PERMANENTPOWER_GRANT.toString(); + } + + // Inform sender + msg(TL.COMMAND_PERMANENTPOWER_SUCCESS, change, targetFaction.describeTo(fme)); + + // Inform all other players + for (FPlayer fplayer : targetFaction.getFPlayersWhereOnline(true)) { + if (fplayer == fme) { + continue; + } + String blame = (fme == null ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true)); + fplayer.msg(TL.COMMAND_PERMANENTPOWER_FACTION, blame, change); + } + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PERMANENTPOWER_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPower.java b/src/main/java/com/massivecraft/factions/cmd/CmdPower.java index 985d8770..755ddbe0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPower.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPower.java @@ -7,50 +7,50 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdPower extends FCommand { - public CmdPower() { - super(); - this.aliases.add("power"); - this.aliases.add("pow"); + public CmdPower() { + super(); + this.aliases.add("power"); + this.aliases.add("pow"); - //this.requiredArgs.add("faction tag"); - this.optionalArgs.put("player name", "you"); + //this.requiredArgs.add("faction tag"); + this.optionalArgs.put("player name", "you"); - this.permission = Permission.POWER.node; - this.disableOnLock = false; + this.permission = Permission.POWER.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - FPlayer target = this.argAsBestFPlayerMatch(0, fme); - if (target == null) { - return; - } + @Override + public void perform() { + FPlayer target = this.argAsBestFPlayerMatch(0, fme); + if (target == null) { + return; + } - if (target != fme && !Permission.POWER_ANY.has(sender, true)) { - return; - } + if (target != fme && !Permission.POWER_ANY.has(sender, true)) { + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostPower, TL.COMMAND_POWER_TOSHOW, TL.COMMAND_POWER_FORSHOW)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostPower, TL.COMMAND_POWER_TOSHOW, TL.COMMAND_POWER_FORSHOW)) { + return; + } - double powerBoost = target.getPowerBoost(); - String boost = (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_POWER_BONUS.toString() : TL.COMMAND_POWER_PENALTY.toString()) + powerBoost + ")"; - msg(TL.COMMAND_POWER_POWER, target.describeTo(fme, true), target.getPowerRounded(), target.getPowerMaxRounded(), boost); - } + double powerBoost = target.getPowerBoost(); + String boost = (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_POWER_BONUS.toString() : TL.COMMAND_POWER_PENALTY.toString()) + powerBoost + ")"; + msg(TL.COMMAND_POWER_POWER, target.describeTo(fme, true), target.getPowerRounded(), target.getPowerMaxRounded(), boost); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_POWER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_POWER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java b/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java index 53290afe..54a4d3b7 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPowerBoost.java @@ -1,88 +1,88 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - -public class CmdPowerBoost extends FCommand { - - public CmdPowerBoost() { - super(); - this.aliases.add("powerboost"); - - this.requiredArgs.add("plugin|f|player|faction"); - this.requiredArgs.add("name"); - this.requiredArgs.add("# or reset"); - - this.permission = Permission.POWERBOOST.node; - this.disableOnLock = true; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - String type = this.argAsString(0).toLowerCase(); - boolean doPlayer = true; - if (type.equals("f") || type.equals("faction")) { - doPlayer = false; - } else if (!type.equals("plugin") && !type.equals("player")) { - msg(TL.COMMAND_POWERBOOST_HELP_1); - msg(TL.COMMAND_POWERBOOST_HELP_2); - return; - } - - Double targetPower = this.argAsDouble(2); - if (targetPower == null) { - if (this.argAsString(2).equalsIgnoreCase("reset")) { - targetPower = 0D; - } else { - msg(TL.COMMAND_POWERBOOST_INVALIDNUM); - return; - } - } - - String target; - - if (doPlayer) { - FPlayer targetPlayer = this.argAsBestFPlayerMatch(1); - if (targetPlayer == null) { - return; - } - - if (targetPower != 0) { - targetPower += targetPlayer.getPowerBoost(); - } - targetPlayer.setPowerBoost(targetPower); - target = TL.COMMAND_POWERBOOST_PLAYER.format(targetPlayer.getName()); - } else { - Faction targetFaction = this.argAsFaction(1); - if (targetFaction == null) { - return; - } - - if (targetPower != 0) { - targetPower += targetFaction.getPowerBoost(); - } - targetFaction.setPowerBoost(targetPower); - target = TL.COMMAND_POWERBOOST_FACTION.format(targetFaction.getTag()); - } - - int roundedPower = (int) Math.round(targetPower); - msg(TL.COMMAND_POWERBOOST_BOOST, target, roundedPower); - if (!senderIsConsole) { - SavageFactions.plugin.log(TL.COMMAND_POWERBOOST_BOOSTLOG.toString(), fme.getName(), target, roundedPower); - } - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_POWERBOOST_DESCRIPTION; - } -} +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + +public class CmdPowerBoost extends FCommand { + + public CmdPowerBoost() { + super(); + this.aliases.add("powerboost"); + + this.requiredArgs.add("plugin|f|player|faction"); + this.requiredArgs.add("name"); + this.requiredArgs.add("# or reset"); + + this.permission = Permission.POWERBOOST.node; + this.disableOnLock = true; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + String type = this.argAsString(0).toLowerCase(); + boolean doPlayer = true; + if (type.equals("f") || type.equals("faction")) { + doPlayer = false; + } else if (!type.equals("plugin") && !type.equals("player")) { + msg(TL.COMMAND_POWERBOOST_HELP_1); + msg(TL.COMMAND_POWERBOOST_HELP_2); + return; + } + + Double targetPower = this.argAsDouble(2); + if (targetPower == null) { + if (this.argAsString(2).equalsIgnoreCase("reset")) { + targetPower = 0D; + } else { + msg(TL.COMMAND_POWERBOOST_INVALIDNUM); + return; + } + } + + String target; + + if (doPlayer) { + FPlayer targetPlayer = this.argAsBestFPlayerMatch(1); + if (targetPlayer == null) { + return; + } + + if (targetPower != 0) { + targetPower += targetPlayer.getPowerBoost(); + } + targetPlayer.setPowerBoost(targetPower); + target = TL.COMMAND_POWERBOOST_PLAYER.format(targetPlayer.getName()); + } else { + Faction targetFaction = this.argAsFaction(1); + if (targetFaction == null) { + return; + } + + if (targetPower != 0) { + targetPower += targetFaction.getPowerBoost(); + } + targetFaction.setPowerBoost(targetPower); + target = TL.COMMAND_POWERBOOST_FACTION.format(targetFaction.getTag()); + } + + int roundedPower = (int) Math.round(targetPower); + msg(TL.COMMAND_POWERBOOST_BOOST, target, roundedPower); + if (!senderIsConsole) { + SavageFactions.plugin.log(TL.COMMAND_POWERBOOST_BOOSTLOG.toString(), fme.getName(), target, roundedPower); + } + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_POWERBOOST_DESCRIPTION; + } +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java b/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java index 699e740d..9bb67d32 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPromote.java @@ -2,9 +2,9 @@ package com.massivecraft.factions.cmd; public class CmdPromote extends FPromoteCommand { - public CmdPromote() { - aliases.add("promote"); - aliases.add("promo"); - this.relative = 1; - } + public CmdPromote() { + aliases.add("promote"); + aliases.add("promo"); + this.relative = 1; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java index 2520994f..c66d907c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationAlly.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationAlly extends FRelationCommand { - public CmdRelationAlly() { - aliases.add("ally"); - targetRelation = Relation.ALLY; - } + public CmdRelationAlly() { + aliases.add("ally"); + targetRelation = Relation.ALLY; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java index 720f0efe..0da925c3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationEnemy.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationEnemy extends FRelationCommand { - public CmdRelationEnemy() { - aliases.add("enemy"); - targetRelation = Relation.ENEMY; - } + public CmdRelationEnemy() { + aliases.add("enemy"); + targetRelation = Relation.ENEMY; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java index 4dba5c03..104186e6 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationNeutral.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationNeutral extends FRelationCommand { - public CmdRelationNeutral() { - aliases.add("neutral"); - targetRelation = Relation.NEUTRAL; - } + public CmdRelationNeutral() { + aliases.add("neutral"); + targetRelation = Relation.NEUTRAL; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java b/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java index 8136b22c..6cbe2a1e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRelationTruce.java @@ -4,8 +4,8 @@ import com.massivecraft.factions.struct.Relation; public class CmdRelationTruce extends FRelationCommand { - public CmdRelationTruce() { - aliases.add("truce"); - targetRelation = Relation.TRUCE; - } + public CmdRelationTruce() { + aliases.add("truce"); + targetRelation = Relation.TRUCE; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdReload.java b/src/main/java/com/massivecraft/factions/cmd/CmdReload.java index 7cf4b193..682fd9a3 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdReload.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdReload.java @@ -8,41 +8,41 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdReload extends FCommand { - public CmdReload() { - super(); - this.aliases.add("reload"); + public CmdReload() { + super(); + this.aliases.add("reload"); - this.permission = Permission.RELOAD.node; - this.disableOnLock = false; + this.permission = Permission.RELOAD.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - long timeInitStart = System.currentTimeMillis(); - Conf.load(); - Conf.save(); - SavageFactions.plugin.reloadConfig(); - SavageFactions.plugin.changeItemIDSInConfig(); - SavageFactions.plugin.loadLang(); - int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); + @Override + public void perform() { + long timeInitStart = System.currentTimeMillis(); + Conf.load(); + Conf.save(); + SavageFactions.plugin.reloadConfig(); + SavageFactions.plugin.changeItemIDSInConfig(); + SavageFactions.plugin.loadLang(); + int version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - SavageFactions.plugin.factionsFlight = true; - } - long timeReload = (System.currentTimeMillis() - timeInitStart); + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + SavageFactions.plugin.factionsFlight = true; + } + long timeReload = (System.currentTimeMillis() - timeInitStart); - msg(TL.COMMAND_RELOAD_TIME, timeReload); - } + msg(TL.COMMAND_RELOAD_TIME, timeReload); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_RELOAD_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_RELOAD_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdRules.java b/src/main/java/com/massivecraft/factions/cmd/CmdRules.java index d0c75666..9f4df0d5 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdRules.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdRules.java @@ -8,84 +8,84 @@ import java.util.HashMap; import java.util.List; public class CmdRules extends FCommand { - public CmdRules() { - super(); - aliases.add("r"); - aliases.add("rule"); - aliases.add("rules"); + public CmdRules() { + super(); + aliases.add("r"); + aliases.add("rule"); + aliases.add("rules"); - this.optionalArgs.put("add/remove/set/clear", ""); - this.errorOnToManyArgs = false; + this.optionalArgs.put("add/remove/set/clear", ""); + this.errorOnToManyArgs = false; - permission = Permission.RULES.node; + permission = Permission.RULES.node; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("frules.Enabled")) { - fme.msg(TL.COMMAND_RULES_DISABLED_MSG); - return; - } - if (this.args.size() == 0) { - HashMap rules = fme.getFaction().getRulesMap(); - if (rules.size() == 0) { - List ruleList = SavageFactions.plugin.getConfig().getStringList("frules.default-rules"); - fme.sendMessage(SavageFactions.plugin.colorList(ruleList)); + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("frules.Enabled")) { + fme.msg(TL.COMMAND_RULES_DISABLED_MSG); + return; + } + if (this.args.size() == 0) { + HashMap rules = fme.getFaction().getRulesMap(); + if (rules.size() == 0) { + List ruleList = SavageFactions.plugin.getConfig().getStringList("frules.default-rules"); + fme.sendMessage(SavageFactions.plugin.colorList(ruleList)); - } else { - for (int i = 0; i <= rules.size() - 1; i++) { - fme.sendMessage(SavageFactions.plugin.color(rules.get(i))); - } - } + } else { + for (int i = 0; i <= rules.size() - 1; i++) { + fme.sendMessage(SavageFactions.plugin.color(rules.get(i))); + } + } - } - if (this.args.size() == 1) { - if (args.get(0).equalsIgnoreCase("add")) { - fme.msg(TL.COMMAND_RULES_ADD_INVALIDARGS); - } - if (args.get(0).equalsIgnoreCase("set")) { - fme.msg(TL.COMMAND_RULES_SET_INVALIDARGS); - } - if (args.get(0).equalsIgnoreCase("remove")) { - fme.msg(TL.COMMAND_RULES_REMOVE_INVALIDARGS); - } - if (args.get(0).equalsIgnoreCase("clear")) { - fme.getFaction().clearRules(); - fme.msg(TL.COMMAND_RULES_CLEAR_SUCCESS); - } + } + if (this.args.size() == 1) { + if (args.get(0).equalsIgnoreCase("add")) { + fme.msg(TL.COMMAND_RULES_ADD_INVALIDARGS); + } + if (args.get(0).equalsIgnoreCase("set")) { + fme.msg(TL.COMMAND_RULES_SET_INVALIDARGS); + } + if (args.get(0).equalsIgnoreCase("remove")) { + fme.msg(TL.COMMAND_RULES_REMOVE_INVALIDARGS); + } + if (args.get(0).equalsIgnoreCase("clear")) { + fme.getFaction().clearRules(); + fme.msg(TL.COMMAND_RULES_CLEAR_SUCCESS); + } - } - if (this.args.size() >= 2) { - if (args.get(0).equalsIgnoreCase("add")) { - String message = ""; - StringBuilder string = new StringBuilder(message); - for (int i = 1; i <= args.size() - 1; i++) { - string.append(" " + args.get(i)); - } - fme.getFaction().addRule(string.toString()); - fme.msg(TL.COMMAND_RULES_ADD_SUCCESS); - } + } + if (this.args.size() >= 2) { + if (args.get(0).equalsIgnoreCase("add")) { + String message = ""; + StringBuilder string = new StringBuilder(message); + for (int i = 1; i <= args.size() - 1; i++) { + string.append(" " + args.get(i)); + } + fme.getFaction().addRule(string.toString()); + fme.msg(TL.COMMAND_RULES_ADD_SUCCESS); + } - if (this.args.size() == 2) { - if (args.get(0).equalsIgnoreCase("remove")) { - int index = argAsInt(1); - fme.getFaction().removeRule(index - 1); - fme.msg(TL.COMMAND_RULES_REMOVE_SUCCESS); - } - } + if (this.args.size() == 2) { + if (args.get(0).equalsIgnoreCase("remove")) { + int index = argAsInt(1); + fme.getFaction().removeRule(index - 1); + fme.msg(TL.COMMAND_RULES_REMOVE_SUCCESS); + } + } - } - } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_RULES_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_RULES_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSB.java b/src/main/java/com/massivecraft/factions/cmd/CmdSB.java index e0f18a3b..dedbfd9d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSB.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSB.java @@ -6,28 +6,28 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSB extends FCommand { - public CmdSB() { - this.aliases.add("sb"); - this.aliases.add("scoreboard"); - this.permission = Permission.SCOREBOARD.node; - this.senderMustBePlayer = true; - } + public CmdSB() { + this.aliases.add("sb"); + this.aliases.add("scoreboard"); + this.permission = Permission.SCOREBOARD.node; + this.senderMustBePlayer = true; + } - @Override - public void perform() { - boolean toggleTo = !fme.showScoreboard(); - FScoreboard board = FScoreboard.get(fme); - if (board == null) { - me.sendMessage(TL.COMMAND_TOGGLESB_DISABLED.toString()); - } else { - me.sendMessage(TL.TOGGLE_SB.toString().replace("{value}", String.valueOf(toggleTo))); - board.setSidebarVisibility(toggleTo); - } - fme.setShowScoreboard(toggleTo); - } + @Override + public void perform() { + boolean toggleTo = !fme.showScoreboard(); + FScoreboard board = FScoreboard.get(fme); + if (board == null) { + me.sendMessage(TL.COMMAND_TOGGLESB_DISABLED.toString()); + } else { + me.sendMessage(TL.TOGGLE_SB.toString().replace("{value}", String.valueOf(toggleTo))); + board.setSidebarVisibility(toggleTo); + } + fme.setShowScoreboard(toggleTo); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SCOREBOARD_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SCOREBOARD_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java index 520708f0..705b957c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java @@ -11,52 +11,52 @@ import org.bukkit.World; public class CmdSafeunclaimall extends FCommand { - public CmdSafeunclaimall() { - this.aliases.add("safeunclaimall"); - this.aliases.add("safedeclaimall"); + public CmdSafeunclaimall() { + this.aliases.add("safeunclaimall"); + this.aliases.add("safedeclaimall"); - //this.requiredArgs.add(""); - this.optionalArgs.put("world", "all"); + //this.requiredArgs.add(""); + this.optionalArgs.put("world", "all"); - this.permission = Permission.MANAGE_SAFE_ZONE.node; - this.disableOnLock = true; + this.permission = Permission.MANAGE_SAFE_ZONE.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - String worldName = argAsString(0); - World world = null; + @Override + public void perform() { + String worldName = argAsString(0); + World world = null; - if (worldName != null) { - world = Bukkit.getWorld(worldName); - } + if (worldName != null) { + world = Bukkit.getWorld(worldName); + } - String id = Factions.getInstance().getSafeZone().getId(); + String id = Factions.getInstance().getSafeZone().getId(); - if (world == null) { - Board.getInstance().unclaimAll(id); - } else { - Board.getInstance().unclaimAllInWorld(id, world); - } + if (world == null) { + Board.getInstance().unclaimAll(id); + } else { + Board.getInstance().unclaimAllInWorld(id, world); + } - msg(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMED); + msg(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMED); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG.format(sender.getName())); - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG.format(sender.getName())); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SAFEUNCLAIMALL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SAFEUNCLAIMALL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java b/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java index 98c23bb1..1d0e27b9 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java @@ -1,44 +1,44 @@ -package com.massivecraft.factions.cmd; - -import com.massivecraft.factions.Board; -import com.massivecraft.factions.Conf; -import com.massivecraft.factions.FPlayers; -import com.massivecraft.factions.Factions; -import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.zcore.util.TL; - -public class CmdSaveAll extends FCommand { - - public CmdSaveAll() { - super(); - this.aliases.add("saveall"); - this.aliases.add("save"); - - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); - - this.permission = Permission.SAVE.node; - this.disableOnLock = false; - - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void perform() { - FPlayers.getInstance().forceSave(false); - Factions.getInstance().forceSave(false); - Board.getInstance().forceSave(false); - Conf.save(); - msg(TL.COMMAND_SAVEALL_SUCCESS); - } - - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SAVEALL_DESCRIPTION; - } - +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.zcore.util.TL; + +public class CmdSaveAll extends FCommand { + + public CmdSaveAll() { + super(); + this.aliases.add("saveall"); + this.aliases.add("save"); + + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); + + this.permission = Permission.SAVE.node; + this.disableOnLock = false; + + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void perform() { + FPlayers.getInstance().forceSave(false); + Factions.getInstance().forceSave(false); + Board.getInstance().forceSave(false); + Conf.save(); + msg(TL.COMMAND_SAVEALL_SUCCESS); + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SAVEALL_DESCRIPTION; + } + } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java b/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java index 72327d6e..a32d1f38 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSeeChunk.java @@ -15,137 +15,137 @@ import java.util.Iterator; public class CmdSeeChunk extends FCommand { - //Used a hashmap cuz imma make a particle selection gui later, will store it where the boolean is rn. - public static HashMap seeChunkMap = new HashMap<>(); - Long interval = 10L; - private boolean useParticles; - private int length; - private ParticleEffect effect; - private int taskID = -1; + //Used a hashmap cuz imma make a particle selection gui later, will store it where the boolean is rn. + public static HashMap seeChunkMap = new HashMap<>(); + Long interval = 10L; + private boolean useParticles; + private int length; + private ParticleEffect effect; + private int taskID = -1; - //I remade it cause of people getting mad that I had the same seechunk as drtshock + //I remade it cause of people getting mad that I had the same seechunk as drtshock - public CmdSeeChunk() { - super(); - aliases.add("seechunk"); - aliases.add("sc"); + public CmdSeeChunk() { + super(); + aliases.add("seechunk"); + aliases.add("sc"); - permission = Permission.SEECHUNK.node; + permission = Permission.SEECHUNK.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - this.useParticles = p.getConfig().getBoolean("see-chunk.particles", true); - interval = SavageFactions.plugin.getConfig().getLong("see-chunk.interval", 10L); - if (effect == null) { - effect = ParticleEffect.REDSTONE; - } + this.useParticles = p.getConfig().getBoolean("see-chunk.particles", true); + interval = SavageFactions.plugin.getConfig().getLong("see-chunk.interval", 10L); + if (effect == null) { + effect = ParticleEffect.REDSTONE; + } - } + } - @Override - public void perform() { - if (seeChunkMap.containsKey(me.getName())) { - seeChunkMap.remove(me.getName()); - msg(TL.COMMAND_SEECHUNK_DISABLED); - } else { - seeChunkMap.put(me.getName(), true); - msg(TL.COMMAND_SEECHUNK_ENABLED); - manageTask(); - } - } + @Override + public void perform() { + if (seeChunkMap.containsKey(me.getName())) { + seeChunkMap.remove(me.getName()); + msg(TL.COMMAND_SEECHUNK_DISABLED); + } else { + seeChunkMap.put(me.getName(), true); + msg(TL.COMMAND_SEECHUNK_ENABLED); + manageTask(); + } + } - private void manageTask() { - if (taskID != -1) { - if (seeChunkMap.keySet().size() == 0) { - Bukkit.getScheduler().cancelTask(taskID); - taskID = -1; - } - } else { - startTask(); - } - } + private void manageTask() { + if (taskID != -1) { + if (seeChunkMap.keySet().size() == 0) { + Bukkit.getScheduler().cancelTask(taskID); + taskID = -1; + } + } else { + startTask(); + } + } - private void startTask() { - taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - Iterator itr = seeChunkMap.keySet().iterator(); - while (itr.hasNext()) { - Object nameObject = itr.next(); - String name = nameObject + ""; - Player player = Bukkit.getPlayer(name); - showBorders(player); - } - manageTask(); - } - }, 0, interval); - } + private void startTask() { + taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + Iterator itr = seeChunkMap.keySet().iterator(); + while (itr.hasNext()) { + Object nameObject = itr.next(); + String name = nameObject + ""; + Player player = Bukkit.getPlayer(name); + showBorders(player); + } + manageTask(); + } + }, 0, interval); + } - private void showBorders(Player me) { - World world = me.getWorld(); - FLocation flocation = new FLocation(me); - int chunkX = (int) flocation.getX(); - int chunkZ = (int) flocation.getZ(); + private void showBorders(Player me) { + World world = me.getWorld(); + FLocation flocation = new FLocation(me); + int chunkX = (int) flocation.getX(); + int chunkZ = (int) flocation.getZ(); - int blockX; - int blockZ; + int blockX; + int blockZ; - blockX = chunkX * 16; - blockZ = chunkZ * 16; - showPillar(me, world, blockX, blockZ); + blockX = chunkX * 16; + blockZ = chunkZ * 16; + showPillar(me, world, blockX, blockZ); - blockX = chunkX * 16 + 15; - blockZ = chunkZ * 16; - showPillar(me, world, blockX, blockZ); + blockX = chunkX * 16 + 15; + blockZ = chunkZ * 16; + showPillar(me, world, blockX, blockZ); - blockX = chunkX * 16; - blockZ = chunkZ * 16 + 15; - showPillar(me, world, blockX, blockZ); + blockX = chunkX * 16; + blockZ = chunkZ * 16 + 15; + showPillar(me, world, blockX, blockZ); - blockX = chunkX * 16 + 15; - blockZ = chunkZ * 16 + 15; - showPillar(me, world, blockX, blockZ); - } + blockX = chunkX * 16 + 15; + blockZ = chunkZ * 16 + 15; + showPillar(me, world, blockX, blockZ); + } - private void showPillar(Player player, World world, int blockX, int blockZ) { - for (int blockY = 0; blockY < player.getLocation().getBlockY() + 30; blockY++) { - Location loc = new Location(world, blockX, blockY, blockZ).add(0.5, 0, 0.5); - if (loc.getBlock().getType() != Material.AIR) { - continue; - } - if (useParticles) { - if (SavageFactions.plugin.useNonPacketParticles) { - // Dust options only exists in the 1.13 API, so we use an - // alternative method to achieve this in lower versions. - if (SavageFactions.plugin.mc113) { - player.spawnParticle(Particle.REDSTONE, loc, 0, new Particle.DustOptions(Color.RED, 1)); - } else { - player.getWorld().spawnParticle(Particle.REDSTONE, loc, 0, 255, 0, 0, 1); - } + private void showPillar(Player player, World world, int blockX, int blockZ) { + for (int blockY = 0; blockY < player.getLocation().getBlockY() + 30; blockY++) { + Location loc = new Location(world, blockX, blockY, blockZ).add(0.5, 0, 0.5); + if (loc.getBlock().getType() != Material.AIR) { + continue; + } + if (useParticles) { + if (SavageFactions.plugin.useNonPacketParticles) { + // Dust options only exists in the 1.13 API, so we use an + // alternative method to achieve this in lower versions. + if (SavageFactions.plugin.mc113) { + player.spawnParticle(Particle.REDSTONE, loc, 0, new Particle.DustOptions(Color.RED, 1)); + } else { + player.getWorld().spawnParticle(Particle.REDSTONE, loc, 0, 255, 0, 0, 1); + } - } else { - this.effect.display(0, 0, 0, 0, 1, loc, player); - } + } else { + this.effect.display(0, 0, 0, 0, 1, loc, player); + } - } else { - Material type = blockY % 5 == 0 ? SavageFactions.plugin.REDSTONE_LAMP_ON : SavageFactions.plugin.STAINED_GLASS; - VisualizeUtil.addLocation(player, loc, type); - } - } - } + } else { + Material type = blockY % 5 == 0 ? SavageFactions.plugin.REDSTONE_LAMP_ON : SavageFactions.plugin.STAINED_GLASS; + VisualizeUtil.addLocation(player, loc, type); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.GENERIC_PLACEHOLDER; - } + @Override + public TL getUsageTranslation() { + return TL.GENERIC_PLACEHOLDER; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java index 1558b54d..ed4e0249 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetBanner.java @@ -5,35 +5,35 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSetBanner extends FCommand { - public CmdSetBanner() { - super(); - aliases.add("setbanner"); + public CmdSetBanner() { + super(); + aliases.add("setbanner"); - permission = Permission.BANNER.node; + permission = Permission.BANNER.node; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = true; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = true; - } + } - public void perform() { - if (!me.getItemInHand().getType().toString().contains("BANNER")) { - fme.msg(TL.COMMAND_SETBANNER_NOTBANNER); - return; - } + public void perform() { + if (!me.getItemInHand().getType().toString().contains("BANNER")) { + fme.msg(TL.COMMAND_SETBANNER_NOTBANNER); + return; + } - fme.getFaction().setBannerPattern(me.getItemInHand()); - fme.msg(TL.COMMAND_SETBANNER_SUCCESS); + fme.getFaction().setBannerPattern(me.getItemInHand()); + fme.msg(TL.COMMAND_SETBANNER_SUCCESS); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETBANNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETBANNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java index 9735f1c0..8bd5a49d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetDefaultRole.java @@ -6,43 +6,43 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSetDefaultRole extends FCommand { - public CmdSetDefaultRole() { - super(); + public CmdSetDefaultRole() { + super(); - this.aliases.add("defaultrole"); - this.aliases.add("defaultrank"); - this.aliases.add("default"); - this.aliases.add("def"); - this.requiredArgs.add("role"); + this.aliases.add("defaultrole"); + this.aliases.add("defaultrank"); + this.aliases.add("default"); + this.aliases.add("def"); + this.requiredArgs.add("role"); - this.senderMustBeAdmin = true; - this.senderMustBePlayer = true; - senderMustBeColeader = false; + this.senderMustBeAdmin = true; + this.senderMustBePlayer = true; + senderMustBeColeader = false; - this.permission = Permission.DEFAULTRANK.node; - } + this.permission = Permission.DEFAULTRANK.node; + } - @Override - public void perform() { - Role target = Role.fromString(argAsString(0).toUpperCase()); - if (target == null) { - msg(TL.COMMAND_SETDEFAULTROLE_INVALIDROLE, argAsString(0)); - return; - } + @Override + public void perform() { + Role target = Role.fromString(argAsString(0).toUpperCase()); + if (target == null) { + msg(TL.COMMAND_SETDEFAULTROLE_INVALIDROLE, argAsString(0)); + return; + } - if (target == Role.LEADER) { - msg(TL.COMMAND_SETDEFAULTROLE_NOTTHATROLE, argAsString(0)); - return; - } + if (target == Role.LEADER) { + msg(TL.COMMAND_SETDEFAULTROLE_NOTTHATROLE, argAsString(0)); + return; + } - myFaction.setDefaultRole(target); - msg(TL.COMMAND_SETDEFAULTROLE_SUCCESS, target.nicename); - } + myFaction.setDefaultRole(target); + msg(TL.COMMAND_SETDEFAULTROLE_SUCCESS, target.nicename); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETDEFAULTROLE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETDEFAULTROLE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java index 6914ac0b..f60d5770 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetFWarp.java @@ -12,72 +12,72 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSetFWarp extends FCommand { - public CmdSetFWarp() { - super(); + public CmdSetFWarp() { + super(); - this.aliases.add("setwarp"); - this.aliases.add("sw"); + this.aliases.add("setwarp"); + this.aliases.add("sw"); - this.requiredArgs.add("warp name"); - this.optionalArgs.put("password", "password"); + this.requiredArgs.add("warp name"); + this.optionalArgs.put("password", "password"); - this.senderMustBeMember = true; - this.senderMustBeModerator = false; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; - this.senderMustBePlayer = true; + this.senderMustBePlayer = true; - this.permission = Permission.SETWARP.node; - } + this.permission = Permission.SETWARP.node; + } - @Override - public void perform() { - if (!(fme.getRelationToLocation() == Relation.MEMBER)) { - fme.msg(TL.COMMAND_SETFWARP_NOTCLAIMED); - return; - } + @Override + public void perform() { + if (!(fme.getRelationToLocation() == Relation.MEMBER)) { + fme.msg(TL.COMMAND_SETFWARP_NOTCLAIMED); + return; + } - // This statement allows us to check if they've specifically denied it, or default to - // the old setting of allowing moderators to set warps. - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.SETWARP); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set warps"); - return; - } - } + // This statement allows us to check if they've specifically denied it, or default to + // the old setting of allowing moderators to set warps. + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.SETWARP); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set warps"); + return; + } + } - String warp = argAsString(0); + String warp = argAsString(0); - // Checks if warp with same name already exists and ignores maxWarp check if it does. - boolean warpExists = myFaction.isWarp(warp); + // Checks if warp with same name already exists and ignores maxWarp check if it does. + boolean warpExists = myFaction.isWarp(warp); - int maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); - boolean tooManyWarps = maxWarps <= myFaction.getWarps().size(); - if (tooManyWarps && !warpExists) { - fme.msg(TL.COMMAND_SETFWARP_LIMIT, maxWarps); - return; - } + int maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); + boolean tooManyWarps = maxWarps <= myFaction.getWarps().size(); + if (tooManyWarps && !warpExists) { + fme.msg(TL.COMMAND_SETFWARP_LIMIT, maxWarps); + return; + } - if (!transact(fme)) { - return; - } + if (!transact(fme)) { + return; + } - String password = argAsString(1); + String password = argAsString(1); - LazyLocation loc = new LazyLocation(fme.getPlayer().getLocation()); - myFaction.setWarp(warp, loc); - if (password != null) { - myFaction.setWarpPassword(warp, password); - } - fme.msg(TL.COMMAND_SETFWARP_SET, warp, password != null ? password : ""); - } + LazyLocation loc = new LazyLocation(fme.getPlayer().getLocation()); + myFaction.setWarp(warp, loc); + if (password != null) { + myFaction.setWarpPassword(warp, password); + } + fme.msg(TL.COMMAND_SETFWARP_SET, warp, password != null ? password : ""); + } - private boolean transact(FPlayer player) { - return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.setwarp", 5), TL.COMMAND_SETFWARP_TOSET.toString(), TL.COMMAND_SETFWARP_FORSET.toString()); - } + private boolean transact(FPlayer player) { + return !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(SavageFactions.plugin.getConfig().getDouble("warp-cost.setwarp", 5), TL.COMMAND_SETFWARP_TOSET.toString(), TL.COMMAND_SETFWARP_FORSET.toString()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETFWARP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETFWARP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java b/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java index 1f3a98f9..de49364e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSetMaxVaults.java @@ -7,44 +7,44 @@ import org.bukkit.ChatColor; public class CmdSetMaxVaults extends FCommand { - public CmdSetMaxVaults() { - this.aliases.add("setmaxvaults"); - this.aliases.add("smv"); + public CmdSetMaxVaults() { + this.aliases.add("setmaxvaults"); + this.aliases.add("smv"); - this.requiredArgs.add("faction"); - this.requiredArgs.add("number"); + this.requiredArgs.add("faction"); + this.requiredArgs.add("number"); - this.permission = Permission.SETMAXVAULTS.node; - this.disableOnLock = false; + this.permission = Permission.SETMAXVAULTS.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - Faction targetFaction = argAsFaction(0); - int value = argAsInt(1, -1); - if (value < 0) { - sender.sendMessage(ChatColor.RED + "Number must be greater than 0."); - return; - } + @Override + public void perform() { + Faction targetFaction = argAsFaction(0); + int value = argAsInt(1, -1); + if (value < 0) { + sender.sendMessage(ChatColor.RED + "Number must be greater than 0."); + return; + } - if (targetFaction == null) { - sender.sendMessage(ChatColor.RED + "Couldn't find Faction: " + ChatColor.YELLOW + argAsString(0)); - return; - } + if (targetFaction == null) { + sender.sendMessage(ChatColor.RED + "Couldn't find Faction: " + ChatColor.YELLOW + argAsString(0)); + return; + } - targetFaction.setMaxVaults(value); - sender.sendMessage(TL.COMMAND_SETMAXVAULTS_SUCCESS.format(targetFaction.getTag(), value)); - } + targetFaction.setMaxVaults(value); + sender.sendMessage(TL.COMMAND_SETMAXVAULTS_SUCCESS.format(targetFaction.getTag(), value)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETMAXVAULTS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETMAXVAULTS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java b/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java index b9440e05..eaf2c94d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java @@ -12,68 +12,68 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdSethome extends FCommand { - public CmdSethome() { - this.aliases.add("sethome"); + public CmdSethome() { + this.aliases.add("sethome"); - //this.requiredArgs.add(""); - this.optionalArgs.put("faction tag", "mine"); + //this.requiredArgs.add(""); + this.optionalArgs.put("faction tag", "mine"); - this.permission = Permission.SETHOME.node; - this.disableOnLock = true; + this.permission = Permission.SETHOME.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!Conf.homesEnabled) { - fme.msg(TL.COMMAND_SETHOME_DISABLED); - return; - } + @Override + public void perform() { + if (!Conf.homesEnabled) { + fme.msg(TL.COMMAND_SETHOME_DISABLED); + return; + } - Faction faction = this.argAsFaction(0, myFaction); - if (faction == null) { - return; - } + Faction faction = this.argAsFaction(0, myFaction); + if (faction == null) { + return; + } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.SETHOME); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.SETHOME_ANY.has(sender, true)) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set home"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.SETHOME); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.SETHOME_ANY.has(sender, true)) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "set home"); + return; + } + } - // Can the player set the faction home HERE? - if (!Permission.BYPASS.has(me) && - Conf.homesMustBeInClaimedTerritory && - Board.getInstance().getFactionAt(new FLocation(me)) != faction) { - fme.msg(TL.COMMAND_SETHOME_NOTCLAIMED); - return; - } + // Can the player set the faction home HERE? + if (!Permission.BYPASS.has(me) && + Conf.homesMustBeInClaimedTerritory && + Board.getInstance().getFactionAt(new FLocation(me)) != faction) { + fme.msg(TL.COMMAND_SETHOME_NOTCLAIMED); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostSethome, TL.COMMAND_SETHOME_TOSET, TL.COMMAND_SETHOME_FORSET)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostSethome, TL.COMMAND_SETHOME_TOSET, TL.COMMAND_SETHOME_FORSET)) { + return; + } - faction.setHome(me.getLocation()); + faction.setHome(me.getLocation()); - faction.msg(TL.COMMAND_SETHOME_SET, fme.describeTo(myFaction, true)); - faction.sendMessage(p.cmdBase.cmdHome.getUseageTemplate()); - if (faction != myFaction) { - fme.msg(TL.COMMAND_SETHOME_SETOTHER, faction.getTag(fme)); - } - } + faction.msg(TL.COMMAND_SETHOME_SET, fme.describeTo(myFaction, true)); + faction.sendMessage(p.cmdBase.cmdHome.getUseageTemplate()); + if (faction != myFaction) { + fme.msg(TL.COMMAND_SETHOME_SETOTHER, faction.getTag(fme)); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SETHOME_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SETHOME_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java index 66ae2ee8..ee437b55 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java @@ -14,105 +14,105 @@ import java.util.List; public class CmdShow extends FCommand { - List defaults = new ArrayList<>(); + List defaults = new ArrayList<>(); - public CmdShow() { - this.aliases.add("show"); - this.aliases.add("who"); + public CmdShow() { + this.aliases.add("show"); + this.aliases.add("who"); - // add defaults to /f show in case config doesnt have it - defaults.add("{header}"); - defaults.add("Description: {description}"); - defaults.add("Joining: {joining} {peaceful}"); - defaults.add("Land / Power / Maxpower: {chunks} / {power} / {maxPower}"); - defaults.add("Founded: {create-date}"); - defaults.add("This faction is permanent, remaining even with no members."); - defaults.add("Land value: {land-value} {land-refund}"); - defaults.add("Balance: {faction-balance}"); - defaults.add("Allies({allies}/{max-allies}): {allies-list}"); - defaults.add("Online: ({online}/{members}): {online-list}"); - defaults.add("Offline: ({offline}/{members}): {offline-list}"); + // add defaults to /f show in case config doesnt have it + defaults.add("{header}"); + defaults.add("Description: {description}"); + defaults.add("Joining: {joining} {peaceful}"); + defaults.add("Land / Power / Maxpower: {chunks} / {power} / {maxPower}"); + defaults.add("Founded: {create-date}"); + defaults.add("This faction is permanent, remaining even with no members."); + defaults.add("Land value: {land-value} {land-refund}"); + defaults.add("Balance: {faction-balance}"); + defaults.add("Allies({allies}/{max-allies}): {allies-list}"); + defaults.add("Online: ({online}/{members}): {online-list}"); + defaults.add("Offline: ({offline}/{members}): {offline-list}"); - // this.requiredArgs.add(""); - this.optionalArgs.put("faction tag", "yours"); + // this.requiredArgs.add(""); + this.optionalArgs.put("faction tag", "yours"); - this.permission = Permission.SHOW.node; - this.disableOnLock = false; + this.permission = Permission.SHOW.node; + this.disableOnLock = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction faction = myFaction; - if (this.argIsSet(0)) - faction = this.argAsFaction(0); + @Override + public void perform() { + Faction faction = myFaction; + if (this.argIsSet(0)) + faction = this.argAsFaction(0); - if (faction == null) - return; + if (faction == null) + return; - if (fme != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt") - && SavageFactions.plugin.getConfig().getStringList("show-exempt").contains(faction.getTag())) { - msg(TL.COMMAND_SHOW_EXEMPT); - return; - } + if (fme != null && !fme.getPlayer().hasPermission("factions.show.bypassexempt") + && SavageFactions.plugin.getConfig().getStringList("show-exempt").contains(faction.getTag())) { + msg(TL.COMMAND_SHOW_EXEMPT); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostShow, TL.COMMAND_SHOW_TOSHOW, TL.COMMAND_SHOW_FORSHOW)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostShow, TL.COMMAND_SHOW_TOSHOW, TL.COMMAND_SHOW_FORSHOW)) { + return; + } - List show = SavageFactions.plugin.getConfig().getStringList("show"); - if (show == null || show.isEmpty()) - show = defaults; + List show = SavageFactions.plugin.getConfig().getStringList("show"); + if (show == null || show.isEmpty()) + show = defaults; - if (!faction.isNormal()) { - String tag = faction.getTag(fme); - // send header and that's all - String header = show.get(0); - if (TagReplacer.HEADER.contains(header)) { - msg(p.txt.titleize(tag)); - } else { - msg(p.txt.parse(TagReplacer.FACTION.replace(header, tag))); - } - return; // we only show header for non-normal factions - } + if (!faction.isNormal()) { + String tag = faction.getTag(fme); + // send header and that's all + String header = show.get(0); + if (TagReplacer.HEADER.contains(header)) { + msg(p.txt.titleize(tag)); + } else { + msg(p.txt.parse(TagReplacer.FACTION.replace(header, tag))); + } + return; // we only show header for non-normal factions + } - for (String raw : show) { - String parsed = TagUtil.parsePlain(faction, fme, raw); // use relations - if (parsed == null) { - continue; // Due to minimal f show. - } + for (String raw : show) { + String parsed = TagUtil.parsePlain(faction, fme, raw); // use relations + if (parsed == null) { + continue; // Due to minimal f show. + } - if (fme != null) { - parsed = TagUtil.parsePlaceholders(fme.getPlayer(), parsed); - } + if (fme != null) { + parsed = TagUtil.parsePlaceholders(fme.getPlayer(), parsed); + } - if (TagUtil.hasFancy(parsed)) { - List fancy = TagUtil.parseFancy(faction, fme, parsed); - if (fancy != null) - sendFancyMessage(fancy); + if (TagUtil.hasFancy(parsed)) { + List fancy = TagUtil.parseFancy(faction, fme, parsed); + if (fancy != null) + sendFancyMessage(fancy); - continue; - } - if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { - if (parsed.contains("{ig}")) { - // replaces all variables with no home TL - parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); - } - if (parsed.contains("%")) { - parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. - } - msg(p.txt.parse(parsed)); - } - } - } + continue; + } + if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { + if (parsed.contains("{ig}")) { + // replaces all variables with no home TL + parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); + } + if (parsed.contains("%")) { + parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. + } + msg(p.txt.parse(parsed)); + } + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SHOW_COMMANDDESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SHOW_COMMANDDESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java b/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java index 10c0492b..f51f662b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShowClaims.java @@ -8,51 +8,51 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdShowClaims extends FCommand { - public CmdShowClaims() { + public CmdShowClaims() { - this.aliases.add("showclaims"); - this.aliases.add("showclaim"); + this.aliases.add("showclaims"); + this.aliases.add("showclaim"); - permission = Permission.SHOWCLAIMS.node; + permission = Permission.SHOWCLAIMS.node; - this.senderMustBePlayer = true; - this.senderMustBeMember = true; - this.senderMustBeModerator = false; - this.senderMustBePlayer = true; + this.senderMustBePlayer = true; + this.senderMustBeMember = true; + this.senderMustBeModerator = false; + this.senderMustBePlayer = true; - } + } - @Override - public void perform() { - sendMessage(TL.COMMAND_SHOWCLAIMS_HEADER.toString().replace("{faction}", fme.getFaction().describeTo(fme))); - ListMultimap chunkMap = ArrayListMultimap.create(); - String format = TL.COMMAND_SHOWCLAIMS_CHUNKSFORMAT.toString(); - for (FLocation fLocation : fme.getFaction().getAllClaims()) { - chunkMap.put(fLocation.getWorldName(), format.replace("{x}", fLocation.getX() + "").replace("{z}", fLocation.getZ() + "")); - } - for (String world : chunkMap.keySet()) { - String message = TL.COMMAND_SHOWCLAIMS_FORMAT.toString().replace("{world}", world); - sendMessage(message.replace("{chunks}", "")); // made {chunks} blank as I removed the placeholder and people wont update their config :shrug: - StringBuilder chunks = new StringBuilder(); - for (String chunkString : chunkMap.get(world)) { - chunks.append(chunkString + ", "); - if (chunks.toString().length() >= 2000) { - sendMessage(chunks.toString()); - chunks.setLength(0); - } - } + @Override + public void perform() { + sendMessage(TL.COMMAND_SHOWCLAIMS_HEADER.toString().replace("{faction}", fme.getFaction().describeTo(fme))); + ListMultimap chunkMap = ArrayListMultimap.create(); + String format = TL.COMMAND_SHOWCLAIMS_CHUNKSFORMAT.toString(); + for (FLocation fLocation : fme.getFaction().getAllClaims()) { + chunkMap.put(fLocation.getWorldName(), format.replace("{x}", fLocation.getX() + "").replace("{z}", fLocation.getZ() + "")); + } + for (String world : chunkMap.keySet()) { + String message = TL.COMMAND_SHOWCLAIMS_FORMAT.toString().replace("{world}", world); + sendMessage(message.replace("{chunks}", "")); // made {chunks} blank as I removed the placeholder and people wont update their config :shrug: + StringBuilder chunks = new StringBuilder(); + for (String chunkString : chunkMap.get(world)) { + chunks.append(chunkString + ", "); + if (chunks.toString().length() >= 2000) { + sendMessage(chunks.toString()); + chunks.setLength(0); + } + } - sendMessage(""); - } + sendMessage(""); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SHOWCLAIMS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SHOWCLAIMS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java b/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java index 4666ff03..79f48b91 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java @@ -10,32 +10,32 @@ import org.bukkit.ChatColor; public class CmdShowInvites extends FCommand { - public CmdShowInvites() { - super(); - aliases.add("showinvites"); - permission = Permission.SHOW_INVITES.node; + public CmdShowInvites() { + super(); + aliases.add("showinvites"); + permission = Permission.SHOW_INVITES.node; - senderMustBePlayer = true; - senderMustBeMember = true; + senderMustBePlayer = true; + senderMustBeMember = true; - } + } - @Override - public void perform() { - FancyMessage msg = new FancyMessage(TL.COMMAND_SHOWINVITES_PENDING.toString()).color(ChatColor.GOLD); - for (String id : myFaction.getInvites()) { - FPlayer fp = FPlayers.getInstance().getById(id); - String name = fp != null ? fp.getName() : id; - msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_SHOWINVITES_CLICKTOREVOKE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); - } + @Override + public void perform() { + FancyMessage msg = new FancyMessage(TL.COMMAND_SHOWINVITES_PENDING.toString()).color(ChatColor.GOLD); + for (String id : myFaction.getInvites()) { + FPlayer fp = FPlayers.getInstance().getById(id); + String name = fp != null ? fp.getName() : id; + msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_SHOWINVITES_CLICKTOREVOKE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name); + } - sendFancyMessage(msg); - } + sendFancyMessage(msg); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_SHOWINVITES_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_SHOWINVITES_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java b/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java index 4dfec779..1df3b189 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdStatus.java @@ -10,35 +10,35 @@ import java.util.ArrayList; public class CmdStatus extends FCommand { - public CmdStatus() { - super(); - this.aliases.add("status"); - this.aliases.add("s"); + public CmdStatus() { + super(); + this.aliases.add("status"); + this.aliases.add("s"); - this.permission = Permission.STATUS.node; + this.permission = Permission.STATUS.node; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - ArrayList ret = new ArrayList<>(); - for (FPlayer fp : myFaction.getFPlayers()) { - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; - String last = fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - String power = ChatColor.YELLOW + String.valueOf(fp.getPowerRounded()) + " / " + fp.getPowerMaxRounded() + ChatColor.RESET; - ret.add(String.format(TL.COMMAND_STATUS_FORMAT.toString(), ChatColor.GOLD + fp.getRole().getPrefix() + fp.getName() + ChatColor.RESET, power, last).trim()); - } - fme.sendMessage(ret); - } + @Override + public void perform() { + ArrayList ret = new ArrayList<>(); + for (FPlayer fp : myFaction.getFPlayers()) { + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + String last = fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + String power = ChatColor.YELLOW + String.valueOf(fp.getPowerRounded()) + " / " + fp.getPowerMaxRounded() + ChatColor.RESET; + ret.add(String.format(TL.COMMAND_STATUS_FORMAT.toString(), ChatColor.GOLD + fp.getRole().getPrefix() + fp.getName() + ChatColor.RESET, power, last).trim()); + } + fme.sendMessage(ret); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_STATUS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_STATUS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java b/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java index fe391273..cd1d9438 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdStealth.java @@ -5,32 +5,32 @@ import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.zcore.util.TL; public class CmdStealth extends FCommand { - public CmdStealth() { - this.aliases.add("ninja"); - this.aliases.add("stealth"); - this.permission = Permission.STEALTH.node; + public CmdStealth() { + this.aliases.add("ninja"); + this.aliases.add("stealth"); + this.permission = Permission.STEALTH.node; - this.disableOnLock = true; + this.disableOnLock = true; - this.senderMustBePlayer = true; - this.senderMustBeMember = false; - this.senderMustBeModerator = false; - this.senderMustBeColeader = false; - this.senderMustBeAdmin = false; + this.senderMustBePlayer = true; + this.senderMustBeMember = false; + this.senderMustBeModerator = false; + this.senderMustBeColeader = false; + this.senderMustBeAdmin = false; - } + } - public void perform() { - Faction faction = fme.getFaction(); - if (faction != null && !faction.getId().equalsIgnoreCase("0") && !faction.getId().equalsIgnoreCase("none") && !faction.getId().equalsIgnoreCase("safezone") && !faction.getId().equalsIgnoreCase("warzone")) { - fme.setStealth(!fme.isStealthEnabled()); - fme.msg(fme.isStealthEnabled() ? TL.COMMAND_STEALTH_ENABLE : TL.COMMAND_STEALTH_DISABLE); - } else { - fme.msg(TL.COMMAND_STEALTH_MUSTBEMEMBER); - } - } + public void perform() { + Faction faction = fme.getFaction(); + if (faction != null && !faction.getId().equalsIgnoreCase("0") && !faction.getId().equalsIgnoreCase("none") && !faction.getId().equalsIgnoreCase("safezone") && !faction.getId().equalsIgnoreCase("warzone")) { + fme.setStealth(!fme.isStealthEnabled()); + fme.msg(fme.isStealthEnabled() ? TL.COMMAND_STEALTH_ENABLE : TL.COMMAND_STEALTH_DISABLE); + } else { + fme.msg(TL.COMMAND_STEALTH_MUSTBEMEMBER); + } + } - public TL getUsageTranslation() { - return TL.COMMAND_STEALTH_DESCRIPTION; - } + public TL getUsageTranslation() { + return TL.COMMAND_STEALTH_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java b/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java index 57b60fb9..f1aa9172 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdStuck.java @@ -14,98 +14,98 @@ import org.bukkit.scheduler.BukkitRunnable; public class CmdStuck extends FCommand { - public CmdStuck() { - super(); + public CmdStuck() { + super(); - this.aliases.add("stuck"); - this.aliases.add("halp!"); // halp!c: + this.aliases.add("stuck"); + this.aliases.add("halp!"); // halp!c: - this.permission = Permission.STUCK.node; - this.disableOnLock = true; + this.permission = Permission.STUCK.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - final Player player = fme.getPlayer(); - final Location sentAt = player.getLocation(); - final FLocation chunk = fme.getLastStoodAt(); - final long delay = SavageFactions.plugin.getConfig().getLong("hcf.stuck.delay", 30); - final int radius = SavageFactions.plugin.getConfig().getInt("hcf.stuck.radius", 10); + @Override + public void perform() { + final Player player = fme.getPlayer(); + final Location sentAt = player.getLocation(); + final FLocation chunk = fme.getLastStoodAt(); + final long delay = SavageFactions.plugin.getConfig().getLong("hcf.stuck.delay", 30); + final int radius = SavageFactions.plugin.getConfig().getInt("hcf.stuck.radius", 10); - if (SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { - long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); - String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); - msg(TL.COMMAND_STUCK_EXISTS, time); - } else { + if (SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { + long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); + String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); + msg(TL.COMMAND_STUCK_EXISTS, time); + } else { - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostStuck, TL.COMMAND_STUCK_TOSTUCK.format(fme.getName()), TL.COMMAND_STUCK_FORSTUCK.format(fme.getName()))) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostStuck, TL.COMMAND_STUCK_TOSTUCK.format(fme.getName()), TL.COMMAND_STUCK_FORSTUCK.format(fme.getName()))) { + return; + } - final int id = Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new BukkitRunnable() { + final int id = Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new BukkitRunnable() { - @Override - public void run() { - if (!SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { - return; - } + @Override + public void run() { + if (!SavageFactions.plugin.getStuckMap().containsKey(player.getUniqueId())) { + return; + } - // check for world difference or radius exceeding - final World world = chunk.getWorld(); - if (world.getUID() != player.getWorld().getUID() || sentAt.distance(player.getLocation()) > radius) { - msg(TL.COMMAND_STUCK_OUTSIDE.format(radius)); - SavageFactions.plugin.getTimers().remove(player.getUniqueId()); - SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); - return; - } + // check for world difference or radius exceeding + final World world = chunk.getWorld(); + if (world.getUID() != player.getWorld().getUID() || sentAt.distance(player.getLocation()) > radius) { + msg(TL.COMMAND_STUCK_OUTSIDE.format(radius)); + SavageFactions.plugin.getTimers().remove(player.getUniqueId()); + SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); + return; + } - final Board board = Board.getInstance(); - // spiral task to find nearest wilderness chunk - new SpiralTask(new FLocation(me), radius * 2) { + final Board board = Board.getInstance(); + // spiral task to find nearest wilderness chunk + new SpiralTask(new FLocation(me), radius * 2) { - @Override - public boolean work() { - FLocation chunk = currentFLocation(); - Faction faction = board.getFactionAt(chunk); - int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); - if (faction.isWilderness() && !chunk.isOutsideWorldBorder(buffer)) { - int cx = FLocation.chunkToBlock((int) chunk.getX()); - int cz = FLocation.chunkToBlock((int) chunk.getZ()); - int y = world.getHighestBlockYAt(cx, cz); - Location tp = new Location(world, cx, y, cz); - msg(TL.COMMAND_STUCK_TELEPORT, tp.getBlockX(), tp.getBlockY(), tp.getBlockZ()); - SavageFactions.plugin.getTimers().remove(player.getUniqueId()); - SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); - if (!Essentials.handleTeleport(player, tp)) { - player.teleport(tp); - SavageFactions.plugin.debug("/f stuck used regular teleport, not essentials!"); - } - this.stop(); - return false; - } - return true; - } - }; - } - }, delay * 20).getTaskId(); + @Override + public boolean work() { + FLocation chunk = currentFLocation(); + Faction faction = board.getFactionAt(chunk); + int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); + if (faction.isWilderness() && !chunk.isOutsideWorldBorder(buffer)) { + int cx = FLocation.chunkToBlock((int) chunk.getX()); + int cz = FLocation.chunkToBlock((int) chunk.getZ()); + int y = world.getHighestBlockYAt(cx, cz); + Location tp = new Location(world, cx, y, cz); + msg(TL.COMMAND_STUCK_TELEPORT, tp.getBlockX(), tp.getBlockY(), tp.getBlockZ()); + SavageFactions.plugin.getTimers().remove(player.getUniqueId()); + SavageFactions.plugin.getStuckMap().remove(player.getUniqueId()); + if (!Essentials.handleTeleport(player, tp)) { + player.teleport(tp); + SavageFactions.plugin.debug("/f stuck used regular teleport, not essentials!"); + } + this.stop(); + return false; + } + return true; + } + }; + } + }, delay * 20).getTaskId(); - SavageFactions.plugin.getTimers().put(player.getUniqueId(), System.currentTimeMillis() + (delay * 1000)); - long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); - String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); - msg(TL.COMMAND_STUCK_START, time); - SavageFactions.plugin.getStuckMap().put(player.getUniqueId(), id); - } - } + SavageFactions.plugin.getTimers().put(player.getUniqueId(), System.currentTimeMillis() + (delay * 1000)); + long wait = SavageFactions.plugin.getTimers().get(player.getUniqueId()) - System.currentTimeMillis(); + String time = DurationFormatUtils.formatDuration(wait, TL.COMMAND_STUCK_TIMEFORMAT.toString(), true); + msg(TL.COMMAND_STUCK_START, time); + SavageFactions.plugin.getStuckMap().put(player.getUniqueId(), id); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_STUCK_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_STUCK_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTag.java b/src/main/java/com/massivecraft/factions/cmd/CmdTag.java index bc65ef26..6eefe687 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTag.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTag.java @@ -12,79 +12,79 @@ import java.util.ArrayList; public class CmdTag extends FCommand { - public CmdTag() { - this.aliases.add("tag"); - this.aliases.add("rename"); + public CmdTag() { + this.aliases.add("tag"); + this.aliases.add("rename"); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("", ""); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("", ""); - this.permission = Permission.TAG.node; - this.disableOnLock = true; + this.permission = Permission.TAG.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - String tag = this.argAsString(0); + @Override + public void perform() { + String tag = this.argAsString(0); - // TODO does not first test cover selfcase? - if (Factions.getInstance().isTagTaken(tag) && !MiscUtil.getComparisonString(tag).equals(myFaction.getComparisonTag())) { - msg(TL.COMMAND_TAG_TAKEN); - return; - } + // TODO does not first test cover selfcase? + if (Factions.getInstance().isTagTaken(tag) && !MiscUtil.getComparisonString(tag).equals(myFaction.getComparisonTag())) { + msg(TL.COMMAND_TAG_TAKEN); + return; + } - ArrayList errors = MiscUtil.validateTag(tag); - if (errors.size() > 0) { - sendMessage(errors); - return; - } + ArrayList errors = MiscUtil.validateTag(tag); + if (errors.size() > 0) { + sendMessage(errors); + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay - if (!canAffordCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE.toString())) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay + if (!canAffordCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE.toString())) { + return; + } - // trigger the faction rename event (cancellable) - FactionRenameEvent renameEvent = new FactionRenameEvent(fme, tag); - Bukkit.getServer().getPluginManager().callEvent(renameEvent); - if (renameEvent.isCancelled()) { - return; - } + // trigger the faction rename event (cancellable) + FactionRenameEvent renameEvent = new FactionRenameEvent(fme, tag); + Bukkit.getServer().getPluginManager().callEvent(renameEvent); + if (renameEvent.isCancelled()) { + return; + } - // then make 'em pay (if applicable) - if (!payForCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE, TL.COMMAND_TAG_FORCHANGE)) { - return; - } + // then make 'em pay (if applicable) + if (!payForCommand(Conf.econCostTag, TL.COMMAND_TAG_TOCHANGE, TL.COMMAND_TAG_FORCHANGE)) { + return; + } - String oldtag = myFaction.getTag(); - myFaction.setTag(tag); + String oldtag = myFaction.getTag(); + myFaction.setTag(tag); - // Inform - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (fplayer.getFactionId().equals(myFaction.getId())) { - fplayer.msg(TL.COMMAND_TAG_FACTION, fme.describeTo(myFaction, true), myFaction.getTag(myFaction)); - continue; - } + // Inform + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.getFactionId().equals(myFaction.getId())) { + fplayer.msg(TL.COMMAND_TAG_FACTION, fme.describeTo(myFaction, true), myFaction.getTag(myFaction)); + continue; + } - // Broadcast the tag change (if applicable) - if (Conf.broadcastTagChanges) { - Faction faction = fplayer.getFaction(); - fplayer.msg(TL.COMMAND_TAG_CHANGED, fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); - } - } + // Broadcast the tag change (if applicable) + if (Conf.broadcastTagChanges) { + Faction faction = fplayer.getFaction(); + fplayer.msg(TL.COMMAND_TAG_CHANGED, fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); + } + } - FTeamWrapper.updatePrefixes(myFaction); - } + FTeamWrapper.updatePrefixes(myFaction); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TAG_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TAG_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java b/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java index 2d716dee..11461956 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTitle.java @@ -8,51 +8,51 @@ import com.massivecraft.factions.zcore.util.TextUtil; public class CmdTitle extends FCommand { - public CmdTitle() { - this.aliases.add("title"); + public CmdTitle() { + this.aliases.add("title"); - this.requiredArgs.add("player name"); - this.optionalArgs.put("title", ""); + this.requiredArgs.add("player name"); + this.optionalArgs.put("title", ""); - this.permission = Permission.TITLE.node; - this.disableOnLock = true; + this.permission = Permission.TITLE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - FPlayer you = this.argAsBestFPlayerMatch(0); - if (you == null) { - return; - } + @Override + public void perform() { + FPlayer you = this.argAsBestFPlayerMatch(0); + if (you == null) { + return; + } - args.remove(0); - String title = TextUtil.implode(args, " "); + args.remove(0); + String title = TextUtil.implode(args, " "); - if (!canIAdministerYou(fme, you)) { - return; - } + if (!canIAdministerYou(fme, you)) { + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(Conf.econCostTitle, TL.COMMAND_TITLE_TOCHANGE, TL.COMMAND_TITLE_FORCHANGE)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostTitle, TL.COMMAND_TITLE_TOCHANGE, TL.COMMAND_TITLE_FORCHANGE)) { + return; + } - you.setTitle(sender, title); + you.setTitle(sender, title); - // Inform - myFaction.msg(TL.COMMAND_TITLE_CHANGED, fme.describeTo(myFaction, true), you.describeTo(myFaction, true)); - } + // Inform + myFaction.msg(TL.COMMAND_TITLE_CHANGED, fme.describeTo(myFaction, true), you.describeTo(myFaction, true)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TITLE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TITLE_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java b/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java index 6bb42301..77f0f55a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTnt.java @@ -12,172 +12,172 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; public class CmdTnt extends FCommand { - public CmdTnt() { - super(); - this.aliases.add("tnt"); + public CmdTnt() { + super(); + this.aliases.add("tnt"); - this.optionalArgs.put("add/take", ""); - this.optionalArgs.put("amount", "number"); + this.optionalArgs.put("add/take", ""); + this.optionalArgs.put("amount", "number"); - this.permission = Permission.TNT.node; - this.disableOnLock = true; + this.permission = Permission.TNT.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("ftnt.Enabled")) { - fme.msg(TL.COMMAND_TNT_DISABLED_MSG); - return; - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("ftnt.Enabled")) { + fme.msg(TL.COMMAND_TNT_DISABLED_MSG); + return; + } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TNTBANK); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt bank"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TNTBANK); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt bank"); + return; + } + } - if (args.size() == 2) { - if (args.get(0).equalsIgnoreCase("add") || args.get(0).equalsIgnoreCase("a")) { - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - int amount = Integer.parseInt(args.get(1)); - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - Inventory inv = me.getInventory(); - int invTnt = 0; - for (int i = 0; i <= inv.getSize(); i++) { - if (inv.getItem(i) == null) { - continue; - } - if (inv.getItem(i).getType() == Material.TNT) { - invTnt += inv.getItem(i).getAmount(); - } - } - if (amount > invTnt) { - fme.msg(TL.COMMAND_TNT_DEPOSIT_NOTENOUGH); - return; - } - ItemStack tnt = new ItemStack(Material.TNT, amount); - if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { - msg(TL.COMMAND_TNT_EXCEEDLIMIT); - return; - } - removeFromInventory(me.getInventory(), tnt); - me.updateInventory(); + if (args.size() == 2) { + if (args.get(0).equalsIgnoreCase("add") || args.get(0).equalsIgnoreCase("a")) { + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + int amount = Integer.parseInt(args.get(1)); + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + Inventory inv = me.getInventory(); + int invTnt = 0; + for (int i = 0; i <= inv.getSize(); i++) { + if (inv.getItem(i) == null) { + continue; + } + if (inv.getItem(i).getType() == Material.TNT) { + invTnt += inv.getItem(i).getAmount(); + } + } + if (amount > invTnt) { + fme.msg(TL.COMMAND_TNT_DEPOSIT_NOTENOUGH); + return; + } + ItemStack tnt = new ItemStack(Material.TNT, amount); + if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { + msg(TL.COMMAND_TNT_EXCEEDLIMIT); + return; + } + removeFromInventory(me.getInventory(), tnt); + me.updateInventory(); - fme.getFaction().addTnt(amount); - fme.msg(TL.COMMAND_TNT_DEPOSIT_SUCCESS); - fme.sendMessage(SavageFactions.plugin.color(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + ""))); - return; + fme.getFaction().addTnt(amount); + fme.msg(TL.COMMAND_TNT_DEPOSIT_SUCCESS); + fme.sendMessage(SavageFactions.plugin.color(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + ""))); + return; - } - if (args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t")) { - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - int amount = Integer.parseInt(args.get(1)); - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - if (fme.getFaction().getTnt() < amount) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if ((remainderAmt == 0 && !hasAvaliableSlot(me, fullStacks))) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); - return; - } - if (!hasAvaliableSlot(me, fullStacks + 1)) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); - return; - } - ItemStack tnt64 = new ItemStack(Material.TNT, 64); - for (int i = 0; i <= fullStacks - 1; i++) { - me.getInventory().addItem(tnt64); - } - if (remainderAmt != 0) { - ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); - me.getInventory().addItem(tnt); - } - fme.getFaction().takeTnt(amount); - me.updateInventory(); - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_SUCCESS); - } - } else if (args.size() == 1) { - fme.msg(TL.GENERIC_ARGS_TOOFEW); - fme.msg(args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t") ? TL.COMMAND_TNT_TAKE_DESCRIPTION : TL.COMMAND_TNT_ADD_DESCRIPTION); - } - fme.sendMessage(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + "")); - } + } + if (args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t")) { + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + int amount = Integer.parseInt(args.get(1)); + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + if (fme.getFaction().getTnt() < amount) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if ((remainderAmt == 0 && !hasAvaliableSlot(me, fullStacks))) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); + return; + } + if (!hasAvaliableSlot(me, fullStacks + 1)) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE); + return; + } + ItemStack tnt64 = new ItemStack(Material.TNT, 64); + for (int i = 0; i <= fullStacks - 1; i++) { + me.getInventory().addItem(tnt64); + } + if (remainderAmt != 0) { + ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); + me.getInventory().addItem(tnt); + } + fme.getFaction().takeTnt(amount); + me.updateInventory(); + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_SUCCESS); + } + } else if (args.size() == 1) { + fme.msg(TL.GENERIC_ARGS_TOOFEW); + fme.msg(args.get(0).equalsIgnoreCase("take") || args.get(0).equalsIgnoreCase("t") ? TL.COMMAND_TNT_TAKE_DESCRIPTION : TL.COMMAND_TNT_ADD_DESCRIPTION); + } + fme.sendMessage(TL.COMMAND_TNT_AMOUNT.toString().replace("{amount}", fme.getFaction().getTnt() + "")); + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - public boolean hasAvaliableSlot(Player player, int howmany) { - Integer check = 0; - for (ItemStack item : player.getInventory().getContents()) { - if (item == null) { - check++; - } - } - return check >= howmany; - } + public boolean hasAvaliableSlot(Player player, int howmany) { + Integer check = 0; + for (ItemStack item : player.getInventory().getContents()) { + if (item == null) { + check++; + } + } + return check >= howmany; + } - public void removeFromInventory(Inventory inventory, ItemStack item) { - int amt = item.getAmount(); - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - if (items[i].getAmount() > amt) { - items[i].setAmount(items[i].getAmount() - amt); - break; - } else if (items[i].getAmount() == amt) { - items[i] = null; - break; - } else { - amt -= items[i].getAmount(); - items[i] = null; - } - } - } - inventory.setContents(items); - } + public void removeFromInventory(Inventory inventory, ItemStack item) { + int amt = item.getAmount(); + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + if (items[i].getAmount() > amt) { + items[i].setAmount(items[i].getAmount() - amt); + break; + } else if (items[i].getAmount() == amt) { + items[i] = null; + break; + } else { + amt -= items[i].getAmount(); + items[i] = null; + } + } + } + inventory.setContents(items); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TNT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TNT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java b/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java index b6237e59..954b89e4 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTntFill.java @@ -16,240 +16,240 @@ import org.bukkit.inventory.PlayerInventory; public class CmdTntFill extends FCommand { - public CmdTntFill() { - super(); - this.aliases.add("tntfill"); + public CmdTntFill() { + super(); + this.aliases.add("tntfill"); - this.requiredArgs.add("radius"); - this.requiredArgs.add("amount"); + this.requiredArgs.add("radius"); + this.requiredArgs.add("amount"); - this.permission = Permission.TNTFILL.node; - this.disableOnLock = true; + this.permission = Permission.TNTFILL.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("Tntfill.enabled")) { - this.fme.msg(TL.GENERIC_DISABLED); - return; - } - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TNTFILL); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt fill"); - return; - } - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("Tntfill.enabled")) { + this.fme.msg(TL.GENERIC_DISABLED); + return; + } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TNTFILL); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "use tnt fill"); + return; + } + } - msg(TL.COMMAND_TNTFILL_HEADER); - int radius = argAsInt(0, 16); - int amount = argAsInt(1, 16); - if (radius > SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius")) { - fme.msg(TL.COMMAND_TNTFILL_RADIUSMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius") + "")); - return; - } - if (amount > SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount")) { - fme.msg(TL.COMMAND_TNTFILL_AMOUNTMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount") + "")); - return; - } + msg(TL.COMMAND_TNTFILL_HEADER); + int radius = argAsInt(0, 16); + int amount = argAsInt(1, 16); + if (radius > SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius")) { + fme.msg(TL.COMMAND_TNTFILL_RADIUSMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-radius") + "")); + return; + } + if (amount > SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount")) { + fme.msg(TL.COMMAND_TNTFILL_AMOUNTMAX.toString().replace("{max}", SavageFactions.plugin.getConfig().getInt("Tntfill.max-amount") + "")); + return; + } - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - boolean bankMode = fme.getRole().isAtLeast(Role.MODERATOR); - Location start = me.getLocation(); - int counter = 0; - for (double x = start.getX() - radius; x <= start.getX() + radius; x++) { - for (double y = start.getY() - radius; y <= start.getY() + radius; y++) { - for (double z = start.getZ() - radius; z <= start.getZ() + radius; z++) { - Location blockLoc = new Location(start.getWorld(), x, y, z); - if (blockLoc.getBlock().getState() instanceof Dispenser) { - Dispenser disp = (Dispenser) blockLoc.getBlock().getState(); - Inventory dispenser = disp.getInventory(); - if (canHold(dispenser, amount)) { - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { - if (!fme.getRole().isAtLeast(Role.MODERATOR)) { - fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); - sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); - me.updateInventory(); - return; - } else if (bankMode) { - //msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}",fme.getRole().nicename)); - bankMode = true; - removeFromBank(amount); - if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { - fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); - sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); - me.updateInventory(); - return; - } - } - } - ItemStack tnt64 = new ItemStack(Material.TNT, 64); - for (int i = 0; i <= fullStacks - 1; i++) { - dispenser.addItem(tnt64); - takeTnt(64); - } - if (remainderAmt != 0) { - ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); - dispenser.addItem(tnt); - takeTnt(remainderAmt); - } - //sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}",amount + "").replace("{x}",(int) x + "").replace("{y}",(int) y + "").replace("{z}",(int) z + "")); - counter++; - } + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + boolean bankMode = fme.getRole().isAtLeast(Role.MODERATOR); + Location start = me.getLocation(); + int counter = 0; + for (double x = start.getX() - radius; x <= start.getX() + radius; x++) { + for (double y = start.getY() - radius; y <= start.getY() + radius; y++) { + for (double z = start.getZ() - radius; z <= start.getZ() + radius; z++) { + Location blockLoc = new Location(start.getWorld(), x, y, z); + if (blockLoc.getBlock().getState() instanceof Dispenser) { + Dispenser disp = (Dispenser) blockLoc.getBlock().getState(); + Inventory dispenser = disp.getInventory(); + if (canHold(dispenser, amount)) { + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { + if (!fme.getRole().isAtLeast(Role.MODERATOR)) { + fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); + sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); + me.updateInventory(); + return; + } else if (bankMode) { + //msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}",fme.getRole().nicename)); + bankMode = true; + removeFromBank(amount); + if (!inventoryContains(me.getInventory(), new ItemStack(Material.TNT, amount))) { + fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH.toString()); + sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); + me.updateInventory(); + return; + } + } + } + ItemStack tnt64 = new ItemStack(Material.TNT, 64); + for (int i = 0; i <= fullStacks - 1; i++) { + dispenser.addItem(tnt64); + takeTnt(64); + } + if (remainderAmt != 0) { + ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); + dispenser.addItem(tnt); + takeTnt(remainderAmt); + } + //sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}",amount + "").replace("{x}",(int) x + "").replace("{y}",(int) y + "").replace("{z}",(int) z + "")); + counter++; + } - } - } - } - } - if (bankMode) { - msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}", fme.getRole().nicename)); - } - sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); - me.updateInventory(); + } + } + } + } + if (bankMode) { + msg(TL.COMMAND_TNTFILL_MOD.toString().replace("{role}", fme.getRole().nicename)); + } + sendMessage(TL.COMMAND_TNTFILL_SUCCESS.toString().replace("{amount}", amount + "").replace("{dispensers}", counter + "")); + me.updateInventory(); - } + } - private void removeFromBank(int amount) { - try { - Integer.parseInt(args.get(1)); - } catch (NumberFormatException e) { - fme.msg(TL.COMMAND_TNT_INVALID_NUM); - return; - } - if (amount < 0) { - fme.msg(TL.COMMAND_TNT_POSITIVE); - return; - } - if (fme.getFaction().getTnt() < amount) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - if (getEmptySlots(me) + 1 <= fullStacks) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return; - } - ItemStack tnt64 = new ItemStack(Material.TNT, 64); - for (int i = 0; i <= fullStacks - 1; i++) { - me.getInventory().addItem(tnt64); - } - if (remainderAmt != 0) { - ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); - me.getInventory().addItem(tnt); - } - fme.getFaction().takeTnt(amount); - me.updateInventory(); - } + private void removeFromBank(int amount) { + try { + Integer.parseInt(args.get(1)); + } catch (NumberFormatException e) { + fme.msg(TL.COMMAND_TNT_INVALID_NUM); + return; + } + if (amount < 0) { + fme.msg(TL.COMMAND_TNT_POSITIVE); + return; + } + if (fme.getFaction().getTnt() < amount) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + if (getEmptySlots(me) + 1 <= fullStacks) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return; + } + ItemStack tnt64 = new ItemStack(Material.TNT, 64); + for (int i = 0; i <= fullStacks - 1; i++) { + me.getInventory().addItem(tnt64); + } + if (remainderAmt != 0) { + ItemStack tnt = new ItemStack(Material.TNT, remainderAmt); + me.getInventory().addItem(tnt); + } + fme.getFaction().takeTnt(amount); + me.updateInventory(); + } - public void takeTnt(int amount) { - Inventory inv = me.getInventory(); - int invTnt = 0; - for (int i = 0; i <= inv.getSize(); i++) { - if (inv.getItem(i) == null) { - continue; - } - if (inv.getItem(i).getType() == Material.TNT) { - invTnt += inv.getItem(i).getAmount(); - } - } - if (amount > invTnt) { - fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH); - return; - } - ItemStack tnt = new ItemStack(Material.TNT, amount); - if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { - msg(TL.COMMAND_TNT_EXCEEDLIMIT); - return; - } - removeFromInventory(me.getInventory(), tnt); - } + public void takeTnt(int amount) { + Inventory inv = me.getInventory(); + int invTnt = 0; + for (int i = 0; i <= inv.getSize(); i++) { + if (inv.getItem(i) == null) { + continue; + } + if (inv.getItem(i).getType() == Material.TNT) { + invTnt += inv.getItem(i).getAmount(); + } + } + if (amount > invTnt) { + fme.msg(TL.COMMAND_TNTFILL_NOTENOUGH); + return; + } + ItemStack tnt = new ItemStack(Material.TNT, amount); + if (fme.getFaction().getTnt() + amount > SavageFactions.plugin.getConfig().getInt("ftnt.Bank-Limit")) { + msg(TL.COMMAND_TNT_EXCEEDLIMIT); + return; + } + removeFromInventory(me.getInventory(), tnt); + } - public boolean canHold(Inventory inventory, int amount) { - int fullStacks = amount / 64; - int remainderAmt = amount % 64; - if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { - return false; - } - if (getEmptySlots(me) + 1 <= fullStacks) { - fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); - return false; - } - return true; - } + public boolean canHold(Inventory inventory, int amount) { + int fullStacks = amount / 64; + int remainderAmt = amount % 64; + if ((remainderAmt == 0 && getEmptySlots(me) <= fullStacks)) { + return false; + } + if (getEmptySlots(me) + 1 <= fullStacks) { + fme.msg(TL.COMMAND_TNT_WIDTHDRAW_NOTENOUGH.toString()); + return false; + } + return true; + } - public boolean inventoryContains(Inventory inventory, ItemStack item) { - int count = 0; - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - count += items[i].getAmount(); - } - if (count >= item.getAmount()) { - return true; - } - } - return false; - } + public boolean inventoryContains(Inventory inventory, ItemStack item) { + int count = 0; + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + count += items[i].getAmount(); + } + if (count >= item.getAmount()) { + return true; + } + } + return false; + } - public void removeFromInventory(Inventory inventory, ItemStack item) { - int amt = item.getAmount(); - ItemStack[] items = inventory.getContents(); - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { - if (items[i].getAmount() > amt) { - items[i].setAmount(items[i].getAmount() - amt); - break; - } else if (items[i].getAmount() == amt) { - items[i] = null; - break; - } else { - amt -= items[i].getAmount(); - items[i] = null; - } - } - } - inventory.setContents(items); - } + public void removeFromInventory(Inventory inventory, ItemStack item) { + int amt = item.getAmount(); + ItemStack[] items = inventory.getContents(); + for (int i = 0; i < items.length; i++) { + if (items[i] != null && items[i].getType() == item.getType() && items[i].getDurability() == item.getDurability()) { + if (items[i].getAmount() > amt) { + items[i].setAmount(items[i].getAmount() - amt); + break; + } else if (items[i].getAmount() == amt) { + items[i] = null; + break; + } else { + amt -= items[i].getAmount(); + items[i] = null; + } + } + } + inventory.setContents(items); + } - public int getEmptySlots(Player p) { - PlayerInventory inventory = p.getInventory(); - ItemStack[] cont = inventory.getContents(); - int i = 0; - for (ItemStack item : cont) - if (item != null && item.getType() != Material.AIR) { - i++; - } - return 36 - i; - } + public int getEmptySlots(Player p) { + PlayerInventory inventory = p.getInventory(); + ItemStack[] cont = inventory.getContents(); + int i = 0; + for (ItemStack item : cont) + if (item != null && item.getType() != Material.AIR) { + i++; + } + return 36 - i; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TNTFILL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TNTFILL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java b/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java index 95664b6d..3f4d45ba 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdToggleAllianceChat.java @@ -6,39 +6,39 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdToggleAllianceChat extends FCommand { - public CmdToggleAllianceChat() { - super(); - this.aliases.add("tac"); - this.aliases.add("togglealliancechat"); - this.aliases.add("ac"); + public CmdToggleAllianceChat() { + super(); + this.aliases.add("tac"); + this.aliases.add("togglealliancechat"); + this.aliases.add("ac"); - this.disableOnLock = false; + this.disableOnLock = false; - this.permission = Permission.TOGGLE_ALLIANCE_CHAT.node; - this.disableOnLock = false; + this.permission = Permission.TOGGLE_ALLIANCE_CHAT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION; + } - @Override - public void perform() { - if (!Conf.factionOnlyChat) { - msg(TL.COMMAND_CHAT_DISABLED.toString()); - return; - } + @Override + public void perform() { + if (!Conf.factionOnlyChat) { + msg(TL.COMMAND_CHAT_DISABLED.toString()); + return; + } - boolean ignoring = fme.isIgnoreAllianceChat(); + boolean ignoring = fme.isIgnoreAllianceChat(); - msg(ignoring ? TL.COMMAND_TOGGLEALLIANCECHAT_UNIGNORE : TL.COMMAND_TOGGLEALLIANCECHAT_IGNORE); - fme.setIgnoreAllianceChat(!ignoring); - } + msg(ignoring ? TL.COMMAND_TOGGLEALLIANCECHAT_UNIGNORE : TL.COMMAND_TOGGLEALLIANCECHAT_IGNORE); + fme.setIgnoreAllianceChat(!ignoring); + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTop.java b/src/main/java/com/massivecraft/factions/cmd/CmdTop.java index 48c9a9f5..5fd1180a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTop.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTop.java @@ -12,167 +12,167 @@ import java.util.ArrayList; public class CmdTop extends FCommand { - public CmdTop() { - super(); - this.aliases.add("top"); - this.aliases.add("t"); + public CmdTop() { + super(); + this.aliases.add("top"); + this.aliases.add("t"); - //this.requiredArgs.add(""); - this.requiredArgs.add("criteria"); - this.optionalArgs.put("page", "1"); + //this.requiredArgs.add(""); + this.requiredArgs.add("criteria"); + this.optionalArgs.put("page", "1"); - this.permission = Permission.TOP.node; - this.disableOnLock = false; + this.permission = Permission.TOP.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - // Can sort by: money, members, online, allies, enemies, power, land. - // Get all Factions and remove non player ones. - ArrayList factionList = Factions.getInstance().getAllFactions(); - factionList.remove(Factions.getInstance().getWilderness()); - factionList.remove(Factions.getInstance().getSafeZone()); - factionList.remove(Factions.getInstance().getWarZone()); + @Override + public void perform() { + // Can sort by: money, members, online, allies, enemies, power, land. + // Get all Factions and remove non player ones. + ArrayList factionList = Factions.getInstance().getAllFactions(); + factionList.remove(Factions.getInstance().getWilderness()); + factionList.remove(Factions.getInstance().getSafeZone()); + factionList.remove(Factions.getInstance().getWarZone()); - String criteria = argAsString(0); + String criteria = argAsString(0); - // TODO: Better way to sort? - if (criteria.equalsIgnoreCase("members")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getFPlayers().size(); - int f2Size = f2.getFPlayers().size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("start")) { - factionList.sort((f1, f2) -> { - long f1start = f1.getFoundedDate(); - long f2start = f2.getFoundedDate(); - // flip signs because a smaller date is farther in the past - if (f1start > f2start) { - return 1; - } else if (f1start < f2start) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("power")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getPowerRounded(); - int f2Size = f2.getPowerRounded(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("land")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getLandRounded(); - int f2Size = f2.getLandRounded(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("online")) { - factionList.sort((f1, f2) -> { - int f1Size = f1.getFPlayersWhereOnline(true).size(); - int f2Size = f2.getFPlayersWhereOnline(true).size(); - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else if (criteria.equalsIgnoreCase("money") || criteria.equalsIgnoreCase("balance") || criteria.equalsIgnoreCase("bal")) { - factionList.sort((f1, f2) -> { - double f1Size = Econ.getBalance(f1.getAccountId()); - // Lets get the balance of /all/ the players in the Faction. - for (FPlayer fp : f1.getFPlayers()) { - f1Size = f1Size + Econ.getBalance(fp.getAccountId()); - } - double f2Size = Econ.getBalance(f2.getAccountId()); - for (FPlayer fp : f2.getFPlayers()) { - f2Size = f2Size + Econ.getBalance(fp.getAccountId()); - } - if (f1Size < f2Size) { - return 1; - } else if (f1Size > f2Size) { - return -1; - } - return 0; - }); - } else { - msg(TL.COMMAND_TOP_INVALID, criteria); - } + // TODO: Better way to sort? + if (criteria.equalsIgnoreCase("members")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getFPlayers().size(); + int f2Size = f2.getFPlayers().size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("start")) { + factionList.sort((f1, f2) -> { + long f1start = f1.getFoundedDate(); + long f2start = f2.getFoundedDate(); + // flip signs because a smaller date is farther in the past + if (f1start > f2start) { + return 1; + } else if (f1start < f2start) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("power")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getPowerRounded(); + int f2Size = f2.getPowerRounded(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("land")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getLandRounded(); + int f2Size = f2.getLandRounded(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("online")) { + factionList.sort((f1, f2) -> { + int f1Size = f1.getFPlayersWhereOnline(true).size(); + int f2Size = f2.getFPlayersWhereOnline(true).size(); + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else if (criteria.equalsIgnoreCase("money") || criteria.equalsIgnoreCase("balance") || criteria.equalsIgnoreCase("bal")) { + factionList.sort((f1, f2) -> { + double f1Size = Econ.getBalance(f1.getAccountId()); + // Lets get the balance of /all/ the players in the Faction. + for (FPlayer fp : f1.getFPlayers()) { + f1Size = f1Size + Econ.getBalance(fp.getAccountId()); + } + double f2Size = Econ.getBalance(f2.getAccountId()); + for (FPlayer fp : f2.getFPlayers()) { + f2Size = f2Size + Econ.getBalance(fp.getAccountId()); + } + if (f1Size < f2Size) { + return 1; + } else if (f1Size > f2Size) { + return -1; + } + return 0; + }); + } else { + msg(TL.COMMAND_TOP_INVALID, criteria); + } - ArrayList lines = new ArrayList<>(); + ArrayList lines = new ArrayList<>(); - final int pageheight = 9; - int pagenumber = this.argAsInt(1, 1); - int pagecount = (factionList.size() / pageheight) + 1; - if (pagenumber > pagecount) { - pagenumber = pagecount; - } else if (pagenumber < 1) { - pagenumber = 1; - } - int start = (pagenumber - 1) * pageheight; - int end = start + pageheight; - if (end > factionList.size()) { - end = factionList.size(); - } + final int pageheight = 9; + int pagenumber = this.argAsInt(1, 1); + int pagecount = (factionList.size() / pageheight) + 1; + if (pagenumber > pagecount) { + pagenumber = pagecount; + } else if (pagenumber < 1) { + pagenumber = 1; + } + int start = (pagenumber - 1) * pageheight; + int end = start + pageheight; + if (end > factionList.size()) { + end = factionList.size(); + } - lines.add(TL.COMMAND_TOP_TOP.format(criteria.toUpperCase(), pagenumber, pagecount)); + lines.add(TL.COMMAND_TOP_TOP.format(criteria.toUpperCase(), pagenumber, pagecount)); - int rank = 1; - for (Faction faction : factionList.subList(start, end)) { - // Get the relation color if player is executing this. - String fac = sender instanceof Player ? faction.getRelationTo(fme).getColor() + faction.getTag() : faction.getTag(); - lines.add(TL.COMMAND_TOP_LINE.format(rank, fac, getValue(faction, criteria))); - rank++; - } + int rank = 1; + for (Faction faction : factionList.subList(start, end)) { + // Get the relation color if player is executing this. + String fac = sender instanceof Player ? faction.getRelationTo(fme).getColor() + faction.getTag() : faction.getTag(); + lines.add(TL.COMMAND_TOP_LINE.format(rank, fac, getValue(faction, criteria))); + rank++; + } - sendMessage(lines); - } + sendMessage(lines); + } - private String getValue(Faction faction, String criteria) { - if (criteria.equalsIgnoreCase("online")) { - return String.valueOf(faction.getFPlayersWhereOnline(true).size()); - } else if (criteria.equalsIgnoreCase("start")) { - return TL.sdf.format(faction.getFoundedDate()); - } else if (criteria.equalsIgnoreCase("members")) { - return String.valueOf(faction.getFPlayers().size()); - } else if (criteria.equalsIgnoreCase("land")) { - return String.valueOf(faction.getLandRounded()); - } else if (criteria.equalsIgnoreCase("power")) { - return String.valueOf(faction.getPowerRounded()); - } else { // Last one is balance, and it has 3 different things it could be. - double balance = Econ.getBalance(faction.getAccountId()); - for (FPlayer fp : faction.getFPlayers()) { - balance = Math.round(balance + Econ.getBalance(fp.getAccountId())); - } - return String.valueOf(balance); - } - } + private String getValue(Faction faction, String criteria) { + if (criteria.equalsIgnoreCase("online")) { + return String.valueOf(faction.getFPlayersWhereOnline(true).size()); + } else if (criteria.equalsIgnoreCase("start")) { + return TL.sdf.format(faction.getFoundedDate()); + } else if (criteria.equalsIgnoreCase("members")) { + return String.valueOf(faction.getFPlayers().size()); + } else if (criteria.equalsIgnoreCase("land")) { + return String.valueOf(faction.getLandRounded()); + } else if (criteria.equalsIgnoreCase("power")) { + return String.valueOf(faction.getPowerRounded()); + } else { // Last one is balance, and it has 3 different things it could be. + double balance = Econ.getBalance(faction.getAccountId()); + for (FPlayer fp : faction.getFPlayers()) { + balance = Math.round(balance + Econ.getBalance(fp.getAccountId())); + } + return String.valueOf(balance); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TOP_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TOP_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java b/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java index 4023e49f..55f81229 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTpBanner.java @@ -8,46 +8,46 @@ import com.massivecraft.factions.util.WarmUpUtil; import com.massivecraft.factions.zcore.util.TL; public class CmdTpBanner extends FCommand { - public CmdTpBanner() { - super(); + public CmdTpBanner() { + super(); - this.aliases.add("tpbanner"); + this.aliases.add("tpbanner"); - this.permission = Permission.TPBANNER.node; - this.disableOnLock = true; + this.permission = Permission.TPBANNER.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { - return; - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fbanners.Enabled")) { + return; + } - final FactionsPlayerListener fpl = new FactionsPlayerListener(); + final FactionsPlayerListener fpl = new FactionsPlayerListener(); - if (FactionsBlockListener.bannerLocations.containsKey(fme.getTag())) { - fme.msg(TL.COMMAND_TPBANNER_SUCCESS); - this.doWarmUp(WarmUpUtil.Warmup.BANNER, TL.WARMUPS_NOTIFY_TELEPORT, "Banner", new Runnable() { - @Override - public void run() { - me.teleport(FactionsBlockListener.bannerLocations.get(fme.getTag())); - } - }, this.p.getConfig().getLong("warmups.f-banner", 0)); - } else { - fme.msg(TL.COMMAND_TPBANNER_NOTSET); - } + if (FactionsBlockListener.bannerLocations.containsKey(fme.getTag())) { + fme.msg(TL.COMMAND_TPBANNER_SUCCESS); + this.doWarmUp(WarmUpUtil.Warmup.BANNER, TL.WARMUPS_NOTIFY_TELEPORT, "Banner", new Runnable() { + @Override + public void run() { + me.teleport(FactionsBlockListener.bannerLocations.get(fme.getTag())); + } + }, this.p.getConfig().getLong("warmups.f-banner", 0)); + } else { + fme.msg(TL.COMMAND_TPBANNER_NOTSET); + } - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_TPBANNER_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_TPBANNER_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java index 86ba4be7..26ac45db 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnban.java @@ -9,51 +9,51 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdUnban extends FCommand { - public CmdUnban() { - super(); - this.aliases.add("unban"); + public CmdUnban() { + super(); + this.aliases.add("unban"); - this.requiredArgs.add("target"); + this.requiredArgs.add("target"); - this.permission = Permission.BAN.node; - this.disableOnLock = true; + this.permission = Permission.BAN.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBeAdmin = false; + } - @Override - public void perform() { - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.BAN); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.BAN.has(sender, true)) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage bans"); - return; - } - } + @Override + public void perform() { + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.BAN); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER && !Permission.BAN.has(sender, true)) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage bans"); + return; + } + } - // Good on permission checks. Now lets just ban the player. - FPlayer target = argAsFPlayer(0); - if (target == null) { - return; // the above method sends a message if fails to find someone. - } + // Good on permission checks. Now lets just ban the player. + FPlayer target = argAsFPlayer(0); + if (target == null) { + return; // the above method sends a message if fails to find someone. + } - if (!myFaction.isBanned(target)) { - fme.msg(TL.COMMAND_UNBAN_NOTBANNED, target.getName()); - return; - } + if (!myFaction.isBanned(target)) { + fme.msg(TL.COMMAND_UNBAN_NOTBANNED, target.getName()); + return; + } - myFaction.unban(target); + myFaction.unban(target); - myFaction.msg(TL.COMMAND_UNBAN_UNBANNED, fme.getName(), target.getName()); - target.msg(TL.COMMAND_UNBAN_TARGET, myFaction.getTag(target)); - } + myFaction.msg(TL.COMMAND_UNBAN_UNBANNED, fme.getName(), target.getName()); + target.msg(TL.COMMAND_UNBAN_TARGET, myFaction.getTag(target)); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UNBAN_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UNBAN_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java index 9fa2293e..3b9d0f4a 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java @@ -13,172 +13,172 @@ import org.bukkit.Bukkit; public class CmdUnclaim extends FCommand { - public CmdUnclaim() { - this.aliases.add("unclaim"); - this.aliases.add("declaim"); + public CmdUnclaim() { + this.aliases.add("unclaim"); + this.aliases.add("declaim"); - this.optionalArgs.put("radius", "1"); + this.optionalArgs.put("radius", "1"); - this.permission = Permission.UNCLAIM.node; - this.disableOnLock = true; + this.permission = Permission.UNCLAIM.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - // Read and validate input - int radius = this.argAsInt(0, 1); // Default to 1 + @Override + public void perform() { + // Read and validate input + int radius = this.argAsInt(0, 1); // Default to 1 - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage faction territory"); - return; - } - } + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.TERRITORY); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "manage faction territory"); + return; + } + } - if (radius < 1) { - msg(TL.COMMAND_CLAIM_INVALIDRADIUS); - return; - } + if (radius < 1) { + msg(TL.COMMAND_CLAIM_INVALIDRADIUS); + return; + } - if (radius < 2) { - // single chunk - unClaim(new FLocation(me)); - } else { - // radius claim - if (!Permission.CLAIM_RADIUS.has(sender, false)) { - msg(TL.COMMAND_CLAIM_DENIED); - return; - } + if (radius < 2) { + // single chunk + unClaim(new FLocation(me)); + } else { + // radius claim + if (!Permission.CLAIM_RADIUS.has(sender, false)) { + msg(TL.COMMAND_CLAIM_DENIED); + return; + } - new SpiralTask(new FLocation(me), radius) { - private final int limit = Conf.radiusClaimFailureLimit - 1; - private int failCount = 0; + new SpiralTask(new FLocation(me), radius) { + private final int limit = Conf.radiusClaimFailureLimit - 1; + private int failCount = 0; - @Override - public boolean work() { - boolean success = unClaim(this.currentFLocation()); - if (success) { - failCount = 0; - } else if (failCount++ >= limit) { - this.stop(); - return false; - } + @Override + public boolean work() { + boolean success = unClaim(this.currentFLocation()); + if (success) { + failCount = 0; + } else if (failCount++ >= limit) { + this.stop(); + return false; + } - return true; - } - }; - } - } + return true; + } + }; + } + } - private boolean unClaim(FLocation target) { - Faction targetFaction = Board.getInstance().getFactionAt(target); - if (targetFaction.isSafeZone()) { - if (Permission.MANAGE_SAFE_ZONE.has(sender)) { - Board.getInstance().removeAt(target); - msg(TL.COMMAND_UNCLAIM_SAFEZONE_SUCCESS); + private boolean unClaim(FLocation target) { + Faction targetFaction = Board.getInstance().getFactionAt(target); + if (targetFaction.isSafeZone()) { + if (Permission.MANAGE_SAFE_ZONE.has(sender)) { + Board.getInstance().removeAt(target); + msg(TL.COMMAND_UNCLAIM_SAFEZONE_SUCCESS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } - return true; - } else { - msg(TL.COMMAND_UNCLAIM_SAFEZONE_NOPERM); - return false; - } - } else if (targetFaction.isWarZone()) { - if (Permission.MANAGE_WAR_ZONE.has(sender)) { - Board.getInstance().removeAt(target); - msg(TL.COMMAND_UNCLAIM_WARZONE_SUCCESS); + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } + return true; + } else { + msg(TL.COMMAND_UNCLAIM_SAFEZONE_NOPERM); + return false; + } + } else if (targetFaction.isWarZone()) { + if (Permission.MANAGE_WAR_ZONE.has(sender)) { + Board.getInstance().removeAt(target); + msg(TL.COMMAND_UNCLAIM_WARZONE_SUCCESS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } - return true; - } else { - msg(TL.COMMAND_UNCLAIM_WARZONE_NOPERM); - return false; - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } + return true; + } else { + msg(TL.COMMAND_UNCLAIM_WARZONE_NOPERM); + return false; + } + } - if (fme.isAdminBypassing()) { - LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); - Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); - if (unclaimEvent.isCancelled()) { - return false; - } + if (fme.isAdminBypassing()) { + LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); + Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); + if (unclaimEvent.isCancelled()) { + return false; + } - Board.getInstance().removeAt(target); + Board.getInstance().removeAt(target); - targetFaction.msg(TL.COMMAND_UNCLAIM_UNCLAIMED, fme.describeTo(targetFaction, true)); - msg(TL.COMMAND_UNCLAIM_UNCLAIMS); + targetFaction.msg(TL.COMMAND_UNCLAIM_UNCLAIMED, fme.describeTo(targetFaction, true)); + msg(TL.COMMAND_UNCLAIM_UNCLAIMS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } - return true; - } + return true; + } - if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) == Access.DENY) { - return false; - } + if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) == Access.DENY) { + return false; + } - if (!assertHasFaction()) { - return false; - } + if (!assertHasFaction()) { + return false; + } - if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) != Access.ALLOW && !assertMinRole(Role.MODERATOR)) { - return false; - } + if (targetFaction.getAccess(fme, PermissableAction.TERRITORY) != Access.ALLOW && !assertMinRole(Role.MODERATOR)) { + return false; + } - if (myFaction != targetFaction) { - msg(TL.COMMAND_UNCLAIM_WRONGFACTION); - return false; - } + if (myFaction != targetFaction) { + msg(TL.COMMAND_UNCLAIM_WRONGFACTION); + return false; + } - LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); - Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); - if (unclaimEvent.isCancelled()) { - return false; - } + LandUnclaimEvent unclaimEvent = new LandUnclaimEvent(target, targetFaction, fme); + Bukkit.getServer().getPluginManager().callEvent(unclaimEvent); + if (unclaimEvent.isCancelled()) { + return false; + } - if (Econ.shouldBeUsed()) { - double refund = Econ.calculateClaimRefund(myFaction.getLandRounded()); + if (Econ.shouldBeUsed()) { + double refund = Econ.calculateClaimRefund(myFaction.getLandRounded()); - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { - if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { - return false; - } - } else { - if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { - return false; - } - } - } + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { + if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { + return false; + } + } else { + if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIM_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIM_FORUNCLAIM.toString())) { + return false; + } + } + } - Board.getInstance().removeAt(target); - myFaction.msg(TL.COMMAND_UNCLAIM_FACTIONUNCLAIMED, fme.describeTo(myFaction, true)); + Board.getInstance().removeAt(target); + myFaction.msg(TL.COMMAND_UNCLAIM_FACTIONUNCLAIMED, fme.describeTo(myFaction, true)); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIM_LOG.format(fme.getName(), target.getCoordString(), targetFaction.getTag())); + } - return true; - } + return true; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UNCLAIM_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UNCLAIM_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java index 5d8efb28..8eef33a2 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java @@ -11,55 +11,55 @@ import org.bukkit.Bukkit; public class CmdUnclaimall extends FCommand { - public CmdUnclaimall() { - this.aliases.add("unclaimall"); - this.aliases.add("declaimall"); + public CmdUnclaimall() { + this.aliases.add("unclaimall"); + this.aliases.add("declaimall"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.UNCLAIM_ALL.node; - this.disableOnLock = true; + this.permission = Permission.UNCLAIM_ALL.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (Econ.shouldBeUsed()) { - double refund = Econ.calculateTotalLandRefund(myFaction.getLandRounded()); - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { - if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { - return; - } - } else { - if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { - return; - } - } - } + @Override + public void perform() { + if (Econ.shouldBeUsed()) { + double refund = Econ.calculateTotalLandRefund(myFaction.getLandRounded()); + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts) { + if (!Econ.modifyMoney(myFaction, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { + return; + } + } else { + if (!Econ.modifyMoney(fme, refund, TL.COMMAND_UNCLAIMALL_TOUNCLAIM.toString(), TL.COMMAND_UNCLAIMALL_FORUNCLAIM.toString())) { + return; + } + } + } - LandUnclaimAllEvent unclaimAllEvent = new LandUnclaimAllEvent(myFaction, fme); - Bukkit.getServer().getPluginManager().callEvent(unclaimAllEvent); - if (unclaimAllEvent.isCancelled()) { - return; - } + LandUnclaimAllEvent unclaimAllEvent = new LandUnclaimAllEvent(myFaction, fme); + Bukkit.getServer().getPluginManager().callEvent(unclaimAllEvent); + if (unclaimAllEvent.isCancelled()) { + return; + } - Board.getInstance().unclaimAll(myFaction.getId()); - myFaction.msg(TL.COMMAND_UNCLAIMALL_UNCLAIMED, fme.describeTo(myFaction, true)); + Board.getInstance().unclaimAll(myFaction.getId()); + myFaction.msg(TL.COMMAND_UNCLAIMALL_UNCLAIMED, fme.describeTo(myFaction, true)); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_UNCLAIMALL_LOG.format(fme.getName(), myFaction.getTag())); - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_UNCLAIMALL_LOG.format(fme.getName(), myFaction.getTag())); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UNCLAIMALL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UNCLAIMALL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java b/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java index ee8ac071..726e7c59 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUpgrades.java @@ -6,37 +6,37 @@ import com.massivecraft.factions.zcore.fupgrades.FUpgradesGUI; import com.massivecraft.factions.zcore.util.TL; public class CmdUpgrades extends FCommand { - public CmdUpgrades() { - super(); - this.aliases.add("upgrades"); - this.aliases.add("upgrade"); + public CmdUpgrades() { + super(); + this.aliases.add("upgrades"); + this.aliases.add("upgrade"); - //this.requiredArgs.add(""); - this.optionalArgs.put("mobs/crops/exp", ""); + //this.requiredArgs.add(""); + this.optionalArgs.put("mobs/crops/exp", ""); - this.permission = Permission.UPGRADES.node; - this.disableOnLock = true; + this.permission = Permission.UPGRADES.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fupgrades.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - FUpgradesGUI fgui = new FUpgradesGUI(); - fgui.openMainMenu(fme); - } + @Override + public void perform() { + if (!SavageFactions.plugin.getConfig().getBoolean("fupgrades.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + FUpgradesGUI fgui = new FUpgradesGUI(); + fgui.openMainMenu(fme); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_UPGRADES_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_UPGRADES_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdVault.java b/src/main/java/com/massivecraft/factions/cmd/CmdVault.java index 55fd8150..c4909596 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdVault.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdVault.java @@ -14,66 +14,66 @@ import org.bukkit.inventory.Inventory; public class CmdVault extends FCommand { - public CmdVault() { - this.aliases.add("vault"); + public CmdVault() { + this.aliases.add("vault"); - //this.requiredArgs.add(""); + //this.requiredArgs.add(""); - this.permission = Permission.VAULT.node; - this.disableOnLock = false; + this.permission = Permission.VAULT.node; + this.disableOnLock = false; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { + @Override + public void perform() { - if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { - fme.sendMessage("This command is disabled!"); - return; - } - Access access = fme.getFaction().getAccess(fme, PermissableAction.VAULT); - if (access.equals(Access.DENY)) { - fme.msg(TL.GENERIC_NOPERMISSION, "vault"); - return; - } + if (!SavageFactions.plugin.getConfig().getBoolean("fvault.Enabled")) { + fme.sendMessage("This command is disabled!"); + return; + } + Access access = fme.getFaction().getAccess(fme, PermissableAction.VAULT); + if (access.equals(Access.DENY)) { + fme.msg(TL.GENERIC_NOPERMISSION, "vault"); + return; + } - if (fme.isInVault()) { - me.closeInventory(); - return; - } - fme.setInVault(true); - Location vaultLocation = fme.getFaction().getVault(); - if (vaultLocation == null) { - fme.msg(TL.COMMAND_VAULT_INVALID); - return; - } - FLocation vaultFLocation = new FLocation(vaultLocation); - if (Board.getInstance().getFactionAt(vaultFLocation) != fme.getFaction()) { - fme.getFaction().setVault(null); - fme.msg(TL.COMMAND_VAULT_INVALID); - return; - } - if (vaultLocation.getBlock().getType() != Material.CHEST) { - fme.getFaction().setVault(null); - fme.msg(TL.COMMAND_VAULT_INVALID); - return; - } - Chest chest = (Chest) vaultLocation.getBlock().getState(); - Inventory chestInv = chest.getBlockInventory(); - fme.msg(TL.COMMAND_VAULT_OPENING); - me.openInventory(chestInv); + if (fme.isInVault()) { + me.closeInventory(); + return; + } + fme.setInVault(true); + Location vaultLocation = fme.getFaction().getVault(); + if (vaultLocation == null) { + fme.msg(TL.COMMAND_VAULT_INVALID); + return; + } + FLocation vaultFLocation = new FLocation(vaultLocation); + if (Board.getInstance().getFactionAt(vaultFLocation) != fme.getFaction()) { + fme.getFaction().setVault(null); + fme.msg(TL.COMMAND_VAULT_INVALID); + return; + } + if (vaultLocation.getBlock().getType() != Material.CHEST) { + fme.getFaction().setVault(null); + fme.msg(TL.COMMAND_VAULT_INVALID); + return; + } + Chest chest = (Chest) vaultLocation.getBlock().getState(); + Inventory chestInv = chest.getBlockInventory(); + fme.msg(TL.COMMAND_VAULT_OPENING); + me.openInventory(chestInv); - } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_VAULT_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_VAULT_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java b/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java index e0772fdc..f10f4e36 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdVersion.java @@ -7,30 +7,30 @@ import com.massivecraft.factions.zcore.util.TL; public class CmdVersion extends FCommand { - public CmdVersion() { - this.aliases.add("version"); - this.aliases.add("ver"); + public CmdVersion() { + this.aliases.add("version"); + this.aliases.add("ver"); - //this.requiredArgs.add(""); - //this.optionalArgs.put("", ""); + //this.requiredArgs.add(""); + //this.optionalArgs.put("", ""); - this.permission = Permission.VERSION.node; - this.disableOnLock = false; + this.permission = Permission.VERSION.node; + this.disableOnLock = false; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - msg(TL.COMMAND_VERSION_NAME); // Did this so people can differentiate between SavageFactions and FactionsUUID (( Requested Feature )) - msg(TL.COMMAND_VERSION_VERSION, SavageFactions.plugin.getDescription().getFullName()); - } + @Override + public void perform() { + msg(TL.COMMAND_VERSION_NAME); // Did this so people can differentiate between SavageFactions and FactionsUUID (( Requested Feature )) + msg(TL.COMMAND_VERSION_VERSION, SavageFactions.plugin.getDescription().getFullName()); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_VERSION_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_VERSION_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java index f69b3390..6a206a1d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java @@ -11,51 +11,51 @@ import org.bukkit.World; public class CmdWarunclaimall extends FCommand { - public CmdWarunclaimall() { - this.aliases.add("warunclaimall"); - this.aliases.add("wardeclaimall"); + public CmdWarunclaimall() { + this.aliases.add("warunclaimall"); + this.aliases.add("wardeclaimall"); - //this.requiredArgs.add(""); - this.optionalArgs.put("world", "all"); + //this.requiredArgs.add(""); + this.optionalArgs.put("world", "all"); - this.permission = Permission.MANAGE_WAR_ZONE.node; - this.disableOnLock = true; + this.permission = Permission.MANAGE_WAR_ZONE.node; + this.disableOnLock = true; - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - } + } - @Override - public void perform() { - String worldName = argAsString(0); - World world = null; + @Override + public void perform() { + String worldName = argAsString(0); + World world = null; - if (worldName != null) { - world = Bukkit.getWorld(worldName); - } + if (worldName != null) { + world = Bukkit.getWorld(worldName); + } - String id = Factions.getInstance().getWarZone().getId(); + String id = Factions.getInstance().getWarZone().getId(); - if (world == null) { - Board.getInstance().unclaimAll(id); - } else { - Board.getInstance().unclaimAllInWorld(id, world); - } + if (world == null) { + Board.getInstance().unclaimAll(id); + } else { + Board.getInstance().unclaimAllInWorld(id, world); + } - fme.msg(TL.COMMAND_WARUNCLAIMALL_SUCCESS); + fme.msg(TL.COMMAND_WARUNCLAIMALL_SUCCESS); - if (Conf.logLandUnclaims) { - SavageFactions.plugin.log(TL.COMMAND_WARUNCLAIMALL_LOG.format(fme.getName())); - } - } + if (Conf.logLandUnclaims) { + SavageFactions.plugin.log(TL.COMMAND_WARUNCLAIMALL_LOG.format(fme.getName())); + } + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_WARUNCLAIMALL_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_WARUNCLAIMALL_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java b/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java index 96cb84f5..e94b5b6f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java +++ b/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java @@ -10,249 +10,249 @@ import java.util.logging.Level; public class FCmdRoot extends FCommand { - public CmdAdmin cmdAdmin = new CmdAdmin(); - public CmdAutoClaim cmdAutoClaim = new CmdAutoClaim(); - public CmdBoom cmdBoom = new CmdBoom(); - public CmdBypass cmdBypass = new CmdBypass(); - public CmdChat cmdChat = new CmdChat(); - public CmdChatSpy cmdChatSpy = new CmdChatSpy(); - public CmdClaim cmdClaim = new CmdClaim(); - public CmdConfig cmdConfig = new CmdConfig(); - public CmdCreate cmdCreate = new CmdCreate(); - public CmdDeinvite cmdDeinvite = new CmdDeinvite(); - public CmdDescription cmdDescription = new CmdDescription(); - public CmdDisband cmdDisband = new CmdDisband(); - public CmdFocus cmdFocus = new CmdFocus(); - public CmdHelp cmdHelp = new CmdHelp(); - public CmdHome cmdHome = new CmdHome(); - public CmdInvite cmdInvite = new CmdInvite(); - public CmdJoin cmdJoin = new CmdJoin(); - public CmdKick cmdKick = new CmdKick(); - public CmdLeave cmdLeave = new CmdLeave(); - public CmdList cmdList = new CmdList(); - public CmdLock cmdLock = new CmdLock(); - public CmdMap cmdMap = new CmdMap(); - public CmdMod cmdMod = new CmdMod(); - public CmdMoney cmdMoney = new CmdMoney(); - public CmdOpen cmdOpen = new CmdOpen(); - public CmdOwner cmdOwner = new CmdOwner(); - public CmdOwnerList cmdOwnerList = new CmdOwnerList(); - public CmdPeaceful cmdPeaceful = new CmdPeaceful(); - public CmdPermanent cmdPermanent = new CmdPermanent(); - public CmdPermanentPower cmdPermanentPower = new CmdPermanentPower(); - public CmdPowerBoost cmdPowerBoost = new CmdPowerBoost(); - public CmdPower cmdPower = new CmdPower(); - public CmdRelationAlly cmdRelationAlly = new CmdRelationAlly(); - public CmdRelationEnemy cmdRelationEnemy = new CmdRelationEnemy(); - public CmdRelationNeutral cmdRelationNeutral = new CmdRelationNeutral(); - public CmdRelationTruce cmdRelationTruce = new CmdRelationTruce(); - public CmdReload cmdReload = new CmdReload(); - public CmdSafeunclaimall cmdSafeunclaimall = new CmdSafeunclaimall(); - public CmdSaveAll cmdSaveAll = new CmdSaveAll(); - public CmdSethome cmdSethome = new CmdSethome(); - public CmdShow cmdShow = new CmdShow(); - public CmdStatus cmdStatus = new CmdStatus(); - public CmdStealth cmdStealth = new CmdStealth(); - public CmdStuck cmdStuck = new CmdStuck(); - public CmdTag cmdTag = new CmdTag(); - public CmdTitle cmdTitle = new CmdTitle(); - public CmdToggleAllianceChat cmdToggleAllianceChat = new CmdToggleAllianceChat(); - public CmdUnclaim cmdUnclaim = new CmdUnclaim(); - public CmdUnclaimall cmdUnclaimall = new CmdUnclaimall(); - public CmdVersion cmdVersion = new CmdVersion(); - public CmdWarunclaimall cmdWarunclaimall = new CmdWarunclaimall(); - public CmdSB cmdSB = new CmdSB(); - public CmdShowInvites cmdShowInvites = new CmdShowInvites(); - public CmdAnnounce cmdAnnounce = new CmdAnnounce(); - public CmdPaypalSet cmdPaypalSet = new CmdPaypalSet(); - public CmdPaypalSee cmdPaypalSee = new CmdPaypalSee(); - public CmdSeeChunk cmdSeeChunk = new CmdSeeChunk(); - public CmdConvert cmdConvert = new CmdConvert(); - public CmdFWarp cmdFWarp = new CmdFWarp(); - public CmdSetFWarp cmdSetFWarp = new CmdSetFWarp(); - public CmdDelFWarp cmdDelFWarp = new CmdDelFWarp(); - public CmdModifyPower cmdModifyPower = new CmdModifyPower(); - public CmdLogins cmdLogins = new CmdLogins(); - public CmdClaimLine cmdClaimLine = new CmdClaimLine(); - public CmdTop cmdTop = new CmdTop(); - public CmdAHome cmdAHome = new CmdAHome(); - public CmdPerm cmdPerm = new CmdPerm(); - public CmdPromote cmdPromote = new CmdPromote(); - public CmdDemote cmdDemote = new CmdDemote(); - public CmdSetDefaultRole cmdSetDefaultRole = new CmdSetDefaultRole(); - public CmdMapHeight cmdMapHeight = new CmdMapHeight(); - public CmdClaimAt cmdClaimAt = new CmdClaimAt(); - public CmdBan cmdban = new CmdBan(); - public CmdUnban cmdUnban = new CmdUnban(); - public CmdBanlist cmdbanlist = new CmdBanlist(); - public CmdRules cmdRules = new CmdRules(); - public CmdCheckpoint cmdCheckpoint = new CmdCheckpoint(); - public CmdTnt cmdTnt = new CmdTnt(); - public CmdNear cmdNear = new CmdNear(); - public CmdUpgrades cmdUpgrades = new CmdUpgrades(); - public CmdVault cmdVault = new CmdVault(); - public CmdGetVault cmdGetVault = new CmdGetVault(); - public CmdFly cmdFly = new CmdFly(); - public CmdColeader cmdColeader = new CmdColeader(); - public CmdBanner cmdBanner = new CmdBanner(); - public CmdTpBanner cmdTpBanner = new CmdTpBanner(); - public CmdKillHolograms cmdKillHolograms = new CmdKillHolograms(); - public CmdInspect cmdInspect = new CmdInspect(); - public CmdCoords cmdCoords = new CmdCoords(); - public CmdShowClaims cmdShowClaims = new CmdShowClaims(); - public CmdLowPower cmdLowPower = new CmdLowPower(); - public CmdTntFill cmdTntFill = new CmdTntFill(); - public CmdChest cmdChest = new CmdChest(); - public CmdSetBanner cmdSetBanner = new CmdSetBanner(); + public CmdAdmin cmdAdmin = new CmdAdmin(); + public CmdAutoClaim cmdAutoClaim = new CmdAutoClaim(); + public CmdBoom cmdBoom = new CmdBoom(); + public CmdBypass cmdBypass = new CmdBypass(); + public CmdChat cmdChat = new CmdChat(); + public CmdChatSpy cmdChatSpy = new CmdChatSpy(); + public CmdClaim cmdClaim = new CmdClaim(); + public CmdConfig cmdConfig = new CmdConfig(); + public CmdCreate cmdCreate = new CmdCreate(); + public CmdDeinvite cmdDeinvite = new CmdDeinvite(); + public CmdDescription cmdDescription = new CmdDescription(); + public CmdDisband cmdDisband = new CmdDisband(); + public CmdFocus cmdFocus = new CmdFocus(); + public CmdHelp cmdHelp = new CmdHelp(); + public CmdHome cmdHome = new CmdHome(); + public CmdInvite cmdInvite = new CmdInvite(); + public CmdJoin cmdJoin = new CmdJoin(); + public CmdKick cmdKick = new CmdKick(); + public CmdLeave cmdLeave = new CmdLeave(); + public CmdList cmdList = new CmdList(); + public CmdLock cmdLock = new CmdLock(); + public CmdMap cmdMap = new CmdMap(); + public CmdMod cmdMod = new CmdMod(); + public CmdMoney cmdMoney = new CmdMoney(); + public CmdOpen cmdOpen = new CmdOpen(); + public CmdOwner cmdOwner = new CmdOwner(); + public CmdOwnerList cmdOwnerList = new CmdOwnerList(); + public CmdPeaceful cmdPeaceful = new CmdPeaceful(); + public CmdPermanent cmdPermanent = new CmdPermanent(); + public CmdPermanentPower cmdPermanentPower = new CmdPermanentPower(); + public CmdPowerBoost cmdPowerBoost = new CmdPowerBoost(); + public CmdPower cmdPower = new CmdPower(); + public CmdRelationAlly cmdRelationAlly = new CmdRelationAlly(); + public CmdRelationEnemy cmdRelationEnemy = new CmdRelationEnemy(); + public CmdRelationNeutral cmdRelationNeutral = new CmdRelationNeutral(); + public CmdRelationTruce cmdRelationTruce = new CmdRelationTruce(); + public CmdReload cmdReload = new CmdReload(); + public CmdSafeunclaimall cmdSafeunclaimall = new CmdSafeunclaimall(); + public CmdSaveAll cmdSaveAll = new CmdSaveAll(); + public CmdSethome cmdSethome = new CmdSethome(); + public CmdShow cmdShow = new CmdShow(); + public CmdStatus cmdStatus = new CmdStatus(); + public CmdStealth cmdStealth = new CmdStealth(); + public CmdStuck cmdStuck = new CmdStuck(); + public CmdTag cmdTag = new CmdTag(); + public CmdTitle cmdTitle = new CmdTitle(); + public CmdToggleAllianceChat cmdToggleAllianceChat = new CmdToggleAllianceChat(); + public CmdUnclaim cmdUnclaim = new CmdUnclaim(); + public CmdUnclaimall cmdUnclaimall = new CmdUnclaimall(); + public CmdVersion cmdVersion = new CmdVersion(); + public CmdWarunclaimall cmdWarunclaimall = new CmdWarunclaimall(); + public CmdSB cmdSB = new CmdSB(); + public CmdShowInvites cmdShowInvites = new CmdShowInvites(); + public CmdAnnounce cmdAnnounce = new CmdAnnounce(); + public CmdPaypalSet cmdPaypalSet = new CmdPaypalSet(); + public CmdPaypalSee cmdPaypalSee = new CmdPaypalSee(); + public CmdSeeChunk cmdSeeChunk = new CmdSeeChunk(); + public CmdConvert cmdConvert = new CmdConvert(); + public CmdFWarp cmdFWarp = new CmdFWarp(); + public CmdSetFWarp cmdSetFWarp = new CmdSetFWarp(); + public CmdDelFWarp cmdDelFWarp = new CmdDelFWarp(); + public CmdModifyPower cmdModifyPower = new CmdModifyPower(); + public CmdLogins cmdLogins = new CmdLogins(); + public CmdClaimLine cmdClaimLine = new CmdClaimLine(); + public CmdTop cmdTop = new CmdTop(); + public CmdAHome cmdAHome = new CmdAHome(); + public CmdPerm cmdPerm = new CmdPerm(); + public CmdPromote cmdPromote = new CmdPromote(); + public CmdDemote cmdDemote = new CmdDemote(); + public CmdSetDefaultRole cmdSetDefaultRole = new CmdSetDefaultRole(); + public CmdMapHeight cmdMapHeight = new CmdMapHeight(); + public CmdClaimAt cmdClaimAt = new CmdClaimAt(); + public CmdBan cmdban = new CmdBan(); + public CmdUnban cmdUnban = new CmdUnban(); + public CmdBanlist cmdbanlist = new CmdBanlist(); + public CmdRules cmdRules = new CmdRules(); + public CmdCheckpoint cmdCheckpoint = new CmdCheckpoint(); + public CmdTnt cmdTnt = new CmdTnt(); + public CmdNear cmdNear = new CmdNear(); + public CmdUpgrades cmdUpgrades = new CmdUpgrades(); + public CmdVault cmdVault = new CmdVault(); + public CmdGetVault cmdGetVault = new CmdGetVault(); + public CmdFly cmdFly = new CmdFly(); + public CmdColeader cmdColeader = new CmdColeader(); + public CmdBanner cmdBanner = new CmdBanner(); + public CmdTpBanner cmdTpBanner = new CmdTpBanner(); + public CmdKillHolograms cmdKillHolograms = new CmdKillHolograms(); + public CmdInspect cmdInspect = new CmdInspect(); + public CmdCoords cmdCoords = new CmdCoords(); + public CmdShowClaims cmdShowClaims = new CmdShowClaims(); + public CmdLowPower cmdLowPower = new CmdLowPower(); + public CmdTntFill cmdTntFill = new CmdTntFill(); + public CmdChest cmdChest = new CmdChest(); + public CmdSetBanner cmdSetBanner = new CmdSetBanner(); - public FCmdRoot() { - super(); - this.aliases.addAll(Conf.baseCommandAliases); - this.aliases.removeAll(Collections.singletonList(null)); // remove any nulls from extra commas - this.allowNoSlashAccess = Conf.allowNoSlashCommand; + public FCmdRoot() { + super(); + this.aliases.addAll(Conf.baseCommandAliases); + this.aliases.removeAll(Collections.singletonList(null)); // remove any nulls from extra commas + this.allowNoSlashAccess = Conf.allowNoSlashCommand; - //this.requiredArgs.add(""); - //this.optionalArgs.put("","") + //this.requiredArgs.add(""); + //this.optionalArgs.put("","") - senderMustBePlayer = false; - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeAdmin = false; + senderMustBePlayer = false; + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeAdmin = false; - this.disableOnLock = false; + this.disableOnLock = false; - this.setHelpShort("The faction base command"); - this.helpLong.add(p.txt.parseTags("This command contains all faction stuff.")); + this.setHelpShort("The faction base command"); + this.helpLong.add(p.txt.parseTags("This command contains all faction stuff.")); - //this.subCommands.add(plugin.cmdHelp); + //this.subCommands.add(plugin.cmdHelp); - this.addSubCommand(this.cmdAdmin); - this.addSubCommand(this.cmdAutoClaim); - this.addSubCommand(this.cmdBoom); - this.addSubCommand(this.cmdBypass); - this.addSubCommand(this.cmdChat); - this.addSubCommand(this.cmdToggleAllianceChat); - this.addSubCommand(this.cmdChatSpy); - this.addSubCommand(this.cmdClaim); - this.addSubCommand(this.cmdConfig); - this.addSubCommand(this.cmdCreate); - this.addSubCommand(this.cmdDeinvite); - this.addSubCommand(this.cmdDescription); - this.addSubCommand(this.cmdDisband); + this.addSubCommand(this.cmdAdmin); + this.addSubCommand(this.cmdAutoClaim); + this.addSubCommand(this.cmdBoom); + this.addSubCommand(this.cmdBypass); + this.addSubCommand(this.cmdChat); + this.addSubCommand(this.cmdToggleAllianceChat); + this.addSubCommand(this.cmdChatSpy); + this.addSubCommand(this.cmdClaim); + this.addSubCommand(this.cmdConfig); + this.addSubCommand(this.cmdCreate); + this.addSubCommand(this.cmdDeinvite); + this.addSubCommand(this.cmdDescription); + this.addSubCommand(this.cmdDisband); - this.addSubCommand(this.cmdHelp); - this.addSubCommand(this.cmdHome); - this.addSubCommand(this.cmdInvite); - this.addSubCommand(this.cmdJoin); - this.addSubCommand(this.cmdKick); - this.addSubCommand(this.cmdLeave); - this.addSubCommand(this.cmdList); - this.addSubCommand(this.cmdLock); - this.addSubCommand(this.cmdMap); - this.addSubCommand(this.cmdMod); - this.addSubCommand(this.cmdMoney); - this.addSubCommand(this.cmdOpen); - this.addSubCommand(this.cmdOwner); - this.addSubCommand(this.cmdOwnerList); - this.addSubCommand(this.cmdPeaceful); - this.addSubCommand(this.cmdPermanent); - this.addSubCommand(this.cmdPermanentPower); - this.addSubCommand(this.cmdPower); - this.addSubCommand(this.cmdPowerBoost); - this.addSubCommand(this.cmdRelationAlly); - this.addSubCommand(this.cmdRelationEnemy); - this.addSubCommand(this.cmdRelationNeutral); - this.addSubCommand(this.cmdRelationTruce); - this.addSubCommand(this.cmdReload); - this.addSubCommand(this.cmdSafeunclaimall); - this.addSubCommand(this.cmdSaveAll); - this.addSubCommand(this.cmdSethome); - this.addSubCommand(this.cmdShow); - this.addSubCommand(this.cmdStatus); - this.addSubCommand(this.cmdStealth); - this.addSubCommand(this.cmdStuck); - this.addSubCommand(this.cmdTag); - this.addSubCommand(this.cmdTitle); - this.addSubCommand(this.cmdUnclaim); - this.addSubCommand(this.cmdUnclaimall); - this.addSubCommand(this.cmdVersion); - this.addSubCommand(this.cmdWarunclaimall); - this.addSubCommand(this.cmdSB); - this.addSubCommand(this.cmdShowInvites); - this.addSubCommand(this.cmdAnnounce); - this.addSubCommand(this.cmdSeeChunk); - this.addSubCommand(this.cmdConvert); - this.addSubCommand(this.cmdFWarp); - this.addSubCommand(this.cmdSetFWarp); - this.addSubCommand(this.cmdDelFWarp); - this.addSubCommand(this.cmdModifyPower); - this.addSubCommand(this.cmdLogins); - this.addSubCommand(this.cmdClaimLine); - this.addSubCommand(this.cmdAHome); - this.addSubCommand(this.cmdPerm); - this.addSubCommand(this.cmdPromote); - this.addSubCommand(this.cmdDemote); - this.addSubCommand(this.cmdSetDefaultRole); - this.addSubCommand(this.cmdMapHeight); - this.addSubCommand(this.cmdClaimAt); - this.addSubCommand(this.cmdban); - this.addSubCommand(this.cmdUnban); - this.addSubCommand(this.cmdbanlist); - this.addSubCommand(this.cmdRules); - this.addSubCommand(this.cmdCheckpoint); - this.addSubCommand(this.cmdTnt); - this.addSubCommand(this.cmdNear); - this.addSubCommand(this.cmdUpgrades); - this.addSubCommand(this.cmdVault); - this.addSubCommand(this.cmdGetVault); - this.addSubCommand(this.cmdColeader); - this.addSubCommand(this.cmdBanner); - this.addSubCommand(this.cmdTpBanner); - this.addSubCommand(this.cmdKillHolograms); - this.addSubCommand(this.cmdCoords); - this.addSubCommand(this.cmdShowClaims); - this.addSubCommand(this.cmdLowPower); - this.addSubCommand(this.cmdTntFill); - this.addSubCommand(this.cmdChest); - this.addSubCommand(this.cmdSetBanner); + this.addSubCommand(this.cmdHelp); + this.addSubCommand(this.cmdHome); + this.addSubCommand(this.cmdInvite); + this.addSubCommand(this.cmdJoin); + this.addSubCommand(this.cmdKick); + this.addSubCommand(this.cmdLeave); + this.addSubCommand(this.cmdList); + this.addSubCommand(this.cmdLock); + this.addSubCommand(this.cmdMap); + this.addSubCommand(this.cmdMod); + this.addSubCommand(this.cmdMoney); + this.addSubCommand(this.cmdOpen); + this.addSubCommand(this.cmdOwner); + this.addSubCommand(this.cmdOwnerList); + this.addSubCommand(this.cmdPeaceful); + this.addSubCommand(this.cmdPermanent); + this.addSubCommand(this.cmdPermanentPower); + this.addSubCommand(this.cmdPower); + this.addSubCommand(this.cmdPowerBoost); + this.addSubCommand(this.cmdRelationAlly); + this.addSubCommand(this.cmdRelationEnemy); + this.addSubCommand(this.cmdRelationNeutral); + this.addSubCommand(this.cmdRelationTruce); + this.addSubCommand(this.cmdReload); + this.addSubCommand(this.cmdSafeunclaimall); + this.addSubCommand(this.cmdSaveAll); + this.addSubCommand(this.cmdSethome); + this.addSubCommand(this.cmdShow); + this.addSubCommand(this.cmdStatus); + this.addSubCommand(this.cmdStealth); + this.addSubCommand(this.cmdStuck); + this.addSubCommand(this.cmdTag); + this.addSubCommand(this.cmdTitle); + this.addSubCommand(this.cmdUnclaim); + this.addSubCommand(this.cmdUnclaimall); + this.addSubCommand(this.cmdVersion); + this.addSubCommand(this.cmdWarunclaimall); + this.addSubCommand(this.cmdSB); + this.addSubCommand(this.cmdShowInvites); + this.addSubCommand(this.cmdAnnounce); + this.addSubCommand(this.cmdSeeChunk); + this.addSubCommand(this.cmdConvert); + this.addSubCommand(this.cmdFWarp); + this.addSubCommand(this.cmdSetFWarp); + this.addSubCommand(this.cmdDelFWarp); + this.addSubCommand(this.cmdModifyPower); + this.addSubCommand(this.cmdLogins); + this.addSubCommand(this.cmdClaimLine); + this.addSubCommand(this.cmdAHome); + this.addSubCommand(this.cmdPerm); + this.addSubCommand(this.cmdPromote); + this.addSubCommand(this.cmdDemote); + this.addSubCommand(this.cmdSetDefaultRole); + this.addSubCommand(this.cmdMapHeight); + this.addSubCommand(this.cmdClaimAt); + this.addSubCommand(this.cmdban); + this.addSubCommand(this.cmdUnban); + this.addSubCommand(this.cmdbanlist); + this.addSubCommand(this.cmdRules); + this.addSubCommand(this.cmdCheckpoint); + this.addSubCommand(this.cmdTnt); + this.addSubCommand(this.cmdNear); + this.addSubCommand(this.cmdUpgrades); + this.addSubCommand(this.cmdVault); + this.addSubCommand(this.cmdGetVault); + this.addSubCommand(this.cmdColeader); + this.addSubCommand(this.cmdBanner); + this.addSubCommand(this.cmdTpBanner); + this.addSubCommand(this.cmdKillHolograms); + this.addSubCommand(this.cmdCoords); + this.addSubCommand(this.cmdShowClaims); + this.addSubCommand(this.cmdLowPower); + this.addSubCommand(this.cmdTntFill); + this.addSubCommand(this.cmdChest); + this.addSubCommand(this.cmdSetBanner); - if (Bukkit.getServer().getPluginManager().getPlugin("CoreProtect") != null) { - SavageFactions.plugin.log("Found CoreProtect, enabling Inspect"); - this.addSubCommand(this.cmdInspect); - } else { - SavageFactions.plugin.log("CoreProtect not found, disabling Inspect"); - } - if (SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { - addSubCommand(this.cmdFocus); - } + if (Bukkit.getServer().getPluginManager().getPlugin("CoreProtect") != null) { + SavageFactions.plugin.log("Found CoreProtect, enabling Inspect"); + this.addSubCommand(this.cmdInspect); + } else { + SavageFactions.plugin.log("CoreProtect not found, disabling Inspect"); + } + if (SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) { + addSubCommand(this.cmdFocus); + } - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { - this.addSubCommand(this.cmdFly); - } - if (Bukkit.getServer().getPluginManager().getPlugin("FactionsTop") != null) { - SavageFactions.plugin.log(Level.INFO, "Found FactionsTop plugin. Disabling our own /f top command."); - } else { - SavageFactions.plugin.log(Level.INFO, "Enabling FactionsTop command, this is a very basic /f top please get a dedicated /f top resource if you want land calculation etc."); - this.addSubCommand(this.cmdTop); - } - if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { - this.addSubCommand(this.cmdPaypalSet); - this.addSubCommand(this.cmdPaypalSee); - } + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight", false)) { + this.addSubCommand(this.cmdFly); + } + if (Bukkit.getServer().getPluginManager().getPlugin("FactionsTop") != null) { + SavageFactions.plugin.log(Level.INFO, "Found FactionsTop plugin. Disabling our own /f top command."); + } else { + SavageFactions.plugin.log(Level.INFO, "Enabling FactionsTop command, this is a very basic /f top please get a dedicated /f top resource if you want land calculation etc."); + this.addSubCommand(this.cmdTop); + } + if (SavageFactions.plugin.getConfig().getBoolean("fpaypal.Enabled")) { + this.addSubCommand(this.cmdPaypalSet); + this.addSubCommand(this.cmdPaypalSee); + } - } + } - @Override - public void perform() { - this.commandChain.add(this); - this.cmdHelp.execute(this.sender, this.args, this.commandChain); - } + @Override + public void perform() { + this.commandChain.add(this); + this.cmdHelp.execute(this.sender, this.args, this.commandChain); + } - @Override - public TL getUsageTranslation() { - return TL.GENERIC_PLACEHOLDER; - } + @Override + public TL getUsageTranslation() { + return TL.GENERIC_PLACEHOLDER; + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/FCommand.java b/src/main/java/com/massivecraft/factions/cmd/FCommand.java index e8e9d635..03aab442 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FCommand.java @@ -15,330 +15,330 @@ import java.util.List; public abstract class FCommand extends MCommand { - public static final SimpleDateFormat sdf = new SimpleDateFormat(TL.DATE_FORMAT.toString()); - - public boolean disableOnLock; - - public FPlayer fme; - public Faction myFaction; - public boolean senderMustBeMember; - public boolean senderMustBeModerator; - public boolean senderMustBeAdmin; - public boolean senderMustBeColeader; - - - public boolean isMoneyCommand; - - public FCommand() { - super(SavageFactions.plugin); - - // Due to safety reasons it defaults to disable on lock. - disableOnLock = true; - - // The money commands must be disabled if money should not be used. - isMoneyCommand = false; - - senderMustBeMember = false; - senderMustBeModerator = false; - senderMustBeColeader = false; - senderMustBeAdmin = false; - } - - @Override - public void setCommandSender(CommandSender sender) { - super.setCommandSender(sender); - if (sender instanceof Player) { - this.fme = FPlayers.getInstance().getByPlayer((Player) sender); - this.myFaction = this.fme.getFaction(); - } else { - this.fme = null; - this.myFaction = null; - } - } - - @Override - public void execute(CommandSender sender, List args, List> commandChain) { - setCommandSender(sender); - super.execute(sender, args, commandChain); - } - - @Override - public boolean isEnabled() { - if (p.getLocked() && this.disableOnLock) { - msg("Factions was locked by an admin. Please try again later."); - return false; - } - - if (this.isMoneyCommand && !Conf.econEnabled) { - msg("Faction economy features are disabled on this server."); - return false; - } - - if (this.isMoneyCommand && !Conf.bankEnabled) { - msg("The faction bank system is disabled on this server."); - return false; - } - - return true; - } - - @Override - public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { - boolean superValid = super.validSenderType(sender, informSenderIfNot); - if (!superValid) { - return false; - } - - if (!(this.senderMustBeMember || this.senderMustBeModerator || this.senderMustBeAdmin || this.senderMustBeColeader)) { - return true; - } - - if (!(sender instanceof Player)) { - return false; - } - - if (!fme.hasFaction()) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("You are not member of any faction.")); - } - return false; - } - - - if (this.senderMustBeModerator && !fme.getRole().isAtLeast(Role.MODERATOR)) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("Only faction moderators can %s.", this.getHelpShort())); - } - return false; - } - - if (this.senderMustBeColeader && !fme.getRole().isAtLeast(Role.COLEADER)) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("Only faction coleaders can %s.", this.getHelpShort())); - } - return false; - } - - if (this.senderMustBeAdmin && !fme.getRole().isAtLeast(Role.LEADER)) { - if (informSenderIfNot) { - sender.sendMessage(p.txt.parse("Only faction admins can %s.", this.getHelpShort())); - } - return false; - } - - - return true; - } - - // -------------------------------------------- // - // Assertions - // -------------------------------------------- // - - public boolean assertHasFaction() { - if (me == null) { - return true; - } - - if (!fme.hasFaction()) { - sendMessage("You are not member of any faction."); - return false; - } - return true; - } - - public boolean assertMinRole(Role role) { - if (me == null) { - return true; - } - - if (fme.getRole().value < role.value) { - msg("You must be " + role + " to " + this.getHelpShort() + "."); - return false; - } - return true; - } - - // -------------------------------------------- // - // Argument Readers - // -------------------------------------------- // - - // FPLAYER ====================== - public FPlayer strAsFPlayer(String name, FPlayer def, boolean msg) { - FPlayer ret = def; - - if (name != null) { - for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { - if (fplayer.getName().equalsIgnoreCase(name)) { - ret = fplayer; - break; - } - } - } - - if (msg && ret == null) { - this.msg("No player \"%s\" could be found.", name); - } - - return ret; - } - - public FPlayer argAsFPlayer(int idx, FPlayer def, boolean msg) { - return this.strAsFPlayer(this.argAsString(idx), def, msg); - } - - public FPlayer argAsFPlayer(int idx, FPlayer def) { - return this.argAsFPlayer(idx, def, true); - } - - public FPlayer argAsFPlayer(int idx) { - return this.argAsFPlayer(idx, null); - } - - // BEST FPLAYER MATCH ====================== - public FPlayer strAsBestFPlayerMatch(String name, FPlayer def, boolean msg) { - return strAsFPlayer(name, def, msg); - } - - public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def, boolean msg) { - return this.strAsBestFPlayerMatch(this.argAsString(idx), def, msg); - } - - public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def) { - return this.argAsBestFPlayerMatch(idx, def, true); - } - - public FPlayer argAsBestFPlayerMatch(int idx) { - return this.argAsBestFPlayerMatch(idx, null); - } - - // FACTION ====================== - public Faction strAsFaction(String name, Faction def, boolean msg) { - Faction ret = def; - - if (name != null) { - // First we try an exact match - Faction faction = Factions.getInstance().getByTag(name); // Checks for faction name match. - - // Now lets try for warzone / safezone. Helpful for custom warzone / safezone names. - // Do this after we check for an exact match in case they rename the warzone / safezone - // and a player created faction took one of the names. - if (faction == null) { - if (name.equalsIgnoreCase("warzone")) { - faction = Factions.getInstance().getWarZone(); - } else if (name.equalsIgnoreCase("safezone")) { - faction = Factions.getInstance().getSafeZone(); - } - } - - // Next we match faction tags - if (faction == null) { - faction = Factions.getInstance().getBestTagMatch(name); - } - - // Next we match player names - if (faction == null) { - FPlayer fplayer = strAsFPlayer(name, null, false); - if (fplayer != null) { - faction = fplayer.getFaction(); - } - } - - if (faction != null) { - ret = faction; - } - } - - if (msg && ret == null) { - this.msg("The faction or player \"%s\" could not be found.", name); - } - - return ret; - } - - public Faction argAsFaction(int idx, Faction def, boolean msg) { - return this.strAsFaction(this.argAsString(idx), def, msg); - } - - public Faction argAsFaction(int idx, Faction def) { - return this.argAsFaction(idx, def, true); - } - - public Faction argAsFaction(int idx) { - return this.argAsFaction(idx, null); - } - - // -------------------------------------------- // - // Commonly used logic - // -------------------------------------------- // - - public boolean canIAdministerYou(FPlayer i, FPlayer you) { - if (!i.getFaction().equals(you.getFaction())) { - i.sendMessage(p.txt.parse("%s is not in the same faction as you.", you.describeTo(i, true))); - return false; - } - - if (i.getRole().value > you.getRole().value || i.getRole().equals(Role.LEADER)) { - return true; - } - - if (you.getRole().equals(Role.LEADER)) { - i.sendMessage(p.txt.parse("Only the faction admin can do that.")); - - } else if ((you.getRole().equals(Role.COLEADER))) { - if (i == you) { - return true; - } else { - i.sendMessage(p.txt.parse("Coleaders can't control each other...")); - } - - } else if (i.getRole().equals(Role.MODERATOR)) { - if (i == you) { - return true; //Moderators can control themselves - } else { - i.sendMessage(p.txt.parse("Moderators can't control each other...")); - } - } else { - i.sendMessage(p.txt.parse("You must be a faction moderator to do that.")); - } - - return false; - } - - // if economy is enabled and they're not on the bypass list, make 'em pay; returns true unless person can't afford the cost - public boolean payForCommand(double cost, String toDoThis, String forDoingThis) { - if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { - return true; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { - return Econ.modifyMoney(myFaction, -cost, toDoThis, forDoingThis); - } else { - return Econ.modifyMoney(fme, -cost, toDoThis, forDoingThis); - } - } - - public boolean payForCommand(double cost, TL toDoThis, TL forDoingThis) { - return payForCommand(cost, toDoThis.toString(), forDoingThis.toString()); - } - - // like above, but just make sure they can pay; returns true unless person can't afford the cost - public boolean canAffordCommand(double cost, String toDoThis) { - if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { - return true; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { - return Econ.hasAtLeast(myFaction, cost, toDoThis); - } else { - return Econ.hasAtLeast(fme, cost, toDoThis); - } - } - - public void doWarmUp(WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { - this.doWarmUp(this.fme, warmup, translationKey, action, runnable, delay); - } - - public void doWarmUp(FPlayer player, WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { - WarmUpUtil.process(player, warmup, translationKey, action, runnable, delay); - } + public static final SimpleDateFormat sdf = new SimpleDateFormat(TL.DATE_FORMAT.toString()); + + public boolean disableOnLock; + + public FPlayer fme; + public Faction myFaction; + public boolean senderMustBeMember; + public boolean senderMustBeModerator; + public boolean senderMustBeAdmin; + public boolean senderMustBeColeader; + + + public boolean isMoneyCommand; + + public FCommand() { + super(SavageFactions.plugin); + + // Due to safety reasons it defaults to disable on lock. + disableOnLock = true; + + // The money commands must be disabled if money should not be used. + isMoneyCommand = false; + + senderMustBeMember = false; + senderMustBeModerator = false; + senderMustBeColeader = false; + senderMustBeAdmin = false; + } + + @Override + public void setCommandSender(CommandSender sender) { + super.setCommandSender(sender); + if (sender instanceof Player) { + this.fme = FPlayers.getInstance().getByPlayer((Player) sender); + this.myFaction = this.fme.getFaction(); + } else { + this.fme = null; + this.myFaction = null; + } + } + + @Override + public void execute(CommandSender sender, List args, List> commandChain) { + setCommandSender(sender); + super.execute(sender, args, commandChain); + } + + @Override + public boolean isEnabled() { + if (p.getLocked() && this.disableOnLock) { + msg("Factions was locked by an admin. Please try again later."); + return false; + } + + if (this.isMoneyCommand && !Conf.econEnabled) { + msg("Faction economy features are disabled on this server."); + return false; + } + + if (this.isMoneyCommand && !Conf.bankEnabled) { + msg("The faction bank system is disabled on this server."); + return false; + } + + return true; + } + + @Override + public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { + boolean superValid = super.validSenderType(sender, informSenderIfNot); + if (!superValid) { + return false; + } + + if (!(this.senderMustBeMember || this.senderMustBeModerator || this.senderMustBeAdmin || this.senderMustBeColeader)) { + return true; + } + + if (!(sender instanceof Player)) { + return false; + } + + if (!fme.hasFaction()) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("You are not member of any faction.")); + } + return false; + } + + + if (this.senderMustBeModerator && !fme.getRole().isAtLeast(Role.MODERATOR)) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("Only faction moderators can %s.", this.getHelpShort())); + } + return false; + } + + if (this.senderMustBeColeader && !fme.getRole().isAtLeast(Role.COLEADER)) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("Only faction coleaders can %s.", this.getHelpShort())); + } + return false; + } + + if (this.senderMustBeAdmin && !fme.getRole().isAtLeast(Role.LEADER)) { + if (informSenderIfNot) { + sender.sendMessage(p.txt.parse("Only faction admins can %s.", this.getHelpShort())); + } + return false; + } + + + return true; + } + + // -------------------------------------------- // + // Assertions + // -------------------------------------------- // + + public boolean assertHasFaction() { + if (me == null) { + return true; + } + + if (!fme.hasFaction()) { + sendMessage("You are not member of any faction."); + return false; + } + return true; + } + + public boolean assertMinRole(Role role) { + if (me == null) { + return true; + } + + if (fme.getRole().value < role.value) { + msg("You must be " + role + " to " + this.getHelpShort() + "."); + return false; + } + return true; + } + + // -------------------------------------------- // + // Argument Readers + // -------------------------------------------- // + + // FPLAYER ====================== + public FPlayer strAsFPlayer(String name, FPlayer def, boolean msg) { + FPlayer ret = def; + + if (name != null) { + for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { + if (fplayer.getName().equalsIgnoreCase(name)) { + ret = fplayer; + break; + } + } + } + + if (msg && ret == null) { + this.msg("No player \"%s\" could be found.", name); + } + + return ret; + } + + public FPlayer argAsFPlayer(int idx, FPlayer def, boolean msg) { + return this.strAsFPlayer(this.argAsString(idx), def, msg); + } + + public FPlayer argAsFPlayer(int idx, FPlayer def) { + return this.argAsFPlayer(idx, def, true); + } + + public FPlayer argAsFPlayer(int idx) { + return this.argAsFPlayer(idx, null); + } + + // BEST FPLAYER MATCH ====================== + public FPlayer strAsBestFPlayerMatch(String name, FPlayer def, boolean msg) { + return strAsFPlayer(name, def, msg); + } + + public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def, boolean msg) { + return this.strAsBestFPlayerMatch(this.argAsString(idx), def, msg); + } + + public FPlayer argAsBestFPlayerMatch(int idx, FPlayer def) { + return this.argAsBestFPlayerMatch(idx, def, true); + } + + public FPlayer argAsBestFPlayerMatch(int idx) { + return this.argAsBestFPlayerMatch(idx, null); + } + + // FACTION ====================== + public Faction strAsFaction(String name, Faction def, boolean msg) { + Faction ret = def; + + if (name != null) { + // First we try an exact match + Faction faction = Factions.getInstance().getByTag(name); // Checks for faction name match. + + // Now lets try for warzone / safezone. Helpful for custom warzone / safezone names. + // Do this after we check for an exact match in case they rename the warzone / safezone + // and a player created faction took one of the names. + if (faction == null) { + if (name.equalsIgnoreCase("warzone")) { + faction = Factions.getInstance().getWarZone(); + } else if (name.equalsIgnoreCase("safezone")) { + faction = Factions.getInstance().getSafeZone(); + } + } + + // Next we match faction tags + if (faction == null) { + faction = Factions.getInstance().getBestTagMatch(name); + } + + // Next we match player names + if (faction == null) { + FPlayer fplayer = strAsFPlayer(name, null, false); + if (fplayer != null) { + faction = fplayer.getFaction(); + } + } + + if (faction != null) { + ret = faction; + } + } + + if (msg && ret == null) { + this.msg("The faction or player \"%s\" could not be found.", name); + } + + return ret; + } + + public Faction argAsFaction(int idx, Faction def, boolean msg) { + return this.strAsFaction(this.argAsString(idx), def, msg); + } + + public Faction argAsFaction(int idx, Faction def) { + return this.argAsFaction(idx, def, true); + } + + public Faction argAsFaction(int idx) { + return this.argAsFaction(idx, null); + } + + // -------------------------------------------- // + // Commonly used logic + // -------------------------------------------- // + + public boolean canIAdministerYou(FPlayer i, FPlayer you) { + if (!i.getFaction().equals(you.getFaction())) { + i.sendMessage(p.txt.parse("%s is not in the same faction as you.", you.describeTo(i, true))); + return false; + } + + if (i.getRole().value > you.getRole().value || i.getRole().equals(Role.LEADER)) { + return true; + } + + if (you.getRole().equals(Role.LEADER)) { + i.sendMessage(p.txt.parse("Only the faction admin can do that.")); + + } else if ((you.getRole().equals(Role.COLEADER))) { + if (i == you) { + return true; + } else { + i.sendMessage(p.txt.parse("Coleaders can't control each other...")); + } + + } else if (i.getRole().equals(Role.MODERATOR)) { + if (i == you) { + return true; //Moderators can control themselves + } else { + i.sendMessage(p.txt.parse("Moderators can't control each other...")); + } + } else { + i.sendMessage(p.txt.parse("You must be a faction moderator to do that.")); + } + + return false; + } + + // if economy is enabled and they're not on the bypass list, make 'em pay; returns true unless person can't afford the cost + public boolean payForCommand(double cost, String toDoThis, String forDoingThis) { + if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { + return true; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { + return Econ.modifyMoney(myFaction, -cost, toDoThis, forDoingThis); + } else { + return Econ.modifyMoney(fme, -cost, toDoThis, forDoingThis); + } + } + + public boolean payForCommand(double cost, TL toDoThis, TL forDoingThis) { + return payForCommand(cost, toDoThis.toString(), forDoingThis.toString()); + } + + // like above, but just make sure they can pay; returns true unless person can't afford the cost + public boolean canAffordCommand(double cost, String toDoThis) { + if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { + return true; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { + return Econ.hasAtLeast(myFaction, cost, toDoThis); + } else { + return Econ.hasAtLeast(fme, cost, toDoThis); + } + } + + public void doWarmUp(WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { + this.doWarmUp(this.fme, warmup, translationKey, action, runnable, delay); + } + + public void doWarmUp(FPlayer player, WarmUpUtil.Warmup warmup, TL translationKey, String action, Runnable runnable, long delay) { + WarmUpUtil.process(player, warmup, translationKey, action, runnable, delay); + } } diff --git a/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java b/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java index d36779ed..94366584 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FPromoteCommand.java @@ -9,86 +9,86 @@ import com.massivecraft.factions.zcore.util.TL; public class FPromoteCommand extends FCommand { - public int relative = 0; + public int relative = 0; - public FPromoteCommand() { - super(); + public FPromoteCommand() { + super(); - this.requiredArgs.add("player"); + this.requiredArgs.add("player"); - this.permission = Permission.PROMOTE.node; - this.disableOnLock = true; + this.permission = Permission.PROMOTE.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = true; - senderMustBeModerator = false; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = true; + senderMustBeModerator = false; + senderMustBeAdmin = false; + } - @Override - public void perform() { - FPlayer target = this.argAsBestFPlayerMatch(0); - if (target == null) { - msg(TL.GENERIC_NOPLAYERFOUND, this.argAsString(0)); - return; - } + @Override + public void perform() { + FPlayer target = this.argAsBestFPlayerMatch(0); + if (target == null) { + msg(TL.GENERIC_NOPLAYERFOUND, this.argAsString(0)); + return; + } - if (!target.getFaction().equals(myFaction)) { - msg(TL.COMMAND_PROMOTE_WRONGFACTION, target.getName()); - return; - } + if (!target.getFaction().equals(myFaction)) { + msg(TL.COMMAND_PROMOTE_WRONGFACTION, target.getName()); + return; + } - Role current = target.getRole(); - Role promotion = Role.getRelative(current, +relative); + Role current = target.getRole(); + Role promotion = Role.getRelative(current, +relative); - // Now it ain't that messy - if (!fme.isAdminBypassing()) { - Access access = myFaction.getAccess(fme, PermissableAction.PROMOTE); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_NOPERMISSION, "manage ranks"); - return; - } - if (target == fme) { - fme.msg(TL.COMMAND_PROMOTE_NOTSELF); - return; - } - // Don't allow people to manage role of their same rank - if (fme.getRole() == current) { - fme.msg(TL.COMMAND_PROMOTE_NOT_SAME); - return; - } - // Don't allow people to promote people to their same or higher rank. - if (fme.getRole().value <= promotion.value) { - fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); - return; - } - } + // Now it ain't that messy + if (!fme.isAdminBypassing()) { + Access access = myFaction.getAccess(fme, PermissableAction.PROMOTE); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_NOPERMISSION, "manage ranks"); + return; + } + if (target == fme) { + fme.msg(TL.COMMAND_PROMOTE_NOTSELF); + return; + } + // Don't allow people to manage role of their same rank + if (fme.getRole() == current) { + fme.msg(TL.COMMAND_PROMOTE_NOT_SAME); + return; + } + // Don't allow people to promote people to their same or higher rank. + if (fme.getRole().value <= promotion.value) { + fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); + return; + } + } - if (promotion == null) { - fme.msg(TL.COMMAND_PROMOTE_NOTTHATPLAYER); - return; - } + if (promotion == null) { + fme.msg(TL.COMMAND_PROMOTE_NOTTHATPLAYER); + return; + } - // Don't allow people to promote people to their same or higher rnak. - if (fme.getRole().value <= promotion.value) { - fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); - return; - } + // Don't allow people to promote people to their same or higher rnak. + if (fme.getRole().value <= promotion.value) { + fme.msg(TL.COMMAND_PROMOTE_NOT_ALLOWED); + return; + } - String action = relative > 0 ? TL.COMMAND_PROMOTE_PROMOTED.toString() : TL.COMMAND_PROMOTE_DEMOTED.toString(); + String action = relative > 0 ? TL.COMMAND_PROMOTE_PROMOTED.toString() : TL.COMMAND_PROMOTE_DEMOTED.toString(); - // Success! - target.setRole(promotion); - if (target.isOnline()) { - target.msg(TL.COMMAND_PROMOTE_TARGET, action, promotion.nicename); - } + // Success! + target.setRole(promotion); + if (target.isOnline()) { + target.msg(TL.COMMAND_PROMOTE_TARGET, action, promotion.nicename); + } - fme.msg(TL.COMMAND_PROMOTE_SUCCESS, action, target.getName(), promotion.nicename); - } + fme.msg(TL.COMMAND_PROMOTE_SUCCESS, action, target.getName(), promotion.nicename); + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_PROMOTE_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_PROMOTE_DESCRIPTION; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java b/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java index 9efbff03..07172c9f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FRelationCommand.java @@ -14,113 +14,113 @@ import org.bukkit.ChatColor; public abstract class FRelationCommand extends FCommand { - public Relation targetRelation; + public Relation targetRelation; - public FRelationCommand() { - super(); - this.requiredArgs.add("faction tag"); - //this.optionalArgs.put("player name", "you"); + public FRelationCommand() { + super(); + this.requiredArgs.add("faction tag"); + //this.optionalArgs.put("player name", "you"); - this.permission = Permission.RELATION.node; - this.disableOnLock = true; + this.permission = Permission.RELATION.node; + this.disableOnLock = true; - senderMustBePlayer = true; - senderMustBeMember = false; - senderMustBeModerator = true; - senderMustBeAdmin = false; - } + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeModerator = true; + senderMustBeAdmin = false; + } - @Override - public void perform() { - Faction them = this.argAsFaction(0); - if (them == null) { - return; - } + @Override + public void perform() { + Faction them = this.argAsFaction(0); + if (them == null) { + return; + } - if (!them.isNormal()) { - msg(TL.COMMAND_RELATIONS_ALLTHENOPE); - return; - } + if (!them.isNormal()) { + msg(TL.COMMAND_RELATIONS_ALLTHENOPE); + return; + } - if (them == myFaction) { - msg(TL.COMMAND_RELATIONS_MORENOPE); - return; - } + if (them == myFaction) { + msg(TL.COMMAND_RELATIONS_MORENOPE); + return; + } - if (myFaction.getRelationWish(them) == targetRelation) { - msg(TL.COMMAND_RELATIONS_ALREADYINRELATIONSHIP, them.getTag()); - return; - } + if (myFaction.getRelationWish(them) == targetRelation) { + msg(TL.COMMAND_RELATIONS_ALREADYINRELATIONSHIP, them.getTag()); + return; + } - if (hasMaxRelations(them, targetRelation)) { - // We message them down there with the count. - return; - } - Relation oldRelation = myFaction.getRelationTo(them, true); - FactionRelationWishEvent wishEvent = new FactionRelationWishEvent(fme, myFaction, them, oldRelation, targetRelation); - Bukkit.getPluginManager().callEvent(wishEvent); - if (wishEvent.isCancelled()) { - return; - } + if (hasMaxRelations(them, targetRelation)) { + // We message them down there with the count. + return; + } + Relation oldRelation = myFaction.getRelationTo(them, true); + FactionRelationWishEvent wishEvent = new FactionRelationWishEvent(fme, myFaction, them, oldRelation, targetRelation); + Bukkit.getPluginManager().callEvent(wishEvent); + if (wishEvent.isCancelled()) { + return; + } - // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay - if (!payForCommand(targetRelation.getRelationCost(), TL.COMMAND_RELATIONS_TOMARRY, TL.COMMAND_RELATIONS_FORMARRY)) { - return; - } + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(targetRelation.getRelationCost(), TL.COMMAND_RELATIONS_TOMARRY, TL.COMMAND_RELATIONS_FORMARRY)) { + return; + } - // try to set the new relation - myFaction.setRelationWish(them, targetRelation); - Relation currentRelation = myFaction.getRelationTo(them, true); - ChatColor currentRelationColor = currentRelation.getColor(); + // try to set the new relation + myFaction.setRelationWish(them, targetRelation); + Relation currentRelation = myFaction.getRelationTo(them, true); + ChatColor currentRelationColor = currentRelation.getColor(); - // if the relation change was successful - if (targetRelation.value == currentRelation.value) { - // trigger the faction relation event - FactionRelationEvent relationEvent = new FactionRelationEvent(myFaction, them, oldRelation, currentRelation); - Bukkit.getServer().getPluginManager().callEvent(relationEvent); + // if the relation change was successful + if (targetRelation.value == currentRelation.value) { + // trigger the faction relation event + FactionRelationEvent relationEvent = new FactionRelationEvent(myFaction, them, oldRelation, currentRelation); + Bukkit.getServer().getPluginManager().callEvent(relationEvent); - them.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + myFaction.getTag()); - myFaction.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + them.getTag()); - } else { - // inform the other faction of your request - them.msg(TL.COMMAND_RELATIONS_PROPOSAL_1, currentRelationColor + myFaction.getTag(), targetRelation.getColor() + targetRelation.getTranslation()); - them.msg(TL.COMMAND_RELATIONS_PROPOSAL_2, Conf.baseCommandAliases.get(0), targetRelation, myFaction.getTag()); - myFaction.msg(TL.COMMAND_RELATIONS_PROPOSAL_SENT, currentRelationColor + them.getTag(), "" + targetRelation.getColor() + targetRelation); - } + them.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + myFaction.getTag()); + myFaction.msg(TL.COMMAND_RELATIONS_MUTUAL, currentRelationColor + targetRelation.getTranslation(), currentRelationColor + them.getTag()); + } else { + // inform the other faction of your request + them.msg(TL.COMMAND_RELATIONS_PROPOSAL_1, currentRelationColor + myFaction.getTag(), targetRelation.getColor() + targetRelation.getTranslation()); + them.msg(TL.COMMAND_RELATIONS_PROPOSAL_2, Conf.baseCommandAliases.get(0), targetRelation, myFaction.getTag()); + myFaction.msg(TL.COMMAND_RELATIONS_PROPOSAL_SENT, currentRelationColor + them.getTag(), "" + targetRelation.getColor() + targetRelation); + } - if (!targetRelation.isNeutral() && them.isPeaceful()) { - them.msg(TL.COMMAND_RELATIONS_PEACEFUL); - myFaction.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); - } + if (!targetRelation.isNeutral() && them.isPeaceful()) { + them.msg(TL.COMMAND_RELATIONS_PEACEFUL); + myFaction.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); + } - if (!targetRelation.isNeutral() && myFaction.isPeaceful()) { - them.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); - myFaction.msg(TL.COMMAND_RELATIONS_PEACEFUL); - } + if (!targetRelation.isNeutral() && myFaction.isPeaceful()) { + them.msg(TL.COMMAND_RELATIONS_PEACEFULOTHER); + myFaction.msg(TL.COMMAND_RELATIONS_PEACEFUL); + } - FTeamWrapper.updatePrefixes(myFaction); - FTeamWrapper.updatePrefixes(them); - } + FTeamWrapper.updatePrefixes(myFaction); + FTeamWrapper.updatePrefixes(them); + } - private boolean hasMaxRelations(Faction them, Relation targetRelation) { - int max = SavageFactions.plugin.getConfig().getInt("max-relations." + targetRelation.toString(), -1); - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", false)) { - if (max != -1) { - if (myFaction.getRelationCount(targetRelation) >= max) { - msg(TL.COMMAND_RELATIONS_EXCEEDS_ME, max, targetRelation.getPluralTranslation()); - return true; - } - if (them.getRelationCount(targetRelation) >= max) { - msg(TL.COMMAND_RELATIONS_EXCEEDS_THEY, max, targetRelation.getPluralTranslation()); - return true; - } - } - } - return false; - } + private boolean hasMaxRelations(Faction them, Relation targetRelation) { + int max = SavageFactions.plugin.getConfig().getInt("max-relations." + targetRelation.toString(), -1); + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", false)) { + if (max != -1) { + if (myFaction.getRelationCount(targetRelation) >= max) { + msg(TL.COMMAND_RELATIONS_EXCEEDS_ME, max, targetRelation.getPluralTranslation()); + return true; + } + if (them.getRelationCount(targetRelation) >= max) { + msg(TL.COMMAND_RELATIONS_EXCEEDS_THEY, max, targetRelation.getPluralTranslation()); + return true; + } + } + } + return false; + } - @Override - public TL getUsageTranslation() { - return TL.COMMAND_RELATIONS_DESCRIPTION; - } + @Override + public TL getUsageTranslation() { + return TL.COMMAND_RELATIONS_DESCRIPTION; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java b/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java index d22632c1..9e9f8c67 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerEnteredFactionEvent.java @@ -6,37 +6,37 @@ import org.bukkit.event.HandlerList; public class FPlayerEnteredFactionEvent extends FactionPlayerEvent { - private static final HandlerList handlers = new HandlerList(); - private FPlayer fPlayer; - private Faction factionTo; - private Faction factionFrom; + private static final HandlerList handlers = new HandlerList(); + private FPlayer fPlayer; + private Faction factionTo; + private Faction factionFrom; - public FPlayerEnteredFactionEvent(Faction factionTo, Faction factionFrom, FPlayer fPlayer) { - super(fPlayer.getFaction(), fPlayer); - this.factionFrom = factionFrom; - this.factionTo = factionTo; - this.fPlayer = fPlayer; - } + public FPlayerEnteredFactionEvent(Faction factionTo, Faction factionFrom, FPlayer fPlayer) { + super(fPlayer.getFaction(), fPlayer); + this.factionFrom = factionFrom; + this.factionTo = factionTo; + this.fPlayer = fPlayer; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } - @Override - public FPlayer getfPlayer() { - return fPlayer; - } + @Override + public FPlayer getfPlayer() { + return fPlayer; + } - public Faction getFactionTo() { - return factionTo; - } + public Faction getFactionTo() { + return factionTo; + } - public Faction getFactionFrom() { - return factionFrom; - } + public Faction getFactionFrom() { + return factionFrom; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java b/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java index fd9617da..1755bdff 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerJoinEvent.java @@ -9,34 +9,34 @@ import org.bukkit.event.Cancellable; */ public class FPlayerJoinEvent extends FactionPlayerEvent implements Cancellable { - PlayerJoinReason reason; - boolean cancelled = false; + PlayerJoinReason reason; + boolean cancelled = false; - public FPlayerJoinEvent(FPlayer fp, Faction f, PlayerJoinReason r) { - super(f, fp); - reason = r; - } + public FPlayerJoinEvent(FPlayer fp, Faction f, PlayerJoinReason r) { + super(f, fp); + reason = r; + } - /** - * Get the reason the player joined the faction. - * - * @return reason player joined the faction. - */ - public PlayerJoinReason getReason() { - return reason; - } + /** + * Get the reason the player joined the faction. + * + * @return reason player joined the faction. + */ + public PlayerJoinReason getReason() { + return reason; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - cancelled = c; - } + @Override + public void setCancelled(boolean c) { + cancelled = c; + } - public enum PlayerJoinReason { - CREATE, LEADER, COMMAND - } + public enum PlayerJoinReason { + CREATE, LEADER, COMMAND + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java b/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java index e9b764d9..0ecb80d1 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerLeaveEvent.java @@ -6,35 +6,35 @@ import org.bukkit.event.Cancellable; public class FPlayerLeaveEvent extends FactionPlayerEvent implements Cancellable { - boolean cancelled = false; - private PlayerLeaveReason reason; + boolean cancelled = false; + private PlayerLeaveReason reason; - public FPlayerLeaveEvent(FPlayer p, Faction f, PlayerLeaveReason r) { - super(f, p); - reason = r; - } + public FPlayerLeaveEvent(FPlayer p, Faction f, PlayerLeaveReason r) { + super(f, p); + reason = r; + } - /** - * Get the reason the player left the faction. - * - * @return reason player left the faction. - */ - public PlayerLeaveReason getReason() { - return reason; - } + /** + * Get the reason the player left the faction. + * + * @return reason player left the faction. + */ + public PlayerLeaveReason getReason() { + return reason; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - // Don't let them cancel factions disbanding. - cancelled = reason != PlayerLeaveReason.DISBAND && reason != PlayerLeaveReason.RESET && c; - } + @Override + public void setCancelled(boolean c) { + // Don't let them cancel factions disbanding. + cancelled = reason != PlayerLeaveReason.DISBAND && reason != PlayerLeaveReason.RESET && c; + } - public enum PlayerLeaveReason { - KICKED, DISBAND, RESET, JOINOTHER, LEAVE, BANNED - } + public enum PlayerLeaveReason { + KICKED, DISBAND, RESET, JOINOTHER, LEAVE, BANNED + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java b/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java index f2f283c8..5a80a15a 100644 --- a/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java +++ b/src/main/java/com/massivecraft/factions/event/FPlayerStoppedFlying.java @@ -4,25 +4,25 @@ import com.massivecraft.factions.FPlayer; import org.bukkit.event.HandlerList; public class FPlayerStoppedFlying extends FactionPlayerEvent { - private static final HandlerList handlers = new HandlerList(); - private FPlayer fPlayer; + private static final HandlerList handlers = new HandlerList(); + private FPlayer fPlayer; - public FPlayerStoppedFlying(FPlayer fPlayer) { - super(fPlayer.getFaction(), fPlayer); - this.fPlayer = fPlayer; - } + public FPlayerStoppedFlying(FPlayer fPlayer) { + super(fPlayer.getFaction(), fPlayer); + this.fPlayer = fPlayer; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - @Override - public FPlayer getfPlayer() { - return fPlayer; - } + @Override + public FPlayer getfPlayer() { + return fPlayer; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java b/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java index afdd1ab4..18791908 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java @@ -12,41 +12,41 @@ import org.bukkit.event.HandlerList; */ public class FactionCreateEvent extends Event implements Cancellable { - private static final HandlerList handlers = new HandlerList(); + private static final HandlerList handlers = new HandlerList(); - private String factionTag; - private Player sender; - private boolean cancelled; + private String factionTag; + private Player sender; + private boolean cancelled; - public FactionCreateEvent(Player sender, String tag) { - this.factionTag = tag; - this.sender = sender; - this.cancelled = false; - } + public FactionCreateEvent(Player sender, String tag) { + this.factionTag = tag; + this.sender = sender; + this.cancelled = false; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - public FPlayer getFPlayer() { - return FPlayers.getInstance().getByPlayer(sender); - } + public FPlayer getFPlayer() { + return FPlayers.getInstance().getByPlayer(sender); + } - public String getFactionTag() { - return factionTag; - } + public String getFactionTag() { + return factionTag; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java b/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java index 1d810c27..0555fa2a 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java @@ -11,42 +11,42 @@ import org.bukkit.event.Cancellable; */ public class FactionDisbandEvent extends FactionEvent implements Cancellable { - private final Player sender; - private final PlayerDisbandReason reason; - private boolean cancelled = false; + private final Player sender; + private final PlayerDisbandReason reason; + private boolean cancelled = false; - public FactionDisbandEvent(Player sender, String factionId, PlayerDisbandReason reason) { - super(Factions.getInstance().getFactionById(factionId)); - this.sender = sender; - this.reason = reason; - } + public FactionDisbandEvent(Player sender, String factionId, PlayerDisbandReason reason) { + super(Factions.getInstance().getFactionById(factionId)); + this.sender = sender; + this.reason = reason; + } - public FPlayer getFPlayer() { - return FPlayers.getInstance().getByPlayer(sender); - } + public FPlayer getFPlayer() { + return FPlayers.getInstance().getByPlayer(sender); + } - public Player getPlayer() { - return sender; - } + public Player getPlayer() { + return sender; + } - public PlayerDisbandReason getReason() { - return reason; - } + public PlayerDisbandReason getReason() { + return reason; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - cancelled = c; - } + @Override + public void setCancelled(boolean c) { + cancelled = c; + } - public enum PlayerDisbandReason { - COMMAND, - PLUGIN, - INACTIVITY, - LEAVE, - } + public enum PlayerDisbandReason { + COMMAND, + PLUGIN, + INACTIVITY, + LEAVE, + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionEvent.java b/src/main/java/com/massivecraft/factions/event/FactionEvent.java index 54595475..892f0ac0 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionEvent.java @@ -9,29 +9,29 @@ import org.bukkit.event.HandlerList; */ public class FactionEvent extends Event { - private static final HandlerList handlers = new HandlerList(); - private final Faction faction; + private static final HandlerList handlers = new HandlerList(); + private final Faction faction; - public FactionEvent(Faction faction) { - this.faction = faction; - } + public FactionEvent(Faction faction) { + this.faction = faction; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - /** - * Get the Faction involved in the event. - * - * @return faction involved in the event. - */ - public Faction getFaction() { - return this.faction; - } + /** + * Get the Faction involved in the event. + * + * @return faction involved in the event. + */ + public Faction getFaction() { + return this.faction; + } - @Override - public HandlerList getHandlers() { - return handlers; - } + @Override + public HandlerList getHandlers() { + return handlers; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java b/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java index ca0f86f4..3a76dcdd 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionPlayerEvent.java @@ -8,14 +8,14 @@ import com.massivecraft.factions.Faction; */ public class FactionPlayerEvent extends FactionEvent { - protected final FPlayer fPlayer; + protected final FPlayer fPlayer; - public FactionPlayerEvent(Faction faction, FPlayer fPlayer) { - super(faction); - this.fPlayer = fPlayer; - } + public FactionPlayerEvent(Faction faction, FPlayer fPlayer) { + super(faction); + this.fPlayer = fPlayer; + } - public FPlayer getfPlayer() { - return this.fPlayer; - } + public FPlayer getfPlayer() { + return this.fPlayer; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java b/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java index 93b6cab2..761fd1a4 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionRelationEvent.java @@ -10,41 +10,41 @@ import org.bukkit.event.HandlerList; */ public class FactionRelationEvent extends Event { - private static final HandlerList handlers = new HandlerList(); + private static final HandlerList handlers = new HandlerList(); - private Faction fsender; - private Faction ftarget; - private Relation foldrel; - private Relation frel; + private Faction fsender; + private Faction ftarget; + private Relation foldrel; + private Relation frel; - public FactionRelationEvent(Faction sender, Faction target, Relation oldrel, Relation rel) { - fsender = sender; - ftarget = target; - foldrel = oldrel; - frel = rel; - } + public FactionRelationEvent(Faction sender, Faction target, Relation oldrel, Relation rel) { + fsender = sender; + ftarget = target; + foldrel = oldrel; + frel = rel; + } - public static HandlerList getHandlerList() { - return handlers; - } + public static HandlerList getHandlerList() { + return handlers; + } - public HandlerList getHandlers() { - return handlers; - } + public HandlerList getHandlers() { + return handlers; + } - public Relation getOldRelation() { - return foldrel; - } + public Relation getOldRelation() { + return foldrel; + } - public Relation getRelation() { - return frel; - } + public Relation getRelation() { + return frel; + } - public Faction getFaction() { - return fsender; - } + public Faction getFaction() { + return fsender; + } - public Faction getTargetFaction() { - return ftarget; - } + public Faction getTargetFaction() { + return ftarget; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java b/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java index 8590f7b4..dfdc6ef6 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionRelationWishEvent.java @@ -6,39 +6,39 @@ import com.massivecraft.factions.struct.Relation; import org.bukkit.event.Cancellable; public class FactionRelationWishEvent extends FactionPlayerEvent implements Cancellable { - private final Faction targetFaction; - private final Relation currentRelation; - private final Relation targetRelation; + private final Faction targetFaction; + private final Relation currentRelation; + private final Relation targetRelation; - private boolean cancelled; + private boolean cancelled; - public FactionRelationWishEvent(FPlayer caller, Faction sender, Faction targetFaction, Relation currentRelation, Relation targetRelation) { - super(sender, caller); + public FactionRelationWishEvent(FPlayer caller, Faction sender, Faction targetFaction, Relation currentRelation, Relation targetRelation) { + super(sender, caller); - this.targetFaction = targetFaction; - this.currentRelation = currentRelation; - this.targetRelation = targetRelation; - } + this.targetFaction = targetFaction; + this.currentRelation = currentRelation; + this.targetRelation = targetRelation; + } - public Faction getTargetFaction() { - return targetFaction; - } + public Faction getTargetFaction() { + return targetFaction; + } - public Relation getCurrentRelation() { - return currentRelation; - } + public Relation getCurrentRelation() { + return currentRelation; + } - public Relation getTargetRelation() { - return targetRelation; - } + public Relation getTargetRelation() { + return targetRelation; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } } diff --git a/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java b/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java index 8dc8f022..cedeec77 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionRenameEvent.java @@ -6,52 +6,52 @@ import org.bukkit.event.Cancellable; public class FactionRenameEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled = false; - private String tag; + private boolean cancelled = false; + private String tag; - public FactionRenameEvent(FPlayer sender, String newTag) { - super(sender.getFaction(), sender); - tag = newTag; - } + public FactionRenameEvent(FPlayer sender, String newTag) { + super(sender.getFaction(), sender); + tag = newTag; + } - /** - * Get the player involved in the event. - * - * @return Player involved in the event. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the player involved in the event. + * + * @return Player involved in the event. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - /** - * Get the faction tag before it was renamed. - * - * @return old faction tag. - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getOldFactionTag() { - return getFaction().getTag(); - } + /** + * Get the faction tag before it was renamed. + * + * @return old faction tag. + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getOldFactionTag() { + return getFaction().getTag(); + } - /** - * Get the new faction tag. - * - * @return new faction tag as String. - */ - public String getFactionTag() { - return tag; - } + /** + * Get the new faction tag. + * + * @return new faction tag as String. + */ + public String getFactionTag() { + return tag; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java b/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java index 8bef95f0..223d6852 100644 --- a/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java +++ b/src/main/java/com/massivecraft/factions/event/LandClaimEvent.java @@ -11,64 +11,64 @@ import org.bukkit.event.Cancellable; */ public class LandClaimEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled; - private FLocation location; + private boolean cancelled; + private FLocation location; - public LandClaimEvent(FLocation loc, Faction f, FPlayer p) { - super(f, p); - cancelled = false; - location = loc; - } + public LandClaimEvent(FLocation loc, Faction f, FPlayer p) { + super(f, p); + cancelled = false; + location = loc; + } - /** - * Get the FLocation involved in this event. - * - * @return the FLocation (also a chunk) involved in this event. - */ - public FLocation getLocation() { - return this.location; - } + /** + * Get the FLocation involved in this event. + * + * @return the FLocation (also a chunk) involved in this event. + */ + public FLocation getLocation() { + return this.location; + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in this event. - * - * @return player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in this event. + * + * @return player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java b/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java index 5b807bfd..47dfa00f 100644 --- a/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java +++ b/src/main/java/com/massivecraft/factions/event/LandUnclaimAllEvent.java @@ -6,52 +6,52 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; public class LandUnclaimAllEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled; + private boolean cancelled; - public LandUnclaimAllEvent(Faction f, FPlayer p) { - super(f, p); - } + public LandUnclaimAllEvent(Faction f, FPlayer p) { + super(f, p); + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in the event. - * - * @return Player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in the event. + * + * @return Player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } } diff --git a/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java b/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java index 402f50e3..72ae23c3 100644 --- a/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java +++ b/src/main/java/com/massivecraft/factions/event/LandUnclaimEvent.java @@ -11,59 +11,59 @@ import org.bukkit.event.Cancellable; */ public class LandUnclaimEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled; - private FLocation location; + private boolean cancelled; + private FLocation location; - public LandUnclaimEvent(FLocation loc, Faction f, FPlayer p) { - super(f, p); - cancelled = false; - location = loc; - } + public LandUnclaimEvent(FLocation loc, Faction f, FPlayer p) { + super(f, p); + cancelled = false; + location = loc; + } - public FLocation getLocation() { - return this.location; - } + public FLocation getLocation() { + return this.location; + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in the event. - * - * @return Player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in the event. + * + * @return Player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - cancelled = c; - } + @Override + public void setCancelled(boolean c) { + cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java b/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java index 45a5b19b..6304e39c 100644 --- a/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java +++ b/src/main/java/com/massivecraft/factions/event/PowerLossEvent.java @@ -10,72 +10,72 @@ import org.bukkit.event.Cancellable; */ public class PowerLossEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled = false; - private String message; + private boolean cancelled = false; + private String message; - public PowerLossEvent(Faction f, FPlayer p) { - super(f, p); - } + public PowerLossEvent(Faction f, FPlayer p) { + super(f, p); + } - /** - * Get the id of the faction. - * - * @return id of faction as String - * @deprecated use getFaction().getId() instead. - */ - @Deprecated - public String getFactionId() { - return getFaction().getId(); - } + /** + * Get the id of the faction. + * + * @return id of faction as String + * @deprecated use getFaction().getId() instead. + */ + @Deprecated + public String getFactionId() { + return getFaction().getId(); + } - /** - * Get the tag of the faction. - * - * @return tag of faction as String - * @deprecated use getFaction().getTag() instead. - */ - @Deprecated - public String getFactionTag() { - return getFaction().getTag(); - } + /** + * Get the tag of the faction. + * + * @return tag of faction as String + * @deprecated use getFaction().getTag() instead. + */ + @Deprecated + public String getFactionTag() { + return getFaction().getTag(); + } - /** - * Get the Player involved in the event. - * - * @return Player from FPlayer. - * @deprecated use getfPlayer().getPlayer() instead. - */ - @Deprecated - public Player getPlayer() { - return getfPlayer().getPlayer(); - } + /** + * Get the Player involved in the event. + * + * @return Player from FPlayer. + * @deprecated use getfPlayer().getPlayer() instead. + */ + @Deprecated + public Player getPlayer() { + return getfPlayer().getPlayer(); + } - /** - * Get the power loss message. - * - * @return power loss message as String. - */ - public String getMessage() { - return message; - } + /** + * Get the power loss message. + * + * @return power loss message as String. + */ + public String getMessage() { + return message; + } - /** - * Set the power loss message. - * - * @param message of powerloss - */ - public void setMessage(String message) { - this.message = message; - } + /** + * Set the power loss message. + * + * @param message of powerloss + */ + public void setMessage(String message) { + this.message = message; + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java b/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java index b9a7ec2c..e1782b8d 100644 --- a/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java +++ b/src/main/java/com/massivecraft/factions/event/PowerRegenEvent.java @@ -9,20 +9,20 @@ import org.bukkit.event.Cancellable; */ public class PowerRegenEvent extends FactionPlayerEvent implements Cancellable { - private boolean cancelled = false; + private boolean cancelled = false; - public PowerRegenEvent(Faction f, FPlayer p) { - super(f, p); - } + public PowerRegenEvent(Faction f, FPlayer p) { + super(f, p); + } - @Override - public boolean isCancelled() { - return cancelled; - } + @Override + public boolean isCancelled() { + return cancelled; + } - @Override - public void setCancelled(boolean c) { - this.cancelled = c; - } + @Override + public void setCancelled(boolean c) { + this.cancelled = c; + } } diff --git a/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java b/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java index 9ceeb827..2d8f4624 100644 --- a/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java +++ b/src/main/java/com/massivecraft/factions/iface/EconomyParticipator.java @@ -4,9 +4,9 @@ import com.massivecraft.factions.zcore.util.TL; public interface EconomyParticipator extends RelationParticipator { - String getAccountId(); + String getAccountId(); - void msg(String str, Object... args); + void msg(String str, Object... args); - void msg(TL translation, Object... args); + void msg(TL translation, Object... args); } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java b/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java index a536c43b..781bed18 100644 --- a/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java +++ b/src/main/java/com/massivecraft/factions/iface/RelationParticipator.java @@ -5,13 +5,13 @@ import org.bukkit.ChatColor; public interface RelationParticipator { - String describeTo(RelationParticipator that); + String describeTo(RelationParticipator that); - String describeTo(RelationParticipator that, boolean ucfirst); + String describeTo(RelationParticipator that, boolean ucfirst); - Relation getRelationTo(RelationParticipator that); + Relation getRelationTo(RelationParticipator that); - Relation getRelationTo(RelationParticipator that, boolean ignorePeaceful); + Relation getRelationTo(RelationParticipator that, boolean ignorePeaceful); - ChatColor getColorTo(RelationParticipator to); + ChatColor getColorTo(RelationParticipator to); } diff --git a/src/main/java/com/massivecraft/factions/integration/Econ.java b/src/main/java/com/massivecraft/factions/integration/Econ.java index 064a150c..650a6b02 100644 --- a/src/main/java/com/massivecraft/factions/integration/Econ.java +++ b/src/main/java/com/massivecraft/factions/integration/Econ.java @@ -23,418 +23,418 @@ import java.util.logging.Level; public class Econ { - private static final DecimalFormat format = new DecimalFormat(TL.ECON_FORMAT.toString()); - private static Economy econ = null; + private static final DecimalFormat format = new DecimalFormat(TL.ECON_FORMAT.toString()); + private static Economy econ = null; - public static void setup() { - if (isSetup()) { - return; - } + public static void setup() { + if (isSetup()) { + return; + } - String integrationFail = "Economy integration is " + (Conf.econEnabled ? "enabled, but" : "disabled, and") + " the plugin \"Vault\" "; + String integrationFail = "Economy integration is " + (Conf.econEnabled ? "enabled, but" : "disabled, and") + " the plugin \"Vault\" "; - if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { - SavageFactions.plugin.log(integrationFail + "is not installed."); - return; - } + if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { + SavageFactions.plugin.log(integrationFail + "is not installed."); + return; + } - RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); - if (rsp == null) { - SavageFactions.plugin.log(integrationFail + "is not hooked into an economy plugin."); - return; - } - econ = rsp.getProvider(); + RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + SavageFactions.plugin.log(integrationFail + "is not hooked into an economy plugin."); + return; + } + econ = rsp.getProvider(); - SavageFactions.plugin.log("Economy integration through Vault plugin successful."); + SavageFactions.plugin.log("Economy integration through Vault plugin successful."); - if (!Conf.econEnabled) { - SavageFactions.plugin.log("NOTE: Economy is disabled. You can enable it with the command: f config econEnabled true"); - } + if (!Conf.econEnabled) { + SavageFactions.plugin.log("NOTE: Economy is disabled. You can enable it with the command: f config econEnabled true"); + } - SavageFactions.plugin.cmdBase.cmdHelp.updateHelp(); - } + SavageFactions.plugin.cmdBase.cmdHelp.updateHelp(); + } - public static boolean shouldBeUsed() { - return Conf.econEnabled && econ != null && econ.isEnabled(); - } + public static boolean shouldBeUsed() { + return Conf.econEnabled && econ != null && econ.isEnabled(); + } - public static boolean isSetup() { - return econ != null; - } + public static boolean isSetup() { + return econ != null; + } - public static void modifyUniverseMoney(double delta) { - if (!shouldBeUsed()) { - return; - } + public static void modifyUniverseMoney(double delta) { + if (!shouldBeUsed()) { + return; + } - if (Conf.econUniverseAccount == null) { - return; - } - if (Conf.econUniverseAccount.length() == 0) { - return; - } - if (!econ.hasAccount(Conf.econUniverseAccount)) { - return; - } + if (Conf.econUniverseAccount == null) { + return; + } + if (Conf.econUniverseAccount.length() == 0) { + return; + } + if (!econ.hasAccount(Conf.econUniverseAccount)) { + return; + } - modifyBalance(Conf.econUniverseAccount, delta); - } + modifyBalance(Conf.econUniverseAccount, delta); + } - public static void sendBalanceInfo(FPlayer to, EconomyParticipator about) { - if (!shouldBeUsed()) { - SavageFactions.plugin.log(Level.WARNING, "Vault does not appear to be hooked into an economy plugin."); - return; - } - to.msg("%s's balance is %s.", about.describeTo(to, true), Econ.moneyString(econ.getBalance(about.getAccountId()))); - } + public static void sendBalanceInfo(FPlayer to, EconomyParticipator about) { + if (!shouldBeUsed()) { + SavageFactions.plugin.log(Level.WARNING, "Vault does not appear to be hooked into an economy plugin."); + return; + } + to.msg("%s's balance is %s.", about.describeTo(to, true), Econ.moneyString(econ.getBalance(about.getAccountId()))); + } - public static boolean canIControllYou(EconomyParticipator i, EconomyParticipator you) { - Faction fI = RelationUtil.getFaction(i); - Faction fYou = RelationUtil.getFaction(you); + public static boolean canIControllYou(EconomyParticipator i, EconomyParticipator you) { + Faction fI = RelationUtil.getFaction(i); + Faction fYou = RelationUtil.getFaction(you); - // This is a system invoker. Accept it. - if (fI == null) { - return true; - } + // This is a system invoker. Accept it. + if (fI == null) { + return true; + } - // Bypassing players can do any kind of transaction - if (i instanceof FPlayer && ((FPlayer) i).isAdminBypassing()) { - return true; - } + // Bypassing players can do any kind of transaction + if (i instanceof FPlayer && ((FPlayer) i).isAdminBypassing()) { + return true; + } - // Players with the any withdraw can do. - if (i instanceof FPlayer && Permission.MONEY_WITHDRAW_ANY.has(((FPlayer) i).getPlayer())) { - return true; - } + // Players with the any withdraw can do. + if (i instanceof FPlayer && Permission.MONEY_WITHDRAW_ANY.has(((FPlayer) i).getPlayer())) { + return true; + } - // You can deposit to anywhere you feel like. It's your loss if you can't withdraw it again. - if (i == you) { - return true; - } + // You can deposit to anywhere you feel like. It's your loss if you can't withdraw it again. + if (i == you) { + return true; + } - // A faction can always transfer away the money of it's members and its own money... - // This will however probably never happen as a faction does not have free will. - // Ohh by the way... Yes it could. For daily rent to the faction. - if (i == fI && fI == fYou) { - return true; - } + // A faction can always transfer away the money of it's members and its own money... + // This will however probably never happen as a faction does not have free will. + // Ohh by the way... Yes it could. For daily rent to the faction. + if (i == fI && fI == fYou) { + return true; + } - // Factions can be controlled by members that are moderators... or any member if any member can withdraw. - if (you instanceof Faction && fI == fYou && (Conf.bankMembersCanWithdraw || ((FPlayer) i).getRole().value >= Role.MODERATOR.value)) { - return true; - } + // Factions can be controlled by members that are moderators... or any member if any member can withdraw. + if (you instanceof Faction && fI == fYou && (Conf.bankMembersCanWithdraw || ((FPlayer) i).getRole().value >= Role.MODERATOR.value)) { + return true; + } - // Otherwise you may not!;,,; - i.msg("%s lacks permission to control %s's money.", i.describeTo(i, true), you.describeTo(i)); - return false; - } + // Otherwise you may not!;,,; + i.msg("%s lacks permission to control %s's money.", i.describeTo(i, true), you.describeTo(i)); + return false; + } - public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { - return transferMoney(invoker, from, to, amount, true); - } + public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { + return transferMoney(invoker, from, to, amount, true); + } - public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount, boolean notify) { - if (!shouldBeUsed()) { - return false; - } + public static boolean transferMoney(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount, boolean notify) { + if (!shouldBeUsed()) { + return false; + } - // The amount must be positive. - // If the amount is negative we must flip and multiply amount with -1. - if (amount < 0) { - amount *= -1; - EconomyParticipator temp = from; - from = to; - to = temp; - } + // The amount must be positive. + // If the amount is negative we must flip and multiply amount with -1. + if (amount < 0) { + amount *= -1; + EconomyParticipator temp = from; + from = to; + to = temp; + } - // Check the rights - if (!canIControllYou(invoker, from)) { - return false; - } + // Check the rights + if (!canIControllYou(invoker, from)) { + return false; + } - OfflinePlayer fromAcc; - OfflinePlayer toAcc; + OfflinePlayer fromAcc; + OfflinePlayer toAcc; - if (isUUID(from.getAccountId())) { - fromAcc = Bukkit.getOfflinePlayer(UUID.fromString(from.getAccountId())); - if (fromAcc.getName() == null) { - return false; - } - } else { - fromAcc = Bukkit.getOfflinePlayer(from.getAccountId()); - } + if (isUUID(from.getAccountId())) { + fromAcc = Bukkit.getOfflinePlayer(UUID.fromString(from.getAccountId())); + if (fromAcc.getName() == null) { + return false; + } + } else { + fromAcc = Bukkit.getOfflinePlayer(from.getAccountId()); + } - if (isUUID(to.getAccountId())) { - toAcc = Bukkit.getOfflinePlayer(UUID.fromString(to.getAccountId())); - if (toAcc.getName() == null) { - return false; - } - } else { - toAcc = Bukkit.getOfflinePlayer(to.getAccountId()); - } + if (isUUID(to.getAccountId())) { + toAcc = Bukkit.getOfflinePlayer(UUID.fromString(to.getAccountId())); + if (toAcc.getName() == null) { + return false; + } + } else { + toAcc = Bukkit.getOfflinePlayer(to.getAccountId()); + } - // Is there enough money for the transaction to happen? - if (!econ.has(fromAcc, amount)) { - // There was not enough money to pay - if (invoker != null && notify) { - invoker.msg("%s can't afford to transfer %s to %s.", from.describeTo(invoker, true), moneyString(amount), to.describeTo(invoker)); - } + // Is there enough money for the transaction to happen? + if (!econ.has(fromAcc, amount)) { + // There was not enough money to pay + if (invoker != null && notify) { + invoker.msg("%s can't afford to transfer %s to %s.", from.describeTo(invoker, true), moneyString(amount), to.describeTo(invoker)); + } - return false; - } + return false; + } - // Transfer money - EconomyResponse erw = econ.withdrawPlayer(fromAcc, amount); + // Transfer money + EconomyResponse erw = econ.withdrawPlayer(fromAcc, amount); - if (erw.transactionSuccess()) { - EconomyResponse erd = econ.depositPlayer(toAcc, amount); - if (erd.transactionSuccess()) { - if (notify) { - sendTransferInfo(invoker, from, to, amount); - } - return true; - } else { - // transaction failed, refund account - econ.depositPlayer(fromAcc, amount); - } - } + if (erw.transactionSuccess()) { + EconomyResponse erd = econ.depositPlayer(toAcc, amount); + if (erd.transactionSuccess()) { + if (notify) { + sendTransferInfo(invoker, from, to, amount); + } + return true; + } else { + // transaction failed, refund account + econ.depositPlayer(fromAcc, amount); + } + } - // if we get here something with the transaction failed - if (notify) { - invoker.msg("Unable to transfer %s to %s from %s.", moneyString(amount), to.describeTo(invoker), from.describeTo(invoker, true)); - } + // if we get here something with the transaction failed + if (notify) { + invoker.msg("Unable to transfer %s to %s from %s.", moneyString(amount), to.describeTo(invoker), from.describeTo(invoker, true)); + } - return false; - } + return false; + } - public static Set getFplayers(EconomyParticipator ep) { - Set fplayers = new HashSet<>(); + public static Set getFplayers(EconomyParticipator ep) { + Set fplayers = new HashSet<>(); - if (ep != null) { - if (ep instanceof FPlayer) { - fplayers.add((FPlayer) ep); - } else if (ep instanceof Faction) { - fplayers.addAll(((Faction) ep).getFPlayers()); - } - } + if (ep != null) { + if (ep instanceof FPlayer) { + fplayers.add((FPlayer) ep); + } else if (ep instanceof Faction) { + fplayers.addAll(((Faction) ep).getFPlayers()); + } + } - return fplayers; - } + return fplayers; + } - public static void sendTransferInfo(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { - Set recipients = new HashSet<>(); - recipients.addAll(getFplayers(invoker)); - recipients.addAll(getFplayers(from)); - recipients.addAll(getFplayers(to)); + public static void sendTransferInfo(EconomyParticipator invoker, EconomyParticipator from, EconomyParticipator to, double amount) { + Set recipients = new HashSet<>(); + recipients.addAll(getFplayers(invoker)); + recipients.addAll(getFplayers(from)); + recipients.addAll(getFplayers(to)); - if (invoker == null) { - for (FPlayer recipient : recipients) { - recipient.msg("%s was transferred from %s to %s.", moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); - } - } else if (invoker == from) { - for (FPlayer recipient : recipients) { - recipient.msg("%s gave %s to %s.", from.describeTo(recipient, true), moneyString(amount), to.describeTo(recipient)); - } - } else if (invoker == to) { - for (FPlayer recipient : recipients) { - recipient.msg("%s took %s from %s.", to.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient)); - } - } else { - for (FPlayer recipient : recipients) { - recipient.msg("%s transferred %s from %s to %s.", invoker.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); - } - } - } + if (invoker == null) { + for (FPlayer recipient : recipients) { + recipient.msg("%s was transferred from %s to %s.", moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); + } + } else if (invoker == from) { + for (FPlayer recipient : recipients) { + recipient.msg("%s gave %s to %s.", from.describeTo(recipient, true), moneyString(amount), to.describeTo(recipient)); + } + } else if (invoker == to) { + for (FPlayer recipient : recipients) { + recipient.msg("%s took %s from %s.", to.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient)); + } + } else { + for (FPlayer recipient : recipients) { + recipient.msg("%s transferred %s from %s to %s.", invoker.describeTo(recipient, true), moneyString(amount), from.describeTo(recipient), to.describeTo(recipient)); + } + } + } - public static boolean hasAtLeast(EconomyParticipator ep, double delta, String toDoThis) { - if (!shouldBeUsed()) { - return true; - } + public static boolean hasAtLeast(EconomyParticipator ep, double delta, String toDoThis) { + if (!shouldBeUsed()) { + return true; + } - // going the hard way round as econ.has refuses to work. - boolean affordable = false; - double currentBalance; + // going the hard way round as econ.has refuses to work. + boolean affordable = false; + double currentBalance; - if (isUUID(ep.getAccountId())) { - OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); - if (offline.getName() != null) { - currentBalance = econ.getBalance(Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId()))); - } else { - currentBalance = 0; - } - } else { - currentBalance = econ.getBalance(ep.getAccountId()); - } + if (isUUID(ep.getAccountId())) { + OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); + if (offline.getName() != null) { + currentBalance = econ.getBalance(Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId()))); + } else { + currentBalance = 0; + } + } else { + currentBalance = econ.getBalance(ep.getAccountId()); + } - if (currentBalance >= delta) { - affordable = true; - } + if (currentBalance >= delta) { + affordable = true; + } - if (!affordable) { - if (toDoThis != null && !toDoThis.isEmpty()) { - ep.msg("%s can't afford %s %s.", ep.describeTo(ep, true), moneyString(delta), toDoThis); - } - return false; - } - return true; - } + if (!affordable) { + if (toDoThis != null && !toDoThis.isEmpty()) { + ep.msg("%s can't afford %s %s.", ep.describeTo(ep, true), moneyString(delta), toDoThis); + } + return false; + } + return true; + } - public static boolean modifyMoney(EconomyParticipator ep, double delta, String toDoThis, String forDoingThis) { - if (!shouldBeUsed()) { - return false; - } + public static boolean modifyMoney(EconomyParticipator ep, double delta, String toDoThis, String forDoingThis) { + if (!shouldBeUsed()) { + return false; + } - OfflinePlayer acc; + OfflinePlayer acc; - if (isUUID(ep.getAccountId())) { - acc = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); - if (acc.getName() == null) { - return false; - } - } else { - acc = Bukkit.getOfflinePlayer(ep.getAccountId()); - } + if (isUUID(ep.getAccountId())) { + acc = Bukkit.getOfflinePlayer(UUID.fromString(ep.getAccountId())); + if (acc.getName() == null) { + return false; + } + } else { + acc = Bukkit.getOfflinePlayer(ep.getAccountId()); + } - String You = ep.describeTo(ep, true); + String You = ep.describeTo(ep, true); - if (delta == 0) { - // no money actually transferred? + if (delta == 0) { + // no money actually transferred? // ep.msg("%s didn't have to pay anything %s.", You, forDoingThis); // might be for gains, might be for losses - return true; - } + return true; + } - if (delta > 0) { - // The player should gain money - // The account might not have enough space - EconomyResponse er = econ.depositPlayer(acc, delta); - if (er.transactionSuccess()) { - modifyUniverseMoney(-delta); - if (forDoingThis != null && !forDoingThis.isEmpty()) { - ep.msg("%s gained %s %s.", You, moneyString(delta), forDoingThis); - } - return true; - } else { - // transfer to account failed - if (forDoingThis != null && !forDoingThis.isEmpty()) { - ep.msg("%s would have gained %s %s, but the deposit failed.", You, moneyString(delta), forDoingThis); - } - return false; - } - } else { - // The player should loose money - // The player might not have enough. + if (delta > 0) { + // The player should gain money + // The account might not have enough space + EconomyResponse er = econ.depositPlayer(acc, delta); + if (er.transactionSuccess()) { + modifyUniverseMoney(-delta); + if (forDoingThis != null && !forDoingThis.isEmpty()) { + ep.msg("%s gained %s %s.", You, moneyString(delta), forDoingThis); + } + return true; + } else { + // transfer to account failed + if (forDoingThis != null && !forDoingThis.isEmpty()) { + ep.msg("%s would have gained %s %s, but the deposit failed.", You, moneyString(delta), forDoingThis); + } + return false; + } + } else { + // The player should loose money + // The player might not have enough. - if (econ.has(acc, -delta) && econ.withdrawPlayer(acc, -delta).transactionSuccess()) { - // There is enough money to pay - modifyUniverseMoney(-delta); - if (forDoingThis != null && !forDoingThis.isEmpty()) { - ep.msg("%s lost %s %s.", You, moneyString(-delta), forDoingThis); - } - return true; - } else { - // There was not enough money to pay - if (toDoThis != null && !toDoThis.isEmpty()) { - ep.msg("%s can't afford %s %s.", You, moneyString(-delta), toDoThis); - } - return false; - } - } - } + if (econ.has(acc, -delta) && econ.withdrawPlayer(acc, -delta).transactionSuccess()) { + // There is enough money to pay + modifyUniverseMoney(-delta); + if (forDoingThis != null && !forDoingThis.isEmpty()) { + ep.msg("%s lost %s %s.", You, moneyString(-delta), forDoingThis); + } + return true; + } else { + // There was not enough money to pay + if (toDoThis != null && !toDoThis.isEmpty()) { + ep.msg("%s can't afford %s %s.", You, moneyString(-delta), toDoThis); + } + return false; + } + } + } - public static String moneyString(double amount) { - return format.format(amount); - } + public static String moneyString(double amount) { + return format.format(amount); + } - // calculate the cost for claiming land - public static double calculateClaimCost(int ownedLand, boolean takingFromAnotherFaction) { - if (!shouldBeUsed()) { - return 0d; - } + // calculate the cost for claiming land + public static double calculateClaimCost(int ownedLand, boolean takingFromAnotherFaction) { + if (!shouldBeUsed()) { + return 0d; + } - // basic claim cost, plus land inflation cost, minus the potential bonus given for claiming from another faction - return Conf.econCostClaimWilderness + (Conf.econCostClaimWilderness * Conf.econClaimAdditionalMultiplier * ownedLand) - (takingFromAnotherFaction ? Conf.econCostClaimFromFactionBonus : 0); - } + // basic claim cost, plus land inflation cost, minus the potential bonus given for claiming from another faction + return Conf.econCostClaimWilderness + (Conf.econCostClaimWilderness * Conf.econClaimAdditionalMultiplier * ownedLand) - (takingFromAnotherFaction ? Conf.econCostClaimFromFactionBonus : 0); + } - // calculate refund amount for unclaiming land - public static double calculateClaimRefund(int ownedLand) { - return calculateClaimCost(ownedLand - 1, false) * Conf.econClaimRefundMultiplier; - } + // calculate refund amount for unclaiming land + public static double calculateClaimRefund(int ownedLand) { + return calculateClaimCost(ownedLand - 1, false) * Conf.econClaimRefundMultiplier; + } - // calculate value of all owned land - public static double calculateTotalLandValue(int ownedLand) { - double amount = 0; - for (int x = 0; x < ownedLand; x++) { - amount += calculateClaimCost(x, false); - } - return amount; - } + // calculate value of all owned land + public static double calculateTotalLandValue(int ownedLand) { + double amount = 0; + for (int x = 0; x < ownedLand; x++) { + amount += calculateClaimCost(x, false); + } + return amount; + } - // -------------------------------------------- // - // Standard account management methods - // -------------------------------------------- // + // -------------------------------------------- // + // Standard account management methods + // -------------------------------------------- // - // calculate refund amount for all owned land - public static double calculateTotalLandRefund(int ownedLand) { - return calculateTotalLandValue(ownedLand) * Conf.econClaimRefundMultiplier; - } + // calculate refund amount for all owned land + public static double calculateTotalLandRefund(int ownedLand) { + return calculateTotalLandValue(ownedLand) * Conf.econClaimRefundMultiplier; + } - public static boolean hasAccount(String name) { - return econ.hasAccount(name); - } + public static boolean hasAccount(String name) { + return econ.hasAccount(name); + } - public static double getBalance(String account) { - return econ.getBalance(account); - } + public static double getBalance(String account) { + return econ.getBalance(account); + } - public static String getFriendlyBalance(UUID uuid) { - OfflinePlayer offline = Bukkit.getOfflinePlayer(uuid); - if (offline.getName() == null) { - return "0"; - } - return format.format(econ.getBalance(offline)); - } + public static String getFriendlyBalance(UUID uuid) { + OfflinePlayer offline = Bukkit.getOfflinePlayer(uuid); + if (offline.getName() == null) { + return "0"; + } + return format.format(econ.getBalance(offline)); + } - public static String getFriendlyBalance(FPlayer player) { - return getFriendlyBalance(UUID.fromString(player.getId())); - } + public static String getFriendlyBalance(FPlayer player) { + return getFriendlyBalance(UUID.fromString(player.getId())); + } - public static boolean setBalance(String account, double amount) { - double current = econ.getBalance(account); - if (current > amount) { - return econ.withdrawPlayer(account, current - amount).transactionSuccess(); - } else { - return econ.depositPlayer(account, amount - current).transactionSuccess(); - } - } + public static boolean setBalance(String account, double amount) { + double current = econ.getBalance(account); + if (current > amount) { + return econ.withdrawPlayer(account, current - amount).transactionSuccess(); + } else { + return econ.depositPlayer(account, amount - current).transactionSuccess(); + } + } - public static boolean modifyBalance(String account, double amount) { - if (amount < 0) { - return econ.withdrawPlayer(account, -amount).transactionSuccess(); - } else { - return econ.depositPlayer(account, amount).transactionSuccess(); - } - } + public static boolean modifyBalance(String account, double amount) { + if (amount < 0) { + return econ.withdrawPlayer(account, -amount).transactionSuccess(); + } else { + return econ.depositPlayer(account, amount).transactionSuccess(); + } + } - public static boolean deposit(String account, double amount) { - return econ.depositPlayer(account, amount).transactionSuccess(); - } + public static boolean deposit(String account, double amount) { + return econ.depositPlayer(account, amount).transactionSuccess(); + } - public static boolean withdraw(String account, double amount) { - return econ.withdrawPlayer(account, amount).transactionSuccess(); - } + public static boolean withdraw(String account, double amount) { + return econ.withdrawPlayer(account, amount).transactionSuccess(); + } - // --------------------------------------- - // Helpful Utilities - // --------------------------------------- + // --------------------------------------- + // Helpful Utilities + // --------------------------------------- - public static boolean isUUID(String uuid) { - try { - UUID.fromString(uuid); - } catch (IllegalArgumentException ex) { - return false; - } + public static boolean isUUID(String uuid) { + try { + UUID.fromString(uuid); + } catch (IllegalArgumentException ex) { + return false; + } - return true; - } + return true; + } } diff --git a/src/main/java/com/massivecraft/factions/integration/Essentials.java b/src/main/java/com/massivecraft/factions/integration/Essentials.java index 8b0f8222..5025515b 100644 --- a/src/main/java/com/massivecraft/factions/integration/Essentials.java +++ b/src/main/java/com/massivecraft/factions/integration/Essentials.java @@ -15,32 +15,32 @@ import java.math.BigDecimal; public class Essentials { - private static IEssentials essentials; + private static IEssentials essentials; - public static void setup() { - Plugin ess = Bukkit.getPluginManager().getPlugin("Essentials"); - if (ess != null) { - essentials = (IEssentials) ess; - } - } + public static void setup() { + Plugin ess = Bukkit.getPluginManager().getPlugin("Essentials"); + if (ess != null) { + essentials = (IEssentials) ess; + } + } - // return false if feature is disabled or Essentials isn't available - public static boolean handleTeleport(Player player, Location loc) { - if (!Conf.homesTeleportCommandEssentialsIntegration || essentials == null) { - return false; - } + // return false if feature is disabled or Essentials isn't available + public static boolean handleTeleport(Player player, Location loc) { + if (!Conf.homesTeleportCommandEssentialsIntegration || essentials == null) { + return false; + } - Teleport teleport = essentials.getUser(player).getTeleport(); - Trade trade = new Trade(new BigDecimal(Conf.econCostHome), essentials); - try { - teleport.teleport(loc, trade, TeleportCause.PLUGIN); - } catch (Exception e) { - player.sendMessage(ChatColor.RED.toString() + e.getMessage()); - } - return true; - } + Teleport teleport = essentials.getUser(player).getTeleport(); + Trade trade = new Trade(new BigDecimal(Conf.econCostHome), essentials); + try { + teleport.teleport(loc, trade, TeleportCause.PLUGIN); + } catch (Exception e) { + player.sendMessage(ChatColor.RED.toString() + e.getMessage()); + } + return true; + } - public static boolean isVanished(Player player) { - return essentials != null && essentials.getUser(player).isVanished(); - } + public static boolean isVanished(Player player) { + return essentials != null && essentials.getUser(player).isVanished(); + } } diff --git a/src/main/java/com/massivecraft/factions/integration/Worldguard.java b/src/main/java/com/massivecraft/factions/integration/Worldguard.java index 0e429077..bc80b247 100644 --- a/src/main/java/com/massivecraft/factions/integration/Worldguard.java +++ b/src/main/java/com/massivecraft/factions/integration/Worldguard.java @@ -30,110 +30,110 @@ import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; public class Worldguard { - private static WorldGuardPlugin wg; - private static boolean enabled = false; + private static WorldGuardPlugin wg; + private static boolean enabled = false; - public static void init(Plugin plugin) { - Plugin wgplug = plugin.getServer().getPluginManager().getPlugin("WorldGuard"); - if (wgplug == null || !(wgplug instanceof WorldGuardPlugin)) { - enabled = false; - wg = null; - SavageFactions.plugin.log("Could not hook to WorldGuard. WorldGuard checks are disabled."); - } else { - wg = (WorldGuardPlugin) wgplug; - enabled = true; - SavageFactions.plugin.log("Successfully hooked to WorldGuard."); - } - } + public static void init(Plugin plugin) { + Plugin wgplug = plugin.getServer().getPluginManager().getPlugin("WorldGuard"); + if (wgplug == null || !(wgplug instanceof WorldGuardPlugin)) { + enabled = false; + wg = null; + SavageFactions.plugin.log("Could not hook to WorldGuard. WorldGuard checks are disabled."); + } else { + wg = (WorldGuardPlugin) wgplug; + enabled = true; + SavageFactions.plugin.log("Successfully hooked to WorldGuard."); + } + } - public static boolean isEnabled() { - return enabled; - } + public static boolean isEnabled() { + return enabled; + } - // PVP Flag check - // Returns: - // True: PVP is allowed - // False: PVP is disallowed - @SuppressWarnings("deprecation") - public static boolean isPVP(Player player) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return true; - } + // PVP Flag check + // Returns: + // True: PVP is allowed + // False: PVP is disallowed + @SuppressWarnings("deprecation") + public static boolean isPVP(Player player) { + if (!enabled) { + // No WG hooks so we'll always bypass this check. + return true; + } - Location loc = player.getLocation(); - World world = loc.getWorld(); - Vector pt = toVector(loc); + Location loc = player.getLocation(); + World world = loc.getWorld(); + Vector pt = toVector(loc); - RegionManager regionManager = wg.getRegionManager(world); - ApplicableRegionSet set = regionManager.getApplicableRegions(pt); - return set.allows(DefaultFlag.PVP); - } + RegionManager regionManager = wg.getRegionManager(world); + ApplicableRegionSet set = regionManager.getApplicableRegions(pt); + return set.allows(DefaultFlag.PVP); + } - // Check if player can build at location by worldguards rules. - // Returns: - // True: Player can build in the region. - // False: Player can not build in the region. - public static boolean playerCanBuild(Player player, Location loc) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return false; - } + // Check if player can build at location by worldguards rules. + // Returns: + // True: Player can build in the region. + // False: Player can not build in the region. + public static boolean playerCanBuild(Player player, Location loc) { + if (!enabled) { + // No WG hooks so we'll always bypass this check. + return false; + } - World world = loc.getWorld(); - Vector pt = toVector(loc); + World world = loc.getWorld(); + Vector pt = toVector(loc); - return wg.getRegionManager(world).getApplicableRegions(pt).size() > 0 && wg.canBuild(player, loc); - } + return wg.getRegionManager(world).getApplicableRegions(pt).size() > 0 && wg.canBuild(player, loc); + } - // Check for Regions in chunk the chunk - // Returns: - // True: Regions found within chunk - // False: No regions found within chunk + // Check for Regions in chunk the chunk + // Returns: + // True: Regions found within chunk + // False: No regions found within chunk - public static boolean checkForRegionsInChunk(FLocation floc) { - Chunk chunk = floc.getWorld().getChunkAt((int) floc.getX(), (int) floc.getZ()); + public static boolean checkForRegionsInChunk(FLocation floc) { + Chunk chunk = floc.getWorld().getChunkAt((int) floc.getX(), (int) floc.getZ()); - return checkForRegionsInChunk(chunk); - } + return checkForRegionsInChunk(chunk); + } - public static boolean checkForRegionsInChunk(Location loc) { - Chunk chunk = loc.getWorld().getChunkAt(loc); + public static boolean checkForRegionsInChunk(Location loc) { + Chunk chunk = loc.getWorld().getChunkAt(loc); - return checkForRegionsInChunk(chunk); - } + return checkForRegionsInChunk(chunk); + } - public static boolean checkForRegionsInChunk(Chunk chunk) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return false; - } + public static boolean checkForRegionsInChunk(Chunk chunk) { + if (!enabled) { + // No WG hooks so we'll always bypass this check. + return false; + } - World world = chunk.getWorld(); - int minChunkX = chunk.getX() << 4; - int minChunkZ = chunk.getZ() << 4; - int maxChunkX = minChunkX + 15; - int maxChunkZ = minChunkZ + 15; + World world = chunk.getWorld(); + int minChunkX = chunk.getX() << 4; + int minChunkZ = chunk.getZ() << 4; + int maxChunkX = minChunkX + 15; + int maxChunkZ = minChunkZ + 15; - int worldHeight = world.getMaxHeight(); // Allow for heights other than default + int worldHeight = world.getMaxHeight(); // Allow for heights other than default - BlockVector minChunk = new BlockVector(minChunkX, 0, minChunkZ); - BlockVector maxChunk = new BlockVector(maxChunkX, worldHeight, maxChunkZ); + BlockVector minChunk = new BlockVector(minChunkX, 0, minChunkZ); + BlockVector maxChunk = new BlockVector(maxChunkX, worldHeight, maxChunkZ); - RegionManager regionManager = wg.getRegionManager(world); - ProtectedCuboidRegion region = new ProtectedCuboidRegion("wgfactionoverlapcheck", minChunk, maxChunk); - Map allregions = regionManager.getRegions(); - Collection allregionslist = new ArrayList<>(allregions.values()); - List overlaps; - boolean foundregions = false; + RegionManager regionManager = wg.getRegionManager(world); + ProtectedCuboidRegion region = new ProtectedCuboidRegion("wgfactionoverlapcheck", minChunk, maxChunk); + Map allregions = regionManager.getRegions(); + Collection allregionslist = new ArrayList<>(allregions.values()); + List overlaps; + boolean foundregions = false; - try { - overlaps = region.getIntersectingRegions(allregionslist); - foundregions = overlaps != null && !overlaps.isEmpty(); - } catch (Exception e) { - e.printStackTrace(); - } + try { + overlaps = region.getIntersectingRegions(allregionslist); + foundregions = overlaps != null && !overlaps.isEmpty(); + } catch (Exception e) { + e.printStackTrace(); + } - return foundregions; - } + return foundregions; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java b/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java index 7fb28c15..239b04e8 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/DynmapStyle.java @@ -3,105 +3,105 @@ package com.massivecraft.factions.integration.dynmap; import com.massivecraft.factions.Conf; public class DynmapStyle { - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public String lineColor = null; - public Double lineOpacity = null; - public Integer lineWeight = null; - public String fillColor = null; - public Double fillOpacity = null; - // NOTE: We just return the string here. We do not return the resolved Dynmap MarkerIcon object. - // The reason is we use this class in the MConf. For serialization to work Dynmap would have to be loaded and we can't require that. - // Using dynmap is optional. - public String homeMarker = null; - public Boolean boost = null; + public String lineColor = null; + public Double lineOpacity = null; + public Integer lineWeight = null; + public String fillColor = null; + public Double fillOpacity = null; + // NOTE: We just return the string here. We do not return the resolved Dynmap MarkerIcon object. + // The reason is we use this class in the MConf. For serialization to work Dynmap would have to be loaded and we can't require that. + // Using dynmap is optional. + public String homeMarker = null; + public Boolean boost = null; - @SafeVarargs - public static T coalesce(T... items) { - for (T item : items) { - if (item != null) { - return item; - } - } - return null; - } + @SafeVarargs + public static T coalesce(T... items) { + for (T item : items) { + if (item != null) { + return item; + } + } + return null; + } - public static int getColor(String string) { - int ret = 0x00FF00; - try { - ret = Integer.parseInt(string.substring(1), 16); - } catch (NumberFormatException ignored) { - } - return ret; - } + public static int getColor(String string) { + int ret = 0x00FF00; + try { + ret = Integer.parseInt(string.substring(1), 16); + } catch (NumberFormatException ignored) { + } + return ret; + } - public int getLineColor() { - return getColor(coalesce(this.lineColor, Conf.dynmapDefaultStyle.lineColor, Conf.DYNMAP_STYLE_LINE_COLOR)); - } + public int getLineColor() { + return getColor(coalesce(this.lineColor, Conf.dynmapDefaultStyle.lineColor, Conf.DYNMAP_STYLE_LINE_COLOR)); + } - public DynmapStyle setStrokeColor(String strokeColor) { - this.lineColor = strokeColor; - return this; - } + public DynmapStyle setStrokeColor(String strokeColor) { + this.lineColor = strokeColor; + return this; + } - public double getLineOpacity() { - return coalesce(this.lineOpacity, Conf.dynmapDefaultStyle.lineOpacity, Conf.DYNMAP_STYLE_LINE_OPACITY); - } + public double getLineOpacity() { + return coalesce(this.lineOpacity, Conf.dynmapDefaultStyle.lineOpacity, Conf.DYNMAP_STYLE_LINE_OPACITY); + } - public DynmapStyle setLineOpacity(Double strokeOpacity) { - this.lineOpacity = strokeOpacity; - return this; - } + public DynmapStyle setLineOpacity(Double strokeOpacity) { + this.lineOpacity = strokeOpacity; + return this; + } - public int getLineWeight() { - return coalesce(this.lineWeight, Conf.dynmapDefaultStyle.lineWeight, Conf.DYNMAP_STYLE_LINE_WEIGHT); - } + public int getLineWeight() { + return coalesce(this.lineWeight, Conf.dynmapDefaultStyle.lineWeight, Conf.DYNMAP_STYLE_LINE_WEIGHT); + } - public DynmapStyle setLineWeight(Integer strokeWeight) { - this.lineWeight = strokeWeight; - return this; - } + public DynmapStyle setLineWeight(Integer strokeWeight) { + this.lineWeight = strokeWeight; + return this; + } - public int getFillColor() { - return getColor(coalesce(this.fillColor, Conf.dynmapDefaultStyle.fillColor, Conf.DYNMAP_STYLE_FILL_COLOR)); - } + public int getFillColor() { + return getColor(coalesce(this.fillColor, Conf.dynmapDefaultStyle.fillColor, Conf.DYNMAP_STYLE_FILL_COLOR)); + } - public DynmapStyle setFillColor(String fillColor) { - this.fillColor = fillColor; - return this; - } + public DynmapStyle setFillColor(String fillColor) { + this.fillColor = fillColor; + return this; + } - public double getFillOpacity() { - return coalesce(this.fillOpacity, Conf.dynmapDefaultStyle.fillOpacity, Conf.DYNMAP_STYLE_FILL_OPACITY); - } + public double getFillOpacity() { + return coalesce(this.fillOpacity, Conf.dynmapDefaultStyle.fillOpacity, Conf.DYNMAP_STYLE_FILL_OPACITY); + } - public DynmapStyle setFillOpacity(Double fillOpacity) { - this.fillOpacity = fillOpacity; - return this; - } + public DynmapStyle setFillOpacity(Double fillOpacity) { + this.fillOpacity = fillOpacity; + return this; + } - public String getHomeMarker() { - return coalesce(this.homeMarker, Conf.dynmapDefaultStyle.homeMarker, Conf.DYNMAP_STYLE_HOME_MARKER); - } + public String getHomeMarker() { + return coalesce(this.homeMarker, Conf.dynmapDefaultStyle.homeMarker, Conf.DYNMAP_STYLE_HOME_MARKER); + } - public DynmapStyle setHomeMarker(String homeMarker) { - this.homeMarker = homeMarker; - return this; - } + public DynmapStyle setHomeMarker(String homeMarker) { + this.homeMarker = homeMarker; + return this; + } - // -------------------------------------------- // - // UTIL - // -------------------------------------------- // + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // - public boolean getBoost() { - return coalesce(this.boost, Conf.dynmapDefaultStyle.boost, Conf.DYNMAP_STYLE_BOOST); - } + public boolean getBoost() { + return coalesce(this.boost, Conf.dynmapDefaultStyle.boost, Conf.DYNMAP_STYLE_BOOST); + } - public DynmapStyle setBoost(Boolean boost) { - this.boost = boost; - return this; - } + public DynmapStyle setBoost(Boolean boost) { + this.boost = boost; + return this; + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java b/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java index 6aad4390..0f15ff22 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/EngineDynmap.java @@ -17,750 +17,750 @@ import java.util.Map.Entry; // This source code is a heavily modified version of mikeprimms plugin Dynmap-Factions. public class EngineDynmap { - // -------------------------------------------- // - // CONSTANTS - // -------------------------------------------- // - - public final static int BLOCKS_PER_CHUNK = 16; - - public final static String DYNMAP_INTEGRATION = "\u00A7dDynmap Integration: \u00A7e"; - - public final static String FACTIONS = "factions"; - public final static String FACTIONS_ = FACTIONS + "_"; - - public final static String FACTIONS_MARKERSET = FACTIONS_ + "markerset"; - - public final static String FACTIONS_HOME = FACTIONS_ + "home"; - public final static String FACTIONS_HOME_ = FACTIONS_HOME + "_"; - - public final static String FACTIONS_PLAYERSET = FACTIONS_ + "playerset"; - public final static String FACTIONS_PLAYERSET_ = FACTIONS_PLAYERSET + "_"; - - // -------------------------------------------- // - // INSTANCE & CONSTRUCT - // -------------------------------------------- // - - private static final EngineDynmap i = new EngineDynmap(); - public DynmapAPI dynmapApi; - public MarkerAPI markerApi; - public MarkerSet markerset; - - private EngineDynmap() { - } - - public static EngineDynmap getInstance() { - return i; - } - - public static String getHtmlPlayerString(Collection playersOfficersList) { - StringBuilder ret = new StringBuilder(); - for (FPlayer fplayer : playersOfficersList) { - if (ret.length() > 0) { - ret.append(", "); - } - ret.append(getHtmlPlayerName(fplayer)); - } - return ret.toString(); - } - - public static String getHtmlPlayerName(FPlayer fplayer) { - return fplayer != null ? escapeHtml(fplayer.getName()) : "none"; - } - - public static String escapeHtml(String string) { - StringBuilder out = new StringBuilder(Math.max(16, string.length())); - for (int i = 0; i < string.length(); i++) { - char c = string.charAt(i); - if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { - out.append("&#") - .append((int) c) - .append(';'); - } else { - out.append(c); - } - } - return out.toString(); - } - - // Thread Safe / Asynchronous: Yes - public static void info(String msg) { - System.out.println(DYNMAP_INTEGRATION + msg); - } - - // -------------------------------------------- // - // UPDATE: HOMES - // -------------------------------------------- // - - // Thread Safe / Asynchronous: Yes - public static void severe(String msg) { - System.out.println(DYNMAP_INTEGRATION + ChatColor.RED.toString() + msg); - } - - public void init() { - Plugin dynmap = Bukkit.getServer().getPluginManager().getPlugin("dynmap"); - - if (dynmap == null || !dynmap.isEnabled()) { - return; - } - - // Should we even use dynmap? - if (!Conf.dynmapUse) { - if (this.markerset != null) { - this.markerset.deleteMarkerSet(); - this.markerset = null; - } - return; - } - - // Shedule non thread safe sync at the end! - Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - - final Map homes = createHomes(); - final Map areas = createAreas(); - final Map> playerSets = createPlayersets(); - - if (!updateCore()) { - return; - } - - // createLayer() is thread safe but it makes use of fields set in updateCore() so we must have it after. - if (!updateLayer(createLayer())) { - return; - } - - updateHomes(homes); - updateAreas(areas); - updatePlayersets(playerSets); - } - }, 100L, 100L); - } - - // -------------------------------------------- // - // UPDATE: AREAS - // -------------------------------------------- // - - // Thread Safe / Asynchronous: No - public boolean updateCore() { - // Get DynmapAPI - this.dynmapApi = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap"); - if (this.dynmapApi == null) { - severe("Could not retrieve the DynmapAPI."); - return false; - } - - // Get MarkerAPI - this.markerApi = this.dynmapApi.getMarkerAPI(); - if (this.markerApi == null) { - severe("Could not retrieve the MarkerAPI."); - return false; - } - - return true; - } - - // Thread Safe / Asynchronous: Yes - public TempMarkerSet createLayer() { - TempMarkerSet ret = new TempMarkerSet(); - ret.label = Conf.dynmapLayerName; - ret.minimumZoom = Conf.dynmapLayerMinimumZoom; - ret.priority = Conf.dynmapLayerPriority; - ret.hideByDefault = !Conf.dynmapLayerVisible; - return ret; - } - - // Thread Safe / Asynchronous: No - public boolean updateLayer(TempMarkerSet temp) { - this.markerset = this.markerApi.getMarkerSet(FACTIONS_MARKERSET); - if (this.markerset == null) { - this.markerset = temp.create(this.markerApi, FACTIONS_MARKERSET); - if (this.markerset == null) { - severe("Could not create the Faction Markerset/Layer"); - return false; - } - } else { - temp.update(this.markerset); - } - return true; - } - - // Thread Safe / Asynchronous: Yes - public Map createHomes() { - Map ret = new HashMap<>(); - - // Loop current factions - for (Faction faction : Factions.getInstance().getAllFactions()) { - Location ps = faction.getHome(); - if (ps == null) { - continue; - } - - DynmapStyle style = getStyle(faction); - - String markerId = FACTIONS_HOME_ + faction.getId(); - - TempMarker temp = new TempMarker(); - temp.label = ChatColor.stripColor(faction.getTag()); - temp.world = ps.getWorld().toString(); - temp.x = ps.getX(); - temp.y = ps.getY(); - temp.z = ps.getZ(); - temp.iconName = style.getHomeMarker(); - temp.description = getDescription(faction); - - ret.put(markerId, temp); - } - - return ret; - } - - // Thread Safe / Asynchronous: No - // This method places out the faction home markers into the factions markerset. - public void updateHomes(Map homes) { - // Put all current faction markers in a map - Map markers = new HashMap<>(); - for (Marker marker : this.markerset.getMarkers()) { - markers.put(marker.getMarkerID(), marker); - } - - // Loop homes - for (Entry entry : homes.entrySet()) { - String markerId = entry.getKey(); - TempMarker temp = entry.getValue(); - - // Get Creative - // NOTE: I remove from the map created just in the beginning of this method. - // NOTE: That way what is left at the end will be outdated markers to remove. - Marker marker = markers.remove(markerId); - if (marker == null) { - marker = temp.create(this.markerApi, this.markerset, markerId); - if (marker == null) { - EngineDynmap.severe("Could not get/create the home marker " + markerId); - } - } else { - temp.update(this.markerApi, marker); - } - } - - // Delete Deprecated Markers - // Only old markers should now be left - for (Marker marker : markers.values()) { - marker.deleteMarker(); - } - } - - // -------------------------------------------- // - // UPDATE: PLAYERSET - // -------------------------------------------- // - - // Thread Safe: YES - public Map createAreas() { - Map>> worldFactionChunks = createWorldFactionChunks(); - return createAreas(worldFactionChunks); - } - - // Thread Safe: YES - public Map>> createWorldFactionChunks() { - // Create map "world name --> faction --> set of chunk coords" - Map>> worldFactionChunks = new HashMap<>(); - - // Note: The board is the world. The board id is the world name. - MemoryBoard board = (MemoryBoard) Board.getInstance(); - - for (Entry entry : board.flocationIds.entrySet()) { - String world = entry.getKey().getWorldName(); - Faction chunkOwner = Factions.getInstance().getFactionById(entry.getValue()); - - Map> factionChunks = worldFactionChunks.get(world); - if (factionChunks == null) { - factionChunks = new HashMap<>(); - worldFactionChunks.put(world, factionChunks); - } - - Set factionTerritory = factionChunks.get(chunkOwner); - if (factionTerritory == null) { - factionTerritory = new HashSet<>(); - factionChunks.put(chunkOwner, factionTerritory); - } - - factionTerritory.add(entry.getKey()); - } - - return worldFactionChunks; - } - - // Thread Safe: YES - public Map createAreas(Map>> worldFactionChunks) { - Map ret = new HashMap<>(); - - // For each world - for (Entry>> entry : worldFactionChunks.entrySet()) { - String world = entry.getKey(); - Map> factionChunks = entry.getValue(); - - // For each faction and its chunks in that world - for (Entry> entry1 : factionChunks.entrySet()) { - Faction faction = entry1.getKey(); - Set chunks = entry1.getValue(); - Map worldFactionMarkers = createAreas(world, faction, chunks); - ret.putAll(worldFactionMarkers); - } - } - - return ret; - } - - // Thread Safe: YES - // Handle specific faction on specific world - // "handle faction on world" - public Map createAreas(String world, Faction faction, Set chunks) { - Map ret = new HashMap<>(); - - // If the faction is visible ... - if (!isVisible(faction, world)) { - return ret; - } - - // ... and has any chunks ... - if (chunks.isEmpty()) { - return ret; - } - - // Index of polygon for given faction - int markerIndex = 0; - - // Create the info window - String description = getDescription(faction); - - // Fetch Style - DynmapStyle style = this.getStyle(faction); - - // Loop through chunks: set flags on chunk map - TileFlags allChunkFlags = new TileFlags(); - LinkedList allChunks = new LinkedList<>(); - for (FLocation chunk : chunks) { - allChunkFlags.setFlag((int) chunk.getX(), (int) chunk.getZ(), true); // Set flag for chunk - allChunks.addLast(chunk); - } - - // Loop through until we don't find more areas - while (allChunks != null) { - TileFlags ourChunkFlags = null; - LinkedList ourChunks = null; - LinkedList newChunks = null; - - int minimumX = Integer.MAX_VALUE; - int minimumZ = Integer.MAX_VALUE; - for (FLocation chunk : allChunks) { - int chunkX = (int) chunk.getX(); - int chunkZ = (int) chunk.getZ(); - - // If we need to start shape, and this block is not part of one yet - if (ourChunkFlags == null && allChunkFlags.getFlag(chunkX, chunkZ)) { - ourChunkFlags = new TileFlags(); // Create map for shape - ourChunks = new LinkedList<>(); - floodFillTarget(allChunkFlags, ourChunkFlags, chunkX, chunkZ); // Copy shape - ourChunks.add(chunk); // Add it to our chunk list - minimumX = chunkX; - minimumZ = chunkZ; - } - // If shape found, and we're in it, add to our node list - else if (ourChunkFlags != null && ourChunkFlags.getFlag(chunkX, chunkZ)) { - ourChunks.add(chunk); - if (chunkX < minimumX) { - minimumX = chunkX; - minimumZ = chunkZ; - } else if (chunkX == minimumX && chunkZ < minimumZ) { - minimumZ = chunkZ; - } - } - // Else, keep it in the list for the next polygon - else { - if (newChunks == null) { - newChunks = new LinkedList<>(); - } - newChunks.add(chunk); - } - } - - // Replace list (null if no more to process) - allChunks = newChunks; - - if (ourChunkFlags == null) { - continue; - } - - // Trace outline of blocks - start from minx, minz going to x+ - int initialX = minimumX; - int initialZ = minimumZ; - int currentX = minimumX; - int currentZ = minimumZ; - Direction direction = Direction.XPLUS; - ArrayList linelist = new ArrayList<>(); - linelist.add(new int[]{initialX, initialZ}); // Add start point - while ((currentX != initialX) || (currentZ != initialZ) || (direction != Direction.ZMINUS)) { - switch (direction) { - case XPLUS: // Segment in X+ direction - if (!ourChunkFlags.getFlag(currentX + 1, currentZ)) { // Right turn? - linelist.add(new int[]{currentX + 1, currentZ}); // Finish line - direction = Direction.ZPLUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ - 1)) { // Straight? - currentX++; - } else { // Left turn - linelist.add(new int[]{currentX + 1, currentZ}); // Finish line - direction = Direction.ZMINUS; - currentX++; - currentZ--; - } - break; - case ZPLUS: // Segment in Z+ direction - if (!ourChunkFlags.getFlag(currentX, currentZ + 1)) { // Right turn? - linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line - direction = Direction.XMINUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ + 1)) { // Straight? - currentZ++; - } else { // Left turn - linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line - direction = Direction.XPLUS; - currentX++; - currentZ++; - } - break; - case XMINUS: // Segment in X- direction - if (!ourChunkFlags.getFlag(currentX - 1, currentZ)) { // Right turn? - linelist.add(new int[]{currentX, currentZ + 1}); // Finish line - direction = Direction.ZMINUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ + 1)) { // Straight? - currentX--; - } else { // Left turn - linelist.add(new int[]{currentX, currentZ + 1}); // Finish line - direction = Direction.ZPLUS; - currentX--; - currentZ++; - } - break; - case ZMINUS: // Segment in Z- direction - if (!ourChunkFlags.getFlag(currentX, currentZ - 1)) { // Right turn? - linelist.add(new int[]{currentX, currentZ}); // Finish line - direction = Direction.XPLUS; // Change direction - } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ - 1)) { // Straight? - currentZ--; - } else { // Left turn - linelist.add(new int[]{currentX, currentZ}); // Finish line - direction = Direction.XMINUS; - currentX--; - currentZ--; - } - break; - } - } - - int sz = linelist.size(); - double[] x = new double[sz]; - double[] z = new double[sz]; - for (int i = 0; i < sz; i++) { - int[] line = linelist.get(i); - x[i] = (double) line[0] * (double) BLOCKS_PER_CHUNK; - z[i] = (double) line[1] * (double) BLOCKS_PER_CHUNK; - } - - // Build information for specific area - String markerId = FACTIONS_ + world + "__" + faction.getId() + "__" + markerIndex; - - TempAreaMarker temp = new TempAreaMarker(); - temp.label = faction.getTag(); - temp.world = world; - temp.x = x; - temp.z = z; - temp.description = description; - - temp.lineColor = style.getLineColor(); - temp.lineOpacity = style.getLineOpacity(); - temp.lineWeight = style.getLineWeight(); - - temp.fillColor = style.getFillColor(); - temp.fillOpacity = style.getFillOpacity(); - - temp.boost = style.getBoost(); - - ret.put(markerId, temp); - - markerIndex++; - } - - return ret; - } - - // -------------------------------------------- // - // UTIL & SHARED - // -------------------------------------------- // - - // Thread Safe: NO - public void updateAreas(Map areas) { - // Map Current - Map markers = new HashMap<>(); - for (AreaMarker marker : this.markerset.getAreaMarkers()) { - markers.put(marker.getMarkerID(), marker); - } - - // Loop New - for (Entry entry : areas.entrySet()) { - String markerId = entry.getKey(); - TempAreaMarker temp = entry.getValue(); - - // Get Creative - // NOTE: I remove from the map created just in the beginning of this method. - // NOTE: That way what is left at the end will be outdated markers to remove. - AreaMarker marker = markers.remove(markerId); - if (marker == null) { - marker = temp.create(this.markerset, markerId); - if (marker == null) { - severe("Could not get/create the area marker " + markerId); - } - } else { - temp.update(marker); - } - } - - // Only old/outdated should now be left. Delete them. - for (AreaMarker marker : markers.values()) { - marker.deleteMarker(); - } - } - - // Thread Safe / Asynchronous: Yes - public String createPlayersetId(Faction faction) { - if (faction == null) { - return null; - } - if (faction.isWilderness()) { - return null; - } - String factionId = faction.getId(); - if (factionId == null) { - return null; - } - return FACTIONS_PLAYERSET_ + factionId; - } - - // Thread Safe / Asynchronous: Yes - public Set createPlayerset(Faction faction) { - if (faction == null) { - return null; - } - if (faction.isWilderness()) { - return null; - } - - Set ret = new HashSet<>(); - - for (FPlayer fplayer : faction.getFPlayers()) { - // NOTE: We add both UUID and name. This might be a good idea for future proofing. - ret.add(fplayer.getId()); - ret.add(fplayer.getName()); - } - - return ret; - } - - // Thread Safe / Asynchronous: Yes - public Map> createPlayersets() { - if (!Conf.dynmapVisibilityByFaction) { - return null; - } - - Map> ret = new HashMap<>(); - - for (Faction faction : Factions.getInstance().getAllFactions()) { - String playersetId = createPlayersetId(faction); - if (playersetId == null) { - continue; - } - Set playerIds = createPlayerset(faction); - if (playerIds == null) { - continue; - } - ret.put(playersetId, playerIds); - } - - return ret; - } - - // Thread Safe / Asynchronous: No - public void updatePlayersets(Map> playersets) { - if (playersets == null) { - return; - } - - // Remove - for (PlayerSet set : this.markerApi.getPlayerSets()) { - if (!set.getSetID().startsWith(FACTIONS_PLAYERSET_)) { - continue; - } - - // (Null means remove all) - if (playersets.containsKey(set.getSetID())) { - continue; - } - - set.deleteSet(); - } - - // Add / Update - for (Entry> entry : playersets.entrySet()) { - // Extract from Entry - String setId = entry.getKey(); - Set playerIds = entry.getValue(); - - // Get Creatively - PlayerSet set = this.markerApi.getPlayerSet(setId); - if (set == null) { - set = this.markerApi.createPlayerSet(setId, // id - true, // symmetric - playerIds, // players - false // persistent - ); - } - if (set == null) { - severe("Could not get/create the player set " + setId); - continue; - } - - // Set Content - set.setPlayers(playerIds); - } - } - - // Thread Safe / Asynchronous: Yes - private String getDescription(Faction faction) { - String ret = "
    " + Conf.dynmapDescription + "
    "; - - // Name - String name = faction.getTag(); - name = escapeHtml(ChatColor.stripColor(name)); - ret = ret.replace("%name%", name); - - // Description - String description = faction.getDescription(); - description = escapeHtml(ChatColor.stripColor(description)); - ret = ret.replace("%description%", description); - - // Money - - String money = "unavailable"; - if (Conf.bankEnabled && Conf.dynmapDescriptionMoney) - money = String.format("%.2f", Econ.getBalance(faction.getAccountId())); - ret = ret.replace("%money%", money); - - - // Players - Set playersList = faction.getFPlayers(); - String playersCount = String.valueOf(playersList.size()); - String players = getHtmlPlayerString(playersList); - - FPlayer playersLeaderObject = faction.getFPlayerAdmin(); - String playersLeader = getHtmlPlayerName(playersLeaderObject); - - ArrayList playersCoAdminsList = faction.getFPlayersWhereRole(Role.COLEADER); - String playersCoAdminsCount = String.valueOf(playersCoAdminsList.size()); - String playersCoAdmins = getHtmlPlayerString(playersCoAdminsList); - - ArrayList playersModeratorsList = faction.getFPlayersWhereRole(Role.MODERATOR); - String playersModeratorsCount = String.valueOf(playersModeratorsList.size()); - String playersModerators = getHtmlPlayerString(playersModeratorsList); - - - ArrayList playersNormalsList = faction.getFPlayersWhereRole(Role.NORMAL); - String playersNormalsCount = String.valueOf(playersNormalsList.size()); - String playersNormals = getHtmlPlayerString(playersNormalsList); - - ret = ret.replace("%players%", players); - ret = ret.replace("%players.count%", playersCount); - ret = ret.replace("%players.leader%", playersLeader); - ret = ret.replace("%players.admins%", playersCoAdmins); - ret = ret.replace("%players.admins.count%", playersCoAdminsCount); - ret = ret.replace("%players.moderators%", playersModerators); - ret = ret.replace("%players.moderators.count%", playersModeratorsCount); - ret = ret.replace("%players.normals%", playersNormals); - ret = ret.replace("%players.normals.count%", playersNormalsCount); - - return ret; - } - - // Thread Safe / Asynchronous: Yes - private boolean isVisible(Faction faction, String world) { - if (faction == null) { - return false; - } - final String factionId = faction.getId(); - if (factionId == null) { - return false; - } - final String factionName = faction.getTag(); - if (factionName == null) { - return false; - } - - Set visible = Conf.dynmapVisibleFactions; - Set hidden = Conf.dynmapHiddenFactions; - - if (!visible.isEmpty() && !visible.contains(factionId) && !visible.contains(factionName) && !visible.contains("world:" + world)) { - return false; - } - - return !hidden.contains(factionId) && !hidden.contains(factionName) && !hidden.contains("world:" + world); - } - - // Thread Safe / Asynchronous: Yes - public DynmapStyle getStyle(Faction faction) { - DynmapStyle ret; - - ret = Conf.dynmapFactionStyles.get(faction.getId()); - if (ret != null) { - return ret; - } - - ret = Conf.dynmapFactionStyles.get(faction.getTag()); - if (ret != null) { - return ret; - } - - return Conf.dynmapDefaultStyle; - } - - // Find all contiguous blocks, set in target and clear in source - private int floodFillTarget(TileFlags source, TileFlags destination, int x, int y) { - int cnt = 0; - ArrayDeque stack = new ArrayDeque<>(); - stack.push(new int[]{x, y}); - - while (!stack.isEmpty()) { - int[] nxt = stack.pop(); - x = nxt[0]; - y = nxt[1]; - if (source.getFlag(x, y)) { // Set in src - source.setFlag(x, y, false); // Clear source - destination.setFlag(x, y, true); // Set in destination - cnt++; - if (source.getFlag(x + 1, y)) { - stack.push(new int[]{x + 1, y}); - } - if (source.getFlag(x - 1, y)) { - stack.push(new int[]{x - 1, y}); - } - if (source.getFlag(x, y + 1)) { - stack.push(new int[]{x, y + 1}); - } - if (source.getFlag(x, y - 1)) { - stack.push(new int[]{x, y - 1}); - } - } - } - return cnt; - } - - enum Direction { - XPLUS, ZPLUS, XMINUS, ZMINUS - } + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + public final static int BLOCKS_PER_CHUNK = 16; + + public final static String DYNMAP_INTEGRATION = "\u00A7dDynmap Integration: \u00A7e"; + + public final static String FACTIONS = "factions"; + public final static String FACTIONS_ = FACTIONS + "_"; + + public final static String FACTIONS_MARKERSET = FACTIONS_ + "markerset"; + + public final static String FACTIONS_HOME = FACTIONS_ + "home"; + public final static String FACTIONS_HOME_ = FACTIONS_HOME + "_"; + + public final static String FACTIONS_PLAYERSET = FACTIONS_ + "playerset"; + public final static String FACTIONS_PLAYERSET_ = FACTIONS_PLAYERSET + "_"; + + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static final EngineDynmap i = new EngineDynmap(); + public DynmapAPI dynmapApi; + public MarkerAPI markerApi; + public MarkerSet markerset; + + private EngineDynmap() { + } + + public static EngineDynmap getInstance() { + return i; + } + + public static String getHtmlPlayerString(Collection playersOfficersList) { + StringBuilder ret = new StringBuilder(); + for (FPlayer fplayer : playersOfficersList) { + if (ret.length() > 0) { + ret.append(", "); + } + ret.append(getHtmlPlayerName(fplayer)); + } + return ret.toString(); + } + + public static String getHtmlPlayerName(FPlayer fplayer) { + return fplayer != null ? escapeHtml(fplayer.getName()) : "none"; + } + + public static String escapeHtml(String string) { + StringBuilder out = new StringBuilder(Math.max(16, string.length())); + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { + out.append("&#") + .append((int) c) + .append(';'); + } else { + out.append(c); + } + } + return out.toString(); + } + + // Thread Safe / Asynchronous: Yes + public static void info(String msg) { + System.out.println(DYNMAP_INTEGRATION + msg); + } + + // -------------------------------------------- // + // UPDATE: HOMES + // -------------------------------------------- // + + // Thread Safe / Asynchronous: Yes + public static void severe(String msg) { + System.out.println(DYNMAP_INTEGRATION + ChatColor.RED.toString() + msg); + } + + public void init() { + Plugin dynmap = Bukkit.getServer().getPluginManager().getPlugin("dynmap"); + + if (dynmap == null || !dynmap.isEnabled()) { + return; + } + + // Should we even use dynmap? + if (!Conf.dynmapUse) { + if (this.markerset != null) { + this.markerset.deleteMarkerSet(); + this.markerset = null; + } + return; + } + + // Shedule non thread safe sync at the end! + Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + + final Map homes = createHomes(); + final Map areas = createAreas(); + final Map> playerSets = createPlayersets(); + + if (!updateCore()) { + return; + } + + // createLayer() is thread safe but it makes use of fields set in updateCore() so we must have it after. + if (!updateLayer(createLayer())) { + return; + } + + updateHomes(homes); + updateAreas(areas); + updatePlayersets(playerSets); + } + }, 100L, 100L); + } + + // -------------------------------------------- // + // UPDATE: AREAS + // -------------------------------------------- // + + // Thread Safe / Asynchronous: No + public boolean updateCore() { + // Get DynmapAPI + this.dynmapApi = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap"); + if (this.dynmapApi == null) { + severe("Could not retrieve the DynmapAPI."); + return false; + } + + // Get MarkerAPI + this.markerApi = this.dynmapApi.getMarkerAPI(); + if (this.markerApi == null) { + severe("Could not retrieve the MarkerAPI."); + return false; + } + + return true; + } + + // Thread Safe / Asynchronous: Yes + public TempMarkerSet createLayer() { + TempMarkerSet ret = new TempMarkerSet(); + ret.label = Conf.dynmapLayerName; + ret.minimumZoom = Conf.dynmapLayerMinimumZoom; + ret.priority = Conf.dynmapLayerPriority; + ret.hideByDefault = !Conf.dynmapLayerVisible; + return ret; + } + + // Thread Safe / Asynchronous: No + public boolean updateLayer(TempMarkerSet temp) { + this.markerset = this.markerApi.getMarkerSet(FACTIONS_MARKERSET); + if (this.markerset == null) { + this.markerset = temp.create(this.markerApi, FACTIONS_MARKERSET); + if (this.markerset == null) { + severe("Could not create the Faction Markerset/Layer"); + return false; + } + } else { + temp.update(this.markerset); + } + return true; + } + + // Thread Safe / Asynchronous: Yes + public Map createHomes() { + Map ret = new HashMap<>(); + + // Loop current factions + for (Faction faction : Factions.getInstance().getAllFactions()) { + Location ps = faction.getHome(); + if (ps == null) { + continue; + } + + DynmapStyle style = getStyle(faction); + + String markerId = FACTIONS_HOME_ + faction.getId(); + + TempMarker temp = new TempMarker(); + temp.label = ChatColor.stripColor(faction.getTag()); + temp.world = ps.getWorld().toString(); + temp.x = ps.getX(); + temp.y = ps.getY(); + temp.z = ps.getZ(); + temp.iconName = style.getHomeMarker(); + temp.description = getDescription(faction); + + ret.put(markerId, temp); + } + + return ret; + } + + // Thread Safe / Asynchronous: No + // This method places out the faction home markers into the factions markerset. + public void updateHomes(Map homes) { + // Put all current faction markers in a map + Map markers = new HashMap<>(); + for (Marker marker : this.markerset.getMarkers()) { + markers.put(marker.getMarkerID(), marker); + } + + // Loop homes + for (Entry entry : homes.entrySet()) { + String markerId = entry.getKey(); + TempMarker temp = entry.getValue(); + + // Get Creative + // NOTE: I remove from the map created just in the beginning of this method. + // NOTE: That way what is left at the end will be outdated markers to remove. + Marker marker = markers.remove(markerId); + if (marker == null) { + marker = temp.create(this.markerApi, this.markerset, markerId); + if (marker == null) { + EngineDynmap.severe("Could not get/create the home marker " + markerId); + } + } else { + temp.update(this.markerApi, marker); + } + } + + // Delete Deprecated Markers + // Only old markers should now be left + for (Marker marker : markers.values()) { + marker.deleteMarker(); + } + } + + // -------------------------------------------- // + // UPDATE: PLAYERSET + // -------------------------------------------- // + + // Thread Safe: YES + public Map createAreas() { + Map>> worldFactionChunks = createWorldFactionChunks(); + return createAreas(worldFactionChunks); + } + + // Thread Safe: YES + public Map>> createWorldFactionChunks() { + // Create map "world name --> faction --> set of chunk coords" + Map>> worldFactionChunks = new HashMap<>(); + + // Note: The board is the world. The board id is the world name. + MemoryBoard board = (MemoryBoard) Board.getInstance(); + + for (Entry entry : board.flocationIds.entrySet()) { + String world = entry.getKey().getWorldName(); + Faction chunkOwner = Factions.getInstance().getFactionById(entry.getValue()); + + Map> factionChunks = worldFactionChunks.get(world); + if (factionChunks == null) { + factionChunks = new HashMap<>(); + worldFactionChunks.put(world, factionChunks); + } + + Set factionTerritory = factionChunks.get(chunkOwner); + if (factionTerritory == null) { + factionTerritory = new HashSet<>(); + factionChunks.put(chunkOwner, factionTerritory); + } + + factionTerritory.add(entry.getKey()); + } + + return worldFactionChunks; + } + + // Thread Safe: YES + public Map createAreas(Map>> worldFactionChunks) { + Map ret = new HashMap<>(); + + // For each world + for (Entry>> entry : worldFactionChunks.entrySet()) { + String world = entry.getKey(); + Map> factionChunks = entry.getValue(); + + // For each faction and its chunks in that world + for (Entry> entry1 : factionChunks.entrySet()) { + Faction faction = entry1.getKey(); + Set chunks = entry1.getValue(); + Map worldFactionMarkers = createAreas(world, faction, chunks); + ret.putAll(worldFactionMarkers); + } + } + + return ret; + } + + // Thread Safe: YES + // Handle specific faction on specific world + // "handle faction on world" + public Map createAreas(String world, Faction faction, Set chunks) { + Map ret = new HashMap<>(); + + // If the faction is visible ... + if (!isVisible(faction, world)) { + return ret; + } + + // ... and has any chunks ... + if (chunks.isEmpty()) { + return ret; + } + + // Index of polygon for given faction + int markerIndex = 0; + + // Create the info window + String description = getDescription(faction); + + // Fetch Style + DynmapStyle style = this.getStyle(faction); + + // Loop through chunks: set flags on chunk map + TileFlags allChunkFlags = new TileFlags(); + LinkedList allChunks = new LinkedList<>(); + for (FLocation chunk : chunks) { + allChunkFlags.setFlag((int) chunk.getX(), (int) chunk.getZ(), true); // Set flag for chunk + allChunks.addLast(chunk); + } + + // Loop through until we don't find more areas + while (allChunks != null) { + TileFlags ourChunkFlags = null; + LinkedList ourChunks = null; + LinkedList newChunks = null; + + int minimumX = Integer.MAX_VALUE; + int minimumZ = Integer.MAX_VALUE; + for (FLocation chunk : allChunks) { + int chunkX = (int) chunk.getX(); + int chunkZ = (int) chunk.getZ(); + + // If we need to start shape, and this block is not part of one yet + if (ourChunkFlags == null && allChunkFlags.getFlag(chunkX, chunkZ)) { + ourChunkFlags = new TileFlags(); // Create map for shape + ourChunks = new LinkedList<>(); + floodFillTarget(allChunkFlags, ourChunkFlags, chunkX, chunkZ); // Copy shape + ourChunks.add(chunk); // Add it to our chunk list + minimumX = chunkX; + minimumZ = chunkZ; + } + // If shape found, and we're in it, add to our node list + else if (ourChunkFlags != null && ourChunkFlags.getFlag(chunkX, chunkZ)) { + ourChunks.add(chunk); + if (chunkX < minimumX) { + minimumX = chunkX; + minimumZ = chunkZ; + } else if (chunkX == minimumX && chunkZ < minimumZ) { + minimumZ = chunkZ; + } + } + // Else, keep it in the list for the next polygon + else { + if (newChunks == null) { + newChunks = new LinkedList<>(); + } + newChunks.add(chunk); + } + } + + // Replace list (null if no more to process) + allChunks = newChunks; + + if (ourChunkFlags == null) { + continue; + } + + // Trace outline of blocks - start from minx, minz going to x+ + int initialX = minimumX; + int initialZ = minimumZ; + int currentX = minimumX; + int currentZ = minimumZ; + Direction direction = Direction.XPLUS; + ArrayList linelist = new ArrayList<>(); + linelist.add(new int[]{initialX, initialZ}); // Add start point + while ((currentX != initialX) || (currentZ != initialZ) || (direction != Direction.ZMINUS)) { + switch (direction) { + case XPLUS: // Segment in X+ direction + if (!ourChunkFlags.getFlag(currentX + 1, currentZ)) { // Right turn? + linelist.add(new int[]{currentX + 1, currentZ}); // Finish line + direction = Direction.ZPLUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ - 1)) { // Straight? + currentX++; + } else { // Left turn + linelist.add(new int[]{currentX + 1, currentZ}); // Finish line + direction = Direction.ZMINUS; + currentX++; + currentZ--; + } + break; + case ZPLUS: // Segment in Z+ direction + if (!ourChunkFlags.getFlag(currentX, currentZ + 1)) { // Right turn? + linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line + direction = Direction.XMINUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX + 1, currentZ + 1)) { // Straight? + currentZ++; + } else { // Left turn + linelist.add(new int[]{currentX + 1, currentZ + 1}); // Finish line + direction = Direction.XPLUS; + currentX++; + currentZ++; + } + break; + case XMINUS: // Segment in X- direction + if (!ourChunkFlags.getFlag(currentX - 1, currentZ)) { // Right turn? + linelist.add(new int[]{currentX, currentZ + 1}); // Finish line + direction = Direction.ZMINUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ + 1)) { // Straight? + currentX--; + } else { // Left turn + linelist.add(new int[]{currentX, currentZ + 1}); // Finish line + direction = Direction.ZPLUS; + currentX--; + currentZ++; + } + break; + case ZMINUS: // Segment in Z- direction + if (!ourChunkFlags.getFlag(currentX, currentZ - 1)) { // Right turn? + linelist.add(new int[]{currentX, currentZ}); // Finish line + direction = Direction.XPLUS; // Change direction + } else if (!ourChunkFlags.getFlag(currentX - 1, currentZ - 1)) { // Straight? + currentZ--; + } else { // Left turn + linelist.add(new int[]{currentX, currentZ}); // Finish line + direction = Direction.XMINUS; + currentX--; + currentZ--; + } + break; + } + } + + int sz = linelist.size(); + double[] x = new double[sz]; + double[] z = new double[sz]; + for (int i = 0; i < sz; i++) { + int[] line = linelist.get(i); + x[i] = (double) line[0] * (double) BLOCKS_PER_CHUNK; + z[i] = (double) line[1] * (double) BLOCKS_PER_CHUNK; + } + + // Build information for specific area + String markerId = FACTIONS_ + world + "__" + faction.getId() + "__" + markerIndex; + + TempAreaMarker temp = new TempAreaMarker(); + temp.label = faction.getTag(); + temp.world = world; + temp.x = x; + temp.z = z; + temp.description = description; + + temp.lineColor = style.getLineColor(); + temp.lineOpacity = style.getLineOpacity(); + temp.lineWeight = style.getLineWeight(); + + temp.fillColor = style.getFillColor(); + temp.fillOpacity = style.getFillOpacity(); + + temp.boost = style.getBoost(); + + ret.put(markerId, temp); + + markerIndex++; + } + + return ret; + } + + // -------------------------------------------- // + // UTIL & SHARED + // -------------------------------------------- // + + // Thread Safe: NO + public void updateAreas(Map areas) { + // Map Current + Map markers = new HashMap<>(); + for (AreaMarker marker : this.markerset.getAreaMarkers()) { + markers.put(marker.getMarkerID(), marker); + } + + // Loop New + for (Entry entry : areas.entrySet()) { + String markerId = entry.getKey(); + TempAreaMarker temp = entry.getValue(); + + // Get Creative + // NOTE: I remove from the map created just in the beginning of this method. + // NOTE: That way what is left at the end will be outdated markers to remove. + AreaMarker marker = markers.remove(markerId); + if (marker == null) { + marker = temp.create(this.markerset, markerId); + if (marker == null) { + severe("Could not get/create the area marker " + markerId); + } + } else { + temp.update(marker); + } + } + + // Only old/outdated should now be left. Delete them. + for (AreaMarker marker : markers.values()) { + marker.deleteMarker(); + } + } + + // Thread Safe / Asynchronous: Yes + public String createPlayersetId(Faction faction) { + if (faction == null) { + return null; + } + if (faction.isWilderness()) { + return null; + } + String factionId = faction.getId(); + if (factionId == null) { + return null; + } + return FACTIONS_PLAYERSET_ + factionId; + } + + // Thread Safe / Asynchronous: Yes + public Set createPlayerset(Faction faction) { + if (faction == null) { + return null; + } + if (faction.isWilderness()) { + return null; + } + + Set ret = new HashSet<>(); + + for (FPlayer fplayer : faction.getFPlayers()) { + // NOTE: We add both UUID and name. This might be a good idea for future proofing. + ret.add(fplayer.getId()); + ret.add(fplayer.getName()); + } + + return ret; + } + + // Thread Safe / Asynchronous: Yes + public Map> createPlayersets() { + if (!Conf.dynmapVisibilityByFaction) { + return null; + } + + Map> ret = new HashMap<>(); + + for (Faction faction : Factions.getInstance().getAllFactions()) { + String playersetId = createPlayersetId(faction); + if (playersetId == null) { + continue; + } + Set playerIds = createPlayerset(faction); + if (playerIds == null) { + continue; + } + ret.put(playersetId, playerIds); + } + + return ret; + } + + // Thread Safe / Asynchronous: No + public void updatePlayersets(Map> playersets) { + if (playersets == null) { + return; + } + + // Remove + for (PlayerSet set : this.markerApi.getPlayerSets()) { + if (!set.getSetID().startsWith(FACTIONS_PLAYERSET_)) { + continue; + } + + // (Null means remove all) + if (playersets.containsKey(set.getSetID())) { + continue; + } + + set.deleteSet(); + } + + // Add / Update + for (Entry> entry : playersets.entrySet()) { + // Extract from Entry + String setId = entry.getKey(); + Set playerIds = entry.getValue(); + + // Get Creatively + PlayerSet set = this.markerApi.getPlayerSet(setId); + if (set == null) { + set = this.markerApi.createPlayerSet(setId, // id + true, // symmetric + playerIds, // players + false // persistent + ); + } + if (set == null) { + severe("Could not get/create the player set " + setId); + continue; + } + + // Set Content + set.setPlayers(playerIds); + } + } + + // Thread Safe / Asynchronous: Yes + private String getDescription(Faction faction) { + String ret = "
    " + Conf.dynmapDescription + "
    "; + + // Name + String name = faction.getTag(); + name = escapeHtml(ChatColor.stripColor(name)); + ret = ret.replace("%name%", name); + + // Description + String description = faction.getDescription(); + description = escapeHtml(ChatColor.stripColor(description)); + ret = ret.replace("%description%", description); + + // Money + + String money = "unavailable"; + if (Conf.bankEnabled && Conf.dynmapDescriptionMoney) + money = String.format("%.2f", Econ.getBalance(faction.getAccountId())); + ret = ret.replace("%money%", money); + + + // Players + Set playersList = faction.getFPlayers(); + String playersCount = String.valueOf(playersList.size()); + String players = getHtmlPlayerString(playersList); + + FPlayer playersLeaderObject = faction.getFPlayerAdmin(); + String playersLeader = getHtmlPlayerName(playersLeaderObject); + + ArrayList playersCoAdminsList = faction.getFPlayersWhereRole(Role.COLEADER); + String playersCoAdminsCount = String.valueOf(playersCoAdminsList.size()); + String playersCoAdmins = getHtmlPlayerString(playersCoAdminsList); + + ArrayList playersModeratorsList = faction.getFPlayersWhereRole(Role.MODERATOR); + String playersModeratorsCount = String.valueOf(playersModeratorsList.size()); + String playersModerators = getHtmlPlayerString(playersModeratorsList); + + + ArrayList playersNormalsList = faction.getFPlayersWhereRole(Role.NORMAL); + String playersNormalsCount = String.valueOf(playersNormalsList.size()); + String playersNormals = getHtmlPlayerString(playersNormalsList); + + ret = ret.replace("%players%", players); + ret = ret.replace("%players.count%", playersCount); + ret = ret.replace("%players.leader%", playersLeader); + ret = ret.replace("%players.admins%", playersCoAdmins); + ret = ret.replace("%players.admins.count%", playersCoAdminsCount); + ret = ret.replace("%players.moderators%", playersModerators); + ret = ret.replace("%players.moderators.count%", playersModeratorsCount); + ret = ret.replace("%players.normals%", playersNormals); + ret = ret.replace("%players.normals.count%", playersNormalsCount); + + return ret; + } + + // Thread Safe / Asynchronous: Yes + private boolean isVisible(Faction faction, String world) { + if (faction == null) { + return false; + } + final String factionId = faction.getId(); + if (factionId == null) { + return false; + } + final String factionName = faction.getTag(); + if (factionName == null) { + return false; + } + + Set visible = Conf.dynmapVisibleFactions; + Set hidden = Conf.dynmapHiddenFactions; + + if (!visible.isEmpty() && !visible.contains(factionId) && !visible.contains(factionName) && !visible.contains("world:" + world)) { + return false; + } + + return !hidden.contains(factionId) && !hidden.contains(factionName) && !hidden.contains("world:" + world); + } + + // Thread Safe / Asynchronous: Yes + public DynmapStyle getStyle(Faction faction) { + DynmapStyle ret; + + ret = Conf.dynmapFactionStyles.get(faction.getId()); + if (ret != null) { + return ret; + } + + ret = Conf.dynmapFactionStyles.get(faction.getTag()); + if (ret != null) { + return ret; + } + + return Conf.dynmapDefaultStyle; + } + + // Find all contiguous blocks, set in target and clear in source + private int floodFillTarget(TileFlags source, TileFlags destination, int x, int y) { + int cnt = 0; + ArrayDeque stack = new ArrayDeque<>(); + stack.push(new int[]{x, y}); + + while (!stack.isEmpty()) { + int[] nxt = stack.pop(); + x = nxt[0]; + y = nxt[1]; + if (source.getFlag(x, y)) { // Set in src + source.setFlag(x, y, false); // Clear source + destination.setFlag(x, y, true); // Set in destination + cnt++; + if (source.getFlag(x + 1, y)) { + stack.push(new int[]{x + 1, y}); + } + if (source.getFlag(x - 1, y)) { + stack.push(new int[]{x - 1, y}); + } + if (source.getFlag(x, y + 1)) { + stack.push(new int[]{x, y + 1}); + } + if (source.getFlag(x, y - 1)) { + stack.push(new int[]{x, y - 1}); + } + } + } + return cnt; + } + + enum Direction { + XPLUS, ZPLUS, XMINUS, ZMINUS + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java b/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java index ec346d53..33e695b4 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/TempAreaMarker.java @@ -4,113 +4,113 @@ import org.dynmap.markers.AreaMarker; import org.dynmap.markers.MarkerSet; public class TempAreaMarker { - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public String label; - public String world; - public double[] x; - public double[] z; - public String description; + public String label; + public String world; + public double[] x; + public double[] z; + public String description; - public int lineColor; - public double lineOpacity; - public int lineWeight; + public int lineColor; + public double lineOpacity; + public int lineWeight; - public int fillColor; - public double fillOpacity; + public int fillColor; + public double fillOpacity; - public boolean boost; + public boolean boost; - // -------------------------------------------- // - // CREATE - // -------------------------------------------- // + // -------------------------------------------- // + // CREATE + // -------------------------------------------- // - public static boolean equals(AreaMarker marker, double[] x, double[] z) { - int length = marker.getCornerCount(); + public static boolean equals(AreaMarker marker, double[] x, double[] z) { + int length = marker.getCornerCount(); - if (x.length != length) { - return false; - } - if (z.length != length) { - return false; - } + if (x.length != length) { + return false; + } + if (z.length != length) { + return false; + } - for (int i = 0; i < length; i++) { - if (marker.getCornerX(i) != x[i]) { - return false; - } - if (marker.getCornerZ(i) != z[i]) { - return false; - } - } + for (int i = 0; i < length; i++) { + if (marker.getCornerX(i) != x[i]) { + return false; + } + if (marker.getCornerZ(i) != z[i]) { + return false; + } + } - return true; - } + return true; + } - // -------------------------------------------- // - // UPDATE - // -------------------------------------------- // + // -------------------------------------------- // + // UPDATE + // -------------------------------------------- // - public AreaMarker create(MarkerSet markerset, String markerId) { - AreaMarker ret = markerset.createAreaMarker(markerId, this.label, false, this.world, this.x, this.z, false // not persistent - ); + public AreaMarker create(MarkerSet markerset, String markerId) { + AreaMarker ret = markerset.createAreaMarker(markerId, this.label, false, this.world, this.x, this.z, false // not persistent + ); - if (ret == null) { - return null; - } + if (ret == null) { + return null; + } - // Description - ret.setDescription(this.description); + // Description + ret.setDescription(this.description); - // Line Style - ret.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); + // Line Style + ret.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); - // Fill Style - ret.setFillStyle(this.fillOpacity, this.fillColor); + // Fill Style + ret.setFillStyle(this.fillOpacity, this.fillColor); - // Boost Flag - ret.setBoostFlag(this.boost); + // Boost Flag + ret.setBoostFlag(this.boost); - return ret; - } + return ret; + } - // -------------------------------------------- // - // UTIL - // -------------------------------------------- // + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // - public void update(AreaMarker marker) { - // Corner Locations - if (!equals(marker, this.x, this.z)) { - marker.setCornerLocations(this.x, this.z); - } + public void update(AreaMarker marker) { + // Corner Locations + if (!equals(marker, this.x, this.z)) { + marker.setCornerLocations(this.x, this.z); + } - // Label - if (!marker.getLabel().equals(this.label)) { - marker.setLabel(this.label); - } + // Label + if (!marker.getLabel().equals(this.label)) { + marker.setLabel(this.label); + } - // Description - if (!marker.getDescription().equals(this.description)) { - marker.setDescription(this.description); - } + // Description + if (!marker.getDescription().equals(this.description)) { + marker.setDescription(this.description); + } - // Line Style - if (marker.getLineWeight() != this.lineWeight || - marker.getLineOpacity() != this.lineOpacity || - marker.getLineColor() != this.lineColor) { - marker.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); - } + // Line Style + if (marker.getLineWeight() != this.lineWeight || + marker.getLineOpacity() != this.lineOpacity || + marker.getLineColor() != this.lineColor) { + marker.setLineStyle(this.lineWeight, this.lineOpacity, this.lineColor); + } - // Fill Style - if ((marker.getFillOpacity() != this.fillOpacity) || (marker.getFillColor() != this.fillColor)) { - marker.setFillStyle(this.fillOpacity, this.fillColor); - } - // Boost Flag - if (marker.getBoostFlag() != this.boost) { - marker.setBoostFlag(this.boost); - } - } + // Fill Style + if ((marker.getFillOpacity() != this.fillOpacity) || (marker.getFillColor() != this.fillColor)) { + marker.setFillStyle(this.fillOpacity, this.fillColor); + } + // Boost Flag + if (marker.getBoostFlag() != this.boost) { + marker.setBoostFlag(this.boost); + } + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java index b8eefdbe..d977ae9f 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarker.java @@ -7,68 +7,68 @@ import org.dynmap.markers.MarkerIcon; import org.dynmap.markers.MarkerSet; public class TempMarker { - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public String label; - public String world; - public double x; - public double y; - public double z; - public String iconName; - public String description; + public String label; + public String world; + public double x; + public double y; + public double z; + public String iconName; + public String description; - // -------------------------------------------- // - // CREATE - // -------------------------------------------- // + // -------------------------------------------- // + // CREATE + // -------------------------------------------- // - public static MarkerIcon getMarkerIcon(MarkerAPI markerApi, String name) { - MarkerIcon ret = markerApi.getMarkerIcon(name); - if (ret == null) { - ret = markerApi.getMarkerIcon(Conf.DYNMAP_STYLE_HOME_MARKER); - } - return ret; - } + public static MarkerIcon getMarkerIcon(MarkerAPI markerApi, String name) { + MarkerIcon ret = markerApi.getMarkerIcon(name); + if (ret == null) { + ret = markerApi.getMarkerIcon(Conf.DYNMAP_STYLE_HOME_MARKER); + } + return ret; + } - // -------------------------------------------- // - // UPDATE - // -------------------------------------------- // + // -------------------------------------------- // + // UPDATE + // -------------------------------------------- // - public Marker create(MarkerAPI markerApi, MarkerSet markerset, String markerId) { - Marker ret = markerset.createMarker(markerId, this.label, this.world, this.x, this.y, this.z, getMarkerIcon(markerApi, this.iconName), false // not persistent - ); + public Marker create(MarkerAPI markerApi, MarkerSet markerset, String markerId) { + Marker ret = markerset.createMarker(markerId, this.label, this.world, this.x, this.y, this.z, getMarkerIcon(markerApi, this.iconName), false // not persistent + ); - if (ret == null) { - return null; - } + if (ret == null) { + return null; + } - ret.setDescription(this.description); + ret.setDescription(this.description); - return ret; - } + return ret; + } - // -------------------------------------------- // - // UTIL - // -------------------------------------------- // + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // - public void update(MarkerAPI markerApi, Marker marker) { - if (!this.world.equals(marker.getWorld()) || this.x != marker.getX() || this.y != marker.getY() || this.z != marker.getZ()) { - marker.setLocation(this.world, this.x, this.y, this.z); - } + public void update(MarkerAPI markerApi, Marker marker) { + if (!this.world.equals(marker.getWorld()) || this.x != marker.getX() || this.y != marker.getY() || this.z != marker.getZ()) { + marker.setLocation(this.world, this.x, this.y, this.z); + } - if (!marker.getLabel().equals(this.label)) { - marker.setLabel(this.label); - } + if (!marker.getLabel().equals(this.label)) { + marker.setLabel(this.label); + } - MarkerIcon icon = getMarkerIcon(markerApi, this.iconName); - if (marker.getMarkerIcon() == null || marker.getMarkerIcon().equals(icon)) { - marker.setMarkerIcon(icon); - } + MarkerIcon icon = getMarkerIcon(markerApi, this.iconName); + if (marker.getMarkerIcon() == null || marker.getMarkerIcon().equals(icon)) { + marker.setMarkerIcon(icon); + } - if (!marker.getDescription().equals(this.description)) { - marker.setDescription(this.description); - } - } + if (!marker.getDescription().equals(this.description)) { + marker.setDescription(this.description); + } + } } diff --git a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java index 553bbde6..828a2f58 100644 --- a/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java +++ b/src/main/java/com/massivecraft/factions/integration/dynmap/TempMarkerSet.java @@ -5,51 +5,51 @@ import org.dynmap.markers.MarkerSet; public class TempMarkerSet { - public String label; - public int minimumZoom; - public int priority; - public boolean hideByDefault; + public String label; + public int minimumZoom; + public int priority; + public boolean hideByDefault; - public MarkerSet create(MarkerAPI markerApi, String id) { - MarkerSet ret = markerApi.createMarkerSet(id, this.label, null, false); // ("null, false" at the end means "all icons allowed, not perisistent") + public MarkerSet create(MarkerAPI markerApi, String id) { + MarkerSet ret = markerApi.createMarkerSet(id, this.label, null, false); // ("null, false" at the end means "all icons allowed, not perisistent") - if (ret == null) { - return null; - } + if (ret == null) { + return null; + } - // Minimum Zoom - if (this.minimumZoom > 0) { - ret.setMinZoom(this.minimumZoom); - } + // Minimum Zoom + if (this.minimumZoom > 0) { + ret.setMinZoom(this.minimumZoom); + } - // Priority - ret.setLayerPriority(this.priority); + // Priority + ret.setLayerPriority(this.priority); - // Hide by Default - ret.setHideByDefault(this.hideByDefault); + // Hide by Default + ret.setHideByDefault(this.hideByDefault); - return ret; - } + return ret; + } - public void update(MarkerSet markerset) { - // Name - if (!markerset.getMarkerSetLabel().equals(this.label)) { - markerset.setMarkerSetLabel(this.label); - } + public void update(MarkerSet markerset) { + // Name + if (!markerset.getMarkerSetLabel().equals(this.label)) { + markerset.setMarkerSetLabel(this.label); + } - if (this.minimumZoom > 0) { - if (markerset.getMinZoom() != this.minimumZoom) { - markerset.setMinZoom(this.minimumZoom); - } - } + if (this.minimumZoom > 0) { + if (markerset.getMinZoom() != this.minimumZoom) { + markerset.setMinZoom(this.minimumZoom); + } + } - if (markerset.getLayerPriority() != this.priority) { - markerset.setLayerPriority(this.priority); - } + if (markerset.getLayerPriority() != this.priority) { + markerset.setLayerPriority(this.priority); + } - if (markerset.getHideByDefault() != this.hideByDefault) { - markerset.setHideByDefault(this.hideByDefault); - } - } + if (markerset.getHideByDefault() != this.hideByDefault) { + markerset.setHideByDefault(this.hideByDefault); + } + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java index 0d2ef465..1d7709b2 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java @@ -33,490 +33,490 @@ import java.util.List; public class FactionsBlockListener implements Listener { - public static HashMap bannerLocations = new HashMap<>(); - private HashMap bannerCooldownMap = new HashMap<>(); + public static HashMap bannerLocations = new HashMap<>(); + private HashMap bannerCooldownMap = new HashMap<>(); - public static boolean playerCanBuildDestroyBlock(Player player, Location location, String action, boolean justCheck) { - String name = player.getName(); - - if (Conf.playersWhoBypassAllProtection.contains(name)) - return true; - - FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); - if (me.isAdminBypassing()) - return true; - - FLocation loc = new FLocation(location); - Faction otherFaction = Board.getInstance().getFactionAt(loc); - - if (otherFaction.isWilderness()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) - return true; // This is not faction territory. Use whatever you like here. - - if (!justCheck) - me.msg("You can't " + action + " in the wilderness."); - - return false; - } else if (otherFaction.isSafeZone()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.safeZoneDenyBuild || Permission.MANAGE_SAFE_ZONE.has(player)) - return true; - - if (!justCheck) - me.msg("You can't " + action + " in a safe zone."); - - return false; - } else if (otherFaction.isWarZone()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.warZoneDenyBuild || Permission.MANAGE_WAR_ZONE.has(player)) - return true; - - if (!justCheck) - me.msg("You can't " + action + " in a war zone."); - - return false; - } - - if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) - return true; - - Faction myFaction = me.getFaction(); - Relation rel = myFaction.getRelationTo(otherFaction); - boolean online = otherFaction.hasPlayersOnline(); - boolean pain = !justCheck && rel.confPainBuild(online); - boolean deny = rel.confDenyBuild(online); - - Access access = otherFaction.getAccess(me, PermissableAction.fromString(action)); - if (access == Access.ALLOW && ((rel == Relation.ALLY) || (rel == Relation.ENEMY) || (rel == Relation.NEUTRAL) || (rel == Relation.TRUCE))) - deny = false; - - // hurt the player for building/destroying in other territory? - if (pain) { - player.damage(Conf.actionDeniedPainAmount); - - if (!deny) { - me.msg("It is painful to try to " + action + " in the territory of " + otherFaction.getTag(myFaction)); - } - } - - - // cancel building/destroying in other territory? - if (deny) { - if (!justCheck) { - me.msg("You can't " + action + " in the territory of " + otherFaction.getTag(myFaction)); - } - - return false; - } - - // Also cancel and/or cause pain if player doesn't have ownership rights for this claim - if (Conf.ownedAreasEnabled && (Conf.ownedAreaDenyBuild || Conf.ownedAreaPainBuild) && !otherFaction.playerHasOwnershipRights(me, loc)) { - if (!pain && Conf.ownedAreaPainBuild && !justCheck) { - player.damage(Conf.actionDeniedPainAmount); - if (!Conf.ownedAreaDenyBuild) { - me.msg("It is painful to try to " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); - } - } - if (Conf.ownedAreaDenyBuild) { - if (!justCheck) { - me.msg("You can't " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); - return false; - } - } - } - - // Check the permission just after making sure the land isn't owned by someone else to avoid bypass. - - if (access != Access.ALLOW && me.getRole() != Role.LEADER) { - // TODO: Update this once new access values are added other than just allow / deny. - if (access == Access.DENY) { - if (!justCheck) - me.msg(TL.GENERIC_NOPERMISSION, action); - return false; - } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { - if (!justCheck) - me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); - return false; - } - } - return true; - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockPlace(BlockPlaceEvent event) { - if (!event.canBuild()) { - return; - } - - // special case for flint&steel, which should only be prevented by DenyUsage list - if (event.getBlockPlaced().getType() == Material.FIRE) { - return; - } - - if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "build", false)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockFromTo(BlockFromToEvent event) { - if (!Conf.handleExploitLiquidFlow) { - return; - } - if (event.getBlock().isLiquid()) { - if (event.getToBlock().isEmpty()) { - Faction from = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - Faction to = Board.getInstance().getFactionAt(new FLocation(event.getToBlock())); - if (from == to) { - // not concerned with inter-faction events - return; - } - // from faction != to faction - if (to.isNormal()) { - if (from.isNormal() && from.getRelationTo(to).isAlly()) { - return; - } - event.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockDamage(BlockDamageEvent event) { - if (event.getInstaBreak() && !playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockPistonExtend(BlockPistonExtendEvent event) { - if (!Conf.pistonProtectionThroughDenyBuild) { - return; - } - - Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - - // target end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air - Block targetBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1); - - // if potentially pushing into air/water/lava in another territory, we need to check it out - if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && !canPistonMoveBlock(pistonFaction, targetBlock.getLocation())) { - event.setCancelled(true); - } - - /* - * note that I originally was testing the territory of each affected block, but since I found that pistons can only push - * up to 12 blocks and the width of any territory is 16 blocks, it should be safe (and much more lightweight) to test - * only the final target block as done above - */ - } - - @EventHandler - public void onVaultPlace(BlockPlaceEvent e) { - if (e.getItemInHand().getType() == Material.CHEST) { - ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); - if (e.getItemInHand().isSimilar(vault)) { - FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - if (fme.getFaction().getVault() != null) { - fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); - e.setCancelled(true); - return; - } - FLocation flocation = new FLocation(e.getBlockPlaced().getLocation()); - if (Board.getInstance().getFactionAt(flocation) != fme.getFaction()) { - fme.msg(TL.COMMAND_GETVAULT_INVALIDLOCATION); - e.setCancelled(true); - return; - } - Block start = e.getBlockPlaced(); - int radius = 1; - for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { - for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { - for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { - Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); - if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { - continue; - } - - Material blockMaterial = blockLoc.getBlock().getType(); - - if (blockMaterial == Material.CHEST || (SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault") && blockMaterial == Material.HOPPER)) { - e.setCancelled(true); - fme.msg(TL.COMMAND_GETVAULT_CHESTNEAR); - return; - } - } - } - } - - fme.msg(TL.COMMAND_GETVAULT_SUCCESS); - fme.getFaction().setVault(e.getBlockPlaced().getLocation()); - - } - } - } - - @EventHandler - public void onHopperPlace(BlockPlaceEvent e) { - - if (e.getItemInHand().getType() != Material.HOPPER && !SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault")) { - return; - } - - Faction factionAt = Board.getInstance().getFactionAt(new FLocation(e.getBlockPlaced().getLocation())); - - if (factionAt.isWilderness() || factionAt.getVault() == null) { - return; - } - - - FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - - Block start = e.getBlockPlaced(); - int radius = 1; - for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { - for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { - for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { - Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); - if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { - continue; - } - - if (blockLoc.getBlock().getType() == Material.CHEST) { - if (factionAt.getVault().equals(blockLoc)) { - e.setCancelled(true); - fme.msg(TL.COMMAND_VAULT_NO_HOPPER); - return; - } - } - } - } - } - - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockPistonRetract(BlockPistonRetractEvent event) { - // if not a sticky piston, retraction should be fine - if (!event.isSticky() || !Conf.pistonProtectionThroughDenyBuild) { - return; - } - - Location targetLoc = event.getRetractLocation(); - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(targetLoc)); - - // Check if the piston is moving in a faction's territory. This disables pistons entirely in faction territory. - if (otherFaction.isNormal() && SavageFactions.plugin.getConfig().getBoolean("disable-pistons-in-territory", false)) { - event.setCancelled(true); - return; - } - - // if potentially retracted block is just air/water/lava, no worries - if (targetLoc.getBlock().isEmpty() || targetLoc.getBlock().isLiquid()) { - return; - } - - Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - - if (!canPistonMoveBlock(pistonFaction, targetLoc)) { - event.setCancelled(true); - } - } - - @EventHandler - public void onBannerPlace(BlockPlaceEvent e) { - if (SavageFactions.plugin.mc17) { - return; - } - - if (e.getItemInHand().getType() == SavageFactions.plugin.BANNER) { - ItemStack bannerInHand = e.getItemInHand(); - FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - ItemStack warBanner = fme.getFaction().getBanner(); - if (warBanner != null) { - ItemMeta warmeta = warBanner.getItemMeta(); - warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); - warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); - warBanner.setItemMeta(warmeta); - } else { - warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); - } - if (warBanner.isSimilar(bannerInHand)) { - - if (fme.getFaction().isWilderness()) { - fme.msg(TL.WARBANNER_NOFACTION); - e.setCancelled(true); - return; - } - int bannerTime = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Time") * 20; - - Location placedLoc = e.getBlockPlaced().getLocation(); - FLocation fplacedLoc = new FLocation(placedLoc); - if ((Board.getInstance().getFactionAt(fplacedLoc).isWarZone() && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Warzone")) - || (fme.getFaction().getRelationTo(Board.getInstance().getFactionAt(fplacedLoc)) == Relation.ENEMY) && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Enemy")) { - if (bannerCooldownMap.containsKey(fme.getTag())) { - fme.msg(TL.WARBANNER_COOLDOWN); - e.setCancelled(true); - return; - } - for (FPlayer fplayer : fme.getFaction().getFPlayers()) { - // if (fplayer == fme) { continue; } //Idk if I wanna not send the title to the player - fplayer.getPlayer().sendTitle(SavageFactions.plugin.color(fme.getTag() + " Placed A WarBanner!"), SavageFactions.plugin.color("&7use &c/f tpbanner&7 to tp to the banner!"), 10, 70, 20); - } - - bannerCooldownMap.put(fme.getTag(), true); - bannerLocations.put(fme.getTag(), e.getBlockPlaced().getLocation()); - final int bannerCooldown = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Place-Cooldown"); - final ArmorStand as = (ArmorStand) e.getBlockPlaced().getLocation().add(0.5, 1, 0.5).getWorld().spawnEntity(e.getBlockPlaced().getLocation().add(0.5, 1, 0.5), EntityType.ARMOR_STAND); //Spawn the ArmorStand - as.setVisible(false); //Makes the ArmorStand invisible - as.setGravity(false); //Make sure it doesn't fall - as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it - as.setCustomName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.BannerHolo").replace("{Faction}", fme.getTag()))); //Set this to the text you want - as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not - final ArmorStand armorStand = as; - final String tag = fme.getTag(); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - bannerCooldownMap.remove(tag); - } - }, Long.parseLong(bannerCooldown + "")); - final Block banner = e.getBlockPlaced(); - final Material bannerType = banner.getType(); - final Faction bannerFaction = fme.getFaction(); - banner.getWorld().strikeLightningEffect(banner.getLocation()); - // e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_LIGHTNING_IMPACT,2.0F,0.5F); - final int radius = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Effect-Radius"); - final List effects = SavageFactions.plugin.getConfig().getStringList("fbanners.Effects"); - final int affectorTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - - for (Entity e : banner.getLocation().getWorld().getNearbyEntities(banner.getLocation(), radius, 255, radius)) { - if (e instanceof Player) { - Player player = (Player) e; - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fplayer.getFaction() == bannerFaction) { - for (String effect : effects) { - String[] components = effect.split(":"); - player.addPotionEffect(new PotionEffect(PotionEffectType.getByName(components[0]), 100, Integer.parseInt(components[1]))); - } - ParticleEffect.LAVA.display(1, 1, 1, 1, 10, banner.getLocation(), 16); - ParticleEffect.FLAME.display(1, 1, 1, 1, 10, banner.getLocation(), 16); - - if (banner.getType() != bannerType) { - banner.setType(bannerType); - } - } - } - } - } - }, 0L, 20L); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - banner.setType(Material.AIR); - as.remove(); - banner.getWorld().strikeLightningEffect(banner.getLocation()); - Bukkit.getScheduler().cancelTask(affectorTask); - bannerLocations.remove(bannerFaction.getTag()); - } - }, Long.parseLong(bannerTime + "")); - } else { - fme.msg(TL.WARBANNER_INVALIDLOC); - e.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onFrostWalker(EntityBlockFormEvent event) { - if (event.getEntity() == null || event.getEntity().getType() != EntityType.PLAYER || event.getBlock() == null) { - return; - } - - Player player = (Player) event.getEntity(); - Location location = event.getBlock().getLocation(); - - // only notify every 10 seconds - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - boolean justCheck = fPlayer.getLastFrostwalkerMessage() + 10000 > System.currentTimeMillis(); - if (!justCheck) { - fPlayer.setLastFrostwalkerMessage(); - } - - // Check if they have build permissions here. If not, block this from happening. - if (!playerCanBuildDestroyBlock(player, location, "frostwalk", justCheck)) { - event.setCancelled(true); - } - } - - private boolean canPistonMoveBlock(Faction pistonFaction, Location target) { - - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(target)); - - if (pistonFaction == otherFaction) { - return true; - } - - if (otherFaction.isWilderness()) { - return !Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(target.getWorld().getName()); - - } else if (otherFaction.isSafeZone()) { - return !Conf.safeZoneDenyBuild; - - } else if (otherFaction.isWarZone()) { - return !Conf.warZoneDenyBuild; - - } - - Relation rel = pistonFaction.getRelationTo(otherFaction); - - return !rel.confDenyBuild(otherFaction.hasPlayersOnline()); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { - event.setCancelled(true); - return; - } - FPlayer fme = FPlayers.getInstance().getByPlayer(event.getPlayer()); - if (!fme.hasFaction()) { - return; - } - if (event.getBlock().getType() == SavageFactions.plugin.MOB_SPANWER) { - if (!fme.isAdminBypassing()) { - Access access = fme.getFaction().getAccess(fme, PermissableAction.SPAWNER); - if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { - fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "mine spawners"); - return; - } - } - } - } - - @EventHandler - public void onFarmLandDamage(EntityChangeBlockEvent event) { - if (event.getEntity() instanceof Player) { - Player player = (Player) event.getEntity(); - if (!playerCanBuildDestroyBlock(player, event.getBlock().getLocation(), PermissableAction.DESTROY.name(), true)) { - FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock().getLocation())); - Faction myFaction = me.getFaction(); - - me.msg("You can't jump on farmland in the territory of " + otherFaction.getTag(myFaction)); - event.setCancelled(true); - } - } - } + public static boolean playerCanBuildDestroyBlock(Player player, Location location, String action, boolean justCheck) { + String name = player.getName(); + + if (Conf.playersWhoBypassAllProtection.contains(name)) + return true; + + FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); + if (me.isAdminBypassing()) + return true; + + FLocation loc = new FLocation(location); + Faction otherFaction = Board.getInstance().getFactionAt(loc); + + if (otherFaction.isWilderness()) { + if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) + return true; + + if (!Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) + return true; // This is not faction territory. Use whatever you like here. + + if (!justCheck) + me.msg("You can't " + action + " in the wilderness."); + + return false; + } else if (otherFaction.isSafeZone()) { + if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) + return true; + + if (!Conf.safeZoneDenyBuild || Permission.MANAGE_SAFE_ZONE.has(player)) + return true; + + if (!justCheck) + me.msg("You can't " + action + " in a safe zone."); + + return false; + } else if (otherFaction.isWarZone()) { + if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) + return true; + + if (!Conf.warZoneDenyBuild || Permission.MANAGE_WAR_ZONE.has(player)) + return true; + + if (!justCheck) + me.msg("You can't " + action + " in a war zone."); + + return false; + } + + if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) + return true; + + Faction myFaction = me.getFaction(); + Relation rel = myFaction.getRelationTo(otherFaction); + boolean online = otherFaction.hasPlayersOnline(); + boolean pain = !justCheck && rel.confPainBuild(online); + boolean deny = rel.confDenyBuild(online); + + Access access = otherFaction.getAccess(me, PermissableAction.fromString(action)); + if (access == Access.ALLOW && ((rel == Relation.ALLY) || (rel == Relation.ENEMY) || (rel == Relation.NEUTRAL) || (rel == Relation.TRUCE))) + deny = false; + + // hurt the player for building/destroying in other territory? + if (pain) { + player.damage(Conf.actionDeniedPainAmount); + + if (!deny) { + me.msg("It is painful to try to " + action + " in the territory of " + otherFaction.getTag(myFaction)); + } + } + + + // cancel building/destroying in other territory? + if (deny) { + if (!justCheck) { + me.msg("You can't " + action + " in the territory of " + otherFaction.getTag(myFaction)); + } + + return false; + } + + // Also cancel and/or cause pain if player doesn't have ownership rights for this claim + if (Conf.ownedAreasEnabled && (Conf.ownedAreaDenyBuild || Conf.ownedAreaPainBuild) && !otherFaction.playerHasOwnershipRights(me, loc)) { + if (!pain && Conf.ownedAreaPainBuild && !justCheck) { + player.damage(Conf.actionDeniedPainAmount); + if (!Conf.ownedAreaDenyBuild) { + me.msg("It is painful to try to " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); + } + } + if (Conf.ownedAreaDenyBuild) { + if (!justCheck) { + me.msg("You can't " + action + " in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); + return false; + } + } + } + + // Check the permission just after making sure the land isn't owned by someone else to avoid bypass. + + if (access != Access.ALLOW && me.getRole() != Role.LEADER) { + // TODO: Update this once new access values are added other than just allow / deny. + if (access == Access.DENY) { + if (!justCheck) + me.msg(TL.GENERIC_NOPERMISSION, action); + return false; + } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { + if (!justCheck) + me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); + return false; + } + } + return true; + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + if (!event.canBuild()) { + return; + } + + // special case for flint&steel, which should only be prevented by DenyUsage list + if (event.getBlockPlaced().getType() == Material.FIRE) { + return; + } + + if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "build", false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockFromTo(BlockFromToEvent event) { + if (!Conf.handleExploitLiquidFlow) { + return; + } + if (event.getBlock().isLiquid()) { + if (event.getToBlock().isEmpty()) { + Faction from = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); + Faction to = Board.getInstance().getFactionAt(new FLocation(event.getToBlock())); + if (from == to) { + // not concerned with inter-faction events + return; + } + // from faction != to faction + if (to.isNormal()) { + if (from.isNormal() && from.getRelationTo(to).isAlly()) { + return; + } + event.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockDamage(BlockDamageEvent event) { + if (event.getInstaBreak() && !playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPistonExtend(BlockPistonExtendEvent event) { + if (!Conf.pistonProtectionThroughDenyBuild) { + return; + } + + Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); + + // target end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air + Block targetBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1); + + // if potentially pushing into air/water/lava in another territory, we need to check it out + if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && !canPistonMoveBlock(pistonFaction, targetBlock.getLocation())) { + event.setCancelled(true); + } + + /* + * note that I originally was testing the territory of each affected block, but since I found that pistons can only push + * up to 12 blocks and the width of any territory is 16 blocks, it should be safe (and much more lightweight) to test + * only the final target block as done above + */ + } + + @EventHandler + public void onVaultPlace(BlockPlaceEvent e) { + if (e.getItemInHand().getType() == Material.CHEST) { + ItemStack vault = SavageFactions.plugin.createItem(Material.CHEST, 1, (short) 0, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fvault.Item.Name")), SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fvault.Item.Lore"))); + if (e.getItemInHand().isSimilar(vault)) { + FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); + if (fme.getFaction().getVault() != null) { + fme.msg(TL.COMMAND_GETVAULT_ALREADYSET); + e.setCancelled(true); + return; + } + FLocation flocation = new FLocation(e.getBlockPlaced().getLocation()); + if (Board.getInstance().getFactionAt(flocation) != fme.getFaction()) { + fme.msg(TL.COMMAND_GETVAULT_INVALIDLOCATION); + e.setCancelled(true); + return; + } + Block start = e.getBlockPlaced(); + int radius = 1; + for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { + for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { + for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { + Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); + if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { + continue; + } + + Material blockMaterial = blockLoc.getBlock().getType(); + + if (blockMaterial == Material.CHEST || (SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault") && blockMaterial == Material.HOPPER)) { + e.setCancelled(true); + fme.msg(TL.COMMAND_GETVAULT_CHESTNEAR); + return; + } + } + } + } + + fme.msg(TL.COMMAND_GETVAULT_SUCCESS); + fme.getFaction().setVault(e.getBlockPlaced().getLocation()); + + } + } + } + + @EventHandler + public void onHopperPlace(BlockPlaceEvent e) { + + if (e.getItemInHand().getType() != Material.HOPPER && !SavageFactions.plugin.getConfig().getBoolean("fvault.No-Hoppers-near-vault")) { + return; + } + + Faction factionAt = Board.getInstance().getFactionAt(new FLocation(e.getBlockPlaced().getLocation())); + + if (factionAt.isWilderness() || factionAt.getVault() == null) { + return; + } + + + FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); + + Block start = e.getBlockPlaced(); + int radius = 1; + for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { + for (double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++) { + for (double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++) { + Location blockLoc = new Location(e.getPlayer().getWorld(), x, y, z); + if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { + continue; + } + + if (blockLoc.getBlock().getType() == Material.CHEST) { + if (factionAt.getVault().equals(blockLoc)) { + e.setCancelled(true); + fme.msg(TL.COMMAND_VAULT_NO_HOPPER); + return; + } + } + } + } + } + + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockPistonRetract(BlockPistonRetractEvent event) { + // if not a sticky piston, retraction should be fine + if (!event.isSticky() || !Conf.pistonProtectionThroughDenyBuild) { + return; + } + + Location targetLoc = event.getRetractLocation(); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(targetLoc)); + + // Check if the piston is moving in a faction's territory. This disables pistons entirely in faction territory. + if (otherFaction.isNormal() && SavageFactions.plugin.getConfig().getBoolean("disable-pistons-in-territory", false)) { + event.setCancelled(true); + return; + } + + // if potentially retracted block is just air/water/lava, no worries + if (targetLoc.getBlock().isEmpty() || targetLoc.getBlock().isLiquid()) { + return; + } + + Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); + + if (!canPistonMoveBlock(pistonFaction, targetLoc)) { + event.setCancelled(true); + } + } + + @EventHandler + public void onBannerPlace(BlockPlaceEvent e) { + if (SavageFactions.plugin.mc17) { + return; + } + + if (e.getItemInHand().getType() == SavageFactions.plugin.BANNER) { + ItemStack bannerInHand = e.getItemInHand(); + FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); + ItemStack warBanner = fme.getFaction().getBanner(); + if (warBanner != null) { + ItemMeta warmeta = warBanner.getItemMeta(); + warmeta.setDisplayName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"))); + warmeta.setLore(SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore"))); + warBanner.setItemMeta(warmeta); + } else { + warBanner = SavageFactions.plugin.createItem(SavageFactions.plugin.BANNER, 1, (short) 1, SavageFactions.plugin.getConfig().getString("fbanners.Item.Name"), SavageFactions.plugin.getConfig().getStringList("fbanners.Item.Lore")); + } + if (warBanner.isSimilar(bannerInHand)) { + + if (fme.getFaction().isWilderness()) { + fme.msg(TL.WARBANNER_NOFACTION); + e.setCancelled(true); + return; + } + int bannerTime = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Time") * 20; + + Location placedLoc = e.getBlockPlaced().getLocation(); + FLocation fplacedLoc = new FLocation(placedLoc); + if ((Board.getInstance().getFactionAt(fplacedLoc).isWarZone() && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Warzone")) + || (fme.getFaction().getRelationTo(Board.getInstance().getFactionAt(fplacedLoc)) == Relation.ENEMY) && SavageFactions.plugin.getConfig().getBoolean("fbanners.Placeable.Enemy")) { + if (bannerCooldownMap.containsKey(fme.getTag())) { + fme.msg(TL.WARBANNER_COOLDOWN); + e.setCancelled(true); + return; + } + for (FPlayer fplayer : fme.getFaction().getFPlayers()) { + // if (fplayer == fme) { continue; } //Idk if I wanna not send the title to the player + fplayer.getPlayer().sendTitle(SavageFactions.plugin.color(fme.getTag() + " Placed A WarBanner!"), SavageFactions.plugin.color("&7use &c/f tpbanner&7 to tp to the banner!"), 10, 70, 20); + } + + bannerCooldownMap.put(fme.getTag(), true); + bannerLocations.put(fme.getTag(), e.getBlockPlaced().getLocation()); + final int bannerCooldown = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Place-Cooldown"); + final ArmorStand as = (ArmorStand) e.getBlockPlaced().getLocation().add(0.5, 1, 0.5).getWorld().spawnEntity(e.getBlockPlaced().getLocation().add(0.5, 1, 0.5), EntityType.ARMOR_STAND); //Spawn the ArmorStand + as.setVisible(false); //Makes the ArmorStand invisible + as.setGravity(false); //Make sure it doesn't fall + as.setCanPickupItems(false); //I'm not sure what happens if you leave this as it is, but you might as well disable it + as.setCustomName(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fbanners.BannerHolo").replace("{Faction}", fme.getTag()))); //Set this to the text you want + as.setCustomNameVisible(true); //This makes the text appear no matter if your looking at the entity or not + final ArmorStand armorStand = as; + final String tag = fme.getTag(); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + bannerCooldownMap.remove(tag); + } + }, Long.parseLong(bannerCooldown + "")); + final Block banner = e.getBlockPlaced(); + final Material bannerType = banner.getType(); + final Faction bannerFaction = fme.getFaction(); + banner.getWorld().strikeLightningEffect(banner.getLocation()); + // e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_LIGHTNING_IMPACT,2.0F,0.5F); + final int radius = SavageFactions.plugin.getConfig().getInt("fbanners.Banner-Effect-Radius"); + final List effects = SavageFactions.plugin.getConfig().getStringList("fbanners.Effects"); + final int affectorTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + + for (Entity e : banner.getLocation().getWorld().getNearbyEntities(banner.getLocation(), radius, 255, radius)) { + if (e instanceof Player) { + Player player = (Player) e; + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer.getFaction() == bannerFaction) { + for (String effect : effects) { + String[] components = effect.split(":"); + player.addPotionEffect(new PotionEffect(PotionEffectType.getByName(components[0]), 100, Integer.parseInt(components[1]))); + } + ParticleEffect.LAVA.display(1, 1, 1, 1, 10, banner.getLocation(), 16); + ParticleEffect.FLAME.display(1, 1, 1, 1, 10, banner.getLocation(), 16); + + if (banner.getType() != bannerType) { + banner.setType(bannerType); + } + } + } + } + } + }, 0L, 20L); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + banner.setType(Material.AIR); + as.remove(); + banner.getWorld().strikeLightningEffect(banner.getLocation()); + Bukkit.getScheduler().cancelTask(affectorTask); + bannerLocations.remove(bannerFaction.getTag()); + } + }, Long.parseLong(bannerTime + "")); + } else { + fme.msg(TL.WARBANNER_INVALIDLOC); + e.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onFrostWalker(EntityBlockFormEvent event) { + if (event.getEntity() == null || event.getEntity().getType() != EntityType.PLAYER || event.getBlock() == null) { + return; + } + + Player player = (Player) event.getEntity(); + Location location = event.getBlock().getLocation(); + + // only notify every 10 seconds + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + boolean justCheck = fPlayer.getLastFrostwalkerMessage() + 10000 > System.currentTimeMillis(); + if (!justCheck) { + fPlayer.setLastFrostwalkerMessage(); + } + + // Check if they have build permissions here. If not, block this from happening. + if (!playerCanBuildDestroyBlock(player, location, "frostwalk", justCheck)) { + event.setCancelled(true); + } + } + + private boolean canPistonMoveBlock(Faction pistonFaction, Location target) { + + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(target)); + + if (pistonFaction == otherFaction) { + return true; + } + + if (otherFaction.isWilderness()) { + return !Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(target.getWorld().getName()); + + } else if (otherFaction.isSafeZone()) { + return !Conf.safeZoneDenyBuild; + + } else if (otherFaction.isWarZone()) { + return !Conf.warZoneDenyBuild; + + } + + Relation rel = pistonFaction.getRelationTo(otherFaction); + + return !rel.confDenyBuild(otherFaction.hasPlayersOnline()); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { + event.setCancelled(true); + return; + } + FPlayer fme = FPlayers.getInstance().getByPlayer(event.getPlayer()); + if (!fme.hasFaction()) { + return; + } + if (event.getBlock().getType() == SavageFactions.plugin.MOB_SPANWER) { + if (!fme.isAdminBypassing()) { + Access access = fme.getFaction().getAccess(fme, PermissableAction.SPAWNER); + if (access != Access.ALLOW && fme.getRole() != Role.LEADER) { + fme.msg(TL.GENERIC_FPERM_NOPERMISSION, "mine spawners"); + return; + } + } + } + } + + @EventHandler + public void onFarmLandDamage(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + if (!playerCanBuildDestroyBlock(player, event.getBlock().getLocation(), PermissableAction.DESTROY.name(), true)) { + FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock().getLocation())); + Faction myFaction = me.getFaction(); + + me.msg("You can't jump on farmland in the territory of " + otherFaction.getTag(myFaction)); + event.setCancelled(true); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java index ff710b86..36505c0c 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java @@ -19,192 +19,192 @@ import java.util.logging.Level; public class FactionsChatListener implements Listener { - // this is for handling slashless command usage and faction/alliance chat, set at lowest priority so Factions gets to them first - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerEarlyChat(AsyncPlayerChatEvent event) { - Player talkingPlayer = event.getPlayer(); - String msg = event.getMessage(); - FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); - ChatMode chat = me.getChatMode(); - // Is the player entering a password for a warp? - if (me.isEnteringPassword()) { - event.setCancelled(true); - me.sendMessage(ChatColor.DARK_GRAY + event.getMessage().replaceAll("(?s).", "*")); - if (me.getFaction().isWarpPassword(me.getEnteringWarp(), event.getMessage())) { - doWarmup(me.getEnteringWarp(), me); - } else { - // Invalid Password - me.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); - } - me.setEnteringPassword(false, ""); - return; - } + // this is for handling slashless command usage and faction/alliance chat, set at lowest priority so Factions gets to them first + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerEarlyChat(AsyncPlayerChatEvent event) { + Player talkingPlayer = event.getPlayer(); + String msg = event.getMessage(); + FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); + ChatMode chat = me.getChatMode(); + // Is the player entering a password for a warp? + if (me.isEnteringPassword()) { + event.setCancelled(true); + me.sendMessage(ChatColor.DARK_GRAY + event.getMessage().replaceAll("(?s).", "*")); + if (me.getFaction().isWarpPassword(me.getEnteringWarp(), event.getMessage())) { + doWarmup(me.getEnteringWarp(), me); + } else { + // Invalid Password + me.msg(TL.COMMAND_FWARP_INVALID_PASSWORD); + } + me.setEnteringPassword(false, ""); + return; + } - //Is it a MOD chat - if (chat == ChatMode.MOD) { - Faction myFaction = me.getFaction(); + //Is it a MOD chat + if (chat == ChatMode.MOD) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.modChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); + String message = String.format(Conf.modChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); - //Send to all mods - if (me.getRole().isAtLeast(Role.MODERATOR)) { - // Iterates only through the factions' members so we enhance performance. - for (FPlayer fplayer : myFaction.getFPlayers()) { - if (fplayer.getRole().isAtLeast(Role.MODERATOR)) { - fplayer.sendMessage(message); - } else if (fplayer.isSpyingChat() && me != fplayer) { - fplayer.sendMessage("[MCspy]: " + message); - } - } - } else { - // Just in case player gets demoted while in faction chat. - me.msg(TL.COMMAND_CHAT_MOD_ONLY); - event.setCancelled(true); - return; - } + //Send to all mods + if (me.getRole().isAtLeast(Role.MODERATOR)) { + // Iterates only through the factions' members so we enhance performance. + for (FPlayer fplayer : myFaction.getFPlayers()) { + if (fplayer.getRole().isAtLeast(Role.MODERATOR)) { + fplayer.sendMessage(message); + } else if (fplayer.isSpyingChat() && me != fplayer) { + fplayer.sendMessage("[MCspy]: " + message); + } + } + } else { + // Just in case player gets demoted while in faction chat. + me.msg(TL.COMMAND_CHAT_MOD_ONLY); + event.setCancelled(true); + return; + } - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("Mod Chat: " + message)); + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("Mod Chat: " + message)); - event.setCancelled(true); - } else if (chat == ChatMode.FACTION) { - Faction myFaction = me.getFaction(); + event.setCancelled(true); + } else if (chat == ChatMode.FACTION) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.factionChatFormat, me.describeTo(myFaction), msg); - myFaction.sendMessage(message); + String message = String.format(Conf.factionChatFormat, me.describeTo(myFaction), msg); + myFaction.sendMessage(message); - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("FactionChat " + myFaction.getTag() + ": " + message)); + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("FactionChat " + myFaction.getTag() + ": " + message)); - //Send to any players who are spying chat - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (fplayer.isSpyingChat() && fplayer.getFaction() != myFaction && me != fplayer) { - fplayer.sendMessage("[FCspy] " + myFaction.getTag() + ": " + message); - } - } + //Send to any players who are spying chat + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.isSpyingChat() && fplayer.getFaction() != myFaction && me != fplayer) { + fplayer.sendMessage("[FCspy] " + myFaction.getTag() + ": " + message); + } + } - event.setCancelled(true); - } else if (chat == ChatMode.ALLIANCE) { - Faction myFaction = me.getFaction(); + event.setCancelled(true); + } else if (chat == ChatMode.ALLIANCE) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.allianceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); + String message = String.format(Conf.allianceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); - //Send message to our own faction - myFaction.sendMessage(message); + //Send message to our own faction + myFaction.sendMessage(message); - //Send to all our allies - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (myFaction.getRelationTo(fplayer) == Relation.ALLY && !fplayer.isIgnoreAllianceChat()) { - fplayer.sendMessage(message); - } else if (fplayer.isSpyingChat() && me != fplayer) { - fplayer.sendMessage("[ACspy]: " + message); - } - } + //Send to all our allies + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (myFaction.getRelationTo(fplayer) == Relation.ALLY && !fplayer.isIgnoreAllianceChat()) { + fplayer.sendMessage(message); + } else if (fplayer.isSpyingChat() && me != fplayer) { + fplayer.sendMessage("[ACspy]: " + message); + } + } - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("AllianceChat: " + message)); + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("AllianceChat: " + message)); - event.setCancelled(true); - } else if (chat == ChatMode.TRUCE) { - Faction myFaction = me.getFaction(); + event.setCancelled(true); + } else if (chat == ChatMode.TRUCE) { + Faction myFaction = me.getFaction(); - String message = String.format(Conf.truceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); + String message = String.format(Conf.truceChatFormat, ChatColor.stripColor(me.getNameAndTag()), msg); - //Send message to our own faction - myFaction.sendMessage(message); + //Send message to our own faction + myFaction.sendMessage(message); - //Send to all our truces - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - if (myFaction.getRelationTo(fplayer) == Relation.TRUCE) { - fplayer.sendMessage(message); - } else if (fplayer.isSpyingChat() && fplayer != me) { - fplayer.sendMessage("[TCspy]: " + message); - } - } + //Send to all our truces + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (myFaction.getRelationTo(fplayer) == Relation.TRUCE) { + fplayer.sendMessage(message); + } else if (fplayer.isSpyingChat() && fplayer != me) { + fplayer.sendMessage("[TCspy]: " + message); + } + } - Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("TruceChat: " + message)); - event.setCancelled(true); - } - } + Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("TruceChat: " + message)); + event.setCancelled(true); + } + } - // this is for handling insertion of the player's faction tag, set at highest priority to give other plugins a chance to modify chat first - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerChat(AsyncPlayerChatEvent event) { - // Are we to insert the Faction tag into the format? - // If we are not to insert it - we are done. - if (!Conf.chatTagEnabled || Conf.chatTagHandledByAnotherPlugin) { - return; - } + // this is for handling insertion of the player's faction tag, set at highest priority to give other plugins a chance to modify chat first + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerChat(AsyncPlayerChatEvent event) { + // Are we to insert the Faction tag into the format? + // If we are not to insert it - we are done. + if (!Conf.chatTagEnabled || Conf.chatTagHandledByAnotherPlugin) { + return; + } - Player talkingPlayer = event.getPlayer(); - String msg = event.getMessage(); - String eventFormat = event.getFormat(); - FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); - int InsertIndex; + Player talkingPlayer = event.getPlayer(); + String msg = event.getMessage(); + String eventFormat = event.getFormat(); + FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); + int InsertIndex; - if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString)) { - // we're using the "replace" method of inserting the faction tags - if (eventFormat.contains("[FACTION_TITLE]")) { - eventFormat = eventFormat.replace("[FACTION_TITLE]", me.getTitle()); - } + if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString)) { + // we're using the "replace" method of inserting the faction tags + if (eventFormat.contains("[FACTION_TITLE]")) { + eventFormat = eventFormat.replace("[FACTION_TITLE]", me.getTitle()); + } - InsertIndex = eventFormat.indexOf(Conf.chatTagReplaceString); - eventFormat = eventFormat.replace(Conf.chatTagReplaceString, ""); - Conf.chatTagPadAfter = false; - Conf.chatTagPadBefore = false; - } else if (!Conf.chatTagInsertAfterString.isEmpty() && eventFormat.contains(Conf.chatTagInsertAfterString)) { - // we're using the "insert after string" method - InsertIndex = eventFormat.indexOf(Conf.chatTagInsertAfterString) + Conf.chatTagInsertAfterString.length(); - } else if (!Conf.chatTagInsertBeforeString.isEmpty() && eventFormat.contains(Conf.chatTagInsertBeforeString)) { - // we're using the "insert before string" method - InsertIndex = eventFormat.indexOf(Conf.chatTagInsertBeforeString); - } else { - // we'll fall back to using the index place method - InsertIndex = Conf.chatTagInsertIndex; - if (InsertIndex > eventFormat.length()) { - return; - } - } + InsertIndex = eventFormat.indexOf(Conf.chatTagReplaceString); + eventFormat = eventFormat.replace(Conf.chatTagReplaceString, ""); + Conf.chatTagPadAfter = false; + Conf.chatTagPadBefore = false; + } else if (!Conf.chatTagInsertAfterString.isEmpty() && eventFormat.contains(Conf.chatTagInsertAfterString)) { + // we're using the "insert after string" method + InsertIndex = eventFormat.indexOf(Conf.chatTagInsertAfterString) + Conf.chatTagInsertAfterString.length(); + } else if (!Conf.chatTagInsertBeforeString.isEmpty() && eventFormat.contains(Conf.chatTagInsertBeforeString)) { + // we're using the "insert before string" method + InsertIndex = eventFormat.indexOf(Conf.chatTagInsertBeforeString); + } else { + // we'll fall back to using the index place method + InsertIndex = Conf.chatTagInsertIndex; + if (InsertIndex > eventFormat.length()) { + return; + } + } - String formatStart = eventFormat.substring(0, InsertIndex) + ((Conf.chatTagPadBefore && !me.getChatTag().isEmpty()) ? " " : ""); - String formatEnd = ((Conf.chatTagPadAfter && !me.getChatTag().isEmpty()) ? " " : "") + eventFormat.substring(InsertIndex); + String formatStart = eventFormat.substring(0, InsertIndex) + ((Conf.chatTagPadBefore && !me.getChatTag().isEmpty()) ? " " : ""); + String formatEnd = ((Conf.chatTagPadAfter && !me.getChatTag().isEmpty()) ? " " : "") + eventFormat.substring(InsertIndex); - String nonColoredMsgFormat = formatStart + me.getChatTag().trim() + formatEnd; + String nonColoredMsgFormat = formatStart + me.getChatTag().trim() + formatEnd; - // Relation Colored? - if (Conf.chatTagRelationColored) { - for (Player listeningPlayer : event.getRecipients()) { - FPlayer you = FPlayers.getInstance().getByPlayer(listeningPlayer); - String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd; - try { - listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); - } catch (UnknownFormatConversionException ex) { - Conf.chatTagInsertIndex = 0; - SavageFactions.plugin.log(Level.SEVERE, "Critical error in chat message formatting!"); - SavageFactions.plugin.log(Level.SEVERE, "NOTE: This has been automatically fixed right now by setting chatTagInsertIndex to 0."); - SavageFactions.plugin.log(Level.SEVERE, "For a more proper fix, please read this regarding chat configuration: http://massivecraft.com/plugins/factions/config#Chat_configuration"); - return; - } - } + // Relation Colored? + if (Conf.chatTagRelationColored) { + for (Player listeningPlayer : event.getRecipients()) { + FPlayer you = FPlayers.getInstance().getByPlayer(listeningPlayer); + String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd; + try { + listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); + } catch (UnknownFormatConversionException ex) { + Conf.chatTagInsertIndex = 0; + SavageFactions.plugin.log(Level.SEVERE, "Critical error in chat message formatting!"); + SavageFactions.plugin.log(Level.SEVERE, "NOTE: This has been automatically fixed right now by setting chatTagInsertIndex to 0."); + SavageFactions.plugin.log(Level.SEVERE, "For a more proper fix, please read this regarding chat configuration: http://massivecraft.com/plugins/factions/config#Chat_configuration"); + return; + } + } - // Messages are sent to players individually - // This still leaves a chance for other plugins to pick it up - event.getRecipients().clear(); - } - // Message with no relation color. - event.setFormat(nonColoredMsgFormat); - } + // Messages are sent to players individually + // This still leaves a chance for other plugins to pick it up + event.getRecipients().clear(); + } + // Message with no relation color. + event.setFormat(nonColoredMsgFormat); + } - private void doWarmup(final String warp, final FPlayer fme) { - WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); - if (player != null) { - player.teleport(fme.getFaction().getWarp(warp).getLocation()); - fme.msg(TL.COMMAND_FWARP_WARPED, warp); - } - } - }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); - } + private void doWarmup(final String warp, final FPlayer fme) { + WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { + @Override + public void run() { + Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); + if (player != null) { + player.teleport(fme.getFaction().getWarp(warp).getLocation()); + fme.msg(TL.COMMAND_FWARP_WARPED, warp); + } + } + }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java index 7ba67a2d..c54a7894 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -31,504 +31,504 @@ import java.util.*; public class FactionsEntityListener implements Listener { - private static final Set badPotionEffects = new LinkedHashSet<>(Arrays.asList(PotionEffectType.BLINDNESS, PotionEffectType.CONFUSION, PotionEffectType.HARM, PotionEffectType.HUNGER, PotionEffectType.POISON, PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.WEAKNESS, PotionEffectType.WITHER)); - - @EventHandler(priority = EventPriority.NORMAL) - public void onEntityDeath(EntityDeathEvent event) { - Entity entity = event.getEntity(); - if (!(entity instanceof Player)) { - return; - } - - Player player = (Player) entity; - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - Faction faction = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); - - PowerLossEvent powerLossEvent = new PowerLossEvent(faction, fplayer); - // Check for no power loss conditions - if (faction.isWarZone()) { - // war zones always override worldsNoPowerLoss either way, thus this layout - if (!Conf.warZonePowerLoss) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WARZONE.toString()); - powerLossEvent.setCancelled(true); - } - if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { - powerLossEvent.setMessage(TL.PLAYER_POWER_LOSS_WARZONE.toString()); - } - } else if (faction.isWilderness() && !Conf.wildernessPowerLoss && !Conf.worldsNoWildernessProtection.contains(player.getWorld().getName())) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WILDERNESS.toString()); - powerLossEvent.setCancelled(true); - } else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WORLD.toString()); - powerLossEvent.setCancelled(true); - } else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful()) { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_PEACEFUL.toString()); - powerLossEvent.setCancelled(true); - } else { - powerLossEvent.setMessage(TL.PLAYER_POWER_NOW.toString()); - } - - // call Event - Bukkit.getPluginManager().callEvent(powerLossEvent); - - // Call player onDeath if the event is not cancelled - if (!powerLossEvent.isCancelled()) { - fplayer.onDeath(); - } - // Send the message from the powerLossEvent - final String msg = powerLossEvent.getMessage(); - if (msg != null && !msg.isEmpty()) { - fplayer.msg(msg, fplayer.getPowerRounded(), fplayer.getPowerMaxRounded()); - } - } - - /** - * Who can I hurt? I can never hurt members or allies. I can always hurt enemies. I can hurt neutrals as long as - * they are outside their own territory. - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityDamage(EntityDamageEvent event) { - if (event instanceof EntityDamageByEntityEvent) { - EntityDamageByEntityEvent sub = (EntityDamageByEntityEvent) event; - if (!this.canDamagerHurtDamagee(sub, true)) { - event.setCancelled(true); - } - // event is not cancelled by factions - - Entity damagee = sub.getEntity(); - Entity damager = sub.getDamager(); - if (damagee instanceof Player) { - if (damager instanceof Player) { - FPlayer fdamager = FPlayers.getInstance().getByPlayer((Player) damager); - FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); - if ((fdamagee.getRelationTo(fdamager) == Relation.ALLY) || - (fdamagee.getRelationTo(fdamager) == Relation.TRUCE) || - (fdamagee.getFaction() == fdamager.getFaction())) { - return; - } - } else { - - // this triggers if damagee is a player and damager is mob ( so like if a skeleton hits u ) - if (damager instanceof Projectile) { - // this will trigger if the damager is a projectile - if (((Projectile) damager).getShooter() instanceof Player) { - Player damagerPlayer = (Player) ((Projectile) damager).getShooter(); - FPlayer fdamager = FPlayers.getInstance().getByPlayer(damagerPlayer); - FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); - Relation relation = fdamager.getRelationTo(fdamagee); - if (relation == Relation.ALLY || relation == Relation.TRUCE || - fdamager.getFaction() == fdamagee.getFaction()) { - // this should disable the fly so - return; - } - } else { - // this should trigger if the attacker shootin the arrow is a mob - return; - } - - } - } - } else { - // Protect armor stands/item frames from being damaged in protected territories - if (damagee.getType() == EntityType.ITEM_FRAME || damagee.getType() == EntityType.ARMOR_STAND) { - // Manage projectiles launched by players - if (damager instanceof Projectile && ((Projectile) damager).getShooter() instanceof Entity) { - damager = (Entity) ((Projectile) damager).getShooter(); - } - - // Run the check for a player - if (damager instanceof Player) { - // Generate the action message. - String entityAction; - - if (damagee.getType() == EntityType.ITEM_FRAME) { - entityAction = "item frames"; - } else { - entityAction = "armor stands"; - } - - if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) damager, damagee.getLocation(), "destroy " + entityAction, false)) { - event.setCancelled(true); - } - } else { - // we don't want to let mobs/arrows destroy item frames/armor stands - // so we only have to run the check as if there had been an explosion at the damager location - if (!this.checkExplosionForBlock(damager, damagee.getLocation().getBlock())) { - event.setCancelled(true); - } - } - - // we don't need to go after - return; - } - - //this one should trigger if something other than a player takes damage - if (damager instanceof Player) { - // now itll only go here if the damage is dealt by a player - return; - // we cancel it so fly isnt removed when you hit a mob etc - } - } - if (damagee != null && damagee instanceof Player) { - cancelFStuckTeleport((Player) damagee); - cancelFFly((Player) damagee); - FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damagee); - if (fplayer.isInspectMode()) { - fplayer.setInspectMode(false); - fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); - } - } - if (damager instanceof Player) { - cancelFStuckTeleport((Player) damager); - cancelFFly((Player) damager); - FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damager); - if (fplayer.isInspectMode()) { - fplayer.setInspectMode(false); - fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); - } - } - } else if (Conf.safeZonePreventAllDamageToPlayers && isPlayerInSafeZone(event.getEntity())) { - // Players can not take any damage in a Safe Zone - event.setCancelled(true); - } else if (event.getCause() == EntityDamageEvent.DamageCause.FALL && event.getEntity() instanceof Player) { - Player player = (Player) event.getEntity(); - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer != null && !fPlayer.shouldTakeFallDamage()) { - event.setCancelled(true); // Falling after /f fly - } - } - - // entity took generic damage? - Entity entity = event.getEntity(); - if (entity instanceof Player) { - Player player = (Player) entity; - FPlayer me = FPlayers.getInstance().getByPlayer(player); - cancelFStuckTeleport(player); - if (me.isWarmingUp()) { - me.clearWarmup(); - me.msg(TL.WARMUPS_CANCELLED); - } - } - } - - private void cancelFFly(Player player) { - if (player == null) { - return; - } - - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer.isFlying()) { - fPlayer.setFFlying(false, true); - } - } - - public void cancelFStuckTeleport(Player player) { - if (player == null) { - return; - } - UUID uuid = player.getUniqueId(); - if (SavageFactions.plugin.getStuckMap().containsKey(uuid)) { - FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_STUCK_CANCELLED); - SavageFactions.plugin.getStuckMap().remove(uuid); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityExplode(EntityExplodeEvent event) { - Entity boomer = event.getEntity(); - - // Before we need to check the location where the block is placed - if (!this.checkExplosionForBlock(boomer, event.getLocation().getBlock())) { - event.setCancelled(true); - return; - } - - // Loop the blocklist to run checks on each aimed block - Iterator blockList = event.blockList().iterator(); - - while (blockList.hasNext()) { - Block block = blockList.next(); - - if (!this.checkExplosionForBlock(boomer, block)) { - // The block don't have to explode - blockList.remove(); - } - } - - // Cancel the event if no block will explode - if (event.blockList().isEmpty()) { - event.setCancelled(true); - - // Or handle the exploit of TNT in water/lava - } else if ((boomer instanceof TNTPrimed || boomer instanceof ExplosiveMinecart) && Conf.handleExploitTNTWaterlog) { - // TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior, but... - // this change below provides workaround for waterwalling providing perfect protection, - // and makes cheap (non-obsidian) TNT cannons require minor maintenance between shots - Block center = event.getLocation().getBlock(); - - if (center.isLiquid()) { - // a single surrounding block in all 6 directions is broken if the material is weak enough - List targets = new ArrayList<>(); - targets.add(center.getRelative(0, 0, 1)); - targets.add(center.getRelative(0, 0, -1)); - targets.add(center.getRelative(0, 1, 0)); - targets.add(center.getRelative(0, -1, 0)); - targets.add(center.getRelative(1, 0, 0)); - targets.add(center.getRelative(-1, 0, 0)); - - for (Block target : targets) { - @SuppressWarnings("deprecation") - int id = target.getType().getId(); - // ignore air, bedrock, water, lava, obsidian, enchanting table, etc.... too bad we can't get a blast resistance value through Bukkit yet - if (id != 0 && (id < 7 || id > 11) && id != 49 && id != 90 && id != 116 && id != 119 && id != 120 && id != 130) { - target.breakNaturally(); - } - } - } - } - } - - private boolean checkExplosionForBlock(Entity boomer, Block block) { - Faction faction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); - - if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) { - // faction is peaceful and has explosions set to disabled - return false; - } - - boolean online = faction.hasPlayersOnline(); - - if (boomer instanceof Creeper && ((faction.isWilderness() && Conf.wildernessBlockCreepers && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || - (faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline)) || - (faction.isWarZone() && Conf.warZoneBlockCreepers) || - faction.isSafeZone())) { - // creeper which needs prevention - return false; - } else if ( - // it's a bit crude just using fireball protection for Wither boss too, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever - (boomer instanceof Fireball || boomer instanceof WitherSkull || boomer instanceof Wither) && ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || - (faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || - (faction.isWarZone() && Conf.warZoneBlockFireballs) || - faction.isSafeZone())) { - // ghast fireball which needs prevention - return false; - } else - return (!(boomer instanceof TNTPrimed) && !(boomer instanceof ExplosiveMinecart)) || ((!faction.isWilderness() || !Conf.wildernessBlockTNT || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) && - (!faction.isNormal() || (online ? !Conf.territoryBlockTNT : !Conf.territoryBlockTNTWhenOffline)) && - (!faction.isWarZone() || !Conf.warZoneBlockTNT) && - (!faction.isSafeZone() || !Conf.safeZoneBlockTNT)); - - // No condition retained, destroy the block! - } - - // mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { - EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0d); - if (!this.canDamagerHurtDamagee(sub, false)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPotionSplashEvent(PotionSplashEvent event) { - // see if the potion has a harmful effect - boolean badjuju = false; - for (PotionEffect effect : event.getPotion().getEffects()) { - if (badPotionEffects.contains(effect.getType())) { - badjuju = true; - break; - } - } - if (!badjuju) { - return; - } - - ProjectileSource thrower = event.getPotion().getShooter(); - if (!(thrower instanceof Entity)) { - return; - } - - if (thrower instanceof Player) { - Player player = (Player) thrower; - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (badjuju && fPlayer.getFaction().isPeaceful()) { - event.setCancelled(true); - return; - } - } - - // scan through affected entities to make sure they're all valid targets - for (LivingEntity target : event.getAffectedEntities()) { - EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent((Entity) thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0); - if (!this.canDamagerHurtDamagee(sub, true)) { - event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works - } - } - } - - public boolean isPlayerInSafeZone(Entity damagee) { - if (!(damagee instanceof Player)) { - return false; - } - return Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone(); - } - - public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub) { - return canDamagerHurtDamagee(sub, true); - } - - public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub, boolean notify) { - Entity damager = sub.getDamager(); - Entity damagee = sub.getEntity(); - - if (!(damagee instanceof Player)) { - return true; - } - - FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee); - - if (defender == null || defender.getPlayer() == null) { - return true; - } - - Location defenderLoc = defender.getPlayer().getLocation(); - Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc)); - - // for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source - if (damager instanceof Projectile) { - Projectile projectile = (Projectile) damager; - - if (!(projectile.getShooter() instanceof Entity)) { - return true; - } - - damager = (Entity) projectile.getShooter(); - } - - if (damager == damagee) // ender pearl usage and other self-inflicted damage - { - return true; - } - - // Players can not take attack damage in a SafeZone, or possibly peaceful territory - if (defLocFaction.noPvPInTerritory()) { - if (damager instanceof Player) { - if (notify) { - FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); - attacker.msg(TL.PLAYER_CANTHURT, (defLocFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); - } - return false; - } - return !defLocFaction.noMonstersInTerritory(); - } - - if (!(damager instanceof Player)) { - return true; - } - - FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); - - if (attacker == null || attacker.getPlayer() == null) { - return true; - } - - if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) { - return true; - } - - if (attacker.hasLoginPvpDisabled()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_LOGIN, Conf.noPVPDamageToOthersForXSecondsAfterLogin); - } - return false; - } - - Faction locFaction = Board.getInstance().getFactionAt(new FLocation(attacker)); - - // so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be? - if (locFaction.noPvPInTerritory()) { - if (notify) { - attacker.msg(TL.PLAYER_CANTHURT, (locFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); - } - return false; - } - - if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) { - return true; - } - - if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) { - return true; - } - - Faction defendFaction = defender.getFaction(); - Faction attackFaction = attacker.getFaction(); - - if (attackFaction.isWilderness() && Conf.disablePVPForFactionlessPlayers) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_REQUIREFACTION); - } - return false; - } else if (defendFaction.isWilderness()) { - if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand) { - // Allow PVP vs. Factionless in attacker's faction territory - return true; - } else if (Conf.disablePVPForFactionlessPlayers) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_FACTIONLESS); - } - return false; - } - } - - if (defendFaction.isPeaceful()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_PEACEFUL); - } - return false; - } else if (attackFaction.isPeaceful()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_PEACEFUL); - } - return false; - } - - Relation relation = defendFaction.getRelationTo(attackFaction); - - // You can not hurt neutral factions - if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_NEUTRAL); - } - return false; - } - - // Players without faction may be hurt anywhere - if (!defender.hasFaction()) { - return true; - } - - // You can never hurt faction members or allies - if (relation.isMember() || relation.isAlly()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_CANTHURT, defender.describeTo(attacker)); - } - return false; - } - - boolean ownTerritory = defender.isInOwnTerritory(); - - // You can not hurt neutrals in their own territory. - if (ownTerritory && relation.isNeutral()) { - if (notify) { - attacker.msg(TL.PLAYER_PVP_NEUTRALFAIL, defender.describeTo(attacker)); - defender.msg(TL.PLAYER_PVP_TRIED, attacker.describeTo(defender, true)); - } - return false; - } - - // Damage will be dealt. However check if the damage should be reduced. + private static final Set badPotionEffects = new LinkedHashSet<>(Arrays.asList(PotionEffectType.BLINDNESS, PotionEffectType.CONFUSION, PotionEffectType.HARM, PotionEffectType.HUNGER, PotionEffectType.POISON, PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.WEAKNESS, PotionEffectType.WITHER)); + + @EventHandler(priority = EventPriority.NORMAL) + public void onEntityDeath(EntityDeathEvent event) { + Entity entity = event.getEntity(); + if (!(entity instanceof Player)) { + return; + } + + Player player = (Player) entity; + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + Faction faction = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); + + PowerLossEvent powerLossEvent = new PowerLossEvent(faction, fplayer); + // Check for no power loss conditions + if (faction.isWarZone()) { + // war zones always override worldsNoPowerLoss either way, thus this layout + if (!Conf.warZonePowerLoss) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WARZONE.toString()); + powerLossEvent.setCancelled(true); + } + if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { + powerLossEvent.setMessage(TL.PLAYER_POWER_LOSS_WARZONE.toString()); + } + } else if (faction.isWilderness() && !Conf.wildernessPowerLoss && !Conf.worldsNoWildernessProtection.contains(player.getWorld().getName())) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WILDERNESS.toString()); + powerLossEvent.setCancelled(true); + } else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WORLD.toString()); + powerLossEvent.setCancelled(true); + } else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful()) { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_PEACEFUL.toString()); + powerLossEvent.setCancelled(true); + } else { + powerLossEvent.setMessage(TL.PLAYER_POWER_NOW.toString()); + } + + // call Event + Bukkit.getPluginManager().callEvent(powerLossEvent); + + // Call player onDeath if the event is not cancelled + if (!powerLossEvent.isCancelled()) { + fplayer.onDeath(); + } + // Send the message from the powerLossEvent + final String msg = powerLossEvent.getMessage(); + if (msg != null && !msg.isEmpty()) { + fplayer.msg(msg, fplayer.getPowerRounded(), fplayer.getPowerMaxRounded()); + } + } + + /** + * Who can I hurt? I can never hurt members or allies. I can always hurt enemies. I can hurt neutrals as long as + * they are outside their own territory. + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityDamage(EntityDamageEvent event) { + if (event instanceof EntityDamageByEntityEvent) { + EntityDamageByEntityEvent sub = (EntityDamageByEntityEvent) event; + if (!this.canDamagerHurtDamagee(sub, true)) { + event.setCancelled(true); + } + // event is not cancelled by factions + + Entity damagee = sub.getEntity(); + Entity damager = sub.getDamager(); + if (damagee instanceof Player) { + if (damager instanceof Player) { + FPlayer fdamager = FPlayers.getInstance().getByPlayer((Player) damager); + FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); + if ((fdamagee.getRelationTo(fdamager) == Relation.ALLY) || + (fdamagee.getRelationTo(fdamager) == Relation.TRUCE) || + (fdamagee.getFaction() == fdamager.getFaction())) { + return; + } + } else { + + // this triggers if damagee is a player and damager is mob ( so like if a skeleton hits u ) + if (damager instanceof Projectile) { + // this will trigger if the damager is a projectile + if (((Projectile) damager).getShooter() instanceof Player) { + Player damagerPlayer = (Player) ((Projectile) damager).getShooter(); + FPlayer fdamager = FPlayers.getInstance().getByPlayer(damagerPlayer); + FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee); + Relation relation = fdamager.getRelationTo(fdamagee); + if (relation == Relation.ALLY || relation == Relation.TRUCE || + fdamager.getFaction() == fdamagee.getFaction()) { + // this should disable the fly so + return; + } + } else { + // this should trigger if the attacker shootin the arrow is a mob + return; + } + + } + } + } else { + // Protect armor stands/item frames from being damaged in protected territories + if (damagee.getType() == EntityType.ITEM_FRAME || damagee.getType() == EntityType.ARMOR_STAND) { + // Manage projectiles launched by players + if (damager instanceof Projectile && ((Projectile) damager).getShooter() instanceof Entity) { + damager = (Entity) ((Projectile) damager).getShooter(); + } + + // Run the check for a player + if (damager instanceof Player) { + // Generate the action message. + String entityAction; + + if (damagee.getType() == EntityType.ITEM_FRAME) { + entityAction = "item frames"; + } else { + entityAction = "armor stands"; + } + + if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) damager, damagee.getLocation(), "destroy " + entityAction, false)) { + event.setCancelled(true); + } + } else { + // we don't want to let mobs/arrows destroy item frames/armor stands + // so we only have to run the check as if there had been an explosion at the damager location + if (!this.checkExplosionForBlock(damager, damagee.getLocation().getBlock())) { + event.setCancelled(true); + } + } + + // we don't need to go after + return; + } + + //this one should trigger if something other than a player takes damage + if (damager instanceof Player) { + // now itll only go here if the damage is dealt by a player + return; + // we cancel it so fly isnt removed when you hit a mob etc + } + } + if (damagee != null && damagee instanceof Player) { + cancelFStuckTeleport((Player) damagee); + cancelFFly((Player) damagee); + FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damagee); + if (fplayer.isInspectMode()) { + fplayer.setInspectMode(false); + fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); + } + } + if (damager instanceof Player) { + cancelFStuckTeleport((Player) damager); + cancelFFly((Player) damager); + FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damager); + if (fplayer.isInspectMode()) { + fplayer.setInspectMode(false); + fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG); + } + } + } else if (Conf.safeZonePreventAllDamageToPlayers && isPlayerInSafeZone(event.getEntity())) { + // Players can not take any damage in a Safe Zone + event.setCancelled(true); + } else if (event.getCause() == EntityDamageEvent.DamageCause.FALL && event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer != null && !fPlayer.shouldTakeFallDamage()) { + event.setCancelled(true); // Falling after /f fly + } + } + + // entity took generic damage? + Entity entity = event.getEntity(); + if (entity instanceof Player) { + Player player = (Player) entity; + FPlayer me = FPlayers.getInstance().getByPlayer(player); + cancelFStuckTeleport(player); + if (me.isWarmingUp()) { + me.clearWarmup(); + me.msg(TL.WARMUPS_CANCELLED); + } + } + } + + private void cancelFFly(Player player) { + if (player == null) { + return; + } + + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer.isFlying()) { + fPlayer.setFFlying(false, true); + } + } + + public void cancelFStuckTeleport(Player player) { + if (player == null) { + return; + } + UUID uuid = player.getUniqueId(); + if (SavageFactions.plugin.getStuckMap().containsKey(uuid)) { + FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_STUCK_CANCELLED); + SavageFactions.plugin.getStuckMap().remove(uuid); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityExplode(EntityExplodeEvent event) { + Entity boomer = event.getEntity(); + + // Before we need to check the location where the block is placed + if (!this.checkExplosionForBlock(boomer, event.getLocation().getBlock())) { + event.setCancelled(true); + return; + } + + // Loop the blocklist to run checks on each aimed block + Iterator blockList = event.blockList().iterator(); + + while (blockList.hasNext()) { + Block block = blockList.next(); + + if (!this.checkExplosionForBlock(boomer, block)) { + // The block don't have to explode + blockList.remove(); + } + } + + // Cancel the event if no block will explode + if (event.blockList().isEmpty()) { + event.setCancelled(true); + + // Or handle the exploit of TNT in water/lava + } else if ((boomer instanceof TNTPrimed || boomer instanceof ExplosiveMinecart) && Conf.handleExploitTNTWaterlog) { + // TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior, but... + // this change below provides workaround for waterwalling providing perfect protection, + // and makes cheap (non-obsidian) TNT cannons require minor maintenance between shots + Block center = event.getLocation().getBlock(); + + if (center.isLiquid()) { + // a single surrounding block in all 6 directions is broken if the material is weak enough + List targets = new ArrayList<>(); + targets.add(center.getRelative(0, 0, 1)); + targets.add(center.getRelative(0, 0, -1)); + targets.add(center.getRelative(0, 1, 0)); + targets.add(center.getRelative(0, -1, 0)); + targets.add(center.getRelative(1, 0, 0)); + targets.add(center.getRelative(-1, 0, 0)); + + for (Block target : targets) { + @SuppressWarnings("deprecation") + int id = target.getType().getId(); + // ignore air, bedrock, water, lava, obsidian, enchanting table, etc.... too bad we can't get a blast resistance value through Bukkit yet + if (id != 0 && (id < 7 || id > 11) && id != 49 && id != 90 && id != 116 && id != 119 && id != 120 && id != 130) { + target.breakNaturally(); + } + } + } + } + } + + private boolean checkExplosionForBlock(Entity boomer, Block block) { + Faction faction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); + + if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) { + // faction is peaceful and has explosions set to disabled + return false; + } + + boolean online = faction.hasPlayersOnline(); + + if (boomer instanceof Creeper && ((faction.isWilderness() && Conf.wildernessBlockCreepers && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || + (faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline)) || + (faction.isWarZone() && Conf.warZoneBlockCreepers) || + faction.isSafeZone())) { + // creeper which needs prevention + return false; + } else if ( + // it's a bit crude just using fireball protection for Wither boss too, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever + (boomer instanceof Fireball || boomer instanceof WitherSkull || boomer instanceof Wither) && ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) || + (faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || + (faction.isWarZone() && Conf.warZoneBlockFireballs) || + faction.isSafeZone())) { + // ghast fireball which needs prevention + return false; + } else + return (!(boomer instanceof TNTPrimed) && !(boomer instanceof ExplosiveMinecart)) || ((!faction.isWilderness() || !Conf.wildernessBlockTNT || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) && + (!faction.isNormal() || (online ? !Conf.territoryBlockTNT : !Conf.territoryBlockTNTWhenOffline)) && + (!faction.isWarZone() || !Conf.warZoneBlockTNT) && + (!faction.isSafeZone() || !Conf.safeZoneBlockTNT)); + + // No condition retained, destroy the block! + } + + // mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { + EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0d); + if (!this.canDamagerHurtDamagee(sub, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPotionSplashEvent(PotionSplashEvent event) { + // see if the potion has a harmful effect + boolean badjuju = false; + for (PotionEffect effect : event.getPotion().getEffects()) { + if (badPotionEffects.contains(effect.getType())) { + badjuju = true; + break; + } + } + if (!badjuju) { + return; + } + + ProjectileSource thrower = event.getPotion().getShooter(); + if (!(thrower instanceof Entity)) { + return; + } + + if (thrower instanceof Player) { + Player player = (Player) thrower; + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (badjuju && fPlayer.getFaction().isPeaceful()) { + event.setCancelled(true); + return; + } + } + + // scan through affected entities to make sure they're all valid targets + for (LivingEntity target : event.getAffectedEntities()) { + EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent((Entity) thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0); + if (!this.canDamagerHurtDamagee(sub, true)) { + event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works + } + } + } + + public boolean isPlayerInSafeZone(Entity damagee) { + if (!(damagee instanceof Player)) { + return false; + } + return Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone(); + } + + public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub) { + return canDamagerHurtDamagee(sub, true); + } + + public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub, boolean notify) { + Entity damager = sub.getDamager(); + Entity damagee = sub.getEntity(); + + if (!(damagee instanceof Player)) { + return true; + } + + FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee); + + if (defender == null || defender.getPlayer() == null) { + return true; + } + + Location defenderLoc = defender.getPlayer().getLocation(); + Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc)); + + // for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source + if (damager instanceof Projectile) { + Projectile projectile = (Projectile) damager; + + if (!(projectile.getShooter() instanceof Entity)) { + return true; + } + + damager = (Entity) projectile.getShooter(); + } + + if (damager == damagee) // ender pearl usage and other self-inflicted damage + { + return true; + } + + // Players can not take attack damage in a SafeZone, or possibly peaceful territory + if (defLocFaction.noPvPInTerritory()) { + if (damager instanceof Player) { + if (notify) { + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); + attacker.msg(TL.PLAYER_CANTHURT, (defLocFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); + } + return false; + } + return !defLocFaction.noMonstersInTerritory(); + } + + if (!(damager instanceof Player)) { + return true; + } + + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); + + if (attacker == null || attacker.getPlayer() == null) { + return true; + } + + if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) { + return true; + } + + if (attacker.hasLoginPvpDisabled()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_LOGIN, Conf.noPVPDamageToOthersForXSecondsAfterLogin); + } + return false; + } + + Faction locFaction = Board.getInstance().getFactionAt(new FLocation(attacker)); + + // so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be? + if (locFaction.noPvPInTerritory()) { + if (notify) { + attacker.msg(TL.PLAYER_CANTHURT, (locFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString())); + } + return false; + } + + if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) { + return true; + } + + if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) { + return true; + } + + Faction defendFaction = defender.getFaction(); + Faction attackFaction = attacker.getFaction(); + + if (attackFaction.isWilderness() && Conf.disablePVPForFactionlessPlayers) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_REQUIREFACTION); + } + return false; + } else if (defendFaction.isWilderness()) { + if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand) { + // Allow PVP vs. Factionless in attacker's faction territory + return true; + } else if (Conf.disablePVPForFactionlessPlayers) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_FACTIONLESS); + } + return false; + } + } + + if (defendFaction.isPeaceful()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_PEACEFUL); + } + return false; + } else if (attackFaction.isPeaceful()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_PEACEFUL); + } + return false; + } + + Relation relation = defendFaction.getRelationTo(attackFaction); + + // You can not hurt neutral factions + if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_NEUTRAL); + } + return false; + } + + // Players without faction may be hurt anywhere + if (!defender.hasFaction()) { + return true; + } + + // You can never hurt faction members or allies + if (relation.isMember() || relation.isAlly()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_CANTHURT, defender.describeTo(attacker)); + } + return false; + } + + boolean ownTerritory = defender.isInOwnTerritory(); + + // You can not hurt neutrals in their own territory. + if (ownTerritory && relation.isNeutral()) { + if (notify) { + attacker.msg(TL.PLAYER_PVP_NEUTRALFAIL, defender.describeTo(attacker)); + defender.msg(TL.PLAYER_PVP_TRIED, attacker.describeTo(defender, true)); + } + return false; + } + + // Damage will be dealt. However check if the damage should be reduced. /* if (damage > 0.0 && ownTerritory && Conf.territoryShieldFactor > 0) { double newDamage = Math.ceil(damage * (1D - Conf.territoryShieldFactor)); @@ -541,236 +541,236 @@ public class FactionsEntityListener implements Listener { } } */ - return true; - } + return true; + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onCreatureSpawn(CreatureSpawnEvent event) { - if (event.getLocation() == null) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onCreatureSpawn(CreatureSpawnEvent event) { + if (event.getLocation() == null) { + return; + } - if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { - event.setCancelled(true); - } - } + if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityTarget(EntityTargetEvent event) { - // if there is a target - Entity target = event.getTarget(); - if (target == null) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityTarget(EntityTargetEvent event) { + // if there is a target + Entity target = event.getTarget(); + if (target == null) { + return; + } - // We are interested in blocking targeting for certain mobs: - if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) { - return; - } + // We are interested in blocking targeting for certain mobs: + if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) { + return; + } - // in case the target is in a safe zone. - if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { - event.setCancelled(true); - } - } + // in case the target is in a safe zone. + if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPaintingBreak(HangingBreakEvent event) { - if (event.getCause() == RemoveCause.EXPLOSION) { - Location loc = event.getEntity().getLocation(); - Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); - if (faction.noExplosionsInTerritory()) { - // faction is peaceful and has explosions set to disabled - event.setCancelled(true); - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPaintingBreak(HangingBreakEvent event) { + if (event.getCause() == RemoveCause.EXPLOSION) { + Location loc = event.getEntity().getLocation(); + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); + if (faction.noExplosionsInTerritory()) { + // faction is peaceful and has explosions set to disabled + event.setCancelled(true); + return; + } - boolean online = faction.hasPlayersOnline(); + boolean online = faction.hasPlayersOnline(); - if ((faction.isWilderness() && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()) && (Conf.wildernessBlockCreepers || Conf.wildernessBlockFireballs || Conf.wildernessBlockTNT)) || - (faction.isNormal() && (online ? (Conf.territoryBlockCreepers || Conf.territoryBlockFireballs || Conf.territoryBlockTNT) : (Conf.territoryBlockCreepersWhenOffline || Conf.territoryBlockFireballsWhenOffline || Conf.territoryBlockTNTWhenOffline))) || - (faction.isWarZone() && (Conf.warZoneBlockCreepers || Conf.warZoneBlockFireballs || Conf.warZoneBlockTNT)) || - faction.isSafeZone()) { - // explosion which needs prevention - event.setCancelled(true); - } - } + if ((faction.isWilderness() && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()) && (Conf.wildernessBlockCreepers || Conf.wildernessBlockFireballs || Conf.wildernessBlockTNT)) || + (faction.isNormal() && (online ? (Conf.territoryBlockCreepers || Conf.territoryBlockFireballs || Conf.territoryBlockTNT) : (Conf.territoryBlockCreepersWhenOffline || Conf.territoryBlockFireballsWhenOffline || Conf.territoryBlockTNTWhenOffline))) || + (faction.isWarZone() && (Conf.warZoneBlockCreepers || Conf.warZoneBlockFireballs || Conf.warZoneBlockTNT)) || + faction.isSafeZone()) { + // explosion which needs prevention + event.setCancelled(true); + } + } - if (!(event instanceof HangingBreakByEntityEvent)) { - return; - } + if (!(event instanceof HangingBreakByEntityEvent)) { + return; + } - Entity breaker = ((HangingBreakByEntityEvent) event).getRemover(); - if (!(breaker instanceof Player)) { - return; - } + Entity breaker = ((HangingBreakByEntityEvent) event).getRemover(); + if (!(breaker instanceof Player)) { + return; + } - if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) breaker, event.getEntity().getLocation(), "remove paintings", false)) { - event.setCancelled(true); - } - } + if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) breaker, event.getEntity().getLocation(), "remove paintings", false)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPaintingPlace(HangingPlaceEvent event) { - if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "place paintings", false)) { - event.setCancelled(true); - // Fix: update player's inventory to avoid items glitches - event.getPlayer().updateInventory(); - } - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPaintingPlace(HangingPlaceEvent event) { + if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "place paintings", false)) { + event.setCancelled(true); + // Fix: update player's inventory to avoid items glitches + event.getPlayer().updateInventory(); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityChangeBlock(EntityChangeBlockEvent event) { - Entity entity = event.getEntity(); + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + Entity entity = event.getEntity(); - // for now, only interested in Enderman and Wither boss tomfoolery - if (!(entity instanceof Enderman) && !(entity instanceof Wither)) { - return; - } + // for now, only interested in Enderman and Wither boss tomfoolery + if (!(entity instanceof Enderman) && !(entity instanceof Wither)) { + return; + } - Location loc = event.getBlock().getLocation(); + Location loc = event.getBlock().getLocation(); - if (entity instanceof Enderman) { - if (stopEndermanBlockManipulation(loc)) { - event.setCancelled(true); - } - } else if (entity instanceof Wither) { - Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); - // it's a bit crude just using fireball protection, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever - if ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName())) || - (faction.isNormal() && (faction.hasPlayersOnline() ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || - (faction.isWarZone() && Conf.warZoneBlockFireballs) || - faction.isSafeZone()) { - event.setCancelled(true); - } - } - } + if (entity instanceof Enderman) { + if (stopEndermanBlockManipulation(loc)) { + event.setCancelled(true); + } + } else if (entity instanceof Wither) { + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); + // it's a bit crude just using fireball protection, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever + if ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName())) || + (faction.isNormal() && (faction.hasPlayersOnline() ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || + (faction.isWarZone() && Conf.warZoneBlockFireballs) || + faction.isSafeZone()) { + event.setCancelled(true); + } + } + } - @EventHandler - public void onTravel(PlayerPortalEvent event) { - if (!SavageFactions.plugin.getConfig().getBoolean("portals.limit", false)) { - return; // Don't do anything if they don't want us to. - } + @EventHandler + public void onTravel(PlayerPortalEvent event) { + if (!SavageFactions.plugin.getConfig().getBoolean("portals.limit", false)) { + return; // Don't do anything if they don't want us to. + } - TravelAgent agent = event.getPortalTravelAgent(); + TravelAgent agent = event.getPortalTravelAgent(); - // If they aren't able to find a portal, it'll try to create one. - if (event.useTravelAgent() && agent.getCanCreatePortal() && agent.findPortal(event.getTo()) == null) { - FLocation loc = new FLocation(event.getTo()); - Faction faction = Board.getInstance().getFactionAt(loc); - if (faction.isWilderness()) { - return; // We don't care about wilderness. - } else if (!faction.isNormal() && !event.getPlayer().isOp()) { - // Don't let non ops make portals in safezone or warzone. - event.setCancelled(true); - return; - } + // If they aren't able to find a portal, it'll try to create one. + if (event.useTravelAgent() && agent.getCanCreatePortal() && agent.findPortal(event.getTo()) == null) { + FLocation loc = new FLocation(event.getTo()); + Faction faction = Board.getInstance().getFactionAt(loc); + if (faction.isWilderness()) { + return; // We don't care about wilderness. + } else if (!faction.isNormal() && !event.getPlayer().isOp()) { + // Don't let non ops make portals in safezone or warzone. + event.setCancelled(true); + return; + } - FPlayer fp = FPlayers.getInstance().getByPlayer(event.getPlayer()); - String mininumRelation = SavageFactions.plugin.getConfig().getString("portals.minimum-relation", "MEMBER"); // Defaults to Neutral if typed wrong. - if (!fp.getFaction().getRelationTo(faction).isAtLeast(Relation.fromString(mininumRelation))) { - event.setCancelled(true); - } - } - } + FPlayer fp = FPlayers.getInstance().getByPlayer(event.getPlayer()); + String mininumRelation = SavageFactions.plugin.getConfig().getString("portals.minimum-relation", "MEMBER"); // Defaults to Neutral if typed wrong. + if (!fp.getFaction().getRelationTo(faction).isAtLeast(Relation.fromString(mininumRelation))) { + event.setCancelled(true); + } + } + } - @EventHandler - public void onHit(EntityDamageByEntityEvent e) { - if (e.getDamager() instanceof Player) { - if (e.getEntity() instanceof Player) { - Player victim = (Player) e.getEntity(); - Player attacker = (Player) e.getDamager(); - FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); - FPlayer fattacker = FPlayers.getInstance().getByPlayer(attacker); - if (fattacker.getRelationTo(fvictim) == Relation.TRUCE) { - fattacker.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fattacker)); - e.setCancelled(true); - } - } - } - } + @EventHandler + public void onHit(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Player) { + if (e.getEntity() instanceof Player) { + Player victim = (Player) e.getEntity(); + Player attacker = (Player) e.getDamager(); + FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); + FPlayer fattacker = FPlayers.getInstance().getByPlayer(attacker); + if (fattacker.getRelationTo(fvictim) == Relation.TRUCE) { + fattacker.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fattacker)); + e.setCancelled(true); + } + } + } + } - @EventHandler - public void onBowHit(EntityDamageByEntityEvent e) { - if (e.getDamager() instanceof Projectile) { - if (e.getEntity() instanceof Player) { - Projectile arrow = ((Projectile) e.getDamager()); - if (arrow.getShooter() instanceof Player) { - Player damager = (Player) ((Projectile) e.getDamager()).getShooter(); - Player victim = (Player) e.getEntity(); - FPlayer fdamager = FPlayers.getInstance().getByPlayer(damager); - FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); - if (fvictim.getRelationTo(fdamager) == Relation.TRUCE) { - fdamager.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fdamager)); - e.setCancelled(true); - } - if (fvictim.getRelationTo(fdamager) == Relation.ENEMY) { - if (fvictim.isFlying()) { - fvictim.setFFlying(false, true); - } - } - } - } - } - } + @EventHandler + public void onBowHit(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Projectile) { + if (e.getEntity() instanceof Player) { + Projectile arrow = ((Projectile) e.getDamager()); + if (arrow.getShooter() instanceof Player) { + Player damager = (Player) ((Projectile) e.getDamager()).getShooter(); + Player victim = (Player) e.getEntity(); + FPlayer fdamager = FPlayers.getInstance().getByPlayer(damager); + FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim); + if (fvictim.getRelationTo(fdamager) == Relation.TRUCE) { + fdamager.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fdamager)); + e.setCancelled(true); + } + if (fvictim.getRelationTo(fdamager) == Relation.ENEMY) { + if (fvictim.isFlying()) { + fvictim.setFFlying(false, true); + } + } + } + } + } + } - // For disabling interactions with item frames in another faction's territory - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - // only need to check for item frames - if (event.getRightClicked().getType() != EntityType.ITEM_FRAME) { - return; - } + // For disabling interactions with item frames in another faction's territory + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { + // only need to check for item frames + if (event.getRightClicked().getType() != EntityType.ITEM_FRAME) { + return; + } - Player player = event.getPlayer(); - Entity entity = event.getRightClicked(); + Player player = event.getPlayer(); + Entity entity = event.getRightClicked(); - if (!FactionsBlockListener.playerCanBuildDestroyBlock(player, entity.getLocation(), "use item frames", false)) { - event.setCancelled(true); - } - } + if (!FactionsBlockListener.playerCanBuildDestroyBlock(player, entity.getLocation(), "use item frames", false)) { + event.setCancelled(true); + } + } - // For disabling interactions with armor stands in another faction's territory - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { - Entity entity = event.getRightClicked(); + // For disabling interactions with armor stands in another faction's territory + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { + Entity entity = event.getRightClicked(); - // only need to check for armor stand and item frames - if (entity.getType() != EntityType.ARMOR_STAND) { - return; - } + // only need to check for armor stand and item frames + if (entity.getType() != EntityType.ARMOR_STAND) { + return; + } - if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), entity.getLocation(), "use armor stands", false)) { - event.setCancelled(true); - } - } + if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), entity.getLocation(), "use armor stands", false)) { + event.setCancelled(true); + } + } - private boolean stopEndermanBlockManipulation(Location loc) { - if (loc == null) { - return false; - } - // quick check to see if all Enderman deny options are enabled; if so, no need to check location - if (Conf.wildernessDenyEndermanBlocks && - Conf.territoryDenyEndermanBlocks && - Conf.territoryDenyEndermanBlocksWhenOffline && - Conf.safeZoneDenyEndermanBlocks && - Conf.warZoneDenyEndermanBlocks) { - return true; - } + private boolean stopEndermanBlockManipulation(Location loc) { + if (loc == null) { + return false; + } + // quick check to see if all Enderman deny options are enabled; if so, no need to check location + if (Conf.wildernessDenyEndermanBlocks && + Conf.territoryDenyEndermanBlocks && + Conf.territoryDenyEndermanBlocksWhenOffline && + Conf.safeZoneDenyEndermanBlocks && + Conf.warZoneDenyEndermanBlocks) { + return true; + } - FLocation fLoc = new FLocation(loc); - Faction claimFaction = Board.getInstance().getFactionAt(fLoc); + FLocation fLoc = new FLocation(loc); + Faction claimFaction = Board.getInstance().getFactionAt(fLoc); - if (claimFaction.isWilderness()) { - return Conf.wildernessDenyEndermanBlocks; - } else if (claimFaction.isNormal()) { - return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline; - } else if (claimFaction.isSafeZone()) { - return Conf.safeZoneDenyEndermanBlocks; - } else if (claimFaction.isWarZone()) { - return Conf.warZoneDenyEndermanBlocks; - } + if (claimFaction.isWilderness()) { + return Conf.wildernessDenyEndermanBlocks; + } else if (claimFaction.isNormal()) { + return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline; + } else if (claimFaction.isSafeZone()) { + return Conf.safeZoneDenyEndermanBlocks; + } else if (claimFaction.isWarZone()) { + return Conf.warZoneDenyEndermanBlocks; + } - return false; - } + return false; + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java index 0639d02c..f9ca6adb 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsExploitListener.java @@ -14,52 +14,52 @@ import org.bukkit.event.player.PlayerTeleportEvent; public class FactionsExploitListener implements Listener { - public static boolean clippingThrough(Location target, Location from, double thickness) { - return ((from.getX() > target.getX() && (from.getX() - target.getX() < thickness)) || (target.getX() > from.getX() && (target.getX() - from.getX() < thickness)) || (from.getZ() > target.getZ() && (from.getZ() - target.getZ() < thickness)) || (target.getZ() > from.getZ() && (target.getZ() - from.getZ() < thickness))); - } + public static boolean clippingThrough(Location target, Location from, double thickness) { + return ((from.getX() > target.getX() && (from.getX() - target.getX() < thickness)) || (target.getX() > from.getX() && (target.getX() - from.getX() < thickness)) || (from.getZ() > target.getZ() && (from.getZ() - target.getZ() < thickness)) || (target.getZ() > from.getZ() && (target.getZ() - from.getZ() < thickness))); + } - @SuppressWarnings("deprecation") - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void obsidianGenerator(BlockFromToEvent event) { - if (!Conf.handleExploitObsidianGenerators) { - return; - } + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void obsidianGenerator(BlockFromToEvent event) { + if (!Conf.handleExploitObsidianGenerators) { + return; + } - // thanks to ObGenBlocker and WorldGuard for this method - Block block = event.getToBlock(); - int source = event.getBlock().getType().getId(); - int target = block.getType().getId(); - if ((target == 55 || target == 132) && (source == 0 || source == 10 || source == 11)) { - block.setType(Material.AIR); - } - } + // thanks to ObGenBlocker and WorldGuard for this method + Block block = event.getToBlock(); + int source = event.getBlock().getType().getId(); + int target = block.getType().getId(); + if ((target == 55 || target == 132) && (source == 0 || source == 10 || source == 11)) { + block.setType(Material.AIR); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void enderPearlTeleport(PlayerTeleportEvent event) { - if (!Conf.handleExploitEnderPearlClipping) { - return; - } - if (event.getCause() != PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void enderPearlTeleport(PlayerTeleportEvent event) { + if (!Conf.handleExploitEnderPearlClipping) { + return; + } + if (event.getCause() != PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { + return; + } - // this exploit works when the target location is within 0.31 blocks or so of a door or glass block or similar... - Location target = event.getTo(); - Location from = event.getFrom(); + // this exploit works when the target location is within 0.31 blocks or so of a door or glass block or similar... + Location target = event.getTo(); + Location from = event.getFrom(); - // blocks who occupy less than 1 block width or length wise need to be handled differently - Material mat = event.getTo().getBlock().getType(); - if (((mat == SavageFactions.plugin.THIN_GLASS - || mat == SavageFactions.plugin.IRON_FENCE) && clippingThrough(target, from, 0.65)) - || ((mat == SavageFactions.plugin.FENCE || mat == SavageFactions.plugin.NETHER_FENCE) && clippingThrough(target, from, 0.45))) { - event.setTo(from); - return; - } + // blocks who occupy less than 1 block width or length wise need to be handled differently + Material mat = event.getTo().getBlock().getType(); + if (((mat == SavageFactions.plugin.THIN_GLASS + || mat == SavageFactions.plugin.IRON_FENCE) && clippingThrough(target, from, 0.65)) + || ((mat == SavageFactions.plugin.FENCE || mat == SavageFactions.plugin.NETHER_FENCE) && clippingThrough(target, from, 0.45))) { + event.setTo(from); + return; + } - // simple fix otherwise: ender pearl target locations are standardized to be in the center (X/Z) of the target block, not at the edges - target.setX(target.getBlockX() + 0.5); - target.setZ(target.getBlockZ() + 0.5); - event.setTo(target); + // simple fix otherwise: ender pearl target locations are standardized to be in the center (X/Z) of the target block, not at the edges + target.setX(target.getBlockX() + 0.5); + target.setZ(target.getBlockZ() + 0.5); + event.setTo(target); - } + } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java index 8ba1daa0..1b5b236c 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -48,856 +48,856 @@ import java.util.logging.Level; public class FactionsPlayerListener implements Listener { - HashMap fallMap = new HashMap<>(); - - // Holds the next time a player can have a map shown. - private HashMap showTimes = new HashMap<>(); - // for handling people who repeatedly spam attempts to open a door (or similar) in another faction's territory - private Map interactSpammers = new HashMap<>(); - - public FactionsPlayerListener() { - for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { - initPlayer(player); - } - } - - public static Boolean isSystemFaction(Faction faction) { - return faction.isSafeZone() || - faction.isWarZone() || - faction.isWilderness(); - } - - public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { - String name = player.getName(); - if (Conf.playersWhoBypassAllProtection.contains(name)) { - return true; - } - - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - if (me.isAdminBypassing()) { - return true; - } - - FLocation loc = new FLocation(location); - Faction otherFaction = Board.getInstance().getFactionAt(loc); - Faction myFaction = me.getFaction(); - Relation rel = myFaction.getRelationTo(otherFaction); - - // Also cancel if player doesn't have ownership rights for this claim - if (Conf.ownedAreasEnabled && myFaction == otherFaction && !myFaction.playerHasOwnershipRights(me, loc)) { - if (!justCheck) { - me.msg("You can't use that in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); - } - return false; - } - - if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) { - return true; - } - - if (otherFaction.hasPlayersOnline()) { - if (!Conf.territoryDenyUseageMaterials.contains(material)) { - return true; // Item isn't one we're preventing for online factions. - } - } else { - if (!Conf.territoryDenyUseageMaterialsWhenOffline.contains(material)) { - return true; // Item isn't one we're preventing for offline factions. - } - } - - if (otherFaction.isWilderness()) { - if (!Conf.wildernessDenyUseage || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) { - return true; // This is not faction territory. Use whatever you like here. - } - - if (!justCheck) { - me.msg(TL.PLAYER_USE_WILDERNESS, TextUtil.getMaterialName(material)); - } - - return false; - } else if (otherFaction.isSafeZone()) { - if (!Conf.safeZoneDenyUseage || Permission.MANAGE_SAFE_ZONE.has(player)) { - return true; - } - - if (!justCheck) { - me.msg(TL.PLAYER_USE_SAFEZONE, TextUtil.getMaterialName(material)); - } - - return false; - } else if (otherFaction.isWarZone()) { - if (!Conf.warZoneDenyUseage || Permission.MANAGE_WAR_ZONE.has(player)) { - return true; - } - - if (!justCheck) { - me.msg(TL.PLAYER_USE_WARZONE, TextUtil.getMaterialName(material)); - } - - return false; - } - - // Cancel if we are not in our own territory - if (rel.confDenyUseage()) { - if (!justCheck) { - me.msg(TL.PLAYER_USE_TERRITORY, TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); - } - - return false; - } - - Access access = otherFaction.getAccess(me, PermissableAction.ITEM); - if (access != null && access != Access.UNDEFINED) { - // TODO: Update this once new access values are added other than just allow / deny. - if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { - return true; - } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { - me.msg("You can't use items in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); - return false; - } else if (access == Access.DENY) { - me.msg(TL.GENERIC_NOPERMISSION, PermissableAction.ITEM); - return false; - } - } - - return true; - } - - @SuppressWarnings("deprecation") - public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { - if (Conf.playersWhoBypassAllProtection.contains(player.getName())) - return true; - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - if (me.isAdminBypassing()) - return true; - - Material material = block.getType(); - // Dupe fix. - FLocation loc = new FLocation(block); - Faction otherFaction = Board.getInstance().getFactionAt(loc); - Faction myFaction = me.getFaction(); - Relation rel = myFaction.getRelationTo(otherFaction); - - // no door/chest/whatever protection in wilderness, war zones, or safe zones - if (!otherFaction.isNormal()) - return true; - - if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) - return true; - - if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc) && player.getItemInHand().getType() != null) { - - if (player.getItemInHand().getType().toString().toUpperCase().contains("DOOR")) - return false; - } - - PermissableAction action = null; - - if (SavageFactions.plugin.mc113) { - switch (block.getType()) { - case LEVER: - action = PermissableAction.LEVER; - break; - - case ACACIA_BUTTON: - case BIRCH_BUTTON: - case DARK_OAK_BUTTON: - case JUNGLE_BUTTON: - case OAK_BUTTON: - case SPRUCE_BUTTON: - case STONE_BUTTON: - action = PermissableAction.BUTTON; - break; - - case ACACIA_DOOR: - case BIRCH_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case OAK_DOOR: - case SPRUCE_DOOR: - case DARK_OAK_DOOR: - - case ACACIA_TRAPDOOR: - case BIRCH_TRAPDOOR: - case DARK_OAK_TRAPDOOR: - case IRON_TRAPDOOR: - case JUNGLE_TRAPDOOR: - case OAK_TRAPDOOR: - case SPRUCE_TRAPDOOR: - - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case JUNGLE_FENCE_GATE: - case OAK_FENCE_GATE: - case SPRUCE_FENCE_GATE: - action = PermissableAction.DOOR; - break; - - case CHEST: - case TRAPPED_CHEST: - case CHEST_MINECART: - - case SHULKER_BOX: - case BLACK_SHULKER_BOX: - case BLUE_SHULKER_BOX: - case BROWN_SHULKER_BOX: - case CYAN_SHULKER_BOX: - case GRAY_SHULKER_BOX: - case GREEN_SHULKER_BOX: - case LIGHT_BLUE_SHULKER_BOX: - case LIGHT_GRAY_SHULKER_BOX: - case LIME_SHULKER_BOX: - case MAGENTA_SHULKER_BOX: - case ORANGE_SHULKER_BOX: - case PINK_SHULKER_BOX: - case PURPLE_SHULKER_BOX: - case RED_SHULKER_BOX: - case WHITE_SHULKER_BOX: - case YELLOW_SHULKER_BOX: - - case FURNACE: - case DROPPER: - case DISPENSER: - case ENCHANTING_TABLE: - case BREWING_STAND: - case CAULDRON: - case HOPPER: - case BEACON: - case JUKEBOX: - - case ANVIL: - case CHIPPED_ANVIL: - case DAMAGED_ANVIL: - action = PermissableAction.CONTAINER; - break; - default: - // Check for doors that might have diff material name in old version. - if (block.getType().name().contains("DOOR")) { - action = PermissableAction.DOOR; - } - break; - } - } else { - if (block.getType().toString().toUpperCase().contains("BUTTON")) { - action = PermissableAction.BUTTON; - } - - switch (block.getType()) { - case LEVER: - action = PermissableAction.LEVER; - break; - case DARK_OAK_DOOR: - case ACACIA_DOOR: - case BIRCH_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case SPRUCE_DOOR: - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case JUNGLE_FENCE_GATE: - case SPRUCE_FENCE_GATE: - action = PermissableAction.DOOR; - break; - case CHEST: - case ENDER_CHEST: - case TRAPPED_CHEST: - case DISPENSER: - case ENCHANTING_TABLE: - case DROPPER: - case FURNACE: - case HOPPER: - case ANVIL: - case CHIPPED_ANVIL: - case DAMAGED_ANVIL: - case BREWING_STAND: - action = PermissableAction.CONTAINER; - break; - default: - // Check for doors that might have diff material name in old version. - if (block.getType().name().contains("DOOR")) - action = PermissableAction.DOOR; - break; - } - } - - // We only care about some material types. - if (otherFaction.hasPlayersOnline()) { - if (!Conf.territoryProtectedMaterials.contains(material)) - return true; - } else { - if (!Conf.territoryProtectedMaterialsWhenOffline.contains(material)) - return true; - } - - // Move up access check to check for exceptions - Access access = otherFaction.getAccess(me, action); - boolean doTerritoryEnemyProtectedCheck = true; - - if (action != null && (action.equals(PermissableAction.CONTAINER) || - action.equals(PermissableAction.DOOR))) { - if (access == Access.ALLOW) { - doTerritoryEnemyProtectedCheck = false; - } - } - - // Did not nest the boolean so that it stands out when Im looking - // through the code later. - if (doTerritoryEnemyProtectedCheck) { - // You may use any block unless it is another faction's territory... - if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials) || (rel.isTruce() && Conf.territoryTruceProtectMaterials)) { - if (!justCheck) { - me.msg(TL.PLAYER_USE_TERRITORY, (material == SavageFactions.plugin.SOIL ? "trample " : "use ") + TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); - } - return false; - } - } - - if (access != Access.ALLOW && me.getRole() != Role.LEADER) { - // TODO: Update this once new access values are added other than just allow / deny. - if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { - return true; - } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { - me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); - return false; - } else if (access == Access.DENY) { - me.msg(TL.GENERIC_NOPERMISSION, action); - return false; - } - } - return true; - } - - public static boolean preventCommand(String fullCmd, Player player) { - if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty() && Conf.permanentFactionMemberDenyCommands.isEmpty() && Conf.warzoneDenyCommands.isEmpty())) { - return false; - } - - fullCmd = fullCmd.toLowerCase(); - - FPlayer me = FPlayers.getInstance().getByPlayer(player); - - String shortCmd; // command without the slash at the beginning - if (fullCmd.startsWith("/")) { - shortCmd = fullCmd.substring(1); - } else { - shortCmd = fullCmd; - fullCmd = "/" + fullCmd; - } - - if (me.hasFaction() && - !me.isAdminBypassing() && - !Conf.permanentFactionMemberDenyCommands.isEmpty() && - me.getFaction().isPermanent() && - isCommandInList(fullCmd, shortCmd, Conf.permanentFactionMemberDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_PERMANENT, fullCmd); - return true; - } - - Faction at = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); - if (at.isWilderness() && !Conf.wildernessDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.wildernessDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_WILDERNESS, fullCmd); - return true; - } - - Relation rel = at.getRelationTo(me); - if (at.isNormal() && rel.isAlly() && !Conf.territoryAllyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryAllyDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_ALLY, fullCmd); - return false; - } - - if (at.isNormal() && rel.isNeutral() && !Conf.territoryNeutralDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryNeutralDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_NEUTRAL, fullCmd); - return true; - } - - if (at.isNormal() && rel.isEnemy() && !Conf.territoryEnemyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryEnemyDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_ENEMY, fullCmd); - return true; - } - - if (at.isWarZone() && !Conf.warzoneDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.warzoneDenyCommands.iterator())) { - me.msg(TL.PLAYER_COMMAND_WARZONE, fullCmd); - return true; - } - - return false; - } - - private static boolean isCommandInList(String fullCmd, String shortCmd, Iterator iter) { - String cmdCheck; - while (iter.hasNext()) { - cmdCheck = iter.next(); - if (cmdCheck == null) { - iter.remove(); - continue; - } - - cmdCheck = cmdCheck.toLowerCase(); - if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck)) { - return true; - } - } - return false; - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerJoin(PlayerJoinEvent event) { - initPlayer(event.getPlayer()); - } - - private void initPlayer(Player player) { - // Make sure that all online players do have a fplayer. - final FPlayer me = FPlayers.getInstance().getByPlayer(player); - ((MemoryFPlayer) me).setName(player.getName()); - - // Update the lastLoginTime for this fplayer - me.setLastLoginTime(System.currentTimeMillis()); - - // Store player's current FLocation and notify them where they are - me.setLastStoodAt(new FLocation(player.getLocation())); - - me.login(); // set kills / deaths - - // Check for Faction announcements. Let's delay this so they actually see it. - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - if (me.isOnline()) { - me.getFaction().sendUnreadAnnouncements(me); - } - } - }, 33L); // Don't ask me why. - - if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false)) { - FScoreboard.init(me); - FScoreboard.get(me).setDefaultSidebar(new FDefaultSidebar(), SavageFactions.plugin.getConfig().getInt("scoreboard.default-update-interval", 20)); - FScoreboard.get(me).setSidebarVisibility(me.showScoreboard()); - } - - Faction myFaction = me.getFaction(); - if (!myFaction.isWilderness()) { - for (FPlayer other : myFaction.getFPlayersWhereOnline(true)) { - if (other != me && other.isMonitoringJoins()) { - other.msg(TL.FACTION_LOGIN, me.getName()); - } - } - } - - - fallMap.put(me.getPlayer(), false); - Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - fallMap.remove(me.getPlayer()); - - } - }, 180L); - - - if (me.isSpyingChat() && !player.hasPermission(Permission.CHATSPY.node)) { - me.setSpyingChat(false); - SavageFactions.plugin.log(Level.INFO, "Found %s spying chat without permission on login. Disabled their chat spying.", player.getName()); - } - - if (me.isAdminBypassing() && !player.hasPermission(Permission.BYPASS.node)) { - me.setIsAdminBypassing(false); - SavageFactions.plugin.log(Level.INFO, "Found %s on admin Bypass without permission on login. Disabled it for them.", player.getName()); - } - - - // If they have the permission, don't let them autoleave. Bad inverted setter :\ - me.setAutoLeave(!player.hasPermission(Permission.AUTO_LEAVE_BYPASS.node)); - me.setTakeFallDamage(true); - } - - @EventHandler - public void onPlayerFall(EntityDamageEvent e) { - if (e.getEntity() instanceof Player) { - if (e.getCause() == EntityDamageEvent.DamageCause.FALL) { - Player player = (Player) e.getEntity(); - if (fallMap.containsKey(player)) { - e.setCancelled(true); - fallMap.remove(player); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerQuit(PlayerQuitEvent event) { - FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); - - // Make sure player's power is up to date when they log off. - me.getPower(); - // and update their last login time to point to when the logged off, for auto-remove routine - me.setLastLoginTime(System.currentTimeMillis()); - - me.logout(); // cache kills / deaths - - // if player is waiting for fstuck teleport but leaves, remove - if (SavageFactions.plugin.getStuckMap().containsKey(me.getPlayer().getUniqueId())) { - FPlayers.getInstance().getByPlayer(me.getPlayer()).msg(TL.COMMAND_STUCK_CANCELLED); - SavageFactions.plugin.getStuckMap().remove(me.getPlayer().getUniqueId()); - SavageFactions.plugin.getTimers().remove(me.getPlayer().getUniqueId()); - } - - Faction myFaction = me.getFaction(); - if (!myFaction.isWilderness()) { - myFaction.memberLoggedOff(); - } - - if (!myFaction.isWilderness()) { - for (FPlayer player : myFaction.getFPlayersWhereOnline(true)) { - if (player != me && player.isMonitoringJoins()) { - player.msg(TL.FACTION_LOGOUT, me.getName()); - } - } - } - - CmdSeeChunk.seeChunkMap.remove(event.getPlayer().getName()); - - FScoreboard.remove(me); - } - - public String parseAllPlaceholders(String string, Faction faction, Player player) { - string = TagUtil.parsePlaceholders(player, string); - - string = string.replace("{Faction}", faction.getTag()) - .replace("{online}", faction.getOnlinePlayers().size() + "") - .replace("{offline}", faction.getFPlayers().size() - faction.getOnlinePlayers().size() + "") - .replace("{chunks}", faction.getAllClaims().size() + "") - .replace("{power}", faction.getPower() + "") - .replace("{leader}", faction.getFPlayerAdmin() + ""); - - return string; - } - - public void enableFly(FPlayer me) { - if (SavageFactions.plugin.getConfig().getBoolean("ffly.AutoEnable")) { - - me.setFlying(true); - CmdFly.flyMap.put(me.getName(), true); - if (CmdFly.id == -1) { - if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { - CmdFly.startParticles(); - } - } - if (CmdFly.flyid == -1) { - CmdFly.startFlyCheck(); - } - } - } - - //inspect - @EventHandler - public void onInspect(PlayerInteractEvent e) { - if (e.getAction().name().contains("BLOCK")) { - FPlayer fplayer = FPlayers.getInstance().getByPlayer(e.getPlayer()); - if (!fplayer.isInspectMode()) { - return; - } - e.setCancelled(true); - if (!fplayer.isAdminBypassing()) { - if (!fplayer.hasFaction()) { - fplayer.setInspectMode(false); - fplayer.msg(TL.COMMAND_INSPECT_DISABLED_NOFAC); - return; - } - if (fplayer.getFaction() != Board.getInstance().getFactionAt(new FLocation(e.getPlayer().getLocation()))) { - fplayer.msg(TL.COMMAND_INSPECT_NOTINCLAIM); - return; - } - } else { - fplayer.msg(TL.COMMAND_INSPECT_BYPASS); - } - List info = CoreProtect.getInstance().getAPI().blockLookup(e.getClickedBlock(), 0); - if (info.size() == 0) { - e.getPlayer().sendMessage(TL.COMMAND_INSPECT_NODATA.toString()); - return; - } - Player player = e.getPlayer(); - CoreProtectAPI coAPI = CoreProtect.getInstance().getAPI(); - player.sendMessage(TL.COMMAND_INSPECT_HEADER.toString().replace("{x}", e.getClickedBlock().getX() + "") - .replace("{y}", e.getClickedBlock().getY() + "") - .replace("{z}", e.getClickedBlock().getZ() + "")); - String rowFormat = TL.COMMAND_INSPECT_ROW.toString(); - for (int i = 0; i < info.size(); i++) { - CoreProtectAPI.ParseResult row = coAPI.parseResult(info.get(0)); - player.sendMessage(rowFormat - .replace("{time}", convertTime(row.getTime())) - .replace("{action}", row.getActionString()) - .replace("{player}", row.getPlayer()) - .replace("{block-type}", row.getType().toString().toLowerCase())); - } - } - } - - //For disabling enderpearl throws - @EventHandler - public void onPearl(PlayerInteractEvent e) { - Player player = e.getPlayer(); - if (player.getItemInHand().getType() == Material.ENDER_PEARL) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer.isFlying()) { - if (Conf.noEnderpearlsInFly) { - fPlayer.msg(TL.COMMAND_FLY_NO_EPEARL); - e.setCancelled(true); - } - } - } - } - - //For Blocking Homes and Blocking Teleportation To Homes - @EventHandler - public void onPlayerHomeCheck(PlayerTeleportEvent event) throws Exception { - if (event.getPlayer().hasMetadata("NPC")){ - return; - } - if (event.getPlayer().hasPermission("factions.homes.bypass")) { - return; - } - if (Bukkit.getPluginManager().getPlugin("Essentials") == null) { - return; - } - boolean isHome = false; - for (String str : SavageFactions.plugin.ess.getUser(event.getPlayer()).getHomes()) { - Location home = SavageFactions.plugin.ess.getUser(event.getPlayer()).getHome(str); - if (home.getBlockX() == event.getTo().getBlockX() && home.getBlockY() == event.getTo().getBlockY() && home.getBlockZ() == event.getTo().getBlockZ()) { - isHome = true; - } - } - if (!isHome) { - return; - } - Location loc = event.getTo(); - FLocation floc = new FLocation(event.getTo()); - Faction fac = Board.getInstance().getFactionAt(floc); - Player player = event.getPlayer(); - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - User user = SavageFactions.plugin.ess.getUser(event.getPlayer()); - List homes = user.getHomes(); - if (fac.isWilderness() || FPlayers.getInstance().getByPlayer(event.getPlayer()).getFactionId().equals(fac.getId())) { - return; - } - //Warzone and SafeZone Home Initializers - if (fac.isWarZone() || fac.isSafeZone() && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-system-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-system-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - - if (fplayer.getFaction().getRelationTo(fac) == Relation.ENEMY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-enemy-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-enemy-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - if (fplayer.getFaction().getRelationTo(fac) == Relation.NEUTRAL && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-neutral-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-neutral-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - if (fplayer.getFaction().getRelationTo(fac) == Relation.ALLY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-ally-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-ally-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - if (fplayer.getFaction().getRelationTo(fac) == Relation.TRUCE && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-truce-factions")) { - event.setCancelled(true); - fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); - if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-truce-factions")) - for (String s : homes) { - if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { - user.delHome(s); - } - } - } - } - - - //Colors a String - public String color(String s) { - return ChatColor.translateAlternateColorCodes('&', s); - } - - - private String convertTime(int time) { - String result = String.valueOf(Math.round((System.currentTimeMillis() / 1000L - time) / 36.0D) / 100.0D); - return (result.length() == 3 ? result + "0" : result) + "/hrs ago"; - } - - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); - FPlayer me = FPlayers.getInstance().getByPlayer(player); - - // clear visualization - if (event.getFrom().getBlockX() != event.getTo().getBlockX() || event.getFrom().getBlockY() != event.getTo().getBlockY() || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { - VisualizeUtil.clear(event.getPlayer()); - if (me.isWarmingUp()) { - me.clearWarmup(); - me.msg(TL.WARMUPS_CANCELLED); - } - } - - // quick check to make sure player is moving between chunks; good performance boost - if (event.getFrom().getBlockX() >> 4 == event.getTo().getBlockX() >> 4 && event.getFrom().getBlockZ() >> 4 == event.getTo().getBlockZ() >> 4 && event.getFrom().getWorld() == event.getTo().getWorld()) { - return; - } - - - // Did we change coord? - FLocation from = me.getLastStoodAt(); - FLocation to = new FLocation(event.getTo()); - - if (from.equals(to)) { - return; - } - - // Yes we did change coord (: - - me.setLastStoodAt(to); - - // Did we change "host"(faction)? - Faction factionFrom = Board.getInstance().getFactionAt(from); - Faction factionTo = Board.getInstance().getFactionAt(to); - boolean changedFaction = (factionFrom != factionTo); - - - if (changedFaction) { - Bukkit.getServer().getPluginManager().callEvent(new FPlayerEnteredFactionEvent(factionTo, factionFrom, me)); - if (SavageFactions.plugin.getConfig().getBoolean("Title.Show-Title")) { - String title = SavageFactions.plugin.getConfig().getString("Title.Format.Title"); - title = title.replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); - title = parseAllPlaceholders(title, factionTo, player); - String subTitle = SavageFactions.plugin.getConfig().getString("Title.Format.Subtitle").replace("{Description}", factionTo.getDescription()).replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); - subTitle = parseAllPlaceholders(subTitle, factionTo, player); - if (!SavageFactions.plugin.mc17) { - if (!SavageFactions.plugin.mc18) { - me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle), SavageFactions.plugin.getConfig().getInt("Title.Options.FadeInTime"), - SavageFactions.plugin.getConfig().getInt("Title.Options.ShowTime"), - SavageFactions.plugin.getConfig().getInt("Title.Options.FadeOutTime")); - } else { - me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle)); - } - - - } - - } - - if (!SavageFactions.plugin.factionsFlight) { - return; - } - - - // enable fly :) - if (me.hasFaction() && !me.isFlying()) { - if (factionTo == me.getFaction()) { - enableFly(me); - } - // bypass checks - Relation relationTo = factionTo.getRelationTo(me); - if ((factionTo.isWilderness() && me.canflyinWilderness()) || - (factionTo.isWarZone() && me.canflyinWarzone()) || - (factionTo.isSafeZone() && me.canflyinSafezone()) || - (relationTo == Relation.ENEMY && me.canflyinEnemy()) || - (relationTo == Relation.ALLY && me.canflyinAlly()) || - (relationTo == Relation.TRUCE && me.canflyinTruce()) || - (relationTo == Relation.NEUTRAL && me.canflyinNeutral() && !isSystemFaction(factionTo))) { - enableFly(me); - } - - } - } - - - if (me.isMapAutoUpdating()) { - if (showTimes.containsKey(player.getUniqueId()) && (showTimes.get(player.getUniqueId()) > System.currentTimeMillis())) { - if (SavageFactions.plugin.getConfig().getBoolean("findfactionsexploit.log", false)) { - SavageFactions.plugin.log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); - } - } else { - me.sendFancyMessage(Board.getInstance().getMap(me, to, player.getLocation().getYaw())); - showTimes.put(player.getUniqueId(), System.currentTimeMillis() + SavageFactions.plugin.getConfig().getLong("findfactionsexploit.cooldown", 2000)); - } - } else { - Faction myFaction = me.getFaction(); - String ownersTo = myFaction.getOwnerListString(to); - if (changedFaction) { - me.sendFactionHereMessage(factionFrom); - if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty()) { - me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); - } - } else if (Conf.ownedAreasEnabled && Conf.ownedMessageInsideTerritory && myFaction == factionTo && !myFaction.isWilderness()) { - String ownersFrom = myFaction.getOwnerListString(from); - if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo)) { - if (!ownersTo.isEmpty()) { - me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); - } else if (!TL.GENERIC_PUBLICLAND.toString().isEmpty()) { - me.sendMessage(TL.GENERIC_PUBLICLAND.toString()); - } - } - } - } - - if (me.getAutoClaimFor() != null) { - me.attemptClaim(me.getAutoClaimFor(), event.getTo(), true); - } else if (me.isAutoSafeClaimEnabled()) { - if (!Permission.MANAGE_SAFE_ZONE.has(player)) { - me.setIsAutoSafeClaimEnabled(false); - } else { - if (!Board.getInstance().getFactionAt(to).isSafeZone()) { - Board.getInstance().setFactionAt(Factions.getInstance().getSafeZone(), to); - me.msg(TL.PLAYER_SAFEAUTO); - } - } - } else if (me.isAutoWarClaimEnabled()) { - if (!Permission.MANAGE_WAR_ZONE.has(player)) { - me.setIsAutoWarClaimEnabled(false); - } else { - if (!Board.getInstance().getFactionAt(to).isWarZone()) { - Board.getInstance().setFactionAt(Factions.getInstance().getWarZone(), to); - me.msg(TL.PLAYER_WARAUTO); - } - } - } - } - - @EventHandler - public void onClose(InventoryCloseEvent e) { - FPlayer fme = FPlayers.getInstance().getById(e.getPlayer().getUniqueId().toString()); - if (fme.isInVault()) - fme.setInVault(false); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerInteract(PlayerInteractEvent event) { - /// Prevents the use of montster eggs in oned land. + HashMap fallMap = new HashMap<>(); + + // Holds the next time a player can have a map shown. + private HashMap showTimes = new HashMap<>(); + // for handling people who repeatedly spam attempts to open a door (or similar) in another faction's territory + private Map interactSpammers = new HashMap<>(); + + public FactionsPlayerListener() { + for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { + initPlayer(player); + } + } + + public static Boolean isSystemFaction(Faction faction) { + return faction.isSafeZone() || + faction.isWarZone() || + faction.isWilderness(); + } + + public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { + String name = player.getName(); + if (Conf.playersWhoBypassAllProtection.contains(name)) { + return true; + } + + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + if (me.isAdminBypassing()) { + return true; + } + + FLocation loc = new FLocation(location); + Faction otherFaction = Board.getInstance().getFactionAt(loc); + Faction myFaction = me.getFaction(); + Relation rel = myFaction.getRelationTo(otherFaction); + + // Also cancel if player doesn't have ownership rights for this claim + if (Conf.ownedAreasEnabled && myFaction == otherFaction && !myFaction.playerHasOwnershipRights(me, loc)) { + if (!justCheck) { + me.msg("You can't use that in this territory, it is owned by: " + otherFaction.getOwnerListString(loc)); + } + return false; + } + + if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) { + return true; + } + + if (otherFaction.hasPlayersOnline()) { + if (!Conf.territoryDenyUseageMaterials.contains(material)) { + return true; // Item isn't one we're preventing for online factions. + } + } else { + if (!Conf.territoryDenyUseageMaterialsWhenOffline.contains(material)) { + return true; // Item isn't one we're preventing for offline factions. + } + } + + if (otherFaction.isWilderness()) { + if (!Conf.wildernessDenyUseage || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) { + return true; // This is not faction territory. Use whatever you like here. + } + + if (!justCheck) { + me.msg(TL.PLAYER_USE_WILDERNESS, TextUtil.getMaterialName(material)); + } + + return false; + } else if (otherFaction.isSafeZone()) { + if (!Conf.safeZoneDenyUseage || Permission.MANAGE_SAFE_ZONE.has(player)) { + return true; + } + + if (!justCheck) { + me.msg(TL.PLAYER_USE_SAFEZONE, TextUtil.getMaterialName(material)); + } + + return false; + } else if (otherFaction.isWarZone()) { + if (!Conf.warZoneDenyUseage || Permission.MANAGE_WAR_ZONE.has(player)) { + return true; + } + + if (!justCheck) { + me.msg(TL.PLAYER_USE_WARZONE, TextUtil.getMaterialName(material)); + } + + return false; + } + + // Cancel if we are not in our own territory + if (rel.confDenyUseage()) { + if (!justCheck) { + me.msg(TL.PLAYER_USE_TERRITORY, TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); + } + + return false; + } + + Access access = otherFaction.getAccess(me, PermissableAction.ITEM); + if (access != null && access != Access.UNDEFINED) { + // TODO: Update this once new access values are added other than just allow / deny. + if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { + return true; + } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { + me.msg("You can't use items in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); + return false; + } else if (access == Access.DENY) { + me.msg(TL.GENERIC_NOPERMISSION, PermissableAction.ITEM); + return false; + } + } + + return true; + } + + @SuppressWarnings("deprecation") + public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { + if (Conf.playersWhoBypassAllProtection.contains(player.getName())) + return true; + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + if (me.isAdminBypassing()) + return true; + + Material material = block.getType(); + // Dupe fix. + FLocation loc = new FLocation(block); + Faction otherFaction = Board.getInstance().getFactionAt(loc); + Faction myFaction = me.getFaction(); + Relation rel = myFaction.getRelationTo(otherFaction); + + // no door/chest/whatever protection in wilderness, war zones, or safe zones + if (!otherFaction.isNormal()) + return true; + + if (SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) + return true; + + if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc) && player.getItemInHand().getType() != null) { + + if (player.getItemInHand().getType().toString().toUpperCase().contains("DOOR")) + return false; + } + + PermissableAction action = null; + + if (SavageFactions.plugin.mc113) { + switch (block.getType()) { + case LEVER: + action = PermissableAction.LEVER; + break; + + case ACACIA_BUTTON: + case BIRCH_BUTTON: + case DARK_OAK_BUTTON: + case JUNGLE_BUTTON: + case OAK_BUTTON: + case SPRUCE_BUTTON: + case STONE_BUTTON: + action = PermissableAction.BUTTON; + break; + + case ACACIA_DOOR: + case BIRCH_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case OAK_DOOR: + case SPRUCE_DOOR: + case DARK_OAK_DOOR: + + case ACACIA_TRAPDOOR: + case BIRCH_TRAPDOOR: + case DARK_OAK_TRAPDOOR: + case IRON_TRAPDOOR: + case JUNGLE_TRAPDOOR: + case OAK_TRAPDOOR: + case SPRUCE_TRAPDOOR: + + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case JUNGLE_FENCE_GATE: + case OAK_FENCE_GATE: + case SPRUCE_FENCE_GATE: + action = PermissableAction.DOOR; + break; + + case CHEST: + case TRAPPED_CHEST: + case CHEST_MINECART: + + case SHULKER_BOX: + case BLACK_SHULKER_BOX: + case BLUE_SHULKER_BOX: + case BROWN_SHULKER_BOX: + case CYAN_SHULKER_BOX: + case GRAY_SHULKER_BOX: + case GREEN_SHULKER_BOX: + case LIGHT_BLUE_SHULKER_BOX: + case LIGHT_GRAY_SHULKER_BOX: + case LIME_SHULKER_BOX: + case MAGENTA_SHULKER_BOX: + case ORANGE_SHULKER_BOX: + case PINK_SHULKER_BOX: + case PURPLE_SHULKER_BOX: + case RED_SHULKER_BOX: + case WHITE_SHULKER_BOX: + case YELLOW_SHULKER_BOX: + + case FURNACE: + case DROPPER: + case DISPENSER: + case ENCHANTING_TABLE: + case BREWING_STAND: + case CAULDRON: + case HOPPER: + case BEACON: + case JUKEBOX: + + case ANVIL: + case CHIPPED_ANVIL: + case DAMAGED_ANVIL: + action = PermissableAction.CONTAINER; + break; + default: + // Check for doors that might have diff material name in old version. + if (block.getType().name().contains("DOOR")) { + action = PermissableAction.DOOR; + } + break; + } + } else { + if (block.getType().toString().toUpperCase().contains("BUTTON")) { + action = PermissableAction.BUTTON; + } + + switch (block.getType()) { + case LEVER: + action = PermissableAction.LEVER; + break; + case DARK_OAK_DOOR: + case ACACIA_DOOR: + case BIRCH_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case SPRUCE_DOOR: + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case JUNGLE_FENCE_GATE: + case SPRUCE_FENCE_GATE: + action = PermissableAction.DOOR; + break; + case CHEST: + case ENDER_CHEST: + case TRAPPED_CHEST: + case DISPENSER: + case ENCHANTING_TABLE: + case DROPPER: + case FURNACE: + case HOPPER: + case ANVIL: + case CHIPPED_ANVIL: + case DAMAGED_ANVIL: + case BREWING_STAND: + action = PermissableAction.CONTAINER; + break; + default: + // Check for doors that might have diff material name in old version. + if (block.getType().name().contains("DOOR")) + action = PermissableAction.DOOR; + break; + } + } + + // We only care about some material types. + if (otherFaction.hasPlayersOnline()) { + if (!Conf.territoryProtectedMaterials.contains(material)) + return true; + } else { + if (!Conf.territoryProtectedMaterialsWhenOffline.contains(material)) + return true; + } + + // Move up access check to check for exceptions + Access access = otherFaction.getAccess(me, action); + boolean doTerritoryEnemyProtectedCheck = true; + + if (action != null && (action.equals(PermissableAction.CONTAINER) || + action.equals(PermissableAction.DOOR))) { + if (access == Access.ALLOW) { + doTerritoryEnemyProtectedCheck = false; + } + } + + // Did not nest the boolean so that it stands out when Im looking + // through the code later. + if (doTerritoryEnemyProtectedCheck) { + // You may use any block unless it is another faction's territory... + if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials) || (rel.isTruce() && Conf.territoryTruceProtectMaterials)) { + if (!justCheck) { + me.msg(TL.PLAYER_USE_TERRITORY, (material == SavageFactions.plugin.SOIL ? "trample " : "use ") + TextUtil.getMaterialName(material), otherFaction.getTag(myFaction)); + } + return false; + } + } + + if (access != Access.ALLOW && me.getRole() != Role.LEADER) { + // TODO: Update this once new access values are added other than just allow / deny. + if ((myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && myFaction.getOwnerListString(loc).contains(player.getName()))) { + return true; + } else if (myFaction.getOwnerListString(loc) != null && !myFaction.getOwnerListString(loc).isEmpty() && !myFaction.getOwnerListString(loc).contains(player.getName())) { + me.msg("You can't " + action + " in this territory, it is owned by: " + myFaction.getOwnerListString(loc)); + return false; + } else if (access == Access.DENY) { + me.msg(TL.GENERIC_NOPERMISSION, action); + return false; + } + } + return true; + } + + public static boolean preventCommand(String fullCmd, Player player) { + if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty() && Conf.permanentFactionMemberDenyCommands.isEmpty() && Conf.warzoneDenyCommands.isEmpty())) { + return false; + } + + fullCmd = fullCmd.toLowerCase(); + + FPlayer me = FPlayers.getInstance().getByPlayer(player); + + String shortCmd; // command without the slash at the beginning + if (fullCmd.startsWith("/")) { + shortCmd = fullCmd.substring(1); + } else { + shortCmd = fullCmd; + fullCmd = "/" + fullCmd; + } + + if (me.hasFaction() && + !me.isAdminBypassing() && + !Conf.permanentFactionMemberDenyCommands.isEmpty() && + me.getFaction().isPermanent() && + isCommandInList(fullCmd, shortCmd, Conf.permanentFactionMemberDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_PERMANENT, fullCmd); + return true; + } + + Faction at = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); + if (at.isWilderness() && !Conf.wildernessDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.wildernessDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_WILDERNESS, fullCmd); + return true; + } + + Relation rel = at.getRelationTo(me); + if (at.isNormal() && rel.isAlly() && !Conf.territoryAllyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryAllyDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_ALLY, fullCmd); + return false; + } + + if (at.isNormal() && rel.isNeutral() && !Conf.territoryNeutralDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryNeutralDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_NEUTRAL, fullCmd); + return true; + } + + if (at.isNormal() && rel.isEnemy() && !Conf.territoryEnemyDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.territoryEnemyDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_ENEMY, fullCmd); + return true; + } + + if (at.isWarZone() && !Conf.warzoneDenyCommands.isEmpty() && !me.isAdminBypassing() && isCommandInList(fullCmd, shortCmd, Conf.warzoneDenyCommands.iterator())) { + me.msg(TL.PLAYER_COMMAND_WARZONE, fullCmd); + return true; + } + + return false; + } + + private static boolean isCommandInList(String fullCmd, String shortCmd, Iterator iter) { + String cmdCheck; + while (iter.hasNext()) { + cmdCheck = iter.next(); + if (cmdCheck == null) { + iter.remove(); + continue; + } + + cmdCheck = cmdCheck.toLowerCase(); + if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck)) { + return true; + } + } + return false; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerJoin(PlayerJoinEvent event) { + initPlayer(event.getPlayer()); + } + + private void initPlayer(Player player) { + // Make sure that all online players do have a fplayer. + final FPlayer me = FPlayers.getInstance().getByPlayer(player); + ((MemoryFPlayer) me).setName(player.getName()); + + // Update the lastLoginTime for this fplayer + me.setLastLoginTime(System.currentTimeMillis()); + + // Store player's current FLocation and notify them where they are + me.setLastStoodAt(new FLocation(player.getLocation())); + + me.login(); // set kills / deaths + + // Check for Faction announcements. Let's delay this so they actually see it. + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + if (me.isOnline()) { + me.getFaction().sendUnreadAnnouncements(me); + } + } + }, 33L); // Don't ask me why. + + if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false)) { + FScoreboard.init(me); + FScoreboard.get(me).setDefaultSidebar(new FDefaultSidebar(), SavageFactions.plugin.getConfig().getInt("scoreboard.default-update-interval", 20)); + FScoreboard.get(me).setSidebarVisibility(me.showScoreboard()); + } + + Faction myFaction = me.getFaction(); + if (!myFaction.isWilderness()) { + for (FPlayer other : myFaction.getFPlayersWhereOnline(true)) { + if (other != me && other.isMonitoringJoins()) { + other.msg(TL.FACTION_LOGIN, me.getName()); + } + } + } + + + fallMap.put(me.getPlayer(), false); + Bukkit.getScheduler().scheduleSyncDelayedTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + fallMap.remove(me.getPlayer()); + + } + }, 180L); + + + if (me.isSpyingChat() && !player.hasPermission(Permission.CHATSPY.node)) { + me.setSpyingChat(false); + SavageFactions.plugin.log(Level.INFO, "Found %s spying chat without permission on login. Disabled their chat spying.", player.getName()); + } + + if (me.isAdminBypassing() && !player.hasPermission(Permission.BYPASS.node)) { + me.setIsAdminBypassing(false); + SavageFactions.plugin.log(Level.INFO, "Found %s on admin Bypass without permission on login. Disabled it for them.", player.getName()); + } + + + // If they have the permission, don't let them autoleave. Bad inverted setter :\ + me.setAutoLeave(!player.hasPermission(Permission.AUTO_LEAVE_BYPASS.node)); + me.setTakeFallDamage(true); + } + + @EventHandler + public void onPlayerFall(EntityDamageEvent e) { + if (e.getEntity() instanceof Player) { + if (e.getCause() == EntityDamageEvent.DamageCause.FALL) { + Player player = (Player) e.getEntity(); + if (fallMap.containsKey(player)) { + e.setCancelled(true); + fallMap.remove(player); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerQuit(PlayerQuitEvent event) { + FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); + + // Make sure player's power is up to date when they log off. + me.getPower(); + // and update their last login time to point to when the logged off, for auto-remove routine + me.setLastLoginTime(System.currentTimeMillis()); + + me.logout(); // cache kills / deaths + + // if player is waiting for fstuck teleport but leaves, remove + if (SavageFactions.plugin.getStuckMap().containsKey(me.getPlayer().getUniqueId())) { + FPlayers.getInstance().getByPlayer(me.getPlayer()).msg(TL.COMMAND_STUCK_CANCELLED); + SavageFactions.plugin.getStuckMap().remove(me.getPlayer().getUniqueId()); + SavageFactions.plugin.getTimers().remove(me.getPlayer().getUniqueId()); + } + + Faction myFaction = me.getFaction(); + if (!myFaction.isWilderness()) { + myFaction.memberLoggedOff(); + } + + if (!myFaction.isWilderness()) { + for (FPlayer player : myFaction.getFPlayersWhereOnline(true)) { + if (player != me && player.isMonitoringJoins()) { + player.msg(TL.FACTION_LOGOUT, me.getName()); + } + } + } + + CmdSeeChunk.seeChunkMap.remove(event.getPlayer().getName()); + + FScoreboard.remove(me); + } + + public String parseAllPlaceholders(String string, Faction faction, Player player) { + string = TagUtil.parsePlaceholders(player, string); + + string = string.replace("{Faction}", faction.getTag()) + .replace("{online}", faction.getOnlinePlayers().size() + "") + .replace("{offline}", faction.getFPlayers().size() - faction.getOnlinePlayers().size() + "") + .replace("{chunks}", faction.getAllClaims().size() + "") + .replace("{power}", faction.getPower() + "") + .replace("{leader}", faction.getFPlayerAdmin() + ""); + + return string; + } + + public void enableFly(FPlayer me) { + if (SavageFactions.plugin.getConfig().getBoolean("ffly.AutoEnable")) { + + me.setFlying(true); + CmdFly.flyMap.put(me.getName(), true); + if (CmdFly.id == -1) { + if (SavageFactions.plugin.getConfig().getBoolean("ffly.Particles.Enabled")) { + CmdFly.startParticles(); + } + } + if (CmdFly.flyid == -1) { + CmdFly.startFlyCheck(); + } + } + } + + //inspect + @EventHandler + public void onInspect(PlayerInteractEvent e) { + if (e.getAction().name().contains("BLOCK")) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(e.getPlayer()); + if (!fplayer.isInspectMode()) { + return; + } + e.setCancelled(true); + if (!fplayer.isAdminBypassing()) { + if (!fplayer.hasFaction()) { + fplayer.setInspectMode(false); + fplayer.msg(TL.COMMAND_INSPECT_DISABLED_NOFAC); + return; + } + if (fplayer.getFaction() != Board.getInstance().getFactionAt(new FLocation(e.getPlayer().getLocation()))) { + fplayer.msg(TL.COMMAND_INSPECT_NOTINCLAIM); + return; + } + } else { + fplayer.msg(TL.COMMAND_INSPECT_BYPASS); + } + List info = CoreProtect.getInstance().getAPI().blockLookup(e.getClickedBlock(), 0); + if (info.size() == 0) { + e.getPlayer().sendMessage(TL.COMMAND_INSPECT_NODATA.toString()); + return; + } + Player player = e.getPlayer(); + CoreProtectAPI coAPI = CoreProtect.getInstance().getAPI(); + player.sendMessage(TL.COMMAND_INSPECT_HEADER.toString().replace("{x}", e.getClickedBlock().getX() + "") + .replace("{y}", e.getClickedBlock().getY() + "") + .replace("{z}", e.getClickedBlock().getZ() + "")); + String rowFormat = TL.COMMAND_INSPECT_ROW.toString(); + for (int i = 0; i < info.size(); i++) { + CoreProtectAPI.ParseResult row = coAPI.parseResult(info.get(0)); + player.sendMessage(rowFormat + .replace("{time}", convertTime(row.getTime())) + .replace("{action}", row.getActionString()) + .replace("{player}", row.getPlayer()) + .replace("{block-type}", row.getType().toString().toLowerCase())); + } + } + } + + //For disabling enderpearl throws + @EventHandler + public void onPearl(PlayerInteractEvent e) { + Player player = e.getPlayer(); + if (player.getItemInHand().getType() == Material.ENDER_PEARL) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + if (fPlayer.isFlying()) { + if (Conf.noEnderpearlsInFly) { + fPlayer.msg(TL.COMMAND_FLY_NO_EPEARL); + e.setCancelled(true); + } + } + } + } + + //For Blocking Homes and Blocking Teleportation To Homes + @EventHandler + public void onPlayerHomeCheck(PlayerTeleportEvent event) throws Exception { + if (event.getPlayer().hasMetadata("NPC")) { + return; + } + if (event.getPlayer().hasPermission("factions.homes.bypass")) { + return; + } + if (Bukkit.getPluginManager().getPlugin("Essentials") == null) { + return; + } + boolean isHome = false; + for (String str : SavageFactions.plugin.ess.getUser(event.getPlayer()).getHomes()) { + Location home = SavageFactions.plugin.ess.getUser(event.getPlayer()).getHome(str); + if (home.getBlockX() == event.getTo().getBlockX() && home.getBlockY() == event.getTo().getBlockY() && home.getBlockZ() == event.getTo().getBlockZ()) { + isHome = true; + } + } + if (!isHome) { + return; + } + Location loc = event.getTo(); + FLocation floc = new FLocation(event.getTo()); + Faction fac = Board.getInstance().getFactionAt(floc); + Player player = event.getPlayer(); + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + User user = SavageFactions.plugin.ess.getUser(event.getPlayer()); + List homes = user.getHomes(); + if (fac.isWilderness() || FPlayers.getInstance().getByPlayer(event.getPlayer()).getFactionId().equals(fac.getId())) { + return; + } + //Warzone and SafeZone Home Initializers + if (fac.isWarZone() || fac.isSafeZone() && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-system-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-system-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + + if (fplayer.getFaction().getRelationTo(fac) == Relation.ENEMY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-enemy-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-enemy-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + if (fplayer.getFaction().getRelationTo(fac) == Relation.NEUTRAL && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-neutral-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-neutral-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + if (fplayer.getFaction().getRelationTo(fac) == Relation.ALLY && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-ally-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-ally-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + if (fplayer.getFaction().getRelationTo(fac) == Relation.TRUCE && SavageFactions.plugin.getConfig().getBoolean("deny-homes-in-truce-factions")) { + event.setCancelled(true); + fplayer.msg(TL.COMMAND_HOME_BLOCKED, fac.getTag()); + if (SavageFactions.plugin.getConfig().getBoolean("remove-homes-in-truce-factions")) + for (String s : homes) { + if (user.getHome(s).getBlock().getLocation().getChunk().equals(loc.getChunk())) { + user.delHome(s); + } + } + } + } + + + //Colors a String + public String color(String s) { + return ChatColor.translateAlternateColorCodes('&', s); + } + + + private String convertTime(int time) { + String result = String.valueOf(Math.round((System.currentTimeMillis() / 1000L - time) / 36.0D) / 100.0D); + return (result.length() == 3 ? result + "0" : result) + "/hrs ago"; + } + + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + FPlayer me = FPlayers.getInstance().getByPlayer(player); + + // clear visualization + if (event.getFrom().getBlockX() != event.getTo().getBlockX() || event.getFrom().getBlockY() != event.getTo().getBlockY() || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { + VisualizeUtil.clear(event.getPlayer()); + if (me.isWarmingUp()) { + me.clearWarmup(); + me.msg(TL.WARMUPS_CANCELLED); + } + } + + // quick check to make sure player is moving between chunks; good performance boost + if (event.getFrom().getBlockX() >> 4 == event.getTo().getBlockX() >> 4 && event.getFrom().getBlockZ() >> 4 == event.getTo().getBlockZ() >> 4 && event.getFrom().getWorld() == event.getTo().getWorld()) { + return; + } + + + // Did we change coord? + FLocation from = me.getLastStoodAt(); + FLocation to = new FLocation(event.getTo()); + + if (from.equals(to)) { + return; + } + + // Yes we did change coord (: + + me.setLastStoodAt(to); + + // Did we change "host"(faction)? + Faction factionFrom = Board.getInstance().getFactionAt(from); + Faction factionTo = Board.getInstance().getFactionAt(to); + boolean changedFaction = (factionFrom != factionTo); + + + if (changedFaction) { + Bukkit.getServer().getPluginManager().callEvent(new FPlayerEnteredFactionEvent(factionTo, factionFrom, me)); + if (SavageFactions.plugin.getConfig().getBoolean("Title.Show-Title")) { + String title = SavageFactions.plugin.getConfig().getString("Title.Format.Title"); + title = title.replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); + title = parseAllPlaceholders(title, factionTo, player); + String subTitle = SavageFactions.plugin.getConfig().getString("Title.Format.Subtitle").replace("{Description}", factionTo.getDescription()).replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); + subTitle = parseAllPlaceholders(subTitle, factionTo, player); + if (!SavageFactions.plugin.mc17) { + if (!SavageFactions.plugin.mc18) { + me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle), SavageFactions.plugin.getConfig().getInt("Title.Options.FadeInTime"), + SavageFactions.plugin.getConfig().getInt("Title.Options.ShowTime"), + SavageFactions.plugin.getConfig().getInt("Title.Options.FadeOutTime")); + } else { + me.getPlayer().sendTitle(SavageFactions.plugin.color(title), SavageFactions.plugin.color(subTitle)); + } + + + } + + } + + if (!SavageFactions.plugin.factionsFlight) { + return; + } + + + // enable fly :) + if (me.hasFaction() && !me.isFlying()) { + if (factionTo == me.getFaction()) { + enableFly(me); + } + // bypass checks + Relation relationTo = factionTo.getRelationTo(me); + if ((factionTo.isWilderness() && me.canflyinWilderness()) || + (factionTo.isWarZone() && me.canflyinWarzone()) || + (factionTo.isSafeZone() && me.canflyinSafezone()) || + (relationTo == Relation.ENEMY && me.canflyinEnemy()) || + (relationTo == Relation.ALLY && me.canflyinAlly()) || + (relationTo == Relation.TRUCE && me.canflyinTruce()) || + (relationTo == Relation.NEUTRAL && me.canflyinNeutral() && !isSystemFaction(factionTo))) { + enableFly(me); + } + + } + } + + + if (me.isMapAutoUpdating()) { + if (showTimes.containsKey(player.getUniqueId()) && (showTimes.get(player.getUniqueId()) > System.currentTimeMillis())) { + if (SavageFactions.plugin.getConfig().getBoolean("findfactionsexploit.log", false)) { + SavageFactions.plugin.log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); + } + } else { + me.sendFancyMessage(Board.getInstance().getMap(me, to, player.getLocation().getYaw())); + showTimes.put(player.getUniqueId(), System.currentTimeMillis() + SavageFactions.plugin.getConfig().getLong("findfactionsexploit.cooldown", 2000)); + } + } else { + Faction myFaction = me.getFaction(); + String ownersTo = myFaction.getOwnerListString(to); + if (changedFaction) { + me.sendFactionHereMessage(factionFrom); + if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty()) { + me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); + } + } else if (Conf.ownedAreasEnabled && Conf.ownedMessageInsideTerritory && myFaction == factionTo && !myFaction.isWilderness()) { + String ownersFrom = myFaction.getOwnerListString(from); + if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo)) { + if (!ownersTo.isEmpty()) { + me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); + } else if (!TL.GENERIC_PUBLICLAND.toString().isEmpty()) { + me.sendMessage(TL.GENERIC_PUBLICLAND.toString()); + } + } + } + } + + if (me.getAutoClaimFor() != null) { + me.attemptClaim(me.getAutoClaimFor(), event.getTo(), true); + } else if (me.isAutoSafeClaimEnabled()) { + if (!Permission.MANAGE_SAFE_ZONE.has(player)) { + me.setIsAutoSafeClaimEnabled(false); + } else { + if (!Board.getInstance().getFactionAt(to).isSafeZone()) { + Board.getInstance().setFactionAt(Factions.getInstance().getSafeZone(), to); + me.msg(TL.PLAYER_SAFEAUTO); + } + } + } else if (me.isAutoWarClaimEnabled()) { + if (!Permission.MANAGE_WAR_ZONE.has(player)) { + me.setIsAutoWarClaimEnabled(false); + } else { + if (!Board.getInstance().getFactionAt(to).isWarZone()) { + Board.getInstance().setFactionAt(Factions.getInstance().getWarZone(), to); + me.msg(TL.PLAYER_WARAUTO); + } + } + } + } + + @EventHandler + public void onClose(InventoryCloseEvent e) { + FPlayer fme = FPlayers.getInstance().getById(e.getPlayer().getUniqueId().toString()); + if (fme.isInVault()) + fme.setInVault(false); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + /// Prevents the use of montster eggs in oned land. /*if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { if (event.hasItem() || event.hasBlock()) { ItemStack itemStack = event.getItem(); @@ -915,159 +915,159 @@ public class FactionsPlayerListener implements Listener { } } }*/ - // only need to check right-clicks and physical as of MC 1.4+; good performance boost - if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) - return; + // only need to check right-clicks and physical as of MC 1.4+; good performance boost + if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) + return; - Block block = event.getClickedBlock(); - Player player = event.getPlayer(); + Block block = event.getClickedBlock(); + Player player = event.getPlayer(); - if (block == null) - return; // clicked in air, apparently + if (block == null) + return; // clicked in air, apparently - if (!canPlayerUseBlock(player, block, false)) { - event.setCancelled(true); - if (Conf.handleExploitInteractionSpam) { - String name = player.getName(); - InteractAttemptSpam attempt = interactSpammers.get(name); - if (attempt == null) { - attempt = new InteractAttemptSpam(); - interactSpammers.put(name, attempt); - } + if (!canPlayerUseBlock(player, block, false)) { + event.setCancelled(true); + if (Conf.handleExploitInteractionSpam) { + String name = player.getName(); + InteractAttemptSpam attempt = interactSpammers.get(name); + if (attempt == null) { + attempt = new InteractAttemptSpam(); + interactSpammers.put(name, attempt); + } - int count = attempt.increment(); - if (count >= 10) { - FPlayer me = FPlayers.getInstance().getByPlayer(player); - me.msg(TL.PLAYER_OUCH); - player.damage(NumberConversions.floor((double) count / 10)); - } - } - return; - } + int count = attempt.increment(); + if (count >= 10) { + FPlayer me = FPlayers.getInstance().getByPlayer(player); + me.msg(TL.PLAYER_OUCH); + player.damage(NumberConversions.floor((double) count / 10)); + } + } + return; + } - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { - return; // only interested on right-clicks for below - } + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; // only interested on right-clicks for below + } - if (!playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false)) { - event.setCancelled(true); - } - } + if (!playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false)) { + event.setCancelled(true); + } + } - @EventHandler - public void onPlayerBoneMeal(PlayerInteractEvent event) { - Block block = event.getClickedBlock(); + @EventHandler + public void onPlayerBoneMeal(PlayerInteractEvent event) { + Block block = event.getClickedBlock(); - if (event.getAction() == Action.RIGHT_CLICK_BLOCK && block.getType() == MultiversionMaterials.GRASS_BLOCK.parseMaterial() - && event.hasItem() && event.getItem().getType() == MultiversionMaterials.BONE_MEAL.parseMaterial()) { - if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), block.getLocation(), PermissableAction.BUILD.name(), true)) { - FPlayer me = FPlayers.getInstance().getById(event.getPlayer().getUniqueId().toString()); - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); - Faction myFaction = me.getFaction(); + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && block.getType() == MultiversionMaterials.GRASS_BLOCK.parseMaterial() + && event.hasItem() && event.getItem().getType() == MultiversionMaterials.BONE_MEAL.parseMaterial()) { + if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), block.getLocation(), PermissableAction.BUILD.name(), true)) { + FPlayer me = FPlayers.getInstance().getById(event.getPlayer().getUniqueId().toString()); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); + Faction myFaction = me.getFaction(); - me.msg("You can't use bone meal in the territory of " + otherFaction.getTag(myFaction)); - event.setCancelled(true); - } - } - } + me.msg("You can't use bone meal in the territory of " + otherFaction.getTag(myFaction)); + event.setCancelled(true); + } + } + } - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerRespawn(PlayerRespawnEvent event) { - FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerRespawn(PlayerRespawnEvent event) { + FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); - me.getPower(); // update power, so they won't have gained any while dead + me.getPower(); // update power, so they won't have gained any while dead - Location home = me.getFaction().getHome(); - if (Conf.homesEnabled && - Conf.homesTeleportToOnDeath && - home != null && - (Conf.homesRespawnFromNoPowerLossWorlds || !Conf.worldsNoPowerLoss.contains(event.getPlayer().getWorld().getName()))) { - event.setRespawnLocation(home); - } - } + Location home = me.getFaction().getHome(); + if (Conf.homesEnabled && + Conf.homesTeleportToOnDeath && + home != null && + (Conf.homesRespawnFromNoPowerLossWorlds || !Conf.worldsNoPowerLoss.contains(event.getPlayer().getWorld().getName()))) { + event.setRespawnLocation(home); + } + } - // For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected), - // but these separate bucket events below always fire without fail - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { - Block block = event.getBlockClicked(); - Player player = event.getPlayer(); + // For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected), + // but these separate bucket events below always fire without fail + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { + Block block = event.getBlockClicked(); + Player player = event.getPlayer(); - if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { - event.setCancelled(true); - } - } + if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerBucketFill(PlayerBucketFillEvent event) { - Block block = event.getBlockClicked(); - Player player = event.getPlayer(); + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerBucketFill(PlayerBucketFillEvent event) { + Block block = event.getBlockClicked(); + Player player = event.getPlayer(); - if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { - event.setCancelled(true); - } - } + if (!playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerInteractGUI(InventoryClickEvent event) { - if (event.getClickedInventory() == null) { - return; - } - if (event.getClickedInventory().getHolder() instanceof FactionGUI) { - event.setCancelled(true); - ((FactionGUI) event.getClickedInventory().getHolder()).onClick(event.getRawSlot(), event.getClick()); - } - } + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerInteractGUI(InventoryClickEvent event) { + if (event.getClickedInventory() == null) { + return; + } + if (event.getClickedInventory().getHolder() instanceof FactionGUI) { + event.setCancelled(true); + ((FactionGUI) event.getClickedInventory().getHolder()).onClick(event.getRawSlot(), event.getClick()); + } + } - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerMoveGUI(InventoryDragEvent event) { - if (event.getInventory().getHolder() instanceof FactionGUI) { - event.setCancelled(true); - } - } + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerMoveGUI(InventoryDragEvent event) { + if (event.getInventory().getHolder() instanceof FactionGUI) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerKick(PlayerKickEvent event) { - FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); - if (badGuy == null) { - return; - } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerKick(PlayerKickEvent event) { + FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); + if (badGuy == null) { + return; + } - // if player was banned (not just kicked), get rid of their stored info - if (Conf.removePlayerDataWhenBanned && event.getReason().equals("Banned by admin.")) { - if (badGuy.getRole() == Role.LEADER) { - badGuy.getFaction().promoteNewLeader(); - } + // if player was banned (not just kicked), get rid of their stored info + if (Conf.removePlayerDataWhenBanned && event.getReason().equals("Banned by admin.")) { + if (badGuy.getRole() == Role.LEADER) { + badGuy.getFaction().promoteNewLeader(); + } - badGuy.leave(false); - badGuy.remove(); - } - } + badGuy.leave(false); + badGuy.remove(); + } + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - final public void onFactionJoin(FPlayerJoinEvent event) { - FTeamWrapper.applyUpdatesLater(event.getFaction()); - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + final public void onFactionJoin(FPlayerJoinEvent event) { + FTeamWrapper.applyUpdatesLater(event.getFaction()); + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onFactionLeave(FPlayerLeaveEvent event) { - FTeamWrapper.applyUpdatesLater(event.getFaction()); - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onFactionLeave(FPlayerLeaveEvent event) { + FTeamWrapper.applyUpdatesLater(event.getFaction()); + } - private static class InteractAttemptSpam { - private int attempts = 0; - private long lastAttempt = System.currentTimeMillis(); + private static class InteractAttemptSpam { + private int attempts = 0; + private long lastAttempt = System.currentTimeMillis(); - // returns the current attempt count - public int increment() { - long now = System.currentTimeMillis(); - if (now > lastAttempt + 2000) { - attempts = 1; - } else { - attempts++; - } - lastAttempt = now; - return attempts; - } - } + // returns the current attempt count + public int increment() { + long now = System.currentTimeMillis(); + if (now > lastAttempt + 2000) { + attempts = 1; + } else { + attempts++; + } + lastAttempt = now; + return attempts; + } + } } diff --git a/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java b/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java index d21d3898..03b6f565 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/BufferedObjective.java @@ -11,152 +11,152 @@ import java.lang.reflect.Method; import java.util.*; public class BufferedObjective { - private static final Method addEntryMethod; - private static final int MAX_LINE_LENGTH; + private static final Method addEntryMethod; + private static final int MAX_LINE_LENGTH; - static { - // Check for long line support. - // We require use of Spigot's `addEntry(String)` method on - // Teams, as adding OfflinePlayers to a team is far too slow. + static { + // Check for long line support. + // We require use of Spigot's `addEntry(String)` method on + // Teams, as adding OfflinePlayers to a team is far too slow. - Method addEntryMethodLookup = null; - try { - addEntryMethodLookup = Team.class.getMethod("addEntry", String.class); - } catch (NoSuchMethodException ignored) { - } + Method addEntryMethodLookup = null; + try { + addEntryMethodLookup = Team.class.getMethod("addEntry", String.class); + } catch (NoSuchMethodException ignored) { + } - addEntryMethod = addEntryMethodLookup; + addEntryMethod = addEntryMethodLookup; - if (addEntryMethod != null) { - MAX_LINE_LENGTH = 48; - } else { - MAX_LINE_LENGTH = 16; - } - } + if (addEntryMethod != null) { + MAX_LINE_LENGTH = 48; + } else { + MAX_LINE_LENGTH = 16; + } + } - private final Scoreboard scoreboard; - private final String baseName; - private final Map contents = new HashMap<>(); - private Objective current; - private List currentTeams = new ArrayList<>(); - private String title; - private DisplaySlot displaySlot; - private int objPtr; - private int teamPtr; - private boolean requiresUpdate = false; + private final Scoreboard scoreboard; + private final String baseName; + private final Map contents = new HashMap<>(); + private Objective current; + private List currentTeams = new ArrayList<>(); + private String title; + private DisplaySlot displaySlot; + private int objPtr; + private int teamPtr; + private boolean requiresUpdate = false; - public BufferedObjective(Scoreboard scoreboard) { - this.scoreboard = scoreboard; - this.baseName = createBaseName(); + public BufferedObjective(Scoreboard scoreboard) { + this.scoreboard = scoreboard; + this.baseName = createBaseName(); - current = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); - } + current = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); + } - private String createBaseName() { - Random random = new Random(); - StringBuilder builder = new StringBuilder(); - while (builder.length() < 14) { - builder.append(Integer.toHexString(random.nextInt())); - } - return builder.toString().substring(0, 14); - } + private String createBaseName() { + Random random = new Random(); + StringBuilder builder = new StringBuilder(); + while (builder.length() < 14) { + builder.append(Integer.toHexString(random.nextInt())); + } + return builder.toString().substring(0, 14); + } - public void setTitle(String title) { - if (this.title == null || !this.title.equals(title)) { - this.title = title; - requiresUpdate = true; - } - } + public void setTitle(String title) { + if (this.title == null || !this.title.equals(title)) { + this.title = title; + requiresUpdate = true; + } + } - public void setDisplaySlot(DisplaySlot slot) { - this.displaySlot = slot; - current.setDisplaySlot(slot); - } + public void setDisplaySlot(DisplaySlot slot) { + this.displaySlot = slot; + current.setDisplaySlot(slot); + } - public void setAllLines(List lines) { - if (lines.size() != contents.size()) { - contents.clear(); - } - for (int i = 0; i < lines.size(); i++) { - setLine(lines.size() - i, lines.get(i)); - } - } + public void setAllLines(List lines) { + if (lines.size() != contents.size()) { + contents.clear(); + } + for (int i = 0; i < lines.size(); i++) { + setLine(lines.size() - i, lines.get(i)); + } + } - public void setLine(int lineNumber, String content) { - if (content.length() > MAX_LINE_LENGTH) { - content = content.substring(0, MAX_LINE_LENGTH); - } - content = ChatColor.translateAlternateColorCodes('&', content); + public void setLine(int lineNumber, String content) { + if (content.length() > MAX_LINE_LENGTH) { + content = content.substring(0, MAX_LINE_LENGTH); + } + content = ChatColor.translateAlternateColorCodes('&', content); - if (contents.get(lineNumber) == null || !contents.get(lineNumber).equals(content)) { - contents.put(lineNumber, content); - requiresUpdate = true; - } - } + if (contents.get(lineNumber) == null || !contents.get(lineNumber).equals(content)) { + contents.put(lineNumber, content); + requiresUpdate = true; + } + } - // Hides the objective from the display slot until flip() is called - public void hide() { - if (displaySlot != null) { - scoreboard.clearSlot(displaySlot); - } - } + // Hides the objective from the display slot until flip() is called + public void hide() { + if (displaySlot != null) { + scoreboard.clearSlot(displaySlot); + } + } - public void flip() { - if (!requiresUpdate) { - return; - } - requiresUpdate = false; + public void flip() { + if (!requiresUpdate) { + return; + } + requiresUpdate = false; - Objective buffer = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); - buffer.setDisplayName(title); + Objective buffer = scoreboard.registerNewObjective(getNextObjectiveName(), "dummy"); + buffer.setDisplayName(title); - List bufferTeams = new ArrayList<>(); + List bufferTeams = new ArrayList<>(); - for (Map.Entry entry : contents.entrySet()) { - if (entry.getValue().length() > 16) { - Team team = scoreboard.registerNewTeam(getNextTeamName()); - bufferTeams.add(team); + for (Map.Entry entry : contents.entrySet()) { + if (entry.getValue().length() > 16) { + Team team = scoreboard.registerNewTeam(getNextTeamName()); + bufferTeams.add(team); - Iterator split = Splitter.fixedLength(16).split(entry.getValue()).iterator(); + Iterator split = Splitter.fixedLength(16).split(entry.getValue()).iterator(); - team.setPrefix(split.next()); - String name = split.next(); - if (split.hasNext()) { // We only guarantee two splits - team.setSuffix(split.next()); - } + team.setPrefix(split.next()); + String name = split.next(); + if (split.hasNext()) { // We only guarantee two splits + team.setSuffix(split.next()); + } - try { - addEntryMethod.invoke(team, name); - } catch (ReflectiveOperationException ignored) { - } - buffer.getScore(name).setScore(entry.getKey()); - } else { - buffer.getScore(entry.getValue()).setScore(entry.getKey()); - } - } + try { + addEntryMethod.invoke(team, name); + } catch (ReflectiveOperationException ignored) { + } + buffer.getScore(name).setScore(entry.getKey()); + } else { + buffer.getScore(entry.getValue()).setScore(entry.getKey()); + } + } - if (displaySlot != null) { - buffer.setDisplaySlot(displaySlot); - } + if (displaySlot != null) { + buffer.setDisplaySlot(displaySlot); + } - // Unregister _ALL_ the old things - current.unregister(); + // Unregister _ALL_ the old things + current.unregister(); - Iterator it = currentTeams.iterator(); - while (it.hasNext()) { - it.next().unregister(); - it.remove(); - } + Iterator it = currentTeams.iterator(); + while (it.hasNext()) { + it.next().unregister(); + it.remove(); + } - current = buffer; - currentTeams = bufferTeams; - } + current = buffer; + currentTeams = bufferTeams; + } - private String getNextObjectiveName() { - return baseName + "_" + ((objPtr++) % 2); - } + private String getNextObjectiveName() { + return baseName + "_" + ((objPtr++) % 2); + } - private String getNextTeamName() { - return baseName.substring(0, 10) + "_" + ((teamPtr++) % 999999); - } + private String getNextTeamName() { + return baseName.substring(0, 10) + "_" + ((teamPtr++) % 999999); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java b/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java index 91b2c1e4..61f667f4 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java @@ -13,137 +13,137 @@ import java.util.HashMap; import java.util.Map; public class FScoreboard { - private static final Map fscoreboards = new HashMap<>(); + private static final Map fscoreboards = new HashMap<>(); - private final Scoreboard scoreboard; - private final FPlayer fplayer; - private final BufferedObjective bufferedObjective; - private FSidebarProvider defaultProvider; - private FSidebarProvider temporaryProvider; - private boolean removed = false; + private final Scoreboard scoreboard; + private final FPlayer fplayer; + private final BufferedObjective bufferedObjective; + private FSidebarProvider defaultProvider; + private FSidebarProvider temporaryProvider; + private boolean removed = false; - private FScoreboard(FPlayer fplayer) { - this.fplayer = fplayer; + private FScoreboard(FPlayer fplayer) { + this.fplayer = fplayer; - if (isSupportedByServer()) { - this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); - this.bufferedObjective = new BufferedObjective(scoreboard); + if (isSupportedByServer()) { + this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + this.bufferedObjective = new BufferedObjective(scoreboard); - fplayer.getPlayer().setScoreboard(scoreboard); - } else { - this.scoreboard = null; - this.bufferedObjective = null; - } - } + fplayer.getPlayer().setScoreboard(scoreboard); + } else { + this.scoreboard = null; + this.bufferedObjective = null; + } + } - // Glowstone doesn't support scoreboards. - // All references to this and related workarounds can be safely - // removed when scoreboards are supported. - public static boolean isSupportedByServer() { - return Bukkit.getScoreboardManager() != null; - } + // Glowstone doesn't support scoreboards. + // All references to this and related workarounds can be safely + // removed when scoreboards are supported. + public static boolean isSupportedByServer() { + return Bukkit.getScoreboardManager() != null; + } - public static void init(FPlayer fplayer) { - FScoreboard fboard = new FScoreboard(fplayer); - fscoreboards.put(fplayer, fboard); + public static void init(FPlayer fplayer) { + FScoreboard fboard = new FScoreboard(fplayer); + fscoreboards.put(fplayer, fboard); - if (fplayer.hasFaction()) { - FTeamWrapper.applyUpdates(fplayer.getFaction()); - } - FTeamWrapper.track(fboard); - } + if (fplayer.hasFaction()) { + FTeamWrapper.applyUpdates(fplayer.getFaction()); + } + FTeamWrapper.track(fboard); + } - public static void remove(FPlayer fplayer) { - FScoreboard fboard = fscoreboards.remove(fplayer); + public static void remove(FPlayer fplayer) { + FScoreboard fboard = fscoreboards.remove(fplayer); - if (fboard != null) { - fboard.removed = true; - FTeamWrapper.untrack(fboard); - } - } + if (fboard != null) { + fboard.removed = true; + FTeamWrapper.untrack(fboard); + } + } - public static FScoreboard get(FPlayer fplayer) { - return fscoreboards.get(fplayer); - } + public static FScoreboard get(FPlayer fplayer) { + return fscoreboards.get(fplayer); + } - public static FScoreboard get(Player player) { - return fscoreboards.get(FPlayers.getInstance().getByPlayer(player)); - } + public static FScoreboard get(Player player) { + return fscoreboards.get(FPlayers.getInstance().getByPlayer(player)); + } - protected FPlayer getFPlayer() { - return fplayer; - } + protected FPlayer getFPlayer() { + return fplayer; + } - protected Scoreboard getScoreboard() { - return scoreboard; - } + protected Scoreboard getScoreboard() { + return scoreboard; + } - public void setSidebarVisibility(boolean visible) { - if (!isSupportedByServer()) { - return; - } + public void setSidebarVisibility(boolean visible) { + if (!isSupportedByServer()) { + return; + } - bufferedObjective.setDisplaySlot(visible ? DisplaySlot.SIDEBAR : null); - } + bufferedObjective.setDisplaySlot(visible ? DisplaySlot.SIDEBAR : null); + } - public void setDefaultSidebar(final FSidebarProvider provider, int updateInterval) { - if (!isSupportedByServer()) { - return; - } + public void setDefaultSidebar(final FSidebarProvider provider, int updateInterval) { + if (!isSupportedByServer()) { + return; + } - defaultProvider = provider; - if (temporaryProvider == null) { - // We have no temporary provider; update the BufferedObjective! - updateObjective(); - } + defaultProvider = provider; + if (temporaryProvider == null) { + // We have no temporary provider; update the BufferedObjective! + updateObjective(); + } - new BukkitRunnable() { - @Override - public void run() { - if (removed || provider != defaultProvider) { - cancel(); - return; - } + new BukkitRunnable() { + @Override + public void run() { + if (removed || provider != defaultProvider) { + cancel(); + return; + } - if (temporaryProvider == null) { - updateObjective(); - } - } - }.runTaskTimer(SavageFactions.plugin, updateInterval, updateInterval); - } + if (temporaryProvider == null) { + updateObjective(); + } + } + }.runTaskTimer(SavageFactions.plugin, updateInterval, updateInterval); + } - public void setTemporarySidebar(final FSidebarProvider provider) { - if (!isSupportedByServer()) { - return; - } + public void setTemporarySidebar(final FSidebarProvider provider) { + if (!isSupportedByServer()) { + return; + } - temporaryProvider = provider; - updateObjective(); + temporaryProvider = provider; + updateObjective(); - new BukkitRunnable() { - @Override - public void run() { - if (removed) { - return; - } + new BukkitRunnable() { + @Override + public void run() { + if (removed) { + return; + } - if (temporaryProvider == provider) { - temporaryProvider = null; - updateObjective(); - } - } - }.runTaskLater(SavageFactions.plugin, SavageFactions.plugin.getConfig().getInt("scoreboard.expiration", 7) * 20); - } + if (temporaryProvider == provider) { + temporaryProvider = null; + updateObjective(); + } + } + }.runTaskLater(SavageFactions.plugin, SavageFactions.plugin.getConfig().getInt("scoreboard.expiration", 7) * 20); + } - private void updateObjective() { - FSidebarProvider provider = temporaryProvider != null ? temporaryProvider : defaultProvider; + private void updateObjective() { + FSidebarProvider provider = temporaryProvider != null ? temporaryProvider : defaultProvider; - if (provider == null) { - bufferedObjective.hide(); - } else { - bufferedObjective.setTitle(provider.getTitle(fplayer)); - bufferedObjective.setAllLines(provider.getLines(fplayer)); - bufferedObjective.flip(); - } - } + if (provider == null) { + bufferedObjective.hide(); + } else { + bufferedObjective.setTitle(provider.getTitle(fplayer)); + bufferedObjective.setAllLines(provider.getLines(fplayer)); + bufferedObjective.flip(); + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java b/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java index a40640f4..6ce4976c 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java @@ -10,32 +10,32 @@ import java.util.List; public abstract class FSidebarProvider { - public abstract String getTitle(FPlayer fplayer); + public abstract String getTitle(FPlayer fplayer); - public abstract List getLines(FPlayer fplayer); + public abstract List getLines(FPlayer fplayer); - public String replaceTags(FPlayer fPlayer, String s) { - s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); + public String replaceTags(FPlayer fPlayer, String s) { + s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); - return qualityAssure(TagUtil.parsePlain(fPlayer, s)); - } + return qualityAssure(TagUtil.parsePlain(fPlayer, s)); + } - public String replaceTags(Faction faction, FPlayer fPlayer, String s) { - // Run through Placeholder API first - s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); + public String replaceTags(Faction faction, FPlayer fPlayer, String s) { + // Run through Placeholder API first + s = TagUtil.parsePlaceholders(fPlayer.getPlayer(), s); - return qualityAssure(TagUtil.parsePlain(faction, fPlayer, s)); - } + return qualityAssure(TagUtil.parsePlain(faction, fPlayer, s)); + } - private String qualityAssure(String line) { - if (line.contains("{notFrozen}") || line.contains("{notPermanent}")) { - return "n/a"; // we dont support support these error variables in scoreboards - } - if (line.contains("{ig}")) { - // since you can't really fit a whole "Faction Home: world, x, y, z" on one line - // we assume it's broken up into two lines, so returning our tl will suffice. - return TL.COMMAND_SHOW_NOHOME.toString(); - } - return SavageFactions.plugin.txt.parse(line); // finally add color :) - } + private String qualityAssure(String line) { + if (line.contains("{notFrozen}") || line.contains("{notPermanent}")) { + return "n/a"; // we dont support support these error variables in scoreboards + } + if (line.contains("{ig}")) { + // since you can't really fit a whole "Faction Home: world, x, y, z" on one line + // we assume it's broken up into two lines, so returning our tl will suffice. + return TL.COMMAND_SHOW_NOHOME.toString(); + } + return SavageFactions.plugin.txt.parse(line); // finally add color :) + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java b/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java index f2f442d2..88ee2663 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java @@ -12,215 +12,215 @@ import org.bukkit.scoreboard.Team; import java.util.*; public class FTeamWrapper { - private static final Map wrappers = new HashMap<>(); - private static final List tracking = new ArrayList<>(); - private static final Set updating = new HashSet<>(); - private static int factionTeamPtr; - private final Map teams = new HashMap<>(); - private final String teamName; - private final Faction faction; - private final Set members = new HashSet<>(); + private static final Map wrappers = new HashMap<>(); + private static final List tracking = new ArrayList<>(); + private static final Set updating = new HashSet<>(); + private static int factionTeamPtr; + private final Map teams = new HashMap<>(); + private final String teamName; + private final Faction faction; + private final Set members = new HashSet<>(); - private FTeamWrapper(Faction faction) { - this.teamName = "faction_" + (factionTeamPtr++); - this.faction = faction; + private FTeamWrapper(Faction faction) { + this.teamName = "faction_" + (factionTeamPtr++); + this.faction = faction; - for (FScoreboard fboard : tracking) { - add(fboard); - } - } + for (FScoreboard fboard : tracking) { + add(fboard); + } + } - public static void applyUpdatesLater(final Faction faction) { - if (!FScoreboard.isSupportedByServer()) { - return; - } + public static void applyUpdatesLater(final Faction faction) { + if (!FScoreboard.isSupportedByServer()) { + return; + } - if (faction.isWilderness()) { - return; - } + if (faction.isWilderness()) { + return; + } - if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { - return; - } + if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { + return; + } - if (updating.add(faction)) { - Bukkit.getScheduler().runTask(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - updating.remove(faction); - applyUpdates(faction); - } - }); - } - } + if (updating.add(faction)) { + Bukkit.getScheduler().runTask(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + updating.remove(faction); + applyUpdates(faction); + } + }); + } + } - public static void applyUpdates(Faction faction) { - if (!FScoreboard.isSupportedByServer()) { - return; - } + public static void applyUpdates(Faction faction) { + if (!FScoreboard.isSupportedByServer()) { + return; + } - if (faction.isWilderness()) { - return; - } + if (faction.isWilderness()) { + return; + } - if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { - return; - } + if (!SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false) || SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members")) { + return; + } - if (updating.contains(faction)) { - // Faction will be updated soon. - return; - } + if (updating.contains(faction)) { + // Faction will be updated soon. + return; + } - FTeamWrapper wrapper = wrappers.get(faction); - Set factionMembers = faction.getFPlayers(); + FTeamWrapper wrapper = wrappers.get(faction); + Set factionMembers = faction.getFPlayers(); - if (wrapper != null && Factions.getInstance().getFactionById(faction.getId()) == null) { - // Faction was disbanded - wrapper.unregister(); - wrappers.remove(faction); - return; - } + if (wrapper != null && Factions.getInstance().getFactionById(faction.getId()) == null) { + // Faction was disbanded + wrapper.unregister(); + wrappers.remove(faction); + return; + } - if (wrapper == null) { - wrapper = new FTeamWrapper(faction); - wrappers.put(faction, wrapper); - } + if (wrapper == null) { + wrapper = new FTeamWrapper(faction); + wrappers.put(faction, wrapper); + } - for (OfflinePlayer player : wrapper.getPlayers()) { - if (!player.isOnline() || !factionMembers.contains(FPlayers.getInstance().getByOfflinePlayer(player))) { - // Player is offline or no longer in faction - wrapper.removePlayer(player); - } - } + for (OfflinePlayer player : wrapper.getPlayers()) { + if (!player.isOnline() || !factionMembers.contains(FPlayers.getInstance().getByOfflinePlayer(player))) { + // Player is offline or no longer in faction + wrapper.removePlayer(player); + } + } - for (FPlayer fmember : factionMembers) { - if (!fmember.isOnline()) { - continue; - } + for (FPlayer fmember : factionMembers) { + if (!fmember.isOnline()) { + continue; + } - // Scoreboard might not have player; add him/her - wrapper.addPlayer(fmember.getPlayer()); - } + // Scoreboard might not have player; add him/her + wrapper.addPlayer(fmember.getPlayer()); + } - wrapper.updatePrefixes(); - } + wrapper.updatePrefixes(); + } - public static void updatePrefixes(Faction faction) { - if (!FScoreboard.isSupportedByServer()) { - return; - } + public static void updatePrefixes(Faction faction) { + if (!FScoreboard.isSupportedByServer()) { + return; + } - if (!wrappers.containsKey(faction)) { - applyUpdates(faction); - } else { - wrappers.get(faction).updatePrefixes(); - } - } + if (!wrappers.containsKey(faction)) { + applyUpdates(faction); + } else { + wrappers.get(faction).updatePrefixes(); + } + } - protected static void track(FScoreboard fboard) { - if (!FScoreboard.isSupportedByServer()) { - return; - } - tracking.add(fboard); - for (FTeamWrapper wrapper : wrappers.values()) { - wrapper.add(fboard); - } - } + protected static void track(FScoreboard fboard) { + if (!FScoreboard.isSupportedByServer()) { + return; + } + tracking.add(fboard); + for (FTeamWrapper wrapper : wrappers.values()) { + wrapper.add(fboard); + } + } - protected static void untrack(FScoreboard fboard) { - if (!FScoreboard.isSupportedByServer()) { - return; - } - tracking.remove(fboard); - for (FTeamWrapper wrapper : wrappers.values()) { - wrapper.remove(fboard); - } - } + protected static void untrack(FScoreboard fboard) { + if (!FScoreboard.isSupportedByServer()) { + return; + } + tracking.remove(fboard); + for (FTeamWrapper wrapper : wrappers.values()) { + wrapper.remove(fboard); + } + } - private void add(FScoreboard fboard) { - Scoreboard board = fboard.getScoreboard(); - Team team = board.registerNewTeam(teamName); - teams.put(fboard, team); + private void add(FScoreboard fboard) { + Scoreboard board = fboard.getScoreboard(); + Team team = board.registerNewTeam(teamName); + teams.put(fboard, team); - for (OfflinePlayer player : getPlayers()) { - team.addPlayer(player); - } + for (OfflinePlayer player : getPlayers()) { + team.addPlayer(player); + } - updatePrefix(fboard); - } + updatePrefix(fboard); + } - private void remove(FScoreboard fboard) { - teams.remove(fboard).unregister(); - } + private void remove(FScoreboard fboard) { + teams.remove(fboard).unregister(); + } - private void updatePrefixes() { - if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { - for (FScoreboard fboard : teams.keySet()) { - updatePrefix(fboard); - } - } - } + private void updatePrefixes() { + if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { + for (FScoreboard fboard : teams.keySet()) { + updatePrefix(fboard); + } + } + } - private void updatePrefix(FScoreboard fboard) { - if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { - FPlayer fplayer = fboard.getFPlayer(); - Team team = teams.get(fboard); - boolean focused = false; + private void updatePrefix(FScoreboard fboard) { + if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-prefixes", false)) { + FPlayer fplayer = fboard.getFPlayer(); + Team team = teams.get(fboard); + boolean focused = false; - if (SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members", false)) { - team.setCanSeeFriendlyInvisibles(true); - } + if (SavageFactions.plugin.getConfig().getBoolean("See-Invisible-Faction-Members", false)) { + team.setCanSeeFriendlyInvisibles(true); + } - if ((SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) && (fplayer.getFaction() != null) && (fplayer.getFaction().getFocused() != null)) { - for (FPlayer fp : faction.getFPlayersWhereOnline(true)) { - if (fplayer.getFaction().getFocused().equalsIgnoreCase(fp.getName())) { - team.setPrefix(ChatColor.translateAlternateColorCodes('&', SavageFactions.plugin.getConfig().getString("ffocus.Prefix", "&7»&b"))); - focused = true; - } - } - } - if (!focused) { - String prefix = TL.DEFAULT_PREFIX.toString(); + if ((SavageFactions.plugin.getConfig().getBoolean("ffocus.Enabled")) && (fplayer.getFaction() != null) && (fplayer.getFaction().getFocused() != null)) { + for (FPlayer fp : faction.getFPlayersWhereOnline(true)) { + if (fplayer.getFaction().getFocused().equalsIgnoreCase(fp.getName())) { + team.setPrefix(ChatColor.translateAlternateColorCodes('&', SavageFactions.plugin.getConfig().getString("ffocus.Prefix", "&7»&b"))); + focused = true; + } + } + } + if (!focused) { + String prefix = TL.DEFAULT_PREFIX.toString(); - prefix = PlaceholderAPI.setPlaceholders(fplayer.getPlayer(), prefix); - prefix = PlaceholderAPI.setBracketPlaceholders(fplayer.getPlayer(), prefix); - prefix = prefix.replace("{relationcolor}", faction.getRelationTo(fplayer).getColor().toString()); - prefix = prefix.replace("{faction}", - faction.getTag().substring(0, Math.min("{faction}".length() + 16 - prefix.length(), faction.getTag().length()))); - if ((team.getPrefix() == null) || (!team.getPrefix().equals(prefix))) { - team.setPrefix(prefix); - } - } - } - } + prefix = PlaceholderAPI.setPlaceholders(fplayer.getPlayer(), prefix); + prefix = PlaceholderAPI.setBracketPlaceholders(fplayer.getPlayer(), prefix); + prefix = prefix.replace("{relationcolor}", faction.getRelationTo(fplayer).getColor().toString()); + prefix = prefix.replace("{faction}", + faction.getTag().substring(0, Math.min("{faction}".length() + 16 - prefix.length(), faction.getTag().length()))); + if ((team.getPrefix() == null) || (!team.getPrefix().equals(prefix))) { + team.setPrefix(prefix); + } + } + } + } - private void addPlayer(OfflinePlayer player) { - if (members.add(player)) { - for (Team team : teams.values()) { - team.addPlayer(player); - } - } - } + private void addPlayer(OfflinePlayer player) { + if (members.add(player)) { + for (Team team : teams.values()) { + team.addPlayer(player); + } + } + } - private void removePlayer(OfflinePlayer player) { - if (members.remove(player)) { - for (Team team : teams.values()) { - team.removePlayer(player); - } - } - } + private void removePlayer(OfflinePlayer player) { + if (members.remove(player)) { + for (Team team : teams.values()) { + team.removePlayer(player); + } + } + } - private Set getPlayers() { - return new HashSet<>(this.members); - } + private Set getPlayers() { + return new HashSet<>(this.members); + } - private void unregister() { - for (Team team : teams.values()) { - team.unregister(); - } - teams.clear(); - } + private void unregister() { + for (Team team : teams.values()) { + team.unregister(); + } + teams.clear(); + } } diff --git a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java index 5bdf32fa..64c68708 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java @@ -10,32 +10,32 @@ import java.util.ListIterator; public class FDefaultSidebar extends FSidebarProvider { - @Override - public String getTitle(FPlayer fplayer) { - return replaceTags(fplayer, SavageFactions.plugin.getConfig().getString("scoreboard.default-title", "{name}")); - } + @Override + public String getTitle(FPlayer fplayer) { + return replaceTags(fplayer, SavageFactions.plugin.getConfig().getString("scoreboard.default-title", "{name}")); + } - @Override - public List getLines(FPlayer fplayer) { - if (fplayer.hasFaction()) { - return getOutput(fplayer, "scoreboard.default"); - } else if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.factionless-enabled", false)) { - return getOutput(fplayer, "scoreboard.factionless"); - } - return getOutput(fplayer, "scoreboard.default"); // no faction, factionless-board disabled - } + @Override + public List getLines(FPlayer fplayer) { + if (fplayer.hasFaction()) { + return getOutput(fplayer, "scoreboard.default"); + } else if (SavageFactions.plugin.getConfig().getBoolean("scoreboard.factionless-enabled", false)) { + return getOutput(fplayer, "scoreboard.factionless"); + } + return getOutput(fplayer, "scoreboard.default"); // no faction, factionless-board disabled + } - public List getOutput(FPlayer fplayer, String list) { - List lines = SavageFactions.plugin.getConfig().getStringList(list); + public List getOutput(FPlayer fplayer, String list) { + List lines = SavageFactions.plugin.getConfig().getStringList(list); - if (lines == null || lines.isEmpty()) { - return new ArrayList<>(); - } + if (lines == null || lines.isEmpty()) { + return new ArrayList<>(); + } - ListIterator it = lines.listIterator(); - while (it.hasNext()) { - it.set(replaceTags(fplayer, it.next())); - } - return lines; - } + ListIterator it = lines.listIterator(); + while (it.hasNext()) { + it.set(replaceTags(fplayer, it.next())); + } + return lines; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java index 93759678..4820387c 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java @@ -9,25 +9,25 @@ import java.util.List; import java.util.ListIterator; public class FInfoSidebar extends FSidebarProvider { - private final Faction faction; + private final Faction faction; - public FInfoSidebar(Faction faction) { - this.faction = faction; - } + public FInfoSidebar(Faction faction) { + this.faction = faction; + } - @Override - public String getTitle(FPlayer fplayer) { - return faction.getRelationTo(fplayer).getColor() + faction.getTag(); - } + @Override + public String getTitle(FPlayer fplayer) { + return faction.getRelationTo(fplayer).getColor() + faction.getTag(); + } - @Override - public List getLines(FPlayer fplayer) { - List lines = SavageFactions.plugin.getConfig().getStringList("scoreboard.finfo"); + @Override + public List getLines(FPlayer fplayer) { + List lines = SavageFactions.plugin.getConfig().getStringList("scoreboard.finfo"); - ListIterator it = lines.listIterator(); - while (it.hasNext()) { - it.set(replaceTags(faction, fplayer, it.next())); - } - return lines; - } + ListIterator it = lines.listIterator(); + while (it.hasNext()) { + it.set(replaceTags(faction, fplayer, it.next())); + } + return lines; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java index 037a9c03..4c33f291 100644 --- a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java +++ b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerFactionExpression.java @@ -18,80 +18,80 @@ import org.bukkit.event.Event; public class PlayerFactionExpression extends SimpleExpression { - static { - Skript.registerExpression(PlayerFactionExpression.class, String.class, ExpressionType.SIMPLE, "[the] faction of %player%", "[the] %player%['s] faction"); - } + static { + Skript.registerExpression(PlayerFactionExpression.class, String.class, ExpressionType.SIMPLE, "[the] faction of %player%", "[the] %player%['s] faction"); + } - Expression playerExpression; + Expression playerExpression; - @Override - public Class getReturnType() { - return String.class; - } + @Override + public Class getReturnType() { + return String.class; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public boolean isSingle() { + return true; + } - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { - playerExpression = (Expression) exprs[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + playerExpression = (Expression) exprs[0]; + return true; + } - @Override - public String toString(Event event, boolean debug) { - return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); - } + @Override + public String toString(Event event, boolean debug) { + return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); + } - @Override - protected String[] get(Event event) { - Player player = playerExpression.getSingle(event); + @Override + protected String[] get(Event event) { + Player player = playerExpression.getSingle(event); - if (player != null) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - return new String[]{fPlayer.getFaction().getTag()}; - } + if (player != null) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + return new String[]{fPlayer.getFaction().getTag()}; + } - return null; + return null; - } + } - @Override - public Class[] acceptChange(final Changer.ChangeMode mode) { - if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { - return CollectionUtils.array(String.class); - } - return null; - } + @Override + public Class[] acceptChange(final Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { + return CollectionUtils.array(String.class); + } + return null; + } - @Override - public void change(Event event, Object[] delta, Changer.ChangeMode mode) { - Player player = playerExpression.getSingle(event); - if (player == null) { - return; - } + @Override + public void change(Event event, Object[] delta, Changer.ChangeMode mode) { + Player player = playerExpression.getSingle(event); + if (player == null) { + return; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - switch (mode) { - case DELETE: - case RESET: - fPlayer.setFaction(Factions.getInstance().getWilderness()); - break; - case SET: - Faction faction = Factions.getInstance().getByTag((String) delta[0]); - if (faction == null) { - faction = Factions.getInstance().getWilderness(); - } - fPlayer.setFaction(faction); - break; - default: - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + switch (mode) { + case DELETE: + case RESET: + fPlayer.setFaction(Factions.getInstance().getWilderness()); + break; + case SET: + Faction faction = Factions.getInstance().getByTag((String) delta[0]); + if (faction == null) { + faction = Factions.getInstance().getWilderness(); + } + fPlayer.setFaction(faction); + break; + default: + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java index 928da2e5..f4d2c4c2 100644 --- a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java +++ b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerPowerExpression.java @@ -16,80 +16,80 @@ import org.bukkit.event.Event; public class PlayerPowerExpression extends SimpleExpression { - static { - Skript.registerExpression(PlayerPowerExpression.class, Number.class, ExpressionType.SIMPLE, "[the] power of %player%", "[the] %player%['s] power"); - } + static { + Skript.registerExpression(PlayerPowerExpression.class, Number.class, ExpressionType.SIMPLE, "[the] power of %player%", "[the] %player%['s] power"); + } - Expression playerExpression; + Expression playerExpression; - @Override - public Class getReturnType() { - return Double.class; - } + @Override + public Class getReturnType() { + return Double.class; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public boolean isSingle() { + return true; + } - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { - playerExpression = (Expression) exprs[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + playerExpression = (Expression) exprs[0]; + return true; + } - @Override - public String toString(Event event, boolean debug) { - return "Player Power with expression player" + playerExpression.toString(event, debug); - } + @Override + public String toString(Event event, boolean debug) { + return "Player Power with expression player" + playerExpression.toString(event, debug); + } - @Override - protected Double[] get(Event event) { - Player player = playerExpression.getSingle(event); + @Override + protected Double[] get(Event event) { + Player player = playerExpression.getSingle(event); - if (player != null) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - return new Double[]{fPlayer.getFaction().getPower()}; - } + if (player != null) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + return new Double[]{fPlayer.getFaction().getPower()}; + } - return null; + return null; - } + } - @Override - public Class[] acceptChange(final Changer.ChangeMode mode) { - if (mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.ADD || mode == Changer.ChangeMode.REMOVE) { - return CollectionUtils.array(Number.class); - } - return null; - } + @Override + public Class[] acceptChange(final Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.ADD || mode == Changer.ChangeMode.REMOVE) { + return CollectionUtils.array(Number.class); + } + return null; + } - @Override - public void change(Event event, Object[] delta, Changer.ChangeMode mode) { - Player player = playerExpression.getSingle(event); - if (player == null) { - return; - } + @Override + public void change(Event event, Object[] delta, Changer.ChangeMode mode) { + Player player = playerExpression.getSingle(event); + if (player == null) { + return; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - switch (mode) { - case ADD: - fPlayer.alterPower(Double.valueOf((Long) delta[0])); - break; - case REMOVE: - fPlayer.alterPower(Double.valueOf((Long) delta[0]) * -1); - break; - case RESET: - fPlayer.alterPower(fPlayer.getPowerMax() * -1); - break; - default: - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + switch (mode) { + case ADD: + fPlayer.alterPower(Double.valueOf((Long) delta[0])); + break; + case REMOVE: + fPlayer.alterPower(Double.valueOf((Long) delta[0]) * -1); + break; + case RESET: + fPlayer.alterPower(fPlayer.getPowerMax() * -1); + break; + default: + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java index 13d96ade..238c6134 100644 --- a/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java +++ b/src/main/java/com/massivecraft/factions/skript/expressions/player/PlayerRoleExpression.java @@ -16,77 +16,77 @@ import org.bukkit.event.Event; public class PlayerRoleExpression extends SimpleExpression { - static { - Skript.registerExpression(PlayerRoleExpression.class, String.class, ExpressionType.SIMPLE, "[the] role of %player%", "[the] %player%['s] role"); - } + static { + Skript.registerExpression(PlayerRoleExpression.class, String.class, ExpressionType.SIMPLE, "[the] role of %player%", "[the] %player%['s] role"); + } - Expression playerExpression; + Expression playerExpression; - @Override - public Class getReturnType() { - return String.class; - } + @Override + public Class getReturnType() { + return String.class; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public boolean isSingle() { + return true; + } - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { - playerExpression = (Expression) exprs[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + playerExpression = (Expression) exprs[0]; + return true; + } - @Override - public String toString(Event event, boolean debug) { - return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); - } + @Override + public String toString(Event event, boolean debug) { + return "Player Faction Name Expression with expression player" + playerExpression.toString(event, debug); + } - @Override - protected String[] get(Event event) { - Player player = playerExpression.getSingle(event); + @Override + protected String[] get(Event event) { + Player player = playerExpression.getSingle(event); - if (player != null) { - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - return new String[]{fPlayer.getRole().toString()}; - } + if (player != null) { + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + return new String[]{fPlayer.getRole().toString()}; + } - return null; + return null; - } + } - @Override - public Class[] acceptChange(final Changer.ChangeMode mode) { - if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { - return CollectionUtils.array(String.class); - } - return null; - } + @Override + public Class[] acceptChange(final Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.RESET || mode == Changer.ChangeMode.SET) { + return CollectionUtils.array(String.class); + } + return null; + } - @Override - public void change(Event event, Object[] delta, Changer.ChangeMode mode) { - Player player = playerExpression.getSingle(event); - if (player == null) { - return; - } + @Override + public void change(Event event, Object[] delta, Changer.ChangeMode mode) { + Player player = playerExpression.getSingle(event); + if (player == null) { + return; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - switch (mode) { - case DELETE: - case RESET: - fPlayer.setRole(Role.RECRUIT); - break; - case SET: - fPlayer.setRole(Role.fromString(((String) delta[0]).toLowerCase())); - break; - default: - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + switch (mode) { + case DELETE: + case RESET: + fPlayer.setRole(Role.RECRUIT); + break; + case SET: + fPlayer.setRole(Role.fromString(((String) delta[0]).toLowerCase())); + break; + default: + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/struct/BanInfo.java b/src/main/java/com/massivecraft/factions/struct/BanInfo.java index 365d7a31..8aacfe24 100644 --- a/src/main/java/com/massivecraft/factions/struct/BanInfo.java +++ b/src/main/java/com/massivecraft/factions/struct/BanInfo.java @@ -2,41 +2,41 @@ package com.massivecraft.factions.struct; public class BanInfo { - // FPlayer IDs - private final String banner; - private final String banned; - private final long time; + // FPlayer IDs + private final String banner; + private final String banned; + private final long time; - public BanInfo(String banner, String banned, long time) { - this.banner = banner; - this.banned = banned; - this.time = time; - } + public BanInfo(String banner, String banned, long time) { + this.banner = banner; + this.banned = banned; + this.time = time; + } - /** - * Get the FPlayer ID of the player who issued the ban. - * - * @return FPlayer ID. - */ - public String getBanner() { - return this.banner; - } + /** + * Get the FPlayer ID of the player who issued the ban. + * + * @return FPlayer ID. + */ + public String getBanner() { + return this.banner; + } - /** - * Get the FPlayer ID of the player who got banned. - * - * @return FPlayer ID. - */ - public String getBanned() { - return banned; - } + /** + * Get the FPlayer ID of the player who got banned. + * + * @return FPlayer ID. + */ + public String getBanned() { + return banned; + } - /** - * Get the server time when the ban was issued. - * - * @return system timestamp. - */ - public long getTime() { - return time; - } + /** + * Get the server time when the ban was issued. + * + * @return system timestamp. + */ + public long getTime() { + return time; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/ChatMode.java b/src/main/java/com/massivecraft/factions/struct/ChatMode.java index 34536416..42471a1e 100644 --- a/src/main/java/com/massivecraft/factions/struct/ChatMode.java +++ b/src/main/java/com/massivecraft/factions/struct/ChatMode.java @@ -3,40 +3,40 @@ package com.massivecraft.factions.struct; import com.massivecraft.factions.zcore.util.TL; public enum ChatMode { - MOD(4, TL.CHAT_MOD), - FACTION(3, TL.CHAT_FACTION), - ALLIANCE(2, TL.CHAT_ALLIANCE), - TRUCE(1, TL.CHAT_TRUCE), - PUBLIC(0, TL.CHAT_PUBLIC); + MOD(4, TL.CHAT_MOD), + FACTION(3, TL.CHAT_FACTION), + ALLIANCE(2, TL.CHAT_ALLIANCE), + TRUCE(1, TL.CHAT_TRUCE), + PUBLIC(0, TL.CHAT_PUBLIC); - public final int value; - public final TL nicename; + public final int value; + public final TL nicename; - ChatMode(final int value, final TL nicename) { - this.value = value; - this.nicename = nicename; - } + ChatMode(final int value, final TL nicename) { + this.value = value; + this.nicename = nicename; + } - public boolean isAtLeast(ChatMode role) { - return this.value >= role.value; - } + public boolean isAtLeast(ChatMode role) { + return this.value >= role.value; + } - public boolean isAtMost(ChatMode role) { - return this.value <= role.value; - } + public boolean isAtMost(ChatMode role) { + return this.value <= role.value; + } - @Override - public String toString() { - return this.nicename.toString(); - } + @Override + public String toString() { + return this.nicename.toString(); + } - public ChatMode getNext() { - if (this == PUBLIC) { - return ALLIANCE; - } - if (this == ALLIANCE) { - return FACTION; - } - return PUBLIC; - } + public ChatMode getNext() { + if (this == PUBLIC) { + return ALLIANCE; + } + if (this == ALLIANCE) { + return FACTION; + } + return PUBLIC; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/Permission.java b/src/main/java/com/massivecraft/factions/struct/Permission.java index 3184485d..c174df31 100644 --- a/src/main/java/com/massivecraft/factions/struct/Permission.java +++ b/src/main/java/com/massivecraft/factions/struct/Permission.java @@ -1,125 +1,125 @@ -package com.massivecraft.factions.struct; - -import com.massivecraft.factions.SavageFactions; -import org.bukkit.command.CommandSender; - -public enum Permission { - MANAGE_SAFE_ZONE("managesafezone"), - MANAGE_WAR_ZONE("managewarzone"), - OWNERSHIP_BYPASS("ownershipbypass"), - ADMIN("admin"), - ADMIN_ANY("admin.any"), - AHOME("ahome"), - ANNOUNCE("announce"), - AUTOCLAIM("autoclaim"), - AUTO_LEAVE_BYPASS("autoleavebypass"), - BAN("ban"), - BYPASS("bypass"), - CHAT("chat"), - CHATSPY("chatspy"), - CLAIM("claim"), - CLAIMAT("claimat"), - CLAIM_LINE("claim.line"), - CLAIM_RADIUS("claim.radius"), - CONFIG("config"), - CONVERT("convert"), - CREATE("create"), - DEFAULTRANK("defaultrank"), - DEINVITE("deinvite"), - DESCRIPTION("description"), - DISBAND("disband"), - DISBAND_ANY("disband.any"), - FLY("fly"), - FOCUS("focus"), - HELP("help"), - HOME("home"), - INVITE("invite"), - JOIN("join"), - JOIN_ANY("join.any"), - JOIN_OTHERS("join.others"), - KICK("kick"), - KICK_ANY("kick.any"), - LEAVE("leave"), - LIST("list"), - LOCK("lock"), - MAP("map"), - MAPHEIGHT("mapheight"), - MOD("mod"), - COLEADER("coleader"), - MOD_ANY("mod.any"), - COLEADER_ANY("coleader.any"), - MODIFY_POWER("modifypower"), - MONEY_BALANCE("money.balance"), - MONEY_BALANCE_ANY("money.balance.any"), - MONEY_DEPOSIT("money.deposit"), - MONEY_WITHDRAW("money.withdraw"), - MONEY_WITHDRAW_ANY("money.withdraw.any"), - MONEY_F2F("money.f2f"), - MONEY_F2P("money.f2p"), - MONEY_P2F("money.p2f"), - MONITOR_LOGINS("monitorlogins"), - NO_BOOM("noboom"), - OPEN("open"), - OWNER("owner"), - OWNERLIST("ownerlist"), - SET_PEACEFUL("setpeaceful"), - SET_PERMANENT("setpermanent"), - SET_PERMANENTPOWER("setpermanentpower"), - SHOW_INVITES("showinvites"), - PAYPALSET("setpaypal"), - PERMISSIONS("permissions"), - POWERBOOST("powerboost"), - POWER("power"), - POWER_ANY("power.any"), - PROMOTE("promote"), - RELATION("relation"), - RELOAD("reload"), - SAVE("save"), - SETHOME("sethome"), - SETHOME_ANY("sethome.any"), - SHOW("show"), - STATUS("status"), - STEALTH("stealth"), - STUCK("stuck"), - TAG("tag"), - TNT("tnt"), - TITLE("title"), - TITLE_COLOR("title.color"), - TOGGLE_ALLIANCE_CHAT("togglealliancechat"), - UNCLAIM("unclaim"), - UNCLAIM_ALL("unclaimall"), - VERSION("version"), - SCOREBOARD("scoreboard"), - SEECHUNK("seechunk"), - SETWARP("setwarp"), - TOP("top"), - VAULT("vault"), - GETVAULT("getvault"), - SETMAXVAULTS("setmaxvaults"), - RULES("rules"), - CHECKPOINT("checkpoint"), - UPGRADES("upgrades"), - BANNER("banner"), - TPBANNER("tpbanner"), - KILLHOLOS("killholos"), - INSPECT("inspect"), - TNTFILL("tntfill"), - COORD("coords"), - SHOWCLAIMS("showclaims"), - WARP("warp"), - CHEST("Chest"); - - public final String node; - - Permission(final String node) { - this.node = "factions." + node; - } - - public boolean has(CommandSender sender, boolean informSenderIfNot) { - return SavageFactions.plugin.perm.has(sender, this.node, informSenderIfNot); - } - - public boolean has(CommandSender sender) { - return has(sender, false); - } -} +package com.massivecraft.factions.struct; + +import com.massivecraft.factions.SavageFactions; +import org.bukkit.command.CommandSender; + +public enum Permission { + MANAGE_SAFE_ZONE("managesafezone"), + MANAGE_WAR_ZONE("managewarzone"), + OWNERSHIP_BYPASS("ownershipbypass"), + ADMIN("admin"), + ADMIN_ANY("admin.any"), + AHOME("ahome"), + ANNOUNCE("announce"), + AUTOCLAIM("autoclaim"), + AUTO_LEAVE_BYPASS("autoleavebypass"), + BAN("ban"), + BYPASS("bypass"), + CHAT("chat"), + CHATSPY("chatspy"), + CLAIM("claim"), + CLAIMAT("claimat"), + CLAIM_LINE("claim.line"), + CLAIM_RADIUS("claim.radius"), + CONFIG("config"), + CONVERT("convert"), + CREATE("create"), + DEFAULTRANK("defaultrank"), + DEINVITE("deinvite"), + DESCRIPTION("description"), + DISBAND("disband"), + DISBAND_ANY("disband.any"), + FLY("fly"), + FOCUS("focus"), + HELP("help"), + HOME("home"), + INVITE("invite"), + JOIN("join"), + JOIN_ANY("join.any"), + JOIN_OTHERS("join.others"), + KICK("kick"), + KICK_ANY("kick.any"), + LEAVE("leave"), + LIST("list"), + LOCK("lock"), + MAP("map"), + MAPHEIGHT("mapheight"), + MOD("mod"), + COLEADER("coleader"), + MOD_ANY("mod.any"), + COLEADER_ANY("coleader.any"), + MODIFY_POWER("modifypower"), + MONEY_BALANCE("money.balance"), + MONEY_BALANCE_ANY("money.balance.any"), + MONEY_DEPOSIT("money.deposit"), + MONEY_WITHDRAW("money.withdraw"), + MONEY_WITHDRAW_ANY("money.withdraw.any"), + MONEY_F2F("money.f2f"), + MONEY_F2P("money.f2p"), + MONEY_P2F("money.p2f"), + MONITOR_LOGINS("monitorlogins"), + NO_BOOM("noboom"), + OPEN("open"), + OWNER("owner"), + OWNERLIST("ownerlist"), + SET_PEACEFUL("setpeaceful"), + SET_PERMANENT("setpermanent"), + SET_PERMANENTPOWER("setpermanentpower"), + SHOW_INVITES("showinvites"), + PAYPALSET("setpaypal"), + PERMISSIONS("permissions"), + POWERBOOST("powerboost"), + POWER("power"), + POWER_ANY("power.any"), + PROMOTE("promote"), + RELATION("relation"), + RELOAD("reload"), + SAVE("save"), + SETHOME("sethome"), + SETHOME_ANY("sethome.any"), + SHOW("show"), + STATUS("status"), + STEALTH("stealth"), + STUCK("stuck"), + TAG("tag"), + TNT("tnt"), + TITLE("title"), + TITLE_COLOR("title.color"), + TOGGLE_ALLIANCE_CHAT("togglealliancechat"), + UNCLAIM("unclaim"), + UNCLAIM_ALL("unclaimall"), + VERSION("version"), + SCOREBOARD("scoreboard"), + SEECHUNK("seechunk"), + SETWARP("setwarp"), + TOP("top"), + VAULT("vault"), + GETVAULT("getvault"), + SETMAXVAULTS("setmaxvaults"), + RULES("rules"), + CHECKPOINT("checkpoint"), + UPGRADES("upgrades"), + BANNER("banner"), + TPBANNER("tpbanner"), + KILLHOLOS("killholos"), + INSPECT("inspect"), + TNTFILL("tntfill"), + COORD("coords"), + SHOWCLAIMS("showclaims"), + WARP("warp"), + CHEST("Chest"); + + public final String node; + + Permission(final String node) { + this.node = "factions." + node; + } + + public boolean has(CommandSender sender, boolean informSenderIfNot) { + return SavageFactions.plugin.perm.has(sender, this.node, informSenderIfNot); + } + + public boolean has(CommandSender sender) { + return has(sender, false); + } +} diff --git a/src/main/java/com/massivecraft/factions/struct/Relation.java b/src/main/java/com/massivecraft/factions/struct/Relation.java index 2072352b..66d6039f 100644 --- a/src/main/java/com/massivecraft/factions/struct/Relation.java +++ b/src/main/java/com/massivecraft/factions/struct/Relation.java @@ -15,221 +15,221 @@ import java.util.List; public enum Relation implements Permissable { - MEMBER(4, TL.RELATION_MEMBER_SINGULAR.toString()), - ALLY(3, TL.RELATION_ALLY_SINGULAR.toString()), - TRUCE(2, TL.RELATION_TRUCE_SINGULAR.toString()), - NEUTRAL(1, TL.RELATION_NEUTRAL_SINGULAR.toString()), - ENEMY(0, TL.RELATION_ENEMY_SINGULAR.toString()); + MEMBER(4, TL.RELATION_MEMBER_SINGULAR.toString()), + ALLY(3, TL.RELATION_ALLY_SINGULAR.toString()), + TRUCE(2, TL.RELATION_TRUCE_SINGULAR.toString()), + NEUTRAL(1, TL.RELATION_NEUTRAL_SINGULAR.toString()), + ENEMY(0, TL.RELATION_ENEMY_SINGULAR.toString()); - public final int value; - public final String nicename; + public final int value; + public final String nicename; - Relation(final int value, final String nicename) { - this.value = value; - this.nicename = nicename; - } + Relation(final int value, final String nicename) { + this.value = value; + this.nicename = nicename; + } - public static Relation fromString(String s) { - // Because Java 6 doesn't allow String switches :( - if (s.equalsIgnoreCase(MEMBER.nicename)) { - return MEMBER; - } else if (s.equalsIgnoreCase(ALLY.nicename)) { - return ALLY; - } else if (s.equalsIgnoreCase(TRUCE.nicename)) { - return TRUCE; - } else if (s.equalsIgnoreCase(ENEMY.nicename)) { - return ENEMY; - } else { - return NEUTRAL; // If they somehow mess things up, go back to default behavior. - } - } + public static Relation fromString(String s) { + // Because Java 6 doesn't allow String switches :( + if (s.equalsIgnoreCase(MEMBER.nicename)) { + return MEMBER; + } else if (s.equalsIgnoreCase(ALLY.nicename)) { + return ALLY; + } else if (s.equalsIgnoreCase(TRUCE.nicename)) { + return TRUCE; + } else if (s.equalsIgnoreCase(ENEMY.nicename)) { + return ENEMY; + } else { + return NEUTRAL; // If they somehow mess things up, go back to default behavior. + } + } - @Override - public String toString() { - return this.nicename; - } + @Override + public String toString() { + return this.nicename; + } - public String getTranslation() { - try { - return TL.valueOf("RELATION_" + name() + "_SINGULAR").toString(); - } catch (IllegalArgumentException e) { - return toString(); - } - } + public String getTranslation() { + try { + return TL.valueOf("RELATION_" + name() + "_SINGULAR").toString(); + } catch (IllegalArgumentException e) { + return toString(); + } + } - public String getPluralTranslation() { - for (TL t : TL.values()) { - if (t.name().equalsIgnoreCase("RELATION_" + name() + "_PLURAL")) { - return t.toString(); - } - } - return toString(); - } + public String getPluralTranslation() { + for (TL t : TL.values()) { + if (t.name().equalsIgnoreCase("RELATION_" + name() + "_PLURAL")) { + return t.toString(); + } + } + return toString(); + } - public boolean isMember() { - return this == MEMBER; - } + public boolean isMember() { + return this == MEMBER; + } - public boolean isAlly() { - return this == ALLY; - } + public boolean isAlly() { + return this == ALLY; + } - public boolean isTruce() { - return this == TRUCE; - } + public boolean isTruce() { + return this == TRUCE; + } - public boolean isNeutral() { - return this == NEUTRAL; - } + public boolean isNeutral() { + return this == NEUTRAL; + } - public boolean isEnemy() { - return this == ENEMY; - } + public boolean isEnemy() { + return this == ENEMY; + } - public boolean isAtLeast(Relation relation) { - return this.value >= relation.value; - } + public boolean isAtLeast(Relation relation) { + return this.value >= relation.value; + } - public boolean isAtMost(Relation relation) { - return this.value <= relation.value; - } + public boolean isAtMost(Relation relation) { + return this.value <= relation.value; + } - public ChatColor getColor() { + public ChatColor getColor() { - switch (this) { - case MEMBER: - return Conf.colorMember; - case ALLY: - return Conf.colorAlly; - case NEUTRAL: - return Conf.colorNeutral; - case TRUCE: - return Conf.colorTruce; - default: - return Conf.colorEnemy; - } - } + switch (this) { + case MEMBER: + return Conf.colorMember; + case ALLY: + return Conf.colorAlly; + case NEUTRAL: + return Conf.colorNeutral; + case TRUCE: + return Conf.colorTruce; + default: + return Conf.colorEnemy; + } + } - // return appropriate Conf setting for DenyBuild based on this relation and their online status - public boolean confDenyBuild(boolean online) { - if (isMember()) { - return false; - } + // return appropriate Conf setting for DenyBuild based on this relation and their online status + public boolean confDenyBuild(boolean online) { + if (isMember()) { + return false; + } - if (online) { - if (isEnemy()) { - return Conf.territoryEnemyDenyBuild; - } else if (isAlly()) { - return Conf.territoryAllyDenyBuild; - } else if (isTruce()) { - return Conf.territoryTruceDenyBuild; - } else { - return Conf.territoryDenyBuild; - } - } else { - if (isEnemy()) { - return Conf.territoryEnemyDenyBuildWhenOffline; - } else if (isAlly()) { - return Conf.territoryAllyDenyBuildWhenOffline; - } else if (isTruce()) { - return Conf.territoryTruceDenyBuildWhenOffline; - } else { - return Conf.territoryDenyBuildWhenOffline; - } - } - } + if (online) { + if (isEnemy()) { + return Conf.territoryEnemyDenyBuild; + } else if (isAlly()) { + return Conf.territoryAllyDenyBuild; + } else if (isTruce()) { + return Conf.territoryTruceDenyBuild; + } else { + return Conf.territoryDenyBuild; + } + } else { + if (isEnemy()) { + return Conf.territoryEnemyDenyBuildWhenOffline; + } else if (isAlly()) { + return Conf.territoryAllyDenyBuildWhenOffline; + } else if (isTruce()) { + return Conf.territoryTruceDenyBuildWhenOffline; + } else { + return Conf.territoryDenyBuildWhenOffline; + } + } + } - // return appropriate Conf setting for PainBuild based on this relation and their online status - public boolean confPainBuild(boolean online) { - if (isMember()) { - return false; - } + // return appropriate Conf setting for PainBuild based on this relation and their online status + public boolean confPainBuild(boolean online) { + if (isMember()) { + return false; + } - if (online) { - if (isEnemy()) { - return Conf.territoryEnemyPainBuild; - } else if (isAlly()) { - return Conf.territoryAllyPainBuild; - } else if (isTruce()) { - return Conf.territoryTrucePainBuild; - } else { - return Conf.territoryPainBuild; - } - } else { - if (isEnemy()) { - return Conf.territoryEnemyPainBuildWhenOffline; - } else if (isAlly()) { - return Conf.territoryAllyPainBuildWhenOffline; - } else if (isTruce()) { - return Conf.territoryTrucePainBuildWhenOffline; - } else { - return Conf.territoryPainBuildWhenOffline; - } - } - } + if (online) { + if (isEnemy()) { + return Conf.territoryEnemyPainBuild; + } else if (isAlly()) { + return Conf.territoryAllyPainBuild; + } else if (isTruce()) { + return Conf.territoryTrucePainBuild; + } else { + return Conf.territoryPainBuild; + } + } else { + if (isEnemy()) { + return Conf.territoryEnemyPainBuildWhenOffline; + } else if (isAlly()) { + return Conf.territoryAllyPainBuildWhenOffline; + } else if (isTruce()) { + return Conf.territoryTrucePainBuildWhenOffline; + } else { + return Conf.territoryPainBuildWhenOffline; + } + } + } - // return appropriate Conf setting for DenyUseage based on this relation - public boolean confDenyUseage() { - if (isMember()) { - return false; - } else if (isEnemy()) { - return Conf.territoryEnemyDenyUseage; - } else if (isAlly()) { - return Conf.territoryAllyDenyUseage; - } else if (isTruce()) { - return Conf.territoryTruceDenyUseage; - } else { - return Conf.territoryDenyUseage; - } - } + // return appropriate Conf setting for DenyUseage based on this relation + public boolean confDenyUseage() { + if (isMember()) { + return false; + } else if (isEnemy()) { + return Conf.territoryEnemyDenyUseage; + } else if (isAlly()) { + return Conf.territoryAllyDenyUseage; + } else if (isTruce()) { + return Conf.territoryTruceDenyUseage; + } else { + return Conf.territoryDenyUseage; + } + } - public double getRelationCost() { - if (isEnemy()) { - return Conf.econCostEnemy; - } else if (isAlly()) { - return Conf.econCostAlly; - } else if (isTruce()) { - return Conf.econCostTruce; - } else { - return Conf.econCostNeutral; - } - } + public double getRelationCost() { + if (isEnemy()) { + return Conf.econCostEnemy; + } else if (isAlly()) { + return Conf.econCostAlly; + } else if (isTruce()) { + return Conf.econCostTruce; + } else { + return Conf.econCostNeutral; + } + } - // Utility method to build items for F Perm GUI - @Override - public ItemStack buildItem() { - final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); + // Utility method to build items for F Perm GUI + @Override + public ItemStack buildItem() { + final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); - String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); - List lore = new ArrayList<>(); + String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); + List lore = new ArrayList<>(); - Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase())); - if (material == null) { - return null; - } + Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase())); + if (material == null) { + return null; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { - lore.add(replacePlaceholders(loreLine)); - } + for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine)); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - public String replacePlaceholders(String string) { - string = ChatColor.translateAlternateColorCodes('&', string); + public String replacePlaceholders(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); - String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); + String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); - string = string.replace("{relation-color}", getColor().toString()); - string = string.replace("{relation}", permissableName); + string = string.replace("{relation-color}", getColor().toString()); + string = string.replace("{relation}", permissableName); - return string; - } + return string; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/Role.java b/src/main/java/com/massivecraft/factions/struct/Role.java index 92a94629..226e912e 100644 --- a/src/main/java/com/massivecraft/factions/struct/Role.java +++ b/src/main/java/com/massivecraft/factions/struct/Role.java @@ -15,140 +15,140 @@ import java.util.ArrayList; import java.util.List; public enum Role implements Permissable { - LEADER(4, TL.ROLE_LEADER), - COLEADER(3, TL.ROLE_COLEADER), - MODERATOR(2, TL.ROLE_MODERATOR), - NORMAL(1, TL.ROLE_NORMAL), - RECRUIT(0, TL.ROLE_RECRUIT); + LEADER(4, TL.ROLE_LEADER), + COLEADER(3, TL.ROLE_COLEADER), + MODERATOR(2, TL.ROLE_MODERATOR), + NORMAL(1, TL.ROLE_NORMAL), + RECRUIT(0, TL.ROLE_RECRUIT); - public final int value; - public final String nicename; - public final TL translation; + public final int value; + public final String nicename; + public final TL translation; - Role(final int value, final TL translation) { - this.value = value; - this.nicename = translation.toString(); - this.translation = translation; - } + Role(final int value, final TL translation) { + this.value = value; + this.nicename = translation.toString(); + this.translation = translation; + } - public static Role getRelative(Role role, int relative) { - return Role.getByValue(role.value + relative); - } + public static Role getRelative(Role role, int relative) { + return Role.getByValue(role.value + relative); + } - public static Role getByValue(int value) { - switch (value) { - case 0: - return RECRUIT; - case 1: - return NORMAL; - case 2: - return MODERATOR; - case 3: - return COLEADER; - case 4: - return LEADER; - } + public static Role getByValue(int value) { + switch (value) { + case 0: + return RECRUIT; + case 1: + return NORMAL; + case 2: + return MODERATOR; + case 3: + return COLEADER; + case 4: + return LEADER; + } - return null; - } + return null; + } - public static Role fromString(String check) { - switch (check.toLowerCase()) { - case "leader": - case "admin": - return LEADER; - case "coleader": - return COLEADER; - case "mod": - case "moderator": - return MODERATOR; - case "normal": - case "member": - return NORMAL; - case "recruit": - case "rec": - return RECRUIT; - } + public static Role fromString(String check) { + switch (check.toLowerCase()) { + case "leader": + case "admin": + return LEADER; + case "coleader": + return COLEADER; + case "mod": + case "moderator": + return MODERATOR; + case "normal": + case "member": + return NORMAL; + case "recruit": + case "rec": + return RECRUIT; + } - return null; - } + return null; + } - public boolean isAtLeast(Role role) { - return this.value >= role.value; - } + public boolean isAtLeast(Role role) { + return this.value >= role.value; + } - public boolean isAtMost(Role role) { - return this.value <= role.value; - } + public boolean isAtMost(Role role) { + return this.value <= role.value; + } - @Override - public String toString() { - return this.nicename; - } + @Override + public String toString() { + return this.nicename; + } - public TL getTranslation() { - return translation; - } + public TL getTranslation() { + return translation; + } - public String getPrefix() { + public String getPrefix() { - switch (this) { - case LEADER: - return Conf.prefixLeader; - case COLEADER: - return Conf.prefixCoLeader; - case MODERATOR: - return Conf.prefixMod; - case NORMAL: - return Conf.prefixNormal; - case RECRUIT: - return Conf.prefixRecruit; - } + switch (this) { + case LEADER: + return Conf.prefixLeader; + case COLEADER: + return Conf.prefixCoLeader; + case MODERATOR: + return Conf.prefixMod; + case NORMAL: + return Conf.prefixNormal; + case RECRUIT: + return Conf.prefixRecruit; + } - return ""; - } + return ""; + } - // Utility method to build items for F Perm GUI - @Override - public ItemStack buildItem() { - final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); + // Utility method to build items for F Perm GUI + @Override + public ItemStack buildItem() { + final ConfigurationSection RELATION_CONFIG = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); - String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); - List lore = new ArrayList<>(); + String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); + List lore = new ArrayList<>(); - Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase(), "STAINED_CLAY")); - if (material == null) { - return null; - } + Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase(), "STAINED_CLAY")); + if (material == null) { + return null; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { - lore.add(replacePlaceholders(loreLine)); - } + for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine)); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); - } + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); + } - item.setItemMeta(itemMeta); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - public String replacePlaceholders(String string) { - string = ChatColor.translateAlternateColorCodes('&', string); + public String replacePlaceholders(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); - String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); + String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); - string = string.replace("{relation-color}", ChatColor.GREEN.toString()); - string = string.replace("{relation}", permissableName); + string = string.replace("{relation-color}", ChatColor.GREEN.toString()); + string = string.replace("{relation}", permissableName); - return string; - } + return string; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/AsciiCompass.java b/src/main/java/com/massivecraft/factions/util/AsciiCompass.java index a4149c94..f2096851 100644 --- a/src/main/java/com/massivecraft/factions/util/AsciiCompass.java +++ b/src/main/java/com/massivecraft/factions/util/AsciiCompass.java @@ -7,104 +7,104 @@ import java.util.ArrayList; public class AsciiCompass { - public static Point getCompassPointForDirection(double inDegrees) { - double degrees = (inDegrees - 180) % 360; - if (degrees < 0) { - degrees += 360; - } + public static Point getCompassPointForDirection(double inDegrees) { + double degrees = (inDegrees - 180) % 360; + if (degrees < 0) { + degrees += 360; + } - if (0 <= degrees && degrees < 22.5) { - return Point.N; - } else if (22.5 <= degrees && degrees < 67.5) { - return Point.NE; - } else if (67.5 <= degrees && degrees < 112.5) { - return Point.E; - } else if (112.5 <= degrees && degrees < 157.5) { - return Point.SE; - } else if (157.5 <= degrees && degrees < 202.5) { - return Point.S; - } else if (202.5 <= degrees && degrees < 247.5) { - return Point.SW; - } else if (247.5 <= degrees && degrees < 292.5) { - return Point.W; - } else if (292.5 <= degrees && degrees < 337.5) { - return Point.NW; - } else if (337.5 <= degrees && degrees < 360.0) { - return Point.N; - } else { - return null; - } - } + if (0 <= degrees && degrees < 22.5) { + return Point.N; + } else if (22.5 <= degrees && degrees < 67.5) { + return Point.NE; + } else if (67.5 <= degrees && degrees < 112.5) { + return Point.E; + } else if (112.5 <= degrees && degrees < 157.5) { + return Point.SE; + } else if (157.5 <= degrees && degrees < 202.5) { + return Point.S; + } else if (202.5 <= degrees && degrees < 247.5) { + return Point.SW; + } else if (247.5 <= degrees && degrees < 292.5) { + return Point.W; + } else if (292.5 <= degrees && degrees < 337.5) { + return Point.NW; + } else if (337.5 <= degrees && degrees < 360.0) { + return Point.N; + } else { + return null; + } + } - public static ArrayList getAsciiCompass(Point point, ChatColor colorActive, String colorDefault) { - ArrayList ret = new ArrayList<>(); - String row; + public static ArrayList getAsciiCompass(Point point, ChatColor colorActive, String colorDefault) { + ArrayList ret = new ArrayList<>(); + String row; - row = ""; - row += Point.NW.toString(Point.NW == point, colorActive, colorDefault); - row += Point.N.toString(Point.N == point, colorActive, colorDefault); - row += Point.NE.toString(Point.NE == point, colorActive, colorDefault); - ret.add(row); + row = ""; + row += Point.NW.toString(Point.NW == point, colorActive, colorDefault); + row += Point.N.toString(Point.N == point, colorActive, colorDefault); + row += Point.NE.toString(Point.NE == point, colorActive, colorDefault); + ret.add(row); - row = ""; - row += Point.W.toString(Point.W == point, colorActive, colorDefault); - row += colorDefault + "+"; - row += Point.E.toString(Point.E == point, colorActive, colorDefault); - ret.add(row); + row = ""; + row += Point.W.toString(Point.W == point, colorActive, colorDefault); + row += colorDefault + "+"; + row += Point.E.toString(Point.E == point, colorActive, colorDefault); + ret.add(row); - row = ""; - row += Point.SW.toString(Point.SW == point, colorActive, colorDefault); - row += Point.S.toString(Point.S == point, colorActive, colorDefault); - row += Point.SE.toString(Point.SE == point, colorActive, colorDefault); - ret.add(row); + row = ""; + row += Point.SW.toString(Point.SW == point, colorActive, colorDefault); + row += Point.S.toString(Point.S == point, colorActive, colorDefault); + row += Point.SE.toString(Point.SE == point, colorActive, colorDefault); + ret.add(row); - return ret; - } + return ret; + } - public static ArrayList getAsciiCompass(double inDegrees, ChatColor colorActive, String colorDefault) { - return getAsciiCompass(getCompassPointForDirection(inDegrees), colorActive, colorDefault); - } + public static ArrayList getAsciiCompass(double inDegrees, ChatColor colorActive, String colorDefault) { + return getAsciiCompass(getCompassPointForDirection(inDegrees), colorActive, colorDefault); + } - public enum Point { + public enum Point { - N('N'), - NE('/'), - E('E'), - SE('\\'), - S('S'), - SW('/'), - W('W'), - NW('\\'); + N('N'), + NE('/'), + E('E'), + SE('\\'), + S('S'), + SW('/'), + W('W'), + NW('\\'); - public final char asciiChar; + public final char asciiChar; - Point(final char asciiChar) { - this.asciiChar = asciiChar; - } + Point(final char asciiChar) { + this.asciiChar = asciiChar; + } - @Override - public String toString() { - return String.valueOf(this.asciiChar); - } + @Override + public String toString() { + return String.valueOf(this.asciiChar); + } - public String getTranslation() { - if (this == N) { - return TL.COMPASS_SHORT_NORTH.toString(); - } - if (this == E) { - return TL.COMPASS_SHORT_EAST.toString(); - } - if (this == S) { - return TL.COMPASS_SHORT_SOUTH.toString(); - } - if (this == W) { - return TL.COMPASS_SHORT_WEST.toString(); - } - return toString(); - } + public String getTranslation() { + if (this == N) { + return TL.COMPASS_SHORT_NORTH.toString(); + } + if (this == E) { + return TL.COMPASS_SHORT_EAST.toString(); + } + if (this == S) { + return TL.COMPASS_SHORT_SOUTH.toString(); + } + if (this == W) { + return TL.COMPASS_SHORT_WEST.toString(); + } + return toString(); + } - public String toString(boolean isActive, ChatColor colorActive, String colorDefault) { - return (isActive ? colorActive : colorDefault) + getTranslation(); - } - } + public String toString(boolean isActive, ChatColor colorActive, String colorDefault) { + return (isActive ? colorActive : colorDefault) + getTranslation(); + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java b/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java index 0cc7fd62..aae7392a 100644 --- a/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java +++ b/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java @@ -10,84 +10,84 @@ import java.util.logging.Level; public class AutoLeaveProcessTask extends BukkitRunnable { - private transient boolean readyToGo = false; - private transient boolean finished = false; - private transient ListIterator iterator; - private transient double toleranceMillis; + private transient boolean readyToGo = false; + private transient boolean finished = false; + private transient ListIterator iterator; + private transient double toleranceMillis; - public AutoLeaveProcessTask() { - ArrayList fplayers = (ArrayList) FPlayers.getInstance().getAllFPlayers(); - this.iterator = fplayers.listIterator(); - this.toleranceMillis = Conf.autoLeaveAfterDaysOfInactivity * 24 * 60 * 60 * 1000; - this.readyToGo = true; - this.finished = false; - } + public AutoLeaveProcessTask() { + ArrayList fplayers = (ArrayList) FPlayers.getInstance().getAllFPlayers(); + this.iterator = fplayers.listIterator(); + this.toleranceMillis = Conf.autoLeaveAfterDaysOfInactivity * 24 * 60 * 60 * 1000; + this.readyToGo = true; + this.finished = false; + } - public void run() { - if (Conf.autoLeaveAfterDaysOfInactivity <= 0.0 || Conf.autoLeaveRoutineMaxMillisecondsPerTick <= 0.0) { - this.stop(); - return; - } + public void run() { + if (Conf.autoLeaveAfterDaysOfInactivity <= 0.0 || Conf.autoLeaveRoutineMaxMillisecondsPerTick <= 0.0) { + this.stop(); + return; + } - if (!readyToGo) { - return; - } - // this is set so it only does one iteration at a time, no matter how frequently the timer fires - readyToGo = false; - // and this is tracked to keep one iteration from dragging on too long and possibly choking the system if there are a very large number of players to go through - long loopStartTime = System.currentTimeMillis(); + if (!readyToGo) { + return; + } + // this is set so it only does one iteration at a time, no matter how frequently the timer fires + readyToGo = false; + // and this is tracked to keep one iteration from dragging on too long and possibly choking the system if there are a very large number of players to go through + long loopStartTime = System.currentTimeMillis(); - while (iterator.hasNext()) { - long now = System.currentTimeMillis(); + while (iterator.hasNext()) { + long now = System.currentTimeMillis(); - // if this iteration has been running for maximum time, stop to take a breather until next tick - if (now > loopStartTime + Conf.autoLeaveRoutineMaxMillisecondsPerTick) { - readyToGo = true; - return; - } + // if this iteration has been running for maximum time, stop to take a breather until next tick + if (now > loopStartTime + Conf.autoLeaveRoutineMaxMillisecondsPerTick) { + readyToGo = true; + return; + } - FPlayer fplayer = iterator.next(); + FPlayer fplayer = iterator.next(); - // Check if they should be exempt from this. - if (!fplayer.willAutoLeave()) { - SavageFactions.plugin.debug(Level.INFO, fplayer.getName() + " was going to be auto-removed but was set not to."); - continue; - } + // Check if they should be exempt from this. + if (!fplayer.willAutoLeave()) { + SavageFactions.plugin.debug(Level.INFO, fplayer.getName() + " was going to be auto-removed but was set not to."); + continue; + } - if (fplayer.isOffline() && now - fplayer.getLastLoginTime() > toleranceMillis) { - if (Conf.logFactionLeave || Conf.logFactionKick) { - SavageFactions.plugin.log("Player " + fplayer.getName() + " was auto-removed due to inactivity."); - } + if (fplayer.isOffline() && now - fplayer.getLastLoginTime() > toleranceMillis) { + if (Conf.logFactionLeave || Conf.logFactionKick) { + SavageFactions.plugin.log("Player " + fplayer.getName() + " was auto-removed due to inactivity."); + } - // if player is faction admin, sort out the faction since he's going away - if (fplayer.getRole() == Role.LEADER) { - Faction faction = fplayer.getFaction(); - if (faction != null) { - fplayer.getFaction().promoteNewLeader(true); - } - } + // if player is faction admin, sort out the faction since he's going away + if (fplayer.getRole() == Role.LEADER) { + Faction faction = fplayer.getFaction(); + if (faction != null) { + fplayer.getFaction().promoteNewLeader(true); + } + } - fplayer.leave(false); - iterator.remove(); // go ahead and remove this list's link to the FPlayer object - if (Conf.autoLeaveDeleteFPlayerData) { - fplayer.remove(); - } - } - } + fplayer.leave(false); + iterator.remove(); // go ahead and remove this list's link to the FPlayer object + if (Conf.autoLeaveDeleteFPlayerData) { + fplayer.remove(); + } + } + } - // looks like we've finished - this.stop(); - } + // looks like we've finished + this.stop(); + } - // we're done, shut down - public void stop() { - readyToGo = false; - finished = true; + // we're done, shut down + public void stop() { + readyToGo = false; + finished = true; - this.cancel(); - } + this.cancel(); + } - public boolean isFinished() { - return finished; - } + public boolean isFinished() { + return finished; + } } diff --git a/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java b/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java index a13ca1d3..4ffd75b6 100644 --- a/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java +++ b/src/main/java/com/massivecraft/factions/util/AutoLeaveTask.java @@ -5,24 +5,24 @@ import com.massivecraft.factions.SavageFactions; public class AutoLeaveTask implements Runnable { - private static AutoLeaveProcessTask task; - double rate; + private static AutoLeaveProcessTask task; + double rate; - public AutoLeaveTask() { - this.rate = Conf.autoLeaveRoutineRunsEveryXMinutes; - } + public AutoLeaveTask() { + this.rate = Conf.autoLeaveRoutineRunsEveryXMinutes; + } - public synchronized void run() { - if (task != null && !task.isFinished()) { - return; - } + public synchronized void run() { + if (task != null && !task.isFinished()) { + return; + } - task = new AutoLeaveProcessTask(); - task.runTaskTimer(SavageFactions.plugin, 1, 1); + task = new AutoLeaveProcessTask(); + task.runTaskTimer(SavageFactions.plugin, 1, 1); - // maybe setting has been changed? if so, restart this task at new rate - if (this.rate != Conf.autoLeaveRoutineRunsEveryXMinutes) { - SavageFactions.plugin.startAutoLeaveTask(true); - } - } + // maybe setting has been changed? if so, restart this task at new rate + if (this.rate != Conf.autoLeaveRoutineRunsEveryXMinutes) { + SavageFactions.plugin.startAutoLeaveTask(true); + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java b/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java index f83b7328..ce552584 100644 --- a/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java +++ b/src/main/java/com/massivecraft/factions/util/ClipPlaceholderAPIManager.java @@ -15,151 +15,151 @@ import java.util.UUID; public class ClipPlaceholderAPIManager extends PlaceholderExpansion implements Relational { - // Identifier for this expansion - @Override - public String getIdentifier() { - return "factionsuuid"; - } + // Identifier for this expansion + @Override + public String getIdentifier() { + return "factionsuuid"; + } - @Override - public String getAuthor() { - return "drtshock"; - } + @Override + public String getAuthor() { + return "drtshock"; + } - // Since we are registering this expansion from the dependency, this can be null - @Override - public String getPlugin() { - return null; - } + // Since we are registering this expansion from the dependency, this can be null + @Override + public String getPlugin() { + return null; + } - // Return the plugin version since this expansion is bundled with the dependency - @Override - public String getVersion() { - return SavageFactions.plugin.getDescription().getVersion(); - } + // Return the plugin version since this expansion is bundled with the dependency + @Override + public String getVersion() { + return SavageFactions.plugin.getDescription().getVersion(); + } - // Relational placeholders - @Override - public String onPlaceholderRequest(Player p1, Player p2, String placeholder) { - if (p1 == null || p2 == null || placeholder == null) { - return ""; - } + // Relational placeholders + @Override + public String onPlaceholderRequest(Player p1, Player p2, String placeholder) { + if (p1 == null || p2 == null || placeholder == null) { + return ""; + } - FPlayer fp1 = FPlayers.getInstance().getByPlayer(p1); - FPlayer fp2 = FPlayers.getInstance().getByPlayer(p2); - if (fp1 == null || fp2 == null) { - return ""; - } + FPlayer fp1 = FPlayers.getInstance().getByPlayer(p1); + FPlayer fp2 = FPlayers.getInstance().getByPlayer(p2); + if (fp1 == null || fp2 == null) { + return ""; + } - switch (placeholder) { - case "relation": - String relationName = fp1.getRelationTo(fp2).nicename; - return relationName != null ? relationName : ""; - case "relation_color": - ChatColor color = fp1.getColorTo(fp2); - return color != null ? color.toString() : ""; - } + switch (placeholder) { + case "relation": + String relationName = fp1.getRelationTo(fp2).nicename; + return relationName != null ? relationName : ""; + case "relation_color": + ChatColor color = fp1.getColorTo(fp2); + return color != null ? color.toString() : ""; + } - return null; - } + return null; + } - @Override - public String onPlaceholderRequest(Player player, String placeholder) { - if (player == null || placeholder == null) { - return ""; - } + @Override + public String onPlaceholderRequest(Player player, String placeholder) { + if (player == null || placeholder == null) { + return ""; + } - FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - Faction faction = fPlayer.getFaction(); - switch (placeholder) { - // First list player stuff - case "player_name": - return fPlayer.getName(); - case "player_lastseen": - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fPlayer.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; - return fPlayer.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fPlayer.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - case "player_group": - return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fPlayer.getId()))); - case "player_balance": - return Econ.isSetup() ? Econ.getFriendlyBalance(fPlayer) : TL.ECON_OFF.format("balance"); - case "player_power": - return String.valueOf(fPlayer.getPowerRounded()); - case "player_maxpower": - return String.valueOf(fPlayer.getPowerMaxRounded()); - case "player_kills": - return String.valueOf(fPlayer.getKills()); - case "player_deaths": - return String.valueOf(fPlayer.getDeaths()); - case "player_role_prefix": - return String.valueOf(fPlayer.getRolePrefix()); - case "player_role": - return fPlayer.hasFaction() ? fPlayer.getRole().getPrefix() : ""; - // Then Faction stuff - case "faction_name": - return fPlayer.hasFaction() ? faction.getTag() : ""; - case "faction_power": - return String.valueOf(faction.getPowerRounded()); - case "faction_powermax": - return String.valueOf(faction.getPowerMaxRounded()); - case "faction_description": - return faction.getDescription(); - case "faction_claims": - return String.valueOf(faction.getAllClaims().size()); - case "faction_founded": - return TL.sdf.format(faction.getFoundedDate()); - case "faction_joining": - return (faction.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); - case "faction_peaceful": - return faction.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; - case "faction_powerboost": - double powerBoost = faction.getPowerBoost(); - return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); - case "faction_leader": - FPlayer fAdmin = faction.getFPlayerAdmin(); - return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); - case "faction_warps": - return String.valueOf(faction.getWarps().size()); - case "faction_raidable": - boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && faction.getLandRounded() >= faction.getPowerRounded(); - return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); - case "faction_home_world": - return faction.hasHome() ? faction.getHome().getWorld().getName() : ""; - case "faction_home_x": - return faction.hasHome() ? String.valueOf(faction.getHome().getBlockX()) : ""; - case "faction_home_y": - return faction.hasHome() ? String.valueOf(faction.getHome().getBlockY()) : ""; - case "faction_home_z": - return faction.hasHome() ? String.valueOf(faction.getHome().getBlockZ()) : ""; - case "facion_land_value": - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(faction.getLandRounded())) : TL.ECON_OFF.format("value"); - case "faction_land_refund": - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(faction.getLandRounded())) : TL.ECON_OFF.format("refund"); - case "faction_bank_balance": - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.getBalance(faction.getAccountId())) : TL.ECON_OFF.format("balance"); - case "faction_allies": - return String.valueOf(faction.getRelationCount(Relation.ALLY)); - case "faction_enemies": - return String.valueOf(faction.getRelationCount(Relation.ENEMY)); - case "faction_truces": - return String.valueOf(faction.getRelationCount(Relation.TRUCE)); - case "faction_online": - return String.valueOf(faction.getOnlinePlayers().size()); - case "faction_offline": - return String.valueOf(faction.getFPlayers().size() - faction.getOnlinePlayers().size()); - case "faction_size": - return String.valueOf(faction.getFPlayers().size()); - case "faction_kills": - return String.valueOf(faction.getKills()); - case "faction_deaths": - return String.valueOf(faction.getDeaths()); - case "faction_maxvaults": - return String.valueOf(faction.getMaxVaults()); - case "faction_name_at_location": - Faction factionAtLocation = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); - return factionAtLocation != null ? factionAtLocation.getTag() : Factions.getInstance().getWilderness().getTag(); - } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + Faction faction = fPlayer.getFaction(); + switch (placeholder) { + // First list player stuff + case "player_name": + return fPlayer.getName(); + case "player_lastseen": + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fPlayer.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + return fPlayer.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fPlayer.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + case "player_group": + return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fPlayer.getId()))); + case "player_balance": + return Econ.isSetup() ? Econ.getFriendlyBalance(fPlayer) : TL.ECON_OFF.format("balance"); + case "player_power": + return String.valueOf(fPlayer.getPowerRounded()); + case "player_maxpower": + return String.valueOf(fPlayer.getPowerMaxRounded()); + case "player_kills": + return String.valueOf(fPlayer.getKills()); + case "player_deaths": + return String.valueOf(fPlayer.getDeaths()); + case "player_role_prefix": + return String.valueOf(fPlayer.getRolePrefix()); + case "player_role": + return fPlayer.hasFaction() ? fPlayer.getRole().getPrefix() : ""; + // Then Faction stuff + case "faction_name": + return fPlayer.hasFaction() ? faction.getTag() : ""; + case "faction_power": + return String.valueOf(faction.getPowerRounded()); + case "faction_powermax": + return String.valueOf(faction.getPowerMaxRounded()); + case "faction_description": + return faction.getDescription(); + case "faction_claims": + return String.valueOf(faction.getAllClaims().size()); + case "faction_founded": + return TL.sdf.format(faction.getFoundedDate()); + case "faction_joining": + return (faction.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); + case "faction_peaceful": + return faction.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; + case "faction_powerboost": + double powerBoost = faction.getPowerBoost(); + return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); + case "faction_leader": + FPlayer fAdmin = faction.getFPlayerAdmin(); + return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); + case "faction_warps": + return String.valueOf(faction.getWarps().size()); + case "faction_raidable": + boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && faction.getLandRounded() >= faction.getPowerRounded(); + return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); + case "faction_home_world": + return faction.hasHome() ? faction.getHome().getWorld().getName() : ""; + case "faction_home_x": + return faction.hasHome() ? String.valueOf(faction.getHome().getBlockX()) : ""; + case "faction_home_y": + return faction.hasHome() ? String.valueOf(faction.getHome().getBlockY()) : ""; + case "faction_home_z": + return faction.hasHome() ? String.valueOf(faction.getHome().getBlockZ()) : ""; + case "facion_land_value": + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(faction.getLandRounded())) : TL.ECON_OFF.format("value"); + case "faction_land_refund": + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(faction.getLandRounded())) : TL.ECON_OFF.format("refund"); + case "faction_bank_balance": + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.getBalance(faction.getAccountId())) : TL.ECON_OFF.format("balance"); + case "faction_allies": + return String.valueOf(faction.getRelationCount(Relation.ALLY)); + case "faction_enemies": + return String.valueOf(faction.getRelationCount(Relation.ENEMY)); + case "faction_truces": + return String.valueOf(faction.getRelationCount(Relation.TRUCE)); + case "faction_online": + return String.valueOf(faction.getOnlinePlayers().size()); + case "faction_offline": + return String.valueOf(faction.getFPlayers().size() - faction.getOnlinePlayers().size()); + case "faction_size": + return String.valueOf(faction.getFPlayers().size()); + case "faction_kills": + return String.valueOf(faction.getKills()); + case "faction_deaths": + return String.valueOf(faction.getDeaths()); + case "faction_maxvaults": + return String.valueOf(faction.getMaxVaults()); + case "faction_name_at_location": + Faction factionAtLocation = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); + return factionAtLocation != null ? factionAtLocation.getTag() : Factions.getInstance().getWilderness().getTag(); + } - return null; - } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java index f5b2b975..2f0ed3e9 100644 --- a/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/EnumTypeAdapter.java @@ -15,52 +15,52 @@ import java.util.Map; public final class EnumTypeAdapter> extends TypeAdapter { - public static final TypeAdapterFactory ENUM_FACTORY = newEnumTypeHierarchyFactory(); - private final Map nameToConstant = new HashMap<>(); - private final Map constantToName = new HashMap<>(); + public static final TypeAdapterFactory ENUM_FACTORY = newEnumTypeHierarchyFactory(); + private final Map nameToConstant = new HashMap<>(); + private final Map constantToName = new HashMap<>(); - public EnumTypeAdapter(Class classOfT) { - try { - for (T constant : classOfT.getEnumConstants()) { - String name = constant.name(); - SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class); - if (annotation != null) { - name = annotation.value(); - } - nameToConstant.put(name, constant); - constantToName.put(constant, name); - } - } catch (NoSuchFieldException e) { - // ignore since it could be a modified enum - } - } + public EnumTypeAdapter(Class classOfT) { + try { + for (T constant : classOfT.getEnumConstants()) { + String name = constant.name(); + SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class); + if (annotation != null) { + name = annotation.value(); + } + nameToConstant.put(name, constant); + constantToName.put(constant, name); + } + } catch (NoSuchFieldException e) { + // ignore since it could be a modified enum + } + } - public static TypeAdapterFactory newEnumTypeHierarchyFactory() { - return new TypeAdapterFactory() { - @SuppressWarnings({"rawtypes", "unchecked"}) - public TypeAdapter create(Gson gson, TypeToken typeToken) { - Class rawType = typeToken.getRawType(); - if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) { - return null; - } - if (!rawType.isEnum()) { - rawType = rawType.getSuperclass(); // handle anonymous subclasses - } - return (TypeAdapter) new EnumTypeAdapter(rawType); - } - }; - } + public static TypeAdapterFactory newEnumTypeHierarchyFactory() { + return new TypeAdapterFactory() { + @SuppressWarnings({"rawtypes", "unchecked"}) + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Class rawType = typeToken.getRawType(); + if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) { + return null; + } + if (!rawType.isEnum()) { + rawType = rawType.getSuperclass(); // handle anonymous subclasses + } + return (TypeAdapter) new EnumTypeAdapter(rawType); + } + }; + } - public T read(JsonReader in) throws IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - return nameToConstant.get(in.nextString()); - } + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return nameToConstant.get(in.nextString()); + } - public void write(JsonWriter out, T value) throws IOException { - out.value(value == null ? null : constantToName.get(value)); - } + public void write(JsonWriter out, T value) throws IOException { + out.value(value == null ? null : constantToName.get(value)); + } } diff --git a/src/main/java/com/massivecraft/factions/util/FactionGUI.java b/src/main/java/com/massivecraft/factions/util/FactionGUI.java index d4b181bf..37d02903 100644 --- a/src/main/java/com/massivecraft/factions/util/FactionGUI.java +++ b/src/main/java/com/massivecraft/factions/util/FactionGUI.java @@ -4,8 +4,8 @@ import org.bukkit.event.inventory.ClickType; public interface FactionGUI { - void onClick(int slot, ClickType action); + void onClick(int slot, ClickType action); - void build(); + void build(); } diff --git a/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java index 0b941b1d..518d2b3c 100644 --- a/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/InventoryTypeAdapter.java @@ -8,20 +8,20 @@ import java.lang.reflect.Type; public class InventoryTypeAdapter implements JsonSerializer, JsonDeserializer { - @Override - public JsonElement serialize(Inventory inventory, Type type, JsonSerializationContext jsonSerializationContext) { + @Override + public JsonElement serialize(Inventory inventory, Type type, JsonSerializationContext jsonSerializationContext) { - JsonObject object = new JsonObject(); - object.add("contents", new JsonPrimitive(InventoryUtil.toBase64(inventory))); - return object; - } + JsonObject object = new JsonObject(); + object.add("contents", new JsonPrimitive(InventoryUtil.toBase64(inventory))); + return object; + } - @Override - public Inventory deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { - JsonObject object = jsonElement.getAsJsonObject(); - return InventoryUtil.fromBase64(object.get("contents").getAsString()); - } + @Override + public Inventory deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { + JsonObject object = jsonElement.getAsJsonObject(); + return InventoryUtil.fromBase64(object.get("contents").getAsString()); + } } diff --git a/src/main/java/com/massivecraft/factions/util/InventoryUtil.java b/src/main/java/com/massivecraft/factions/util/InventoryUtil.java index 98f31df6..a64ad690 100644 --- a/src/main/java/com/massivecraft/factions/util/InventoryUtil.java +++ b/src/main/java/com/massivecraft/factions/util/InventoryUtil.java @@ -14,78 +14,78 @@ import java.io.IOException; public class InventoryUtil { - public static String InventoryToString(ItemStack[] items) throws IllegalStateException { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); - dataOutput.writeInt(items.length); - for (ItemStack item : items) { - dataOutput.writeObject(item); - } - dataOutput.close(); - return Base64Coder.encodeLines(outputStream.toByteArray()); - } catch (Exception e) { - throw new IllegalStateException("Unable to save item stacks.", e); - } - } + public static String InventoryToString(ItemStack[] items) throws IllegalStateException { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + dataOutput.writeInt(items.length); + for (ItemStack item : items) { + dataOutput.writeObject(item); + } + dataOutput.close(); + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + throw new IllegalStateException("Unable to save item stacks.", e); + } + } - public static ItemStack[] StringToInventory(String data) throws IOException { - try { - ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); - BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); - ItemStack[] items = new ItemStack[dataInput.readInt()]; - for (int i = 0; i < items.length; i++) { - items[i] = (ItemStack) dataInput.readObject(); - } - dataInput.close(); - return items; - } catch (ClassNotFoundException e) { - throw new IOException("Unable to decode class type.", e); - } - } + public static ItemStack[] StringToInventory(String data) throws IOException { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + ItemStack[] items = new ItemStack[dataInput.readInt()]; + for (int i = 0; i < items.length; i++) { + items[i] = (ItemStack) dataInput.readObject(); + } + dataInput.close(); + return items; + } catch (ClassNotFoundException e) { + throw new IOException("Unable to decode class type.", e); + } + } - public static String toBase64(Inventory inventory) { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + public static String toBase64(Inventory inventory) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); - // Write the size of the inventory - dataOutput.writeInt(inventory.getSize()); + // Write the size of the inventory + dataOutput.writeInt(inventory.getSize()); - // Save every element in the list - for (int i = 0; i < inventory.getSize(); i++) { - dataOutput.writeObject(inventory.getItem(i)); - } + // Save every element in the list + for (int i = 0; i < inventory.getSize(); i++) { + dataOutput.writeObject(inventory.getItem(i)); + } - // Serialize that array - dataOutput.close(); - return Base64Coder.encodeLines(outputStream.toByteArray()); - } catch (Exception e) { - throw new IllegalStateException("Cannot into itemstacksz!", e); - } - } + // Serialize that array + dataOutput.close(); + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + throw new IllegalStateException("Cannot into itemstacksz!", e); + } + } - public static String toBase64(ItemStack[] is, int size) { - Inventory inventory = Bukkit.createInventory(null, size); - inventory.setContents(is); - return toBase64(inventory); - } + public static String toBase64(ItemStack[] is, int size) { + Inventory inventory = Bukkit.createInventory(null, size); + inventory.setContents(is); + return toBase64(inventory); + } - public static Inventory fromBase64(String data) { - try { - ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); - BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); - Inventory inventory = Bukkit.getServer().createInventory(null, dataInput.readInt()); + public static Inventory fromBase64(String data) { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + Inventory inventory = Bukkit.getServer().createInventory(null, dataInput.readInt()); - // Read the serialized inventory - for (int i = 0; i < inventory.getSize(); i++) { - inventory.setItem(i, (ItemStack) dataInput.readObject()); - } - dataInput.close(); - return inventory; - } catch (Exception e) { - } - return null; - } + // Read the serialized inventory + for (int i = 0; i < inventory.getSize(); i++) { + inventory.setItem(i, (ItemStack) dataInput.readObject()); + } + dataInput.close(); + return inventory; + } catch (Exception e) { + } + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/util/LazyLocation.java b/src/main/java/com/massivecraft/factions/util/LazyLocation.java index a141bbc7..1682d8d3 100644 --- a/src/main/java/com/massivecraft/factions/util/LazyLocation.java +++ b/src/main/java/com/massivecraft/factions/util/LazyLocation.java @@ -12,90 +12,90 @@ import java.io.Serializable; */ public class LazyLocation implements Serializable { - private static final long serialVersionUID = -6049901271320963314L; - private transient Location location = null; - private String worldName; - private double x; - private double y; - private double z; - private float pitch; - private float yaw; + private static final long serialVersionUID = -6049901271320963314L; + private transient Location location = null; + private String worldName; + private double x; + private double y; + private double z; + private float pitch; + private float yaw; - public LazyLocation(Location loc) { - setLocation(loc); - } + public LazyLocation(Location loc) { + setLocation(loc); + } - public LazyLocation(final String worldName, final double x, final double y, final double z) { - this(worldName, x, y, z, 0, 0); - } + public LazyLocation(final String worldName, final double x, final double y, final double z) { + this(worldName, x, y, z, 0, 0); + } - public LazyLocation(final String worldName, final double x, final double y, final double z, final float yaw, final float pitch) { - this.worldName = worldName; - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; - } + public LazyLocation(final String worldName, final double x, final double y, final double z, final float yaw, final float pitch) { + this.worldName = worldName; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } - // This returns the actual Location - public final Location getLocation() { - // make sure Location is initialized before returning it - initLocation(); - return location; - } + // This returns the actual Location + public final Location getLocation() { + // make sure Location is initialized before returning it + initLocation(); + return location; + } - // change the Location - public final void setLocation(Location loc) { - this.location = loc; - this.worldName = loc.getWorld().getName(); - this.x = loc.getX(); - this.y = loc.getY(); - this.z = loc.getZ(); - this.yaw = loc.getYaw(); - this.pitch = loc.getPitch(); - } + // change the Location + public final void setLocation(Location loc) { + this.location = loc; + this.worldName = loc.getWorld().getName(); + this.x = loc.getX(); + this.y = loc.getY(); + this.z = loc.getZ(); + this.yaw = loc.getYaw(); + this.pitch = loc.getPitch(); + } - // This initializes the Location - private void initLocation() { - // if location is already initialized, simply return - if (location != null) { - return; - } + // This initializes the Location + private void initLocation() { + // if location is already initialized, simply return + if (location != null) { + return; + } - // get World; hopefully it's initialized at this point - World world = Bukkit.getWorld(worldName); - if (world == null) { - return; - } + // get World; hopefully it's initialized at this point + World world = Bukkit.getWorld(worldName); + if (world == null) { + return; + } - // store the Location for future calls, and pass it on - location = new Location(world, x, y, z, yaw, pitch); - } + // store the Location for future calls, and pass it on + location = new Location(world, x, y, z, yaw, pitch); + } - public final String getWorldName() { - return worldName; - } + public final String getWorldName() { + return worldName; + } - public final double getX() { - return x; - } + public final double getX() { + return x; + } - public final double getY() { - return y; - } + public final double getY() { + return y; + } - public final double getZ() { - return z; - } + public final double getZ() { + return z; + } - public final double getPitch() { - return pitch; - } + public final double getPitch() { + return pitch; + } - public final double getYaw() { - return yaw; - } + public final double getYaw() { + return yaw; + } } diff --git a/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java index 6c5880a7..99905a00 100644 --- a/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/LocationTypeAdapter.java @@ -10,41 +10,41 @@ import java.util.logging.Level; public class LocationTypeAdapter implements JsonSerializer, JsonDeserializer { - @Override - public JsonElement serialize(Location location, Type type, JsonSerializationContext jsonSerializationContext) { - JsonObject object = new JsonObject(); - try { - object.add("x", new JsonPrimitive(location.getX())); - object.add("y", new JsonPrimitive(location.getY())); - object.add("z", new JsonPrimitive(location.getZ())); - object.add("world", new JsonPrimitive(location.getWorld().toString())); - return object; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Location."); - return object; - } - } + @Override + public JsonElement serialize(Location location, Type type, JsonSerializationContext jsonSerializationContext) { + JsonObject object = new JsonObject(); + try { + object.add("x", new JsonPrimitive(location.getX())); + object.add("y", new JsonPrimitive(location.getY())); + object.add("z", new JsonPrimitive(location.getZ())); + object.add("world", new JsonPrimitive(location.getWorld().toString())); + return object; + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Location."); + return object; + } + } - @Override - public Location deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { - JsonObject object = jsonElement.getAsJsonObject(); - try { + @Override + public Location deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { + JsonObject object = jsonElement.getAsJsonObject(); + try { - return new Location(Bukkit.getWorld(object.get("world").getAsString()), - object.get("x").getAsDouble(), - object.get("y").getAsDouble(), - object.get("z").getAsDouble()); - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while" + - " deserializing a Location."); - return null; - } + return new Location(Bukkit.getWorld(object.get("world").getAsString()), + object.get("x").getAsDouble(), + object.get("y").getAsDouble(), + object.get("z").getAsDouble()); + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while" + + " deserializing a Location."); + return null; + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java index e1d6b60b..a95843d3 100644 --- a/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java @@ -16,89 +16,89 @@ import java.util.logging.Level; public class MapFLocToStringSetTypeAdapter implements JsonDeserializer>>, JsonSerializer>> { - @Override - public Map> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - try { - JsonObject obj = json.getAsJsonObject(); - if (obj == null) { - return null; - } + @Override + public Map> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + JsonObject obj = json.getAsJsonObject(); + if (obj == null) { + return null; + } - Map> locationMap = new ConcurrentHashMap<>(); - Set nameSet; - Iterator iter; - String worldName; - String[] coords; - int x, z; + Map> locationMap = new ConcurrentHashMap<>(); + Set nameSet; + Iterator iter; + String worldName; + String[] coords; + int x, z; - for (Entry entry : obj.entrySet()) { - worldName = entry.getKey(); - for (Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { - coords = entry2.getKey().trim().split("[,\\s]+"); - x = Integer.parseInt(coords[0]); - z = Integer.parseInt(coords[1]); + for (Entry entry : obj.entrySet()) { + worldName = entry.getKey(); + for (Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { + coords = entry2.getKey().trim().split("[,\\s]+"); + x = Integer.parseInt(coords[0]); + z = Integer.parseInt(coords[1]); - nameSet = new HashSet<>(); - iter = entry2.getValue().getAsJsonArray().iterator(); - while (iter.hasNext()) { - nameSet.add(iter.next().getAsString()); - } + nameSet = new HashSet<>(); + iter = entry2.getValue().getAsJsonArray().iterator(); + while (iter.hasNext()) { + nameSet.add(iter.next().getAsString()); + } - locationMap.put(new FLocation(worldName, x, z), nameSet); - } - } + locationMap.put(new FLocation(worldName, x, z), nameSet); + } + } - return locationMap; + return locationMap; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a Map of FLocations to String Sets."); - return null; - } - } + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a Map of FLocations to String Sets."); + return null; + } + } - @Override - public JsonElement serialize(Map> src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject obj = new JsonObject(); + @Override + public JsonElement serialize(Map> src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); - try { - if (src != null) { - FLocation loc; - String locWorld; - Set nameSet; - Iterator iter; - JsonArray nameArray; - JsonPrimitive nameElement; + try { + if (src != null) { + FLocation loc; + String locWorld; + Set nameSet; + Iterator iter; + JsonArray nameArray; + JsonPrimitive nameElement; - for (Entry> entry : src.entrySet()) { - loc = entry.getKey(); - locWorld = loc.getWorldName(); - nameSet = entry.getValue(); + for (Entry> entry : src.entrySet()) { + loc = entry.getKey(); + locWorld = loc.getWorldName(); + nameSet = entry.getValue(); - if (nameSet == null || nameSet.isEmpty()) { - continue; - } + if (nameSet == null || nameSet.isEmpty()) { + continue; + } - nameArray = new JsonArray(); - iter = nameSet.iterator(); - while (iter.hasNext()) { - nameElement = new JsonPrimitive(iter.next()); - nameArray.add(nameElement); - } + nameArray = new JsonArray(); + iter = nameSet.iterator(); + while (iter.hasNext()) { + nameElement = new JsonPrimitive(iter.next()); + nameArray.add(nameElement); + } - if (!obj.has(locWorld)) { - obj.add(locWorld, new JsonObject()); - } + if (!obj.has(locWorld)) { + obj.add(locWorld, new JsonObject()); + } - obj.get(locWorld).getAsJsonObject().add(loc.getCoordString(), nameArray); - } - } - return obj; + obj.get(locWorld).getAsJsonObject().add(loc.getCoordString(), nameArray); + } + } + return obj; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Map of FLocations to String Sets."); - return obj; - } - } + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a Map of FLocations to String Sets."); + return obj; + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/MiscUtil.java b/src/main/java/com/massivecraft/factions/util/MiscUtil.java index 07ff1b49..76536007 100644 --- a/src/main/java/com/massivecraft/factions/util/MiscUtil.java +++ b/src/main/java/com/massivecraft/factions/util/MiscUtil.java @@ -18,113 +18,113 @@ import java.util.logging.Level; public class MiscUtil { - /// TODO create tag whitelist!! - public static HashSet substanceChars = - new HashSet<>(Arrays.asList("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""))); + /// TODO create tag whitelist!! + public static HashSet substanceChars = + new HashSet<>(Arrays.asList("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""))); - public static EntityType creatureTypeFromEntity(Entity entity) { - if (!(entity instanceof Creature)) { - return null; - } + public static EntityType creatureTypeFromEntity(Entity entity) { + if (!(entity instanceof Creature)) { + return null; + } - String name = entity.getClass().getSimpleName(); - name = name.substring(5); // Remove "Craft" + String name = entity.getClass().getSimpleName(); + name = name.substring(5); // Remove "Craft" - return EntityType.fromName(name); - } + return EntityType.fromName(name); + } - // Inclusive range - public static long[] range(long start, long end) { - long[] values = new long[(int) Math.abs(end - start) + 1]; + // Inclusive range + public static long[] range(long start, long end) { + long[] values = new long[(int) Math.abs(end - start) + 1]; - if (end < start) { - long oldstart = start; - start = end; - end = oldstart; - } + if (end < start) { + long oldstart = start; + start = end; + end = oldstart; + } - for (long i = start; i <= end; i++) { - values[(int) (i - start)] = i; - } + for (long i = start; i <= end; i++) { + values[(int) (i - start)] = i; + } - return values; - } + return values; + } - public static String getComparisonString(String str) { - StringBuilder ret = new StringBuilder(); + public static String getComparisonString(String str) { + StringBuilder ret = new StringBuilder(); - str = ChatColor.stripColor(str); - str = str.toLowerCase(); + str = ChatColor.stripColor(str); + str = str.toLowerCase(); - for (char c : str.toCharArray()) { - if (substanceChars.contains(String.valueOf(c))) { - ret.append(c); - } - } - return ret.toString().toLowerCase(); - } + for (char c : str.toCharArray()) { + if (substanceChars.contains(String.valueOf(c))) { + ret.append(c); + } + } + return ret.toString().toLowerCase(); + } - public static ArrayList validateTag(String str) { - ArrayList errors = new ArrayList<>(); + public static ArrayList validateTag(String str) { + ArrayList errors = new ArrayList<>(); - if (getComparisonString(str).length() < Conf.factionTagLengthMin) { - errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOSHORT.toString(), Conf.factionTagLengthMin)); - } + if (getComparisonString(str).length() < Conf.factionTagLengthMin) { + errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOSHORT.toString(), Conf.factionTagLengthMin)); + } - if (str.length() > Conf.factionTagLengthMax) { - errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOLONG.toString(), Conf.factionTagLengthMax)); - } + if (str.length() > Conf.factionTagLengthMax) { + errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_TOOLONG.toString(), Conf.factionTagLengthMax)); + } - for (char c : str.toCharArray()) { - if (!substanceChars.contains(String.valueOf(c))) { - errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_ALPHANUMERIC.toString(), c)); - } - } + for (char c : str.toCharArray()) { + if (!substanceChars.contains(String.valueOf(c))) { + errors.add(SavageFactions.plugin.txt.parse(TL.GENERIC_FACTIONTAG_ALPHANUMERIC.toString(), c)); + } + } - return errors; - } + return errors; + } - public static Iterable rankOrder(Iterable players) { - List admins = new ArrayList<>(); - List coleaders = new ArrayList<>(); - List moderators = new ArrayList<>(); - List normal = new ArrayList<>(); - List recruit = new ArrayList<>(); + public static Iterable rankOrder(Iterable players) { + List admins = new ArrayList<>(); + List coleaders = new ArrayList<>(); + List moderators = new ArrayList<>(); + List normal = new ArrayList<>(); + List recruit = new ArrayList<>(); - for (FPlayer player : players) { + for (FPlayer player : players) { - // Fix for some data being broken when we added the recruit rank. - if (player.getRole() == null) { - player.setRole(Role.NORMAL); - SavageFactions.plugin.log(Level.WARNING, String.format("Player %s had null role. Setting them to normal. This isn't good D:", player.getName())); - } + // Fix for some data being broken when we added the recruit rank. + if (player.getRole() == null) { + player.setRole(Role.NORMAL); + SavageFactions.plugin.log(Level.WARNING, String.format("Player %s had null role. Setting them to normal. This isn't good D:", player.getName())); + } - switch (player.getRole()) { - case LEADER: - admins.add(player); - break; - case COLEADER: - admins.add(player); - break; - case MODERATOR: - moderators.add(player); - break; - case NORMAL: - normal.add(player); - break; - case RECRUIT: - recruit.add(player); - break; - } - } + switch (player.getRole()) { + case LEADER: + admins.add(player); + break; + case COLEADER: + admins.add(player); + break; + case MODERATOR: + moderators.add(player); + break; + case NORMAL: + normal.add(player); + break; + case RECRUIT: + recruit.add(player); + break; + } + } - List ret = new ArrayList<>(); - ret.addAll(admins); - ret.addAll(coleaders); - ret.addAll(moderators); - ret.addAll(normal); - ret.addAll(recruit); - return ret; - } + List ret = new ArrayList<>(); + ret.addAll(admins); + ret.addAll(coleaders); + ret.addAll(moderators); + ret.addAll(normal); + ret.addAll(recruit); + return ret; + } } diff --git a/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java b/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java index df243e72..6ded7b7d 100644 --- a/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java +++ b/src/main/java/com/massivecraft/factions/util/MultiversionMaterials.java @@ -7,968 +7,968 @@ import java.util.HashMap; public enum MultiversionMaterials { - ACACIA_BOAT("BOAT_ACACIA", 0), - ACACIA_BUTTON("WOOD_BUTTON", 0), - ACACIA_DOOR("ACACIA_DOOR", 0), - ACACIA_FENCE("ACACIA_FENCE", 0), - ACACIA_FENCE_GATE("ACACIA_FENCE_GATE", 0), - ACACIA_LEAVES("LEAVES_2", 0), - ACACIA_LOG("LOG_2", 0), - ACACIA_PLANKS("WOOD", 4), - ACACIA_PRESSURE_PLATE("WOOD_PLATE", 0), - ACACIA_SAPLING("SAPLING", 4), - ACACIA_SLAB("WOOD_STEP", 4), - ACACIA_STAIRS("ACACIA_STAIRS", 4), - ACACIA_TRAPDOOR("TRAP_DOOR", 0), - ACACIA_WOOD("LOG_2", 0), - ACTIVATOR_RAIL("ACTIVATOR_RAIL", 0), - AIR("AIR", 0), - ALLIUM("STONE", 0), - ANDESITE("STONE", 5), - ANVIL("ANVIL", 0), - APPLE("APPLE", 0), - ARMOR_STAND("ARMOR_STAND", 0), - ARROW("ARROW", 0), - ATTACHED_MELON_STEM("MELON_STEM", 7), - ATTACHED_PUMPKIN_STEM("PUMPKIN_STEM", 7), - AZURE_BLUET("RED_ROSE", 3), - BAKED_POTATO("BAKED_POTATO", 0), - BARRIER("BARRIER", 0), - BAT_SPAWN_EGG("MONSTER_EGG", 0), - BEACON("BEACON", 0), - BEDROCK("BEDROCK", 0), - BEEF("RAW_BEEF", 0), - BEETROOT("BEETROOT", 0), - BEETROOTS("BEETROOT", 0), - BEETROOT_SEEDS("BEETROOT_SEEDS", 0), - BEETROOT_SOUP("BEETROOT_SOUP", 0), - BIRCH_BOAT("BOAT_BIRCH", 0), - BIRCH_BUTTON("WOOD_BUTTON", 0), - BIRCH_DOOR("BIRCH_DOOR", 0), - BIRCH_FENCE("BIRCH_FENCE", 0), - BIRCH_FENCE_GATE("BIRCH_FENCE_GATE", 0), - BIRCH_LEAVES("LEAVES", 2), - BIRCH_LOG("LOG", 2), - BIRCH_PLANKS("WOOD", 2), - BIRCH_PRESSURE_PLATE("WOOD_PLATE", 0), - BIRCH_SAPLING("SAPLING", 2), - BIRCH_SLAB("WOOD_STEP", 2), - BIRCH_STAIRS("BIRCH_WOOD_STAIRS", 0), - BIRCH_TRAPDOOR("TRAP_DOOR", 0), - BIRCH_WOOD("LOG", 2), - BLACK_BANNER("BANNER", 0), - BLACK_BED("BED", 15), - BLACK_CARPET("CARPET", 15), - BLACK_CONCRETE("CONCRETE", 15), - BLACK_CONCRETE_POWDER("CONCRETE_POWDER", 15), - BLACK_GLAZED_TERRACOTTA("BLACK_GLAZED_TERRACOTTA", 0), - BLACK_SHULKER_BOX("BLACK_SHULKER_BOX", 0), - BLACK_STAINED_GLASS("STAINED_GLASS", 15), - BLACK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 15), - BLACK_TERRACOTTA("STAINED_CLAY", 15), - BLACK_WALL_BANNER("WALL_BANNER", 0), - BLACK_WOOL("WOOL", 15), - BLAZE_POWDER("BLAZE_POWDER", 0), - BLAZE_ROD("BLAZE_ROD", 0), - BLAZE_SPAWN_EGG("MONSTER_EGG", 0), - BLUE_BANNER("BANNER", 11), - BLUE_BED("BED", 4), - BLUE_CARPET("CARPET", 11), - BLUE_CONCRETE("CONCRETE", 11), - BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 11), - BLUE_GLAZED_TERRACOTTA("BLUE_GLAZED_TERRACOTTA", 0), - BLUE_ICE("PACKED_ICE", 0), - BLUE_ORCHID("RED_ROSE", 1), - BLUE_SHULKER_BOX("BLUE_SHULKER_BOX", 0), - BLUE_STAINED_GLASS("STAINED_GLASS", 11), - BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 11), - BLUE_TERRACOTTA("STAINED_CLAY", 11), - BLUE_WALL_BANNER("WALL_BANNER", 11), - BLUE_WOOL("WOOL", 11), - BONE("BONE", 0), - BONE_BLOCK("BONE_BLOCK", 0), - BONE_MEAL("INK_SACK", 15), - BOOK("BOOK", 0), - BOOKSHELF("BOOKSHELF", 0), - BOW("BOW", 0), - BOWL("BOWL", 0), - BRAIN_CORAL("STONE", 0), - BRAIN_CORAL_BLOCK("STONE", 0), - BRAIN_CORAL_FAN("STONE", 0), - BREAD("BREAD", 0), - BREWING_STAND("BREWING_STAND", 0), - BRICK("CLAY_BRICK", 0), - BRICKS("BRICK", 0), - BRICK_SLAB("STEP", 4), - BRICK_STAIRS("BRICK_STAIRS", 0), - BROWN_BANNER("BANNER", 3), - BROWN_BED("BED", 12), - BROWN_CARPET("CARPET", 12), - BROWN_CONCRETE("CONCRETE", 12), - BROWN_CONCRETE_POWDER("CONCRETE_POWDER", 12), - BROWN_GLAZED_TERRACOTTA("BROWN_GLAZED_TERRACOTTA", 0), - BROWN_MUSHROOM("BROWN_MUSHROOM", 0), - BROWN_MUSHROOM_BLOCK("BROWN_MUSHROOM", 0), //UNSURE - BROWN_SHULKER_BOX("BROWN_SHULKER_BOX", 0), - BROWN_STAINED_GLASS("STAINED_GLASS", 12), - BROWN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 12), - BROWN_TERRACOTTA("STAINED_CLAY", 12), - BROWN_WALL_BANNER("WALL_BANNER", 3), - BROWN_WOOL("WOOL", 12), - BUBBLE_COLUMN("STONE", 0), - BUBBLE_CORAL("STONE", 0), - BUBBLE_CORAL_BLOCK("STONE", 0), - BUBBLE_CORAL_FAN("STONE", 0), - BUCKET("BUCKET", 0), - CACTUS("CACTUS", 0), - CACTUS_GREEN("INK_SACK", 2), - CAKE("CAKE", 0), - CARROT("CARROT_ITEM", 0), - CARROTS("CARROT", 0), - CARROT_ON_A_STICK("CARROT_STICK", 0), - CARVED_PUMPKIN("PUMPKIN", 0), - CAULDRON("CAULDRON", 0), - CAVE_AIR("AIR", 0), - CAVE_SPIDER_SPAWN_EGG("MONSTER_EGG", 0), - CHAINMAIL_BOOTS("CHAINMAIL_BOOTS", 0), - CHAINMAIL_CHESTPLATE("CHAINMAIL_CHESTPLATE", 0), - CHAINMAIL_HELMET("CHAINMAIL_HELMET", 0), - CHAINMAIL_LEGGINGS("CHAINMAIL_LEGGINGS", 0), - CHAIN_COMMAND_BLOCK("COMMAND_CHAIN", 0), - CHARCOAL("COAL", 1), - CHEST("CHEST", 0), - CHEST_MINECART("STORAGE_MINECART", 0), - CHICKEN("RAW_CHICKEN", 0), - CHICKEN_SPAWN_EGG("MONSTER_EGG", 0), - CHIPPED_ANVIL("ANVIL", 1), - CHISELED_QUARTZ_BLOCK("QUARTZ_BLOCK", 1), - CHISELED_RED_SANDSTONE("RED_SANDSTONE", 1), - CHISELED_SANDSTONE("SANDSTONE", 1), - CHISELED_STONE_BRICKS("SMOOTH_BRICK", 3), - CHORUS_FLOWER("CHORUS_FLOWER", 0), - CHORUS_FRUIT("CHORUS_FRUIT", 0), - CHORUS_PLANT("CHORUS_PLANT", 0), - CLAY("CLAY", 0), - CLAY_BALL("CLAY_BALL", 0), - CLOCK("WATCH", 0), - COAL("COAL", 0), - COAL_BLOCK("COAL_BLOCK", 0), - COAL_ORE("COAL_ORE", 0), - COARSE_DIRT("DIRT", 1), - COBBLESTONE("COBBLESTONE", 0), - COBBLESTONE_SLAB("STEP", 3), - COBBLESTONE_STAIRS("COBBLESTONE_STAIRS", 0), - COBBLESTONE_WALL("COBBLE_WALL", 0), - COBWEB("WEB", 0), - COCOA("COCOA", 0), - COCOA_BEANS("INK_SACK", 3), - COD("RAW_FISH", 0), - COD_BUCKET("BUCKET", 0), - COD_SPAWN_EGG("MONSTER_EGG", 0), - COMMAND_BLOCK("COMMAND", 0), - COMMAND_BLOCK_MINECART("COMMAND_MINECART", 0), - COMPARATOR("REDSTONE_COMPARATOR", 0), - COMPASS("COMPASS", 0), - CONDUIT("STONE", 0), - COOKED_BEEF("COOKED_BEEF", 0), - COOKED_CHICKEN("COOKED_CHICKEN", 0), - COOKED_COD("COOKED_FISH", 0), - COOKED_MUTTON("COOKED_MUTTON", 0), - COOKED_PORKCHOP("GRILLED_PORK", 0), - COOKED_RABBIT("COOKED_RABBIT", 0), - COOKED_SALMON("COOKED_FISH", 1), - COOKIE("COOKIE", 0), - COW_SPAWN_EGG("MONSTER_EGG", 0), - CRACKED_STONE_BRICKS("SMOOTH_BRICK", 2), - CRAFTING_TABLE("WORKBENCH", 0), - CREEPER_HEAD("SKULL", 0), - CREEPER_SPAWN_EGG("MONSTER_EGG", 0), - CREEPER_WALL_HEAD("SKULL", 0), - CUT_RED_SANDSTONE("STONE", 0), - CUT_SANDSTONE("STONE", 0), - CYAN_BANNER("BANNER", 6), - CYAN_BED("BED", 9), - CYAN_CARPET("CARPET", 9), - CYAN_CONCRETE("CONCRETE", 9), - CYAN_CONCRETE_POWDER("CONCRETE_POWDER", 9), - CYAN_DYE("INK_SACK", 6), - CYAN_GLAZED_TERRACOTTA("CYAN_GLAZED_TERRACOTTA", 0), - CYAN_SHULKER_BOX("CYAN_SHULKER_BOX", 0), - CYAN_STAINED_GLASS("STAINED_GLASS", 9), - CYAN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 9), - CYAN_TERRACOTTA("STAINED_CLAY", 9), - CYAN_WALL_BANNER("WALL_BANNER", 0), - CYAN_WOOL("WOOL", 9), - DAMAGED_ANVIL("ANVIL", 2), - DANDELION("YELLOW_FLOWER", 0), - DANDELION_YELLOW("INK_SACK", 11), - DARK_OAK_BOAT("BOAT_DARK_OAK", 0), - DARK_OAK_BUTTON("WOOD_BUTTON", 0), - DARK_OAK_DOOR("DARK_OAK_DOOR", 0), - DARK_OAK_FENCE("DARK_OAK_FENCE", 0), - DARK_OAK_FENCE_GATE("DARK_OAK_FENCE_GATE", 0), - DARK_OAK_LEAVES("LEAVES_2", 1), - DARK_OAK_LOG("LOG_2", 1), - DARK_OAK_PLANKS("WOOD", 5), - DARK_OAK_PRESSURE_PLATE("WOOD_PLATE", 0), - DARK_OAK_SAPLING("SAPLING", 5), - DARK_OAK_SLAB("WOOD_STEP", 0), - DARK_OAK_STAIRS("DARK_OAK_STAIRS", 0), - DARK_OAK_TRAPDOOR("TRAP_DOOR", 0), - DARK_OAK_WOOD("LOG_2", 1), - DARK_PRISMARINE("PRISMARINE", 2), - DARK_PRISMARINE_SLAB("STONE", 0), - DARK_PRISMARINE_STAIRS("STONE", 0), - DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR", 0), - DEAD_BRAIN_CORAL_BLOCK("STONE", 0), - DEAD_BUBBLE_CORAL_BLOCK("STONE", 0), - DEAD_BUSH("DEAD_BUSH", 0), - DEAD_FIRE_CORAL_BLOCK("STONE", 0), - DEAD_HORN_CORAL_BLOCK("STONE", 0), - DEAD_TUBE_CORAL_BLOCK("STONE", 0), - DEBUG_STICK("STICK", 0), - DETECTOR_RAIL("DETECTOR_RAIL", 0), - DIAMOND("DIAMOND", 0), - DIAMOND_AXE("DIAMOND_AXE", 0), - DIAMOND_BLOCK("DIAMOND_BLOCK", 0), - DIAMOND_BOOTS("DIAMOND_BOOTS", 0), - DIAMOND_CHESTPLATE("DIAMOND_CHESTPLATE", 0), - DIAMOND_HELMET("DIAMOND_HELMET", 0), - DIAMOND_HOE("DIAMOND_HOE", 0), - DIAMOND_HORSE_ARMOR("DIAMOND_BARDING", 0), - DIAMOND_LEGGINGS("DIAMOND_LEGGINGS", 0), - DIAMOND_ORE("DIAMOND_ORE", 0), - DIAMOND_PICKAXE("DIAMOND_PICKAXE", 0), - DIAMOND_SHOVEL("DIAMOND_SPADE", 0), - DIAMOND_SWORD("DIAMOND_SWORD", 0), - DIORITE("STONE", 3), - DIRT("DIRT", 0), - DISPENSER("DISPENSER", 0), - DOLPHIN_SPAWN_EGG("MONSTER_EGG", 0), - DONKEY_SPAWN_EGG("MONSTER_EGG", 0), - DRAGON_BREATH("DRAGONS_BREATH", 0), - DRAGON_EGG("DRAGON_EGG", 0), - DRAGON_HEAD("SKULL", 5), - DRAGON_WALL_HEAD("SKULL", 0), - DRIED_KELP("STONE", 0), - DRIED_KELP_BLOCK("STONE", 0), - DROPPER("DROPPER", 0), - DROWNED_SPAWN_EGG("MONSTER_EGG", 0), - EGG("EGG", 0), - ELDER_GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), - ELYTRA("ELYTRA", 0), - EMERALD("EMERALD", 0), - EMERALD_BLOCK("EMERALD_BLOCK", 0), - EMERALD_ORE("EMERALD_ORE", 0), - ENCHANTED_BOOK("ENCHANTED_BOOK", 0), - ENCHANTED_GOLDEN_APPLE("GOLDEN_APPLE", 1), - ENCHANTING_TABLE("ENCHANTING_TABLE", 0), - ENDERMAN_SPAWN_EGG("MONSTER_EGG", 0), - ENDERMITE_SPAWN_EGG("MONSTER_EGG", 0), - ENDER_CHEST("ENDER_CHEST", 0), - ENDER_EYE("EYE_OF_ENDER", 0), - ENDER_PEARL("ENDER_PEARL", 0), - END_CRYSTAL("END_CRYSTAL", 0), - END_GATEWAY("END_GATEWAY", 0), - END_PORTAL("ENDER_PORTAL", 0), - END_PORTAL_FRAME("ENDER_PORTAL_FRAME", 0), - END_ROD("END_ROD", 0), - END_STONE("ENDER_STONE", 0), - END_STONE_BRICKS("END_BRICKS", 0), - EVOKER_SPAWN_EGG("MONSTER_EGG", 0), - EXPERIENCE_BOTTLE("EXP_BOTTLE", 0), - FARMLAND("SOIL", 0), - FEATHER("FEATHER", 0), - FERMENTED_SPIDER_EYE("FERMENTED_SPIDER_EYE", 0), - FERN("LONG_GRASS", 2), - FILLED_MAP("MAP", 0), - FIRE("FIRE", 0), - FIREWORK_ROCKET("FIREWORK", 0), - FIREWORK_STAR("FIREWORK_CHARGE", 0), - FIRE_CHARGE("FIREBALL", 0), - FIRE_CORAL("STONE", 0), - FIRE_CORAL_BLOCK("STONE", 0), - FIRE_CORAL_FAN("STONE", 0), - FISHING_ROD("FISHING_ROD", 0), - FLINT("FLINT", 0), - FLINT_AND_STEEL("FLINT_AND_STEEL", 0), - FLOWER_POT("FLOWER_POT", 0), - FROSTED_ICE("FROSTED_ICE", 0), - FURNACE("FURNACE", 0), - FURNACE_MINECART("POWERED_MINECART", 0), - GHAST_SPAWN_EGG("MONSTER_EGG", 0), - GHAST_TEAR("GHAST_TEAR", 0), - GLASS("GLASS", 0), - GLASS_BOTTLE("GLASS_BOTTLE", 0), - GLASS_PANE("THIN_GLASS", 0), - GLISTERING_MELON_SLICE("SPECKLED_MELON", 0), - GLOWSTONE("GLOWSTONE", 0), - GLOWSTONE_DUST("GLOWSTONE_DUST", 0), - GOLDEN_APPLE("GOLDEN_APPLE", 0), - GOLDEN_AXE("GOLD_AXE", 0), - GOLDEN_BOOTS("GOLD_BOOTS", 0), - GOLDEN_CARROT("GOLDEN_CARROT", 0), - GOLDEN_CHESTPLATE("GOLD_CHESTPLATE", 0), - GOLDEN_HELMET("GOLD_HELMET", 0), - GOLDEN_HOE("GOLD_HOE", 0), - GOLDEN_HORSE_ARMOR("GOLD_BARDING", 0), - GOLDEN_LEGGINGS("GOLD_LEGGINGS", 0), - GOLDEN_PICKAXE("GOLD_PICKAXE", 0), - GOLDEN_SHOVEL("GOLD_SPADE", 0), - GOLDEN_SWORD("GOLD_SWORD", 0), - GOLD_BLOCK("GOLD_BLOCK", 0), - GOLD_INGOT("GOLD_INGOT", 0), - GOLD_NUGGET("GOLD_NUGGET", 0), - GOLD_ORE("GOLD_ORE", 0), - GRANITE("STONE", 1), - GRASS("GRASS", 0), - GRASS_BLOCK("GRASS", 0), - GRASS_PATH("GRASS_PATH", 0), - GRAVEL("GRAVEL", 0), - GRAY_BANNER("BANNER", 8), - GRAY_BED("BED", 7), - GRAY_CARPET("CARPET", 7), - GRAY_CONCRETE("CONCRETE", 7), - GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 7), - GRAY_DYE("INK_SACK", 8), - GRAY_GLAZED_TERRACOTTA("GRAY_GLAZED_TERRACOTTA", 0), - GRAY_SHULKER_BOX("GRAY_SHULKER_BOX", 0), - GRAY_STAINED_GLASS("STAINED_GLASS", 7), - GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 7), - GRAY_TERRACOTTA("STAINED_CLAY", 7), - GRAY_WALL_BANNER("WALL_BANNER", 0), - GRAY_WOOL("WOOL", 7), - GREEN_BANNER("BANNER", 2), - GREEN_BED("BED", 13), - GREEN_CARPET("CARPET", 13), - GREEN_CONCRETE("CONCRETE", 13), - GREEN_CONCRETE_POWDER("CONCRETE_POWDER", 13), - GREEN_GLAZED_TERRACOTTA("GREEN_GLAZED_TERRACOTTA", 0), - GREEN_SHULKER_BOX("GREEN_SHULKER_BOX", 0), - GREEN_STAINED_GLASS("STAINED_GLASS", 13), - GREEN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 13), - GREEN_TERRACOTTA("STAINED_CLAY", 13), - GREEN_WALL_BANNER("WALL_BANNER", 0), - GREEN_WOOL("WOOL", 13), - GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), - GUNPOWDER("SULPHUR", 0), - HAY_BLOCK("HAY_BLOCK", 0), - HEART_OF_THE_SEA("STONE", 0), - HEAVY_WEIGHTED_PRESSURE_PLATE("IRON_PLATE", 0), - HOPPER("HOPPER", 0), - HOPPER_MINECART("HOPPER_MINECART", 0), - HORN_CORAL("STONE", 0), - HORN_CORAL_BLOCK("STONE", 0), - HORN_CORAL_FAN("STONE", 0), - HORSE_SPAWN_EGG("MONSTER_EGG", 0), - HUSK_SPAWN_EGG("MONSTER_EGG", 0), - ICE("ICE", 0), - INFESTED_CHISELED_STONE_BRICKS("MONSTER_EGGS", 5), - INFESTED_COBBLESTONE("MONSTER_EGGS", 1), - INFESTED_CRACKED_STONE_BRICKS("MONSTER_EGGS", 4), - INFESTED_MOSSY_STONE_BRICKS("MONSTER_EGGS", 3), - INFESTED_STONE("MONSTER_EGGS", 0), - INFESTED_STONE_BRICKS("MONSTER_EGGS", 2), - INK_SAC("INK_SACK", 0), - IRON_AXE("IRON_AXE", 0), - IRON_BARS("IRON_FENCE", 0), - IRON_BLOCK("IRON_BLOCK", 0), - IRON_BOOTS("IRON_BOOTS", 0), - IRON_CHESTPLATE("IRON_CHESTPLATE", 0), - IRON_DOOR("IRON_DOOR", 0), - IRON_HELMET("IRON_HELMET", 0), - IRON_HOE("IRON_HOE", 0), - IRON_HORSE_ARMOR("IRON_BARDING", 0), - IRON_INGOT("IRON_INGOT", 0), - IRON_LEGGINGS("IRON_LEGGINGS", 0), - IRON_NUGGET("IRON_NUGGET", 0), - IRON_ORE("IRON_ORE", 0), - IRON_PICKAXE("IRON_PICKAXE", 0), - IRON_SHOVEL("IRON_SPADE", 0), - IRON_SWORD("IRON_SWORD", 0), - IRON_TRAPDOOR("IRON_TRAPDOOR", 0), - ITEM_FRAME("ITEM_FRAME", 0), - JACK_O_LANTERN("JACK_O_LANTERN", 0), - JUKEBOX("JUKEBOX", 0), - JUNGLE_BOAT("BOAT_JUNGLE", 0), - JUNGLE_BUTTON("WOOD_BUTTON", 0), - JUNGLE_DOOR("JUNGLE_DOOR", 0), - JUNGLE_FENCE("JUNGLE_FENCE", 0), - JUNGLE_FENCE_GATE("JUNGLE_FENCE_GATE", 0), - JUNGLE_LEAVES("LEAVES", 3), - JUNGLE_LOG("LOG", 3), - JUNGLE_PLANKS("WOOD", 3), - JUNGLE_PRESSURE_PLATE("WOOD_PLATE", 0), - JUNGLE_SAPLING("SAPLING", 3), - JUNGLE_SLAB("WOOD_STEP", 3), - JUNGLE_STAIRS("JUNGLE_WOOD_STAIRS", 0), - JUNGLE_TRAPDOOR("TRAP_DOOR", 0), - JUNGLE_WOOD("LOG", 3), - KELP("STONE", 0), - KELP_PLANT("STONE", 0), - KNOWLEDGE_BOOK("KNOWLEDGE_BOOK", 0), - LADDER("LADDER", 0), - LAPIS_BLOCK("LAPIS_BLOCK", 0), - LAPIS_LAZULI("INK_SACK", 4), - LAPIS_ORE("LAPIS_ORE", 0), - LARGE_FERN("DOUBLE_PLANT", 3), - LAVA("LAVA", 0), - LAVA_BUCKET("LAVA_BUCKET", 0), - LEAD("LEASH", 0), - LEATHER("LEATHER", 0), - LEATHER_BOOTS("LEATHER_BOOTS", 0), - LEATHER_CHESTPLATE("LEATHER_CHESTPLATE", 0), - LEATHER_HELMET("LEATHER_HELMET", 0), - LEATHER_LEGGINGS("LEATHER_LEGGINGS", 0), - LEVER("LEVER", 0), - LIGHT_BLUE_BANNER("BANNER", 12), - LIGHT_BLUE_BED("BED", 3), - LIGHT_BLUE_CARPET("CARPET", 3), - LIGHT_BLUE_CONCRETE("CONCRETE", 3), - LIGHT_BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 3), - LIGHT_BLUE_DYE("INK_SACK", 12), - LIGHT_BLUE_GLAZED_TERRACOTTA("LIGHT_BLUE_GLAZED_TERRACOTTA", 0), - LIGHT_BLUE_SHULKER_BOX("LIGHT_BLUE_SHULKER_BOX", 0), - LIGHT_BLUE_STAINED_GLASS("STAINED_GLASS", 3), - LIGHT_BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 3), - LIGHT_BLUE_TERRACOTTA("STAINED_CLAY", 3), - LIGHT_BLUE_WALL_BANNER("BANNER", 0), - LIGHT_BLUE_WOOL("WOOL", 3), - LIGHT_GRAY_BANNER("BANNER", 7), - LIGHT_GRAY_BED("BED", 8), - LIGHT_GRAY_CARPET("CARPET", 8), - LIGHT_GRAY_CONCRETE("CONCRETE", 8), - LIGHT_GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 8), - LIGHT_GRAY_DYE("INK_SACK", 7), - LIGHT_GRAY_GLAZED_TERRACOTTA("SILVER_GLAZED_TERRACOTTA", 0), - LIGHT_GRAY_SHULKER_BOX("SILVER_SHULKER_BOX", 0), - LIGHT_GRAY_STAINED_GLASS("STAINED_GLASS", 8), - LIGHT_GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 8), - LIGHT_GRAY_TERRACOTTA("STAINED_CLAY", 8), - LIGHT_GRAY_WALL_BANNER("WALL_BANNER", 0), - LIGHT_GRAY_WOOL("WOOL", 8), - LIGHT_WEIGHTED_PRESSURE_PLATE("GOLD_PLATE", 0), - LILAC("DOUBLE_PLANT", 1), - LILY_PAD("WATER_LILY", 0), - LIME_BANNER("BANNER", 10), - LIME_BED("BED", 5), - LIME_CARPET("CARPET", 5), - LIME_CONCRETE("CONCRETE", 5), - LIME_CONCRETE_POWDER("CONCRETE_POWDER", 5), - LIME_DYE("INK_SACK", 10), - LIME_GLAZED_TERRACOTTA("LIME_GLAZED_TERRACOTTA", 0), - LIME_SHULKER_BOX("LIME_SHULKER_BOX", 0), - LIME_STAINED_GLASS("STAINED_GLASS", 5), - LIME_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 5), - LIME_TERRACOTTA("STAINED_CLAY", 5), - LIME_WALL_BANNER("WALL_BANNER", 0), - LIME_WOOL("WOOL", 5), - LINGERING_POTION("LINGERING_POTION", 0), - LLAMA_SPAWN_EGG("MONSTER_EGG", 0), - MAGENTA_BANNER("BANNER", 13), - MAGENTA_BED("BED", 2), - MAGENTA_CARPET("CARPET", 2), - MAGENTA_CONCRETE("CONCRETE", 2), - MAGENTA_CONCRETE_POWDER("CONCRETE_POWDER", 2), - MAGENTA_DYE("INK_SACK", 13), - MAGENTA_GLAZED_TERRACOTTA("MAGENTA_GLAZED_TERRACOTTA", 0), - MAGENTA_SHULKER_BOX("MAGENTA_SHULKER_BOX", 0), - MAGENTA_STAINED_GLASS("STAINED_GLASS", 2), - MAGENTA_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 2), - MAGENTA_TERRACOTTA("STAINED_CLAY", 2), - MAGENTA_WALL_BANNER("WALL_BANNER", 0), - MAGENTA_WOOL("WOOL", 2), - MAGMA_BLOCK("MAGMA", 0), - MAGMA_CREAM("MAGMA_CREAM", 0), - MAGMA_CUBE_SPAWN_EGG("MONSTER_EGG", 0), - MAP("MAP", 0), - MELON("MELON_BLOCK", 0), - MELON_SEEDS("MELON_SEEDS", 0), - MELON_SLICE("MELON", 0), - MELON_STEM("MELON_STEM", 0), - MILK_BUCKET("MILK_BUCKET", 0), - MINECART("MINECART", 0), - MOOSHROOM_SPAWN_EGG("MONSTER_EGG", 0), - MOSSY_COBBLESTONE("MOSSY_COBBLESTONE", 0), - MOSSY_COBBLESTONE_WALL("COBBLE_WALL", 1), - MOSSY_STONE_BRICKS("SMOOTH_BRICK", 1), - MOVING_PISTON("PISTON_MOVING_PIECE", 0), - MULE_SPAWN_EGG("MONSTER_EGG", 0), - MUSHROOM_STEM("BROWN_MUSHROOM", 0), - MUSHROOM_STEW("MUSHROOM_SOUP", 0), - MUSIC_DISC_11("GOLD_RECORD", 0), - MUSIC_DISC_13("GREEN_RECORD", 0), - MUSIC_DISC_BLOCKS("RECORD_3", 0), - MUSIC_DISC_CAT("RECORD_4", 0), - MUSIC_DISC_CHIRP("RECORD_5", 0), - MUSIC_DISC_FAR("RECORD_6", 0), - MUSIC_DISC_MALL("RECORD_7", 0), - MUSIC_DISC_MELLOHI("RECORD_8", 0), - MUSIC_DISC_STAL("RECORD_9", 0), - MUSIC_DISC_STRAD("RECORD_10", 0), - MUSIC_DISC_WAIT("RECORD_11", 0), - MUSIC_DISC_WARD("RECORD_12", 0), - MUTTON("MUTTON", 0), - MYCELIUM("MYCEL", 0), - NAME_TAG("NAME_TAG", 0), - NAUTILUS_SHELL("STONE", 0), - NETHERRACK("NETHERRACK", 0), - NETHER_BRICK("NETHER_BRICK", 0), - NETHER_BRICKS("NETHER_BRICK", 0), - NETHER_BRICK_FENCE("NETHER_FENCE", 0), - NETHER_BRICK_SLAB("STEP", 6), - NETHER_BRICK_STAIRS("NETHER_BRICK_STAIRS", 0), - NETHER_PORTAL("PORTAL", 0), - NETHER_QUARTZ_ORE("QUARTZ_ORE", 0), - NETHER_STAR("NETHER_STAR", 0), - NETHER_WART("NETHER_STALK", 0), - NETHER_WART_BLOCK("NETHER_WART_BLOCK", 0), - NOTE_BLOCK("NOTE_BLOCK", 0), - OAK_BOAT("BOAT", 0), - OAK_BUTTON("WOOD_BUTTON", 0), - OAK_DOOR("WOOD_DOOR", 0), - OAK_FENCE("FENCE", 0), - OAK_FENCE_GATE("FENCE_GATE", 0), - OAK_LEAVES("LEAVES", 0), - OAK_LOG("LOG", 0), - OAK_PLANKS("WOOD", 0), - OAK_PRESSURE_PLATE("WOOD_PLATE", 0), - OAK_SAPLING("SAPLING", 0), - OAK_SLAB("WOOD_STEP", 0), - OAK_STAIRS("WOOD_STAIRS", 0), - OAK_TRAPDOOR("TRAP_DOOR", 0), - OAK_WOOD("LOG", 0), - OBSERVER("OBSERVER", 0), - OBSIDIAN("OBSIDIAN", 0), - OCELOT_SPAWN_EGG("RECORD_12", 0), - ORANGE_BANNER("BANNER", 14), - ORANGE_BED("BED", 1), - ORANGE_CARPET("CARPET", 1), - ORANGE_CONCRETE("CONCRETE", 1), - ORANGE_CONCRETE_POWDER("CONCRETE_POWDER", 1), - ORANGE_DYE("INK_SACK", 14), - ORANGE_GLAZED_TERRACOTTA("ORANGE_GLAZED_TERRACOTTA", 0), - ORANGE_SHULKER_BOX("ORANGE_SHULKER_BOX", 0), - ORANGE_STAINED_GLASS("STAINED_GLASS", 1), - ORANGE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 1), - ORANGE_TERRACOTTA("STAINED_CLAY", 1), - ORANGE_TULIP("RED_ROSE", 5), - ORANGE_WALL_BANNER("WALL_BANNER", 0), - ORANGE_WOOL("WOOL", 1), - OXEYE_DAISY("RED_ROSE", 8), - PACKED_ICE("PACKED_ICE", 0), - PAINTING("PAINTING", 0), - PAPER("PAPER", 0), - PARROT_SPAWN_EGG("MONSTER_EGG", 0), - PEONY("DOUBLE_PLANT", 5), - PETRIFIED_OAK_SLAB("STONE", 0), - PHANTOM_MEMBRANE("STONE", 0), - PHANTOM_SPAWN_EGG("MONSTER_EGG", 0), - PIG_SPAWN_EGG("MONSTER_EGG", 0), - PINK_BANNER("BANNER", 9), - PINK_BED("BED", 6), - PINK_CARPET("CARPET", 6), - PINK_CONCRETE("CONCRETE", 6), - PINK_CONCRETE_POWDER("CONCRETE_POWDER", 6), - PINK_DYE("INK_SACK", 9), - PINK_GLAZED_TERRACOTTA("PINK_GLAZED_TERRACOTTA", 0), - PINK_SHULKER_BOX("PINK_SHULKER_BOX", 0), - PINK_STAINED_GLASS("STAINED_GLASS", 6), - PINK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 6), - PINK_TERRACOTTA("STAINED_CLAY", 6), - PINK_TULIP("RED_ROSE", 7), - PINK_WALL_BANNER("WALL_BANNER", 0), - PINK_WOOL("WOOL", 6), - PISTON("PISTON_BASE", 0), - PISTON_HEAD("PISTON_EXTENSION", 0), - PLAYER_HEAD("SKULL", 0), - PLAYER_WALL_HEAD("SKULL", 0), - PODZOL("DIRT", 2), - POISONOUS_POTATO("POISONOUS_POTATO", 0), - POLAR_BEAR_SPAWN_EGG("MONSTER_EGG", 0), - POLISHED_ANDESITE("STONE", 6), - POLISHED_DIORITE("STONE", 4), - POLISHED_GRANITE("STONE", 2), - POPPED_CHORUS_FRUIT("CHORUS_FRUIT_POPPED", 0), - POPPY("RED_ROSE", 0), - PORKCHOP("PORK", 0), - POTATO("POTATO_ITEM", 0), - POTATOES("POTATO", 0), - POTION("POTION", 0), - POTTED_ACACIA_SAPLING("FLOWER_POT", 0), - POTTED_ALLIUM("FLOWER_POT", 0), - POTTED_AZURE_BLUET("FLOWER_POT", 0), - POTTED_BIRCH_SAPLING("FLOWER_POT", 0), - POTTED_BLUE_ORCHID("FLOWER_POT", 0), - POTTED_BROWN_MUSHROOM("FLOWER_POT", 0), - POTTED_CACTUS("FLOWER_POT", 0), - POTTED_DANDELION("FLOWER_POT", 0), - POTTED_DARK_OAK_SAPLING("FLOWER_POT", 0), - POTTED_DEAD_BUSH("FLOWER_POT", 0), - POTTED_FERN("FLOWER_POT", 0), - POTTED_JUNGLE_SAPLING("FLOWER_POT", 0), - POTTED_OAK_SAPLING("FLOWER_POT", 0), - POTTED_ORANGE_TULIP("FLOWER_POT", 0), - POTTED_OXEYE_DAISY("FLOWER_POT", 0), - POTTED_PINK_TULIP("FLOWER_POT", 0), - POTTED_POPPY("FLOWER_POT", 0), - POTTED_RED_MUSHROOM("FLOWER_POT", 0), - POTTED_RED_TULIP("FLOWER_POT", 0), - POTTED_SPRUCE_SAPLING("FLOWER_POT", 0), - POTTED_WHITE_TULIP("FLOWER_POT", 0), - POWERED_RAIL("POWERED_RAIL", 0), - PRISMARINE("PRISMARINE", 0), - PRISMARINE_BRICKS("PRISMARINE", 1), - PRISMARINE_BRICK_SLAB("STONE", 0), - PRISMARINE_BRICK_STAIRS("STONE", 0), - PRISMARINE_CRYSTALS("PRISMARINE_CRYSTALS", 0), - PRISMARINE_SHARD("PRISMARINE_SHARD", 0), - PRISMARINE_SLAB("STONE", 0), - PRISMARINE_STAIRS("STONE", 0), - PUFFERFISH("RAW_FISH", 3), - PUFFERFISH_BUCKET("STONE", 0), - PUFFERFISH_SPAWN_EGG("MONSTER_EGG", 0), - PUMPKIN("PUMPKIN", 0), - PUMPKIN_PIE("PUMPKIN_PIE", 0), - PUMPKIN_SEEDS("PUMPKIN_SEEDS", 0), - PUMPKIN_STEM("PUMPKIN_STEM", 0), - PURPLE_BANNER("BANNER", 5), - PURPLE_BED("BED", 10), - PURPLE_CARPET("CARPET", 10), - PURPLE_CONCRETE("CONCRETE", 10), - PURPLE_CONCRETE_POWDER("CONCRETE_POWDER", 10), - PURPLE_DYE("INK_SACK", 5), - PURPLE_GLAZED_TERRACOTTA("PURPLE_GLAZED_TERRACOTTA", 0), - PURPLE_SHULKER_BOX("PURPLE_SHULKER_BOX", 0), - PURPLE_STAINED_GLASS("STAINED_GLASS", 10), - PURPLE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 10), - PURPLE_TERRACOTTA("STAINED_CLAY", 10), - PURPLE_WALL_BANNER("WALL_BANNER", 0), - PURPLE_WOOL("WOOL", 10), - PURPUR_BLOCK("PURPUR_BLOCK", 0), - PURPUR_PILLAR("PURPUR_PILLAR", 0), - PURPUR_SLAB("PURPUR_SLAB", 0), - PURPUR_STAIRS("PURPUR_STAIRS", 0), - QUARTZ("QUARTZ", 0), - QUARTZ_BLOCK("QUARTZ_BLOCK", 0), - QUARTZ_PILLAR("QUARTZ_BLOCK", 2), - QUARTZ_SLAB("STEP", 7), - QUARTZ_STAIRS("QUARTZ_STAIRS", 0), - RABBIT("RABBIT", 0), - RABBIT_FOOT("RABBIT_FOOT", 0), - RABBIT_HIDE("RABBIT_HIDE", 0), - RABBIT_SPAWN_EGG("MONSTER_EGG", 0), - RABBIT_STEW("RABBIT_STEW", 0), - RAIL("RAILS", 0), - REDSTONE("REDSTONE", 0), - REDSTONE_BLOCK("REDSTONE_BLOCK", 0), - REDSTONE_LAMP("REDSTONE_LAMP_OFF", 0), - REDSTONE_ORE("REDSTONE_ORE", 0), - REDSTONE_TORCH("REDSTONE_TORCH_ON", 0), - REDSTONE_WALL_TORCH("REDSTONE_TORCH_ON", 1), - REDSTONE_WIRE("REDSTONE_WIRE", 0), - RED_BANNER("BANNER", 1), - RED_BED("BED", 14), - RED_CARPET("CARPET", 14), - RED_CONCRETE("CONCRETE", 14), - RED_CONCRETE_POWDER("CONCRETE_POWDER", 14), - RED_GLAZED_TERRACOTTA("RED_GLAZED_TERRACOTTA", 0), - RED_MUSHROOM("RED_MUSHROOM", 0), - RED_MUSHROOM_BLOCK("RED_MUSHROOM", 0), - RED_NETHER_BRICKS("RED_NETHER_BRICK", 0), - RED_SAND("SAND", 1), - RED_SANDSTONE("RED_SANDSTONE", 0), - RED_SANDSTONE_SLAB("STONE_SLAB2", 0), - RED_SANDSTONE_STAIRS("RED_SANDSTONE_STAIRS", 0), - RED_SHULKER_BOX("RED_SHULKER_BOX", 0), - RED_STAINED_GLASS("STAINED_GLASS", 14), - RED_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 14), - RED_TERRACOTTA("STAINED_CLAY", 14), - RED_TULIP("RED_ROSE", 4), - RED_WALL_BANNER("WALL_BANNER", 0), - RED_WOOL("WOOL", 14), - REPEATER("DIODE", 0), - REPEATING_COMMAND_BLOCK("COMMAND_REPEATING", 0), - ROSE_BUSH("DOUBLE_PLANT", 4), - ROSE_RED("INK_SACK", 1), - ROTTEN_FLESH("ROTTEN_FLESH", 0), - SADDLE("SADDLE", 0), - SALMON("RAW_FISH", 1), - SALMON_BUCKET("BUCKET", 0), - SALMON_SPAWN_EGG("MONSTER_EGG", 0), - SAND("SAND", 0), - SANDSTONE("SANDSTONE", 0), - SANDSTONE_SLAB("STEP", 1), - SANDSTONE_STAIRS("SANDSTONE_STAIRS", 0), - SCUTE("STONE", 0), - SEAGRASS("STONE", 0), - SEA_LANTERN("SEA_LANTERN", 0), - SEA_PICKLE("STONE", 0), - SHEARS("SHEARS", 0), - SHEEP_SPAWN_EGG("MONSTER_EGG", 0), - SHIELD("SHIELD", 0), - SHULKER_BOX("PURPLE_SHULKER_BOX", 0), - SHULKER_SHELL("SHULKER_SHELL", 0), - SHULKER_SPAWN_EGG("MONSTER_EGG", 0), - SIGN("SIGN", 0), - SILVERFISH_SPAWN_EGG("MONSTER_EGG", 0), - SKELETON_HORSE_SPAWN_EGG("MONSTER_EGG", 0), - SKELETON_SKULL("SKULL", 0), - SKELETON_SPAWN_EGG("MONSTER_EGG", 0), - SKELETON_WALL_SKULL("SKULL", 0), - SLIME_BALL("SLIME_BALL", 0), - SLIME_BLOCK("SLIME_BLOCK", 0), - SLIME_SPAWN_EGG("MONSTER_EGG", 0), - SMOOTH_QUARTZ("STONE", 0), - SMOOTH_RED_SANDSTONE("RED_SANDSTONE", 2), - SMOOTH_SANDSTONE("SANDSTONE", 2), - SMOOTH_STONE("STEP", 0), - SNOW("SNOW", 0), - SNOWBALL("SNOW_BALL", 0), - SNOW_BLOCK("SNOW_BLOCK", 0), - SOUL_SAND("SOUL_SAND", 0), - SPAWNER("MOB_SPAWNER", 0), - SPECTRAL_ARROW("SPECTRAL_ARROW", 0), - SPIDER_EYE("SPIDER_EYE", 0), - SPIDER_SPAWN_EGG("MONSTER_EGG", 0), - SPLASH_POTION("SPLASH_POTION", 0), - SPONGE("SPONGE", 0), - SPRUCE_BOAT("BOAT_SPRUCE", 0), - SPRUCE_BUTTON("WOOD_BUTTON", 0), - SPRUCE_DOOR("SPRUCE_DOOR", 0), - SPRUCE_FENCE("SPRUCE_FENCE", 0), - SPRUCE_FENCE_GATE("SPRUCE_FENCE_GATE", 0), - SPRUCE_LEAVES("LEAVES", 1), - SPRUCE_LOG("LOG", 1), - SPRUCE_PLANKS("WOOD", 1), - SPRUCE_PRESSURE_PLATE("WOOD_PLATE", 0), - SPRUCE_SAPLING("SAPLING", 1), - SPRUCE_SLAB("WOOD_STEP", 1), - SPRUCE_STAIRS("SPRUCE_WOOD_STAIRS", 0), - SPRUCE_TRAPDOOR("TRAP_DOOR", 0), - SPRUCE_WOOD("LOG", 1), - SQUID_SPAWN_EGG("MONSTER_EGG", 0), - STICK("STICK", 0), - STICKY_PISTON("PISTON_STICKY_BASE", 0), - STONE("STONE", 0), - STONE_AXE("STONE_AXE", 0), - STONE_BRICKS("SMOOTH_BRICK", 0), - STONE_BRICK_SLAB("STEP", 5), - STONE_BRICK_STAIRS("SMOOTH_STAIRS", 0), - STONE_BUTTON("STONE_BUTTON", 0), - STONE_HOE("STONE_HOE", 0), - STONE_PICKAXE("STONE_PICKAXE", 0), - STONE_PRESSURE_PLATE("STONE_PLATE", 0), - STONE_SHOVEL("STONE_SPADE", 0), - STONE_SLAB("STEP", 0), - STONE_SWORD("STONE_SWORD", 0), - STRAY_SPAWN_EGG("MONSTER_EGG", 0), - STRING("STRING", 0), - STRIPPED_ACACIA_LOG("STONE", 0), - STRIPPED_ACACIA_WOOD("STONE", 0), - STRIPPED_BIRCH_LOG("STONE", 0), - STRIPPED_BIRCH_WOOD("STONE", 0), - STRIPPED_DARK_OAK_LOG("STONE", 0), - STRIPPED_DARK_OAK_WOOD("STONE", 0), - STRIPPED_JUNGLE_LOG("STONE", 0), - STRIPPED_JUNGLE_WOOD("STONE", 0), - STRIPPED_OAK_LOG("STONE", 0), - STRIPPED_OAK_WOOD("STONE", 0), - STRIPPED_SPRUCE_LOG("STONE", 0), - STRIPPED_SPRUCE_WOOD("STONE", 0), - STRUCTURE_BLOCK("STRUCTURE_BLOCK", 0), - STRUCTURE_VOID("STRUCTURE_VOID", 0), - SUGAR("SUGAR", 0), - SUGAR_CANE("SUGAR_CANE", 0), - SUNFLOWER("DOUBLE_PLANT", 0), - TALL_GRASS("DOUBLE_PLANT", 2), - TALL_SEAGRASS("STONE", 0), - TERRACOTTA("HARD_CLAY", 0), - TIPPED_ARROW("TIPPED_ARROW", 0), - TNT("TNT", 0), - TNT_MINECART("EXPLOSIVE_MINECART", 0), - TORCH("TORCH", 0), - TOTEM_OF_UNDYING("TOTEM", 0), - TRAPPED_CHEST("TRAPPED_CHEST", 0), - TRIDENT("STONE", 0), - TRIPWIRE("TRIPWIRE", 0), - TRIPWIRE_HOOK("TRIPWIRE_HOOK", 0), - TROPICAL_FISH("RAW_FISH", 0), - TROPICAL_FISH_BUCKET("BUCKET", 0), - TROPICAL_FISH_SPAWN_EGG("MONSTER_EGG", 0), - TUBE_CORAL("STONE", 0), - TUBE_CORAL_BLOCK("STONE", 0), - TUBE_CORAL_FAN("STONE", 0), - TURTLE_EGG("MONSTER_EGG", 0), - TURTLE_HELMET("STONE", 0), - TURTLE_SPAWN_EGG("MONSTER_EGG", 0), - VEX_SPAWN_EGG("MONSTER_EGG", 0), - VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), - VINDICATOR_SPAWN_EGG("MONSTER_EGG", 0), - VINE("VINE", 0), - VOID_AIR("AIR", 0), - WALL_SIGN("WALL_SIGN", 0), - WALL_TORCH("TORCH", 1), - WATER("WATER", 0), - WATER_BUCKET("WATER_BUCKET", 0), - WET_SPONGE("SPONGE", 1), - WHEAT("WHEAT", 0), - WHEAT_SEEDS("SEEDS", 0), - WHITE_BANNER("BANNER", 15), - WHITE_BED("BED", 0), - WHITE_CARPET("CARPET", 0), - WHITE_CONCRETE("CONCRETE", 0), - WHITE_CONCRETE_POWDER("CONCRETE_POWDER", 0), - WHITE_GLAZED_TERRACOTTA("WHITE_GLAZED_TERRACOTTA", 0), - WHITE_SHULKER_BOX("WHITE_SHULKER_BOX", 0), - WHITE_STAINED_GLASS("STAINED_GLASS", 0), - WHITE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 0), - WHITE_TERRACOTTA("TERRACOTTA", 0), - WHITE_TULIP("RED_ROSE", 6), - WHITE_WALL_BANNER("WALL_BANNER", 0), - WHITE_WOOL("WOOL", 0), - WITCH_SPAWN_EGG("MONSTER_EGG", 0), - WITHER_SKELETON_SKULL("SKULL", 0), - WITHER_SKELETON_SPAWN_EGG("MONSTER_EGG", 0), - WITHER_SKELETON_WALL_SKULL("SKULL", 0), - WOLF_SPAWN_EGG("MONSTER_EGG", 0), - WOODEN_AXE("WOOD_AXE", 0), - WOODEN_HOE("WOOD_HOE", 0), - WOODEN_PICKAXE("WOOD_PICKAXE", 0), - WOODEN_SHOVEL("WOOD_SPADE", 0), - WOODEN_SWORD("WOOD_SWORD", 0), - WRITABLE_BOOK("BOOK_AND_QUILL", 0), - WRITTEN_BOOK("WRITTEN_BOOK", 0), - YELLOW_BANNER("BANNER", 11), - YELLOW_BED("BED", 4), - YELLOW_CARPET("CARPET", 4), - YELLOW_CONCRETE("CONCRETE", 4), - YELLOW_CONCRETE_POWDER("CONCRETE_POWDER", 4), - YELLOW_GLAZED_TERRACOTTA("YELLOW_GLAZED_TERRACOTTA", 0), - YELLOW_SHULKER_BOX("YELLOW_SHULKER_BOX", 0), - YELLOW_STAINED_GLASS("STAINED_GLASS", 4), - YELLOW_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 4), - YELLOW_TERRACOTTA("STAINED_CLAY", 4), - YELLOW_WALL_BANNER("WALL_BANNER", 0), - YELLOW_WOOL("WOOL", 4), - ZOMBIE_HEAD("SKULL", 0), - ZOMBIE_HORSE_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_PIGMAN_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), - ZOMBIE_WALL_HEAD("SKULL", 0), - ; + ACACIA_BOAT("BOAT_ACACIA", 0), + ACACIA_BUTTON("WOOD_BUTTON", 0), + ACACIA_DOOR("ACACIA_DOOR", 0), + ACACIA_FENCE("ACACIA_FENCE", 0), + ACACIA_FENCE_GATE("ACACIA_FENCE_GATE", 0), + ACACIA_LEAVES("LEAVES_2", 0), + ACACIA_LOG("LOG_2", 0), + ACACIA_PLANKS("WOOD", 4), + ACACIA_PRESSURE_PLATE("WOOD_PLATE", 0), + ACACIA_SAPLING("SAPLING", 4), + ACACIA_SLAB("WOOD_STEP", 4), + ACACIA_STAIRS("ACACIA_STAIRS", 4), + ACACIA_TRAPDOOR("TRAP_DOOR", 0), + ACACIA_WOOD("LOG_2", 0), + ACTIVATOR_RAIL("ACTIVATOR_RAIL", 0), + AIR("AIR", 0), + ALLIUM("STONE", 0), + ANDESITE("STONE", 5), + ANVIL("ANVIL", 0), + APPLE("APPLE", 0), + ARMOR_STAND("ARMOR_STAND", 0), + ARROW("ARROW", 0), + ATTACHED_MELON_STEM("MELON_STEM", 7), + ATTACHED_PUMPKIN_STEM("PUMPKIN_STEM", 7), + AZURE_BLUET("RED_ROSE", 3), + BAKED_POTATO("BAKED_POTATO", 0), + BARRIER("BARRIER", 0), + BAT_SPAWN_EGG("MONSTER_EGG", 0), + BEACON("BEACON", 0), + BEDROCK("BEDROCK", 0), + BEEF("RAW_BEEF", 0), + BEETROOT("BEETROOT", 0), + BEETROOTS("BEETROOT", 0), + BEETROOT_SEEDS("BEETROOT_SEEDS", 0), + BEETROOT_SOUP("BEETROOT_SOUP", 0), + BIRCH_BOAT("BOAT_BIRCH", 0), + BIRCH_BUTTON("WOOD_BUTTON", 0), + BIRCH_DOOR("BIRCH_DOOR", 0), + BIRCH_FENCE("BIRCH_FENCE", 0), + BIRCH_FENCE_GATE("BIRCH_FENCE_GATE", 0), + BIRCH_LEAVES("LEAVES", 2), + BIRCH_LOG("LOG", 2), + BIRCH_PLANKS("WOOD", 2), + BIRCH_PRESSURE_PLATE("WOOD_PLATE", 0), + BIRCH_SAPLING("SAPLING", 2), + BIRCH_SLAB("WOOD_STEP", 2), + BIRCH_STAIRS("BIRCH_WOOD_STAIRS", 0), + BIRCH_TRAPDOOR("TRAP_DOOR", 0), + BIRCH_WOOD("LOG", 2), + BLACK_BANNER("BANNER", 0), + BLACK_BED("BED", 15), + BLACK_CARPET("CARPET", 15), + BLACK_CONCRETE("CONCRETE", 15), + BLACK_CONCRETE_POWDER("CONCRETE_POWDER", 15), + BLACK_GLAZED_TERRACOTTA("BLACK_GLAZED_TERRACOTTA", 0), + BLACK_SHULKER_BOX("BLACK_SHULKER_BOX", 0), + BLACK_STAINED_GLASS("STAINED_GLASS", 15), + BLACK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 15), + BLACK_TERRACOTTA("STAINED_CLAY", 15), + BLACK_WALL_BANNER("WALL_BANNER", 0), + BLACK_WOOL("WOOL", 15), + BLAZE_POWDER("BLAZE_POWDER", 0), + BLAZE_ROD("BLAZE_ROD", 0), + BLAZE_SPAWN_EGG("MONSTER_EGG", 0), + BLUE_BANNER("BANNER", 11), + BLUE_BED("BED", 4), + BLUE_CARPET("CARPET", 11), + BLUE_CONCRETE("CONCRETE", 11), + BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 11), + BLUE_GLAZED_TERRACOTTA("BLUE_GLAZED_TERRACOTTA", 0), + BLUE_ICE("PACKED_ICE", 0), + BLUE_ORCHID("RED_ROSE", 1), + BLUE_SHULKER_BOX("BLUE_SHULKER_BOX", 0), + BLUE_STAINED_GLASS("STAINED_GLASS", 11), + BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 11), + BLUE_TERRACOTTA("STAINED_CLAY", 11), + BLUE_WALL_BANNER("WALL_BANNER", 11), + BLUE_WOOL("WOOL", 11), + BONE("BONE", 0), + BONE_BLOCK("BONE_BLOCK", 0), + BONE_MEAL("INK_SACK", 15), + BOOK("BOOK", 0), + BOOKSHELF("BOOKSHELF", 0), + BOW("BOW", 0), + BOWL("BOWL", 0), + BRAIN_CORAL("STONE", 0), + BRAIN_CORAL_BLOCK("STONE", 0), + BRAIN_CORAL_FAN("STONE", 0), + BREAD("BREAD", 0), + BREWING_STAND("BREWING_STAND", 0), + BRICK("CLAY_BRICK", 0), + BRICKS("BRICK", 0), + BRICK_SLAB("STEP", 4), + BRICK_STAIRS("BRICK_STAIRS", 0), + BROWN_BANNER("BANNER", 3), + BROWN_BED("BED", 12), + BROWN_CARPET("CARPET", 12), + BROWN_CONCRETE("CONCRETE", 12), + BROWN_CONCRETE_POWDER("CONCRETE_POWDER", 12), + BROWN_GLAZED_TERRACOTTA("BROWN_GLAZED_TERRACOTTA", 0), + BROWN_MUSHROOM("BROWN_MUSHROOM", 0), + BROWN_MUSHROOM_BLOCK("BROWN_MUSHROOM", 0), //UNSURE + BROWN_SHULKER_BOX("BROWN_SHULKER_BOX", 0), + BROWN_STAINED_GLASS("STAINED_GLASS", 12), + BROWN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 12), + BROWN_TERRACOTTA("STAINED_CLAY", 12), + BROWN_WALL_BANNER("WALL_BANNER", 3), + BROWN_WOOL("WOOL", 12), + BUBBLE_COLUMN("STONE", 0), + BUBBLE_CORAL("STONE", 0), + BUBBLE_CORAL_BLOCK("STONE", 0), + BUBBLE_CORAL_FAN("STONE", 0), + BUCKET("BUCKET", 0), + CACTUS("CACTUS", 0), + CACTUS_GREEN("INK_SACK", 2), + CAKE("CAKE", 0), + CARROT("CARROT_ITEM", 0), + CARROTS("CARROT", 0), + CARROT_ON_A_STICK("CARROT_STICK", 0), + CARVED_PUMPKIN("PUMPKIN", 0), + CAULDRON("CAULDRON", 0), + CAVE_AIR("AIR", 0), + CAVE_SPIDER_SPAWN_EGG("MONSTER_EGG", 0), + CHAINMAIL_BOOTS("CHAINMAIL_BOOTS", 0), + CHAINMAIL_CHESTPLATE("CHAINMAIL_CHESTPLATE", 0), + CHAINMAIL_HELMET("CHAINMAIL_HELMET", 0), + CHAINMAIL_LEGGINGS("CHAINMAIL_LEGGINGS", 0), + CHAIN_COMMAND_BLOCK("COMMAND_CHAIN", 0), + CHARCOAL("COAL", 1), + CHEST("CHEST", 0), + CHEST_MINECART("STORAGE_MINECART", 0), + CHICKEN("RAW_CHICKEN", 0), + CHICKEN_SPAWN_EGG("MONSTER_EGG", 0), + CHIPPED_ANVIL("ANVIL", 1), + CHISELED_QUARTZ_BLOCK("QUARTZ_BLOCK", 1), + CHISELED_RED_SANDSTONE("RED_SANDSTONE", 1), + CHISELED_SANDSTONE("SANDSTONE", 1), + CHISELED_STONE_BRICKS("SMOOTH_BRICK", 3), + CHORUS_FLOWER("CHORUS_FLOWER", 0), + CHORUS_FRUIT("CHORUS_FRUIT", 0), + CHORUS_PLANT("CHORUS_PLANT", 0), + CLAY("CLAY", 0), + CLAY_BALL("CLAY_BALL", 0), + CLOCK("WATCH", 0), + COAL("COAL", 0), + COAL_BLOCK("COAL_BLOCK", 0), + COAL_ORE("COAL_ORE", 0), + COARSE_DIRT("DIRT", 1), + COBBLESTONE("COBBLESTONE", 0), + COBBLESTONE_SLAB("STEP", 3), + COBBLESTONE_STAIRS("COBBLESTONE_STAIRS", 0), + COBBLESTONE_WALL("COBBLE_WALL", 0), + COBWEB("WEB", 0), + COCOA("COCOA", 0), + COCOA_BEANS("INK_SACK", 3), + COD("RAW_FISH", 0), + COD_BUCKET("BUCKET", 0), + COD_SPAWN_EGG("MONSTER_EGG", 0), + COMMAND_BLOCK("COMMAND", 0), + COMMAND_BLOCK_MINECART("COMMAND_MINECART", 0), + COMPARATOR("REDSTONE_COMPARATOR", 0), + COMPASS("COMPASS", 0), + CONDUIT("STONE", 0), + COOKED_BEEF("COOKED_BEEF", 0), + COOKED_CHICKEN("COOKED_CHICKEN", 0), + COOKED_COD("COOKED_FISH", 0), + COOKED_MUTTON("COOKED_MUTTON", 0), + COOKED_PORKCHOP("GRILLED_PORK", 0), + COOKED_RABBIT("COOKED_RABBIT", 0), + COOKED_SALMON("COOKED_FISH", 1), + COOKIE("COOKIE", 0), + COW_SPAWN_EGG("MONSTER_EGG", 0), + CRACKED_STONE_BRICKS("SMOOTH_BRICK", 2), + CRAFTING_TABLE("WORKBENCH", 0), + CREEPER_HEAD("SKULL", 0), + CREEPER_SPAWN_EGG("MONSTER_EGG", 0), + CREEPER_WALL_HEAD("SKULL", 0), + CUT_RED_SANDSTONE("STONE", 0), + CUT_SANDSTONE("STONE", 0), + CYAN_BANNER("BANNER", 6), + CYAN_BED("BED", 9), + CYAN_CARPET("CARPET", 9), + CYAN_CONCRETE("CONCRETE", 9), + CYAN_CONCRETE_POWDER("CONCRETE_POWDER", 9), + CYAN_DYE("INK_SACK", 6), + CYAN_GLAZED_TERRACOTTA("CYAN_GLAZED_TERRACOTTA", 0), + CYAN_SHULKER_BOX("CYAN_SHULKER_BOX", 0), + CYAN_STAINED_GLASS("STAINED_GLASS", 9), + CYAN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 9), + CYAN_TERRACOTTA("STAINED_CLAY", 9), + CYAN_WALL_BANNER("WALL_BANNER", 0), + CYAN_WOOL("WOOL", 9), + DAMAGED_ANVIL("ANVIL", 2), + DANDELION("YELLOW_FLOWER", 0), + DANDELION_YELLOW("INK_SACK", 11), + DARK_OAK_BOAT("BOAT_DARK_OAK", 0), + DARK_OAK_BUTTON("WOOD_BUTTON", 0), + DARK_OAK_DOOR("DARK_OAK_DOOR", 0), + DARK_OAK_FENCE("DARK_OAK_FENCE", 0), + DARK_OAK_FENCE_GATE("DARK_OAK_FENCE_GATE", 0), + DARK_OAK_LEAVES("LEAVES_2", 1), + DARK_OAK_LOG("LOG_2", 1), + DARK_OAK_PLANKS("WOOD", 5), + DARK_OAK_PRESSURE_PLATE("WOOD_PLATE", 0), + DARK_OAK_SAPLING("SAPLING", 5), + DARK_OAK_SLAB("WOOD_STEP", 0), + DARK_OAK_STAIRS("DARK_OAK_STAIRS", 0), + DARK_OAK_TRAPDOOR("TRAP_DOOR", 0), + DARK_OAK_WOOD("LOG_2", 1), + DARK_PRISMARINE("PRISMARINE", 2), + DARK_PRISMARINE_SLAB("STONE", 0), + DARK_PRISMARINE_STAIRS("STONE", 0), + DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR", 0), + DEAD_BRAIN_CORAL_BLOCK("STONE", 0), + DEAD_BUBBLE_CORAL_BLOCK("STONE", 0), + DEAD_BUSH("DEAD_BUSH", 0), + DEAD_FIRE_CORAL_BLOCK("STONE", 0), + DEAD_HORN_CORAL_BLOCK("STONE", 0), + DEAD_TUBE_CORAL_BLOCK("STONE", 0), + DEBUG_STICK("STICK", 0), + DETECTOR_RAIL("DETECTOR_RAIL", 0), + DIAMOND("DIAMOND", 0), + DIAMOND_AXE("DIAMOND_AXE", 0), + DIAMOND_BLOCK("DIAMOND_BLOCK", 0), + DIAMOND_BOOTS("DIAMOND_BOOTS", 0), + DIAMOND_CHESTPLATE("DIAMOND_CHESTPLATE", 0), + DIAMOND_HELMET("DIAMOND_HELMET", 0), + DIAMOND_HOE("DIAMOND_HOE", 0), + DIAMOND_HORSE_ARMOR("DIAMOND_BARDING", 0), + DIAMOND_LEGGINGS("DIAMOND_LEGGINGS", 0), + DIAMOND_ORE("DIAMOND_ORE", 0), + DIAMOND_PICKAXE("DIAMOND_PICKAXE", 0), + DIAMOND_SHOVEL("DIAMOND_SPADE", 0), + DIAMOND_SWORD("DIAMOND_SWORD", 0), + DIORITE("STONE", 3), + DIRT("DIRT", 0), + DISPENSER("DISPENSER", 0), + DOLPHIN_SPAWN_EGG("MONSTER_EGG", 0), + DONKEY_SPAWN_EGG("MONSTER_EGG", 0), + DRAGON_BREATH("DRAGONS_BREATH", 0), + DRAGON_EGG("DRAGON_EGG", 0), + DRAGON_HEAD("SKULL", 5), + DRAGON_WALL_HEAD("SKULL", 0), + DRIED_KELP("STONE", 0), + DRIED_KELP_BLOCK("STONE", 0), + DROPPER("DROPPER", 0), + DROWNED_SPAWN_EGG("MONSTER_EGG", 0), + EGG("EGG", 0), + ELDER_GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), + ELYTRA("ELYTRA", 0), + EMERALD("EMERALD", 0), + EMERALD_BLOCK("EMERALD_BLOCK", 0), + EMERALD_ORE("EMERALD_ORE", 0), + ENCHANTED_BOOK("ENCHANTED_BOOK", 0), + ENCHANTED_GOLDEN_APPLE("GOLDEN_APPLE", 1), + ENCHANTING_TABLE("ENCHANTING_TABLE", 0), + ENDERMAN_SPAWN_EGG("MONSTER_EGG", 0), + ENDERMITE_SPAWN_EGG("MONSTER_EGG", 0), + ENDER_CHEST("ENDER_CHEST", 0), + ENDER_EYE("EYE_OF_ENDER", 0), + ENDER_PEARL("ENDER_PEARL", 0), + END_CRYSTAL("END_CRYSTAL", 0), + END_GATEWAY("END_GATEWAY", 0), + END_PORTAL("ENDER_PORTAL", 0), + END_PORTAL_FRAME("ENDER_PORTAL_FRAME", 0), + END_ROD("END_ROD", 0), + END_STONE("ENDER_STONE", 0), + END_STONE_BRICKS("END_BRICKS", 0), + EVOKER_SPAWN_EGG("MONSTER_EGG", 0), + EXPERIENCE_BOTTLE("EXP_BOTTLE", 0), + FARMLAND("SOIL", 0), + FEATHER("FEATHER", 0), + FERMENTED_SPIDER_EYE("FERMENTED_SPIDER_EYE", 0), + FERN("LONG_GRASS", 2), + FILLED_MAP("MAP", 0), + FIRE("FIRE", 0), + FIREWORK_ROCKET("FIREWORK", 0), + FIREWORK_STAR("FIREWORK_CHARGE", 0), + FIRE_CHARGE("FIREBALL", 0), + FIRE_CORAL("STONE", 0), + FIRE_CORAL_BLOCK("STONE", 0), + FIRE_CORAL_FAN("STONE", 0), + FISHING_ROD("FISHING_ROD", 0), + FLINT("FLINT", 0), + FLINT_AND_STEEL("FLINT_AND_STEEL", 0), + FLOWER_POT("FLOWER_POT", 0), + FROSTED_ICE("FROSTED_ICE", 0), + FURNACE("FURNACE", 0), + FURNACE_MINECART("POWERED_MINECART", 0), + GHAST_SPAWN_EGG("MONSTER_EGG", 0), + GHAST_TEAR("GHAST_TEAR", 0), + GLASS("GLASS", 0), + GLASS_BOTTLE("GLASS_BOTTLE", 0), + GLASS_PANE("THIN_GLASS", 0), + GLISTERING_MELON_SLICE("SPECKLED_MELON", 0), + GLOWSTONE("GLOWSTONE", 0), + GLOWSTONE_DUST("GLOWSTONE_DUST", 0), + GOLDEN_APPLE("GOLDEN_APPLE", 0), + GOLDEN_AXE("GOLD_AXE", 0), + GOLDEN_BOOTS("GOLD_BOOTS", 0), + GOLDEN_CARROT("GOLDEN_CARROT", 0), + GOLDEN_CHESTPLATE("GOLD_CHESTPLATE", 0), + GOLDEN_HELMET("GOLD_HELMET", 0), + GOLDEN_HOE("GOLD_HOE", 0), + GOLDEN_HORSE_ARMOR("GOLD_BARDING", 0), + GOLDEN_LEGGINGS("GOLD_LEGGINGS", 0), + GOLDEN_PICKAXE("GOLD_PICKAXE", 0), + GOLDEN_SHOVEL("GOLD_SPADE", 0), + GOLDEN_SWORD("GOLD_SWORD", 0), + GOLD_BLOCK("GOLD_BLOCK", 0), + GOLD_INGOT("GOLD_INGOT", 0), + GOLD_NUGGET("GOLD_NUGGET", 0), + GOLD_ORE("GOLD_ORE", 0), + GRANITE("STONE", 1), + GRASS("GRASS", 0), + GRASS_BLOCK("GRASS", 0), + GRASS_PATH("GRASS_PATH", 0), + GRAVEL("GRAVEL", 0), + GRAY_BANNER("BANNER", 8), + GRAY_BED("BED", 7), + GRAY_CARPET("CARPET", 7), + GRAY_CONCRETE("CONCRETE", 7), + GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 7), + GRAY_DYE("INK_SACK", 8), + GRAY_GLAZED_TERRACOTTA("GRAY_GLAZED_TERRACOTTA", 0), + GRAY_SHULKER_BOX("GRAY_SHULKER_BOX", 0), + GRAY_STAINED_GLASS("STAINED_GLASS", 7), + GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 7), + GRAY_TERRACOTTA("STAINED_CLAY", 7), + GRAY_WALL_BANNER("WALL_BANNER", 0), + GRAY_WOOL("WOOL", 7), + GREEN_BANNER("BANNER", 2), + GREEN_BED("BED", 13), + GREEN_CARPET("CARPET", 13), + GREEN_CONCRETE("CONCRETE", 13), + GREEN_CONCRETE_POWDER("CONCRETE_POWDER", 13), + GREEN_GLAZED_TERRACOTTA("GREEN_GLAZED_TERRACOTTA", 0), + GREEN_SHULKER_BOX("GREEN_SHULKER_BOX", 0), + GREEN_STAINED_GLASS("STAINED_GLASS", 13), + GREEN_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 13), + GREEN_TERRACOTTA("STAINED_CLAY", 13), + GREEN_WALL_BANNER("WALL_BANNER", 0), + GREEN_WOOL("WOOL", 13), + GUARDIAN_SPAWN_EGG("MONSTER_EGG", 0), + GUNPOWDER("SULPHUR", 0), + HAY_BLOCK("HAY_BLOCK", 0), + HEART_OF_THE_SEA("STONE", 0), + HEAVY_WEIGHTED_PRESSURE_PLATE("IRON_PLATE", 0), + HOPPER("HOPPER", 0), + HOPPER_MINECART("HOPPER_MINECART", 0), + HORN_CORAL("STONE", 0), + HORN_CORAL_BLOCK("STONE", 0), + HORN_CORAL_FAN("STONE", 0), + HORSE_SPAWN_EGG("MONSTER_EGG", 0), + HUSK_SPAWN_EGG("MONSTER_EGG", 0), + ICE("ICE", 0), + INFESTED_CHISELED_STONE_BRICKS("MONSTER_EGGS", 5), + INFESTED_COBBLESTONE("MONSTER_EGGS", 1), + INFESTED_CRACKED_STONE_BRICKS("MONSTER_EGGS", 4), + INFESTED_MOSSY_STONE_BRICKS("MONSTER_EGGS", 3), + INFESTED_STONE("MONSTER_EGGS", 0), + INFESTED_STONE_BRICKS("MONSTER_EGGS", 2), + INK_SAC("INK_SACK", 0), + IRON_AXE("IRON_AXE", 0), + IRON_BARS("IRON_FENCE", 0), + IRON_BLOCK("IRON_BLOCK", 0), + IRON_BOOTS("IRON_BOOTS", 0), + IRON_CHESTPLATE("IRON_CHESTPLATE", 0), + IRON_DOOR("IRON_DOOR", 0), + IRON_HELMET("IRON_HELMET", 0), + IRON_HOE("IRON_HOE", 0), + IRON_HORSE_ARMOR("IRON_BARDING", 0), + IRON_INGOT("IRON_INGOT", 0), + IRON_LEGGINGS("IRON_LEGGINGS", 0), + IRON_NUGGET("IRON_NUGGET", 0), + IRON_ORE("IRON_ORE", 0), + IRON_PICKAXE("IRON_PICKAXE", 0), + IRON_SHOVEL("IRON_SPADE", 0), + IRON_SWORD("IRON_SWORD", 0), + IRON_TRAPDOOR("IRON_TRAPDOOR", 0), + ITEM_FRAME("ITEM_FRAME", 0), + JACK_O_LANTERN("JACK_O_LANTERN", 0), + JUKEBOX("JUKEBOX", 0), + JUNGLE_BOAT("BOAT_JUNGLE", 0), + JUNGLE_BUTTON("WOOD_BUTTON", 0), + JUNGLE_DOOR("JUNGLE_DOOR", 0), + JUNGLE_FENCE("JUNGLE_FENCE", 0), + JUNGLE_FENCE_GATE("JUNGLE_FENCE_GATE", 0), + JUNGLE_LEAVES("LEAVES", 3), + JUNGLE_LOG("LOG", 3), + JUNGLE_PLANKS("WOOD", 3), + JUNGLE_PRESSURE_PLATE("WOOD_PLATE", 0), + JUNGLE_SAPLING("SAPLING", 3), + JUNGLE_SLAB("WOOD_STEP", 3), + JUNGLE_STAIRS("JUNGLE_WOOD_STAIRS", 0), + JUNGLE_TRAPDOOR("TRAP_DOOR", 0), + JUNGLE_WOOD("LOG", 3), + KELP("STONE", 0), + KELP_PLANT("STONE", 0), + KNOWLEDGE_BOOK("KNOWLEDGE_BOOK", 0), + LADDER("LADDER", 0), + LAPIS_BLOCK("LAPIS_BLOCK", 0), + LAPIS_LAZULI("INK_SACK", 4), + LAPIS_ORE("LAPIS_ORE", 0), + LARGE_FERN("DOUBLE_PLANT", 3), + LAVA("LAVA", 0), + LAVA_BUCKET("LAVA_BUCKET", 0), + LEAD("LEASH", 0), + LEATHER("LEATHER", 0), + LEATHER_BOOTS("LEATHER_BOOTS", 0), + LEATHER_CHESTPLATE("LEATHER_CHESTPLATE", 0), + LEATHER_HELMET("LEATHER_HELMET", 0), + LEATHER_LEGGINGS("LEATHER_LEGGINGS", 0), + LEVER("LEVER", 0), + LIGHT_BLUE_BANNER("BANNER", 12), + LIGHT_BLUE_BED("BED", 3), + LIGHT_BLUE_CARPET("CARPET", 3), + LIGHT_BLUE_CONCRETE("CONCRETE", 3), + LIGHT_BLUE_CONCRETE_POWDER("CONCRETE_POWDER", 3), + LIGHT_BLUE_DYE("INK_SACK", 12), + LIGHT_BLUE_GLAZED_TERRACOTTA("LIGHT_BLUE_GLAZED_TERRACOTTA", 0), + LIGHT_BLUE_SHULKER_BOX("LIGHT_BLUE_SHULKER_BOX", 0), + LIGHT_BLUE_STAINED_GLASS("STAINED_GLASS", 3), + LIGHT_BLUE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 3), + LIGHT_BLUE_TERRACOTTA("STAINED_CLAY", 3), + LIGHT_BLUE_WALL_BANNER("BANNER", 0), + LIGHT_BLUE_WOOL("WOOL", 3), + LIGHT_GRAY_BANNER("BANNER", 7), + LIGHT_GRAY_BED("BED", 8), + LIGHT_GRAY_CARPET("CARPET", 8), + LIGHT_GRAY_CONCRETE("CONCRETE", 8), + LIGHT_GRAY_CONCRETE_POWDER("CONCRETE_POWDER", 8), + LIGHT_GRAY_DYE("INK_SACK", 7), + LIGHT_GRAY_GLAZED_TERRACOTTA("SILVER_GLAZED_TERRACOTTA", 0), + LIGHT_GRAY_SHULKER_BOX("SILVER_SHULKER_BOX", 0), + LIGHT_GRAY_STAINED_GLASS("STAINED_GLASS", 8), + LIGHT_GRAY_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 8), + LIGHT_GRAY_TERRACOTTA("STAINED_CLAY", 8), + LIGHT_GRAY_WALL_BANNER("WALL_BANNER", 0), + LIGHT_GRAY_WOOL("WOOL", 8), + LIGHT_WEIGHTED_PRESSURE_PLATE("GOLD_PLATE", 0), + LILAC("DOUBLE_PLANT", 1), + LILY_PAD("WATER_LILY", 0), + LIME_BANNER("BANNER", 10), + LIME_BED("BED", 5), + LIME_CARPET("CARPET", 5), + LIME_CONCRETE("CONCRETE", 5), + LIME_CONCRETE_POWDER("CONCRETE_POWDER", 5), + LIME_DYE("INK_SACK", 10), + LIME_GLAZED_TERRACOTTA("LIME_GLAZED_TERRACOTTA", 0), + LIME_SHULKER_BOX("LIME_SHULKER_BOX", 0), + LIME_STAINED_GLASS("STAINED_GLASS", 5), + LIME_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 5), + LIME_TERRACOTTA("STAINED_CLAY", 5), + LIME_WALL_BANNER("WALL_BANNER", 0), + LIME_WOOL("WOOL", 5), + LINGERING_POTION("LINGERING_POTION", 0), + LLAMA_SPAWN_EGG("MONSTER_EGG", 0), + MAGENTA_BANNER("BANNER", 13), + MAGENTA_BED("BED", 2), + MAGENTA_CARPET("CARPET", 2), + MAGENTA_CONCRETE("CONCRETE", 2), + MAGENTA_CONCRETE_POWDER("CONCRETE_POWDER", 2), + MAGENTA_DYE("INK_SACK", 13), + MAGENTA_GLAZED_TERRACOTTA("MAGENTA_GLAZED_TERRACOTTA", 0), + MAGENTA_SHULKER_BOX("MAGENTA_SHULKER_BOX", 0), + MAGENTA_STAINED_GLASS("STAINED_GLASS", 2), + MAGENTA_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 2), + MAGENTA_TERRACOTTA("STAINED_CLAY", 2), + MAGENTA_WALL_BANNER("WALL_BANNER", 0), + MAGENTA_WOOL("WOOL", 2), + MAGMA_BLOCK("MAGMA", 0), + MAGMA_CREAM("MAGMA_CREAM", 0), + MAGMA_CUBE_SPAWN_EGG("MONSTER_EGG", 0), + MAP("MAP", 0), + MELON("MELON_BLOCK", 0), + MELON_SEEDS("MELON_SEEDS", 0), + MELON_SLICE("MELON", 0), + MELON_STEM("MELON_STEM", 0), + MILK_BUCKET("MILK_BUCKET", 0), + MINECART("MINECART", 0), + MOOSHROOM_SPAWN_EGG("MONSTER_EGG", 0), + MOSSY_COBBLESTONE("MOSSY_COBBLESTONE", 0), + MOSSY_COBBLESTONE_WALL("COBBLE_WALL", 1), + MOSSY_STONE_BRICKS("SMOOTH_BRICK", 1), + MOVING_PISTON("PISTON_MOVING_PIECE", 0), + MULE_SPAWN_EGG("MONSTER_EGG", 0), + MUSHROOM_STEM("BROWN_MUSHROOM", 0), + MUSHROOM_STEW("MUSHROOM_SOUP", 0), + MUSIC_DISC_11("GOLD_RECORD", 0), + MUSIC_DISC_13("GREEN_RECORD", 0), + MUSIC_DISC_BLOCKS("RECORD_3", 0), + MUSIC_DISC_CAT("RECORD_4", 0), + MUSIC_DISC_CHIRP("RECORD_5", 0), + MUSIC_DISC_FAR("RECORD_6", 0), + MUSIC_DISC_MALL("RECORD_7", 0), + MUSIC_DISC_MELLOHI("RECORD_8", 0), + MUSIC_DISC_STAL("RECORD_9", 0), + MUSIC_DISC_STRAD("RECORD_10", 0), + MUSIC_DISC_WAIT("RECORD_11", 0), + MUSIC_DISC_WARD("RECORD_12", 0), + MUTTON("MUTTON", 0), + MYCELIUM("MYCEL", 0), + NAME_TAG("NAME_TAG", 0), + NAUTILUS_SHELL("STONE", 0), + NETHERRACK("NETHERRACK", 0), + NETHER_BRICK("NETHER_BRICK", 0), + NETHER_BRICKS("NETHER_BRICK", 0), + NETHER_BRICK_FENCE("NETHER_FENCE", 0), + NETHER_BRICK_SLAB("STEP", 6), + NETHER_BRICK_STAIRS("NETHER_BRICK_STAIRS", 0), + NETHER_PORTAL("PORTAL", 0), + NETHER_QUARTZ_ORE("QUARTZ_ORE", 0), + NETHER_STAR("NETHER_STAR", 0), + NETHER_WART("NETHER_STALK", 0), + NETHER_WART_BLOCK("NETHER_WART_BLOCK", 0), + NOTE_BLOCK("NOTE_BLOCK", 0), + OAK_BOAT("BOAT", 0), + OAK_BUTTON("WOOD_BUTTON", 0), + OAK_DOOR("WOOD_DOOR", 0), + OAK_FENCE("FENCE", 0), + OAK_FENCE_GATE("FENCE_GATE", 0), + OAK_LEAVES("LEAVES", 0), + OAK_LOG("LOG", 0), + OAK_PLANKS("WOOD", 0), + OAK_PRESSURE_PLATE("WOOD_PLATE", 0), + OAK_SAPLING("SAPLING", 0), + OAK_SLAB("WOOD_STEP", 0), + OAK_STAIRS("WOOD_STAIRS", 0), + OAK_TRAPDOOR("TRAP_DOOR", 0), + OAK_WOOD("LOG", 0), + OBSERVER("OBSERVER", 0), + OBSIDIAN("OBSIDIAN", 0), + OCELOT_SPAWN_EGG("RECORD_12", 0), + ORANGE_BANNER("BANNER", 14), + ORANGE_BED("BED", 1), + ORANGE_CARPET("CARPET", 1), + ORANGE_CONCRETE("CONCRETE", 1), + ORANGE_CONCRETE_POWDER("CONCRETE_POWDER", 1), + ORANGE_DYE("INK_SACK", 14), + ORANGE_GLAZED_TERRACOTTA("ORANGE_GLAZED_TERRACOTTA", 0), + ORANGE_SHULKER_BOX("ORANGE_SHULKER_BOX", 0), + ORANGE_STAINED_GLASS("STAINED_GLASS", 1), + ORANGE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 1), + ORANGE_TERRACOTTA("STAINED_CLAY", 1), + ORANGE_TULIP("RED_ROSE", 5), + ORANGE_WALL_BANNER("WALL_BANNER", 0), + ORANGE_WOOL("WOOL", 1), + OXEYE_DAISY("RED_ROSE", 8), + PACKED_ICE("PACKED_ICE", 0), + PAINTING("PAINTING", 0), + PAPER("PAPER", 0), + PARROT_SPAWN_EGG("MONSTER_EGG", 0), + PEONY("DOUBLE_PLANT", 5), + PETRIFIED_OAK_SLAB("STONE", 0), + PHANTOM_MEMBRANE("STONE", 0), + PHANTOM_SPAWN_EGG("MONSTER_EGG", 0), + PIG_SPAWN_EGG("MONSTER_EGG", 0), + PINK_BANNER("BANNER", 9), + PINK_BED("BED", 6), + PINK_CARPET("CARPET", 6), + PINK_CONCRETE("CONCRETE", 6), + PINK_CONCRETE_POWDER("CONCRETE_POWDER", 6), + PINK_DYE("INK_SACK", 9), + PINK_GLAZED_TERRACOTTA("PINK_GLAZED_TERRACOTTA", 0), + PINK_SHULKER_BOX("PINK_SHULKER_BOX", 0), + PINK_STAINED_GLASS("STAINED_GLASS", 6), + PINK_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 6), + PINK_TERRACOTTA("STAINED_CLAY", 6), + PINK_TULIP("RED_ROSE", 7), + PINK_WALL_BANNER("WALL_BANNER", 0), + PINK_WOOL("WOOL", 6), + PISTON("PISTON_BASE", 0), + PISTON_HEAD("PISTON_EXTENSION", 0), + PLAYER_HEAD("SKULL", 0), + PLAYER_WALL_HEAD("SKULL", 0), + PODZOL("DIRT", 2), + POISONOUS_POTATO("POISONOUS_POTATO", 0), + POLAR_BEAR_SPAWN_EGG("MONSTER_EGG", 0), + POLISHED_ANDESITE("STONE", 6), + POLISHED_DIORITE("STONE", 4), + POLISHED_GRANITE("STONE", 2), + POPPED_CHORUS_FRUIT("CHORUS_FRUIT_POPPED", 0), + POPPY("RED_ROSE", 0), + PORKCHOP("PORK", 0), + POTATO("POTATO_ITEM", 0), + POTATOES("POTATO", 0), + POTION("POTION", 0), + POTTED_ACACIA_SAPLING("FLOWER_POT", 0), + POTTED_ALLIUM("FLOWER_POT", 0), + POTTED_AZURE_BLUET("FLOWER_POT", 0), + POTTED_BIRCH_SAPLING("FLOWER_POT", 0), + POTTED_BLUE_ORCHID("FLOWER_POT", 0), + POTTED_BROWN_MUSHROOM("FLOWER_POT", 0), + POTTED_CACTUS("FLOWER_POT", 0), + POTTED_DANDELION("FLOWER_POT", 0), + POTTED_DARK_OAK_SAPLING("FLOWER_POT", 0), + POTTED_DEAD_BUSH("FLOWER_POT", 0), + POTTED_FERN("FLOWER_POT", 0), + POTTED_JUNGLE_SAPLING("FLOWER_POT", 0), + POTTED_OAK_SAPLING("FLOWER_POT", 0), + POTTED_ORANGE_TULIP("FLOWER_POT", 0), + POTTED_OXEYE_DAISY("FLOWER_POT", 0), + POTTED_PINK_TULIP("FLOWER_POT", 0), + POTTED_POPPY("FLOWER_POT", 0), + POTTED_RED_MUSHROOM("FLOWER_POT", 0), + POTTED_RED_TULIP("FLOWER_POT", 0), + POTTED_SPRUCE_SAPLING("FLOWER_POT", 0), + POTTED_WHITE_TULIP("FLOWER_POT", 0), + POWERED_RAIL("POWERED_RAIL", 0), + PRISMARINE("PRISMARINE", 0), + PRISMARINE_BRICKS("PRISMARINE", 1), + PRISMARINE_BRICK_SLAB("STONE", 0), + PRISMARINE_BRICK_STAIRS("STONE", 0), + PRISMARINE_CRYSTALS("PRISMARINE_CRYSTALS", 0), + PRISMARINE_SHARD("PRISMARINE_SHARD", 0), + PRISMARINE_SLAB("STONE", 0), + PRISMARINE_STAIRS("STONE", 0), + PUFFERFISH("RAW_FISH", 3), + PUFFERFISH_BUCKET("STONE", 0), + PUFFERFISH_SPAWN_EGG("MONSTER_EGG", 0), + PUMPKIN("PUMPKIN", 0), + PUMPKIN_PIE("PUMPKIN_PIE", 0), + PUMPKIN_SEEDS("PUMPKIN_SEEDS", 0), + PUMPKIN_STEM("PUMPKIN_STEM", 0), + PURPLE_BANNER("BANNER", 5), + PURPLE_BED("BED", 10), + PURPLE_CARPET("CARPET", 10), + PURPLE_CONCRETE("CONCRETE", 10), + PURPLE_CONCRETE_POWDER("CONCRETE_POWDER", 10), + PURPLE_DYE("INK_SACK", 5), + PURPLE_GLAZED_TERRACOTTA("PURPLE_GLAZED_TERRACOTTA", 0), + PURPLE_SHULKER_BOX("PURPLE_SHULKER_BOX", 0), + PURPLE_STAINED_GLASS("STAINED_GLASS", 10), + PURPLE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 10), + PURPLE_TERRACOTTA("STAINED_CLAY", 10), + PURPLE_WALL_BANNER("WALL_BANNER", 0), + PURPLE_WOOL("WOOL", 10), + PURPUR_BLOCK("PURPUR_BLOCK", 0), + PURPUR_PILLAR("PURPUR_PILLAR", 0), + PURPUR_SLAB("PURPUR_SLAB", 0), + PURPUR_STAIRS("PURPUR_STAIRS", 0), + QUARTZ("QUARTZ", 0), + QUARTZ_BLOCK("QUARTZ_BLOCK", 0), + QUARTZ_PILLAR("QUARTZ_BLOCK", 2), + QUARTZ_SLAB("STEP", 7), + QUARTZ_STAIRS("QUARTZ_STAIRS", 0), + RABBIT("RABBIT", 0), + RABBIT_FOOT("RABBIT_FOOT", 0), + RABBIT_HIDE("RABBIT_HIDE", 0), + RABBIT_SPAWN_EGG("MONSTER_EGG", 0), + RABBIT_STEW("RABBIT_STEW", 0), + RAIL("RAILS", 0), + REDSTONE("REDSTONE", 0), + REDSTONE_BLOCK("REDSTONE_BLOCK", 0), + REDSTONE_LAMP("REDSTONE_LAMP_OFF", 0), + REDSTONE_ORE("REDSTONE_ORE", 0), + REDSTONE_TORCH("REDSTONE_TORCH_ON", 0), + REDSTONE_WALL_TORCH("REDSTONE_TORCH_ON", 1), + REDSTONE_WIRE("REDSTONE_WIRE", 0), + RED_BANNER("BANNER", 1), + RED_BED("BED", 14), + RED_CARPET("CARPET", 14), + RED_CONCRETE("CONCRETE", 14), + RED_CONCRETE_POWDER("CONCRETE_POWDER", 14), + RED_GLAZED_TERRACOTTA("RED_GLAZED_TERRACOTTA", 0), + RED_MUSHROOM("RED_MUSHROOM", 0), + RED_MUSHROOM_BLOCK("RED_MUSHROOM", 0), + RED_NETHER_BRICKS("RED_NETHER_BRICK", 0), + RED_SAND("SAND", 1), + RED_SANDSTONE("RED_SANDSTONE", 0), + RED_SANDSTONE_SLAB("STONE_SLAB2", 0), + RED_SANDSTONE_STAIRS("RED_SANDSTONE_STAIRS", 0), + RED_SHULKER_BOX("RED_SHULKER_BOX", 0), + RED_STAINED_GLASS("STAINED_GLASS", 14), + RED_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 14), + RED_TERRACOTTA("STAINED_CLAY", 14), + RED_TULIP("RED_ROSE", 4), + RED_WALL_BANNER("WALL_BANNER", 0), + RED_WOOL("WOOL", 14), + REPEATER("DIODE", 0), + REPEATING_COMMAND_BLOCK("COMMAND_REPEATING", 0), + ROSE_BUSH("DOUBLE_PLANT", 4), + ROSE_RED("INK_SACK", 1), + ROTTEN_FLESH("ROTTEN_FLESH", 0), + SADDLE("SADDLE", 0), + SALMON("RAW_FISH", 1), + SALMON_BUCKET("BUCKET", 0), + SALMON_SPAWN_EGG("MONSTER_EGG", 0), + SAND("SAND", 0), + SANDSTONE("SANDSTONE", 0), + SANDSTONE_SLAB("STEP", 1), + SANDSTONE_STAIRS("SANDSTONE_STAIRS", 0), + SCUTE("STONE", 0), + SEAGRASS("STONE", 0), + SEA_LANTERN("SEA_LANTERN", 0), + SEA_PICKLE("STONE", 0), + SHEARS("SHEARS", 0), + SHEEP_SPAWN_EGG("MONSTER_EGG", 0), + SHIELD("SHIELD", 0), + SHULKER_BOX("PURPLE_SHULKER_BOX", 0), + SHULKER_SHELL("SHULKER_SHELL", 0), + SHULKER_SPAWN_EGG("MONSTER_EGG", 0), + SIGN("SIGN", 0), + SILVERFISH_SPAWN_EGG("MONSTER_EGG", 0), + SKELETON_HORSE_SPAWN_EGG("MONSTER_EGG", 0), + SKELETON_SKULL("SKULL", 0), + SKELETON_SPAWN_EGG("MONSTER_EGG", 0), + SKELETON_WALL_SKULL("SKULL", 0), + SLIME_BALL("SLIME_BALL", 0), + SLIME_BLOCK("SLIME_BLOCK", 0), + SLIME_SPAWN_EGG("MONSTER_EGG", 0), + SMOOTH_QUARTZ("STONE", 0), + SMOOTH_RED_SANDSTONE("RED_SANDSTONE", 2), + SMOOTH_SANDSTONE("SANDSTONE", 2), + SMOOTH_STONE("STEP", 0), + SNOW("SNOW", 0), + SNOWBALL("SNOW_BALL", 0), + SNOW_BLOCK("SNOW_BLOCK", 0), + SOUL_SAND("SOUL_SAND", 0), + SPAWNER("MOB_SPAWNER", 0), + SPECTRAL_ARROW("SPECTRAL_ARROW", 0), + SPIDER_EYE("SPIDER_EYE", 0), + SPIDER_SPAWN_EGG("MONSTER_EGG", 0), + SPLASH_POTION("SPLASH_POTION", 0), + SPONGE("SPONGE", 0), + SPRUCE_BOAT("BOAT_SPRUCE", 0), + SPRUCE_BUTTON("WOOD_BUTTON", 0), + SPRUCE_DOOR("SPRUCE_DOOR", 0), + SPRUCE_FENCE("SPRUCE_FENCE", 0), + SPRUCE_FENCE_GATE("SPRUCE_FENCE_GATE", 0), + SPRUCE_LEAVES("LEAVES", 1), + SPRUCE_LOG("LOG", 1), + SPRUCE_PLANKS("WOOD", 1), + SPRUCE_PRESSURE_PLATE("WOOD_PLATE", 0), + SPRUCE_SAPLING("SAPLING", 1), + SPRUCE_SLAB("WOOD_STEP", 1), + SPRUCE_STAIRS("SPRUCE_WOOD_STAIRS", 0), + SPRUCE_TRAPDOOR("TRAP_DOOR", 0), + SPRUCE_WOOD("LOG", 1), + SQUID_SPAWN_EGG("MONSTER_EGG", 0), + STICK("STICK", 0), + STICKY_PISTON("PISTON_STICKY_BASE", 0), + STONE("STONE", 0), + STONE_AXE("STONE_AXE", 0), + STONE_BRICKS("SMOOTH_BRICK", 0), + STONE_BRICK_SLAB("STEP", 5), + STONE_BRICK_STAIRS("SMOOTH_STAIRS", 0), + STONE_BUTTON("STONE_BUTTON", 0), + STONE_HOE("STONE_HOE", 0), + STONE_PICKAXE("STONE_PICKAXE", 0), + STONE_PRESSURE_PLATE("STONE_PLATE", 0), + STONE_SHOVEL("STONE_SPADE", 0), + STONE_SLAB("STEP", 0), + STONE_SWORD("STONE_SWORD", 0), + STRAY_SPAWN_EGG("MONSTER_EGG", 0), + STRING("STRING", 0), + STRIPPED_ACACIA_LOG("STONE", 0), + STRIPPED_ACACIA_WOOD("STONE", 0), + STRIPPED_BIRCH_LOG("STONE", 0), + STRIPPED_BIRCH_WOOD("STONE", 0), + STRIPPED_DARK_OAK_LOG("STONE", 0), + STRIPPED_DARK_OAK_WOOD("STONE", 0), + STRIPPED_JUNGLE_LOG("STONE", 0), + STRIPPED_JUNGLE_WOOD("STONE", 0), + STRIPPED_OAK_LOG("STONE", 0), + STRIPPED_OAK_WOOD("STONE", 0), + STRIPPED_SPRUCE_LOG("STONE", 0), + STRIPPED_SPRUCE_WOOD("STONE", 0), + STRUCTURE_BLOCK("STRUCTURE_BLOCK", 0), + STRUCTURE_VOID("STRUCTURE_VOID", 0), + SUGAR("SUGAR", 0), + SUGAR_CANE("SUGAR_CANE", 0), + SUNFLOWER("DOUBLE_PLANT", 0), + TALL_GRASS("DOUBLE_PLANT", 2), + TALL_SEAGRASS("STONE", 0), + TERRACOTTA("HARD_CLAY", 0), + TIPPED_ARROW("TIPPED_ARROW", 0), + TNT("TNT", 0), + TNT_MINECART("EXPLOSIVE_MINECART", 0), + TORCH("TORCH", 0), + TOTEM_OF_UNDYING("TOTEM", 0), + TRAPPED_CHEST("TRAPPED_CHEST", 0), + TRIDENT("STONE", 0), + TRIPWIRE("TRIPWIRE", 0), + TRIPWIRE_HOOK("TRIPWIRE_HOOK", 0), + TROPICAL_FISH("RAW_FISH", 0), + TROPICAL_FISH_BUCKET("BUCKET", 0), + TROPICAL_FISH_SPAWN_EGG("MONSTER_EGG", 0), + TUBE_CORAL("STONE", 0), + TUBE_CORAL_BLOCK("STONE", 0), + TUBE_CORAL_FAN("STONE", 0), + TURTLE_EGG("MONSTER_EGG", 0), + TURTLE_HELMET("STONE", 0), + TURTLE_SPAWN_EGG("MONSTER_EGG", 0), + VEX_SPAWN_EGG("MONSTER_EGG", 0), + VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), + VINDICATOR_SPAWN_EGG("MONSTER_EGG", 0), + VINE("VINE", 0), + VOID_AIR("AIR", 0), + WALL_SIGN("WALL_SIGN", 0), + WALL_TORCH("TORCH", 1), + WATER("WATER", 0), + WATER_BUCKET("WATER_BUCKET", 0), + WET_SPONGE("SPONGE", 1), + WHEAT("WHEAT", 0), + WHEAT_SEEDS("SEEDS", 0), + WHITE_BANNER("BANNER", 15), + WHITE_BED("BED", 0), + WHITE_CARPET("CARPET", 0), + WHITE_CONCRETE("CONCRETE", 0), + WHITE_CONCRETE_POWDER("CONCRETE_POWDER", 0), + WHITE_GLAZED_TERRACOTTA("WHITE_GLAZED_TERRACOTTA", 0), + WHITE_SHULKER_BOX("WHITE_SHULKER_BOX", 0), + WHITE_STAINED_GLASS("STAINED_GLASS", 0), + WHITE_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 0), + WHITE_TERRACOTTA("TERRACOTTA", 0), + WHITE_TULIP("RED_ROSE", 6), + WHITE_WALL_BANNER("WALL_BANNER", 0), + WHITE_WOOL("WOOL", 0), + WITCH_SPAWN_EGG("MONSTER_EGG", 0), + WITHER_SKELETON_SKULL("SKULL", 0), + WITHER_SKELETON_SPAWN_EGG("MONSTER_EGG", 0), + WITHER_SKELETON_WALL_SKULL("SKULL", 0), + WOLF_SPAWN_EGG("MONSTER_EGG", 0), + WOODEN_AXE("WOOD_AXE", 0), + WOODEN_HOE("WOOD_HOE", 0), + WOODEN_PICKAXE("WOOD_PICKAXE", 0), + WOODEN_SHOVEL("WOOD_SPADE", 0), + WOODEN_SWORD("WOOD_SWORD", 0), + WRITABLE_BOOK("BOOK_AND_QUILL", 0), + WRITTEN_BOOK("WRITTEN_BOOK", 0), + YELLOW_BANNER("BANNER", 11), + YELLOW_BED("BED", 4), + YELLOW_CARPET("CARPET", 4), + YELLOW_CONCRETE("CONCRETE", 4), + YELLOW_CONCRETE_POWDER("CONCRETE_POWDER", 4), + YELLOW_GLAZED_TERRACOTTA("YELLOW_GLAZED_TERRACOTTA", 0), + YELLOW_SHULKER_BOX("YELLOW_SHULKER_BOX", 0), + YELLOW_STAINED_GLASS("STAINED_GLASS", 4), + YELLOW_STAINED_GLASS_PANE("STAINED_GLASS_PANE", 4), + YELLOW_TERRACOTTA("STAINED_CLAY", 4), + YELLOW_WALL_BANNER("WALL_BANNER", 0), + YELLOW_WOOL("WOOL", 4), + ZOMBIE_HEAD("SKULL", 0), + ZOMBIE_HORSE_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_PIGMAN_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_VILLAGER_SPAWN_EGG("MONSTER_EGG", 0), + ZOMBIE_WALL_HEAD("SKULL", 0), + ; - static int newV = -1; - private static HashMap cachedSearch = new HashMap<>(); - String m; - int data; + static int newV = -1; + private static HashMap cachedSearch = new HashMap<>(); + String m; + int data; - MultiversionMaterials(String m, int data) { - this.m = m; - this.data = data; - } + MultiversionMaterials(String m, int data) { + this.m = m; + this.data = data; + } - public static boolean isNewVersion() { - if (newV == 0) return false; - if (newV == 1) return true; + public static boolean isNewVersion() { + if (newV == 0) return false; + if (newV == 1) return true; - Material mat = Material.matchMaterial("RED_WOOL"); - if (mat != null) { - newV = 1; - return true; - } + Material mat = Material.matchMaterial("RED_WOOL"); + if (mat != null) { + newV = 1; + return true; + } - newV = 0; - return false; - } + newV = 0; + return false; + } - public static MultiversionMaterials requestXMaterial(String name, byte data) { - if (cachedSearch.containsKey(name.toUpperCase() + "," + data)) { - return cachedSearch.get(name.toUpperCase() + "," + data); - } - for (MultiversionMaterials mat : MultiversionMaterials.values()) { - if (name.toUpperCase().equals(mat.m) && ((byte) mat.data) == data) { - cachedSearch.put(mat.m + "," + data, mat); - return mat; - } - } - return null; - } + public static MultiversionMaterials requestXMaterial(String name, byte data) { + if (cachedSearch.containsKey(name.toUpperCase() + "," + data)) { + return cachedSearch.get(name.toUpperCase() + "," + data); + } + for (MultiversionMaterials mat : MultiversionMaterials.values()) { + if (name.toUpperCase().equals(mat.m) && ((byte) mat.data) == data) { + cachedSearch.put(mat.m + "," + data, mat); + return mat; + } + } + return null; + } - public static MultiversionMaterials fromString(String key) { - try { - return MultiversionMaterials.valueOf(key); - } catch (IllegalArgumentException e) { - String[] split = key.split(":"); + public static MultiversionMaterials fromString(String key) { + try { + return MultiversionMaterials.valueOf(key); + } catch (IllegalArgumentException e) { + String[] split = key.split(":"); - return split.length == 1 ? requestXMaterial(key, (byte) 0) : requestXMaterial(split[0], (byte) Integer.parseInt(split[1])); - } - } + return split.length == 1 ? requestXMaterial(key, (byte) 0) : requestXMaterial(split[0], (byte) Integer.parseInt(split[1])); + } + } - public ItemStack parseItem() { - Material mat = parseMaterial(); - if (isNewVersion()) { - return new ItemStack(mat); - } - return new ItemStack(mat, 1, (byte) data); - } + public ItemStack parseItem() { + Material mat = parseMaterial(); + if (isNewVersion()) { + return new ItemStack(mat); + } + return new ItemStack(mat, 1, (byte) data); + } - public boolean isSameMaterial(ItemStack comp) { - if (isNewVersion()) { - return comp.getType() == this.parseMaterial(); - } - if (comp.getType() == this.parseMaterial() && - (int) comp.getData().getData() == this.data) { - return true; - } - MultiversionMaterials xmat = fromMaterial(comp.getType()); - if (isDamageable(xmat)) { - return this.parseMaterial() == comp.getType(); - } - return false; - } + public boolean isSameMaterial(ItemStack comp) { + if (isNewVersion()) { + return comp.getType() == this.parseMaterial(); + } + if (comp.getType() == this.parseMaterial() && + (int) comp.getData().getData() == this.data) { + return true; + } + MultiversionMaterials xmat = fromMaterial(comp.getType()); + if (isDamageable(xmat)) { + return this.parseMaterial() == comp.getType(); + } + return false; + } - public MultiversionMaterials fromMaterial(Material mat) { - try { - return MultiversionMaterials.valueOf(mat.toString()); - } catch (IllegalArgumentException e) { - for (MultiversionMaterials xmat : MultiversionMaterials.values()) { - if (xmat.m.equals(mat.toString())) { - return xmat; - } - } - } - return null; - } + public MultiversionMaterials fromMaterial(Material mat) { + try { + return MultiversionMaterials.valueOf(mat.toString()); + } catch (IllegalArgumentException e) { + for (MultiversionMaterials xmat : MultiversionMaterials.values()) { + if (xmat.m.equals(mat.toString())) { + return xmat; + } + } + } + return null; + } - public boolean isDamageable(MultiversionMaterials type) { - String[] split = type.toString().split("_"); + public boolean isDamageable(MultiversionMaterials type) { + String[] split = type.toString().split("_"); - switch (split[split.length - 1]) { - case "HELMET": - case "CHESTPLATE": - case "LEGGINGS": - case "BOOTS": - case "SWORD": - case "AXE": - case "PICKAXE": - case "SHOVEL": - case "HOE": - case "ELYTRA": - case "TURTLE_HELMET": - case "TRIDENT": - case "HORSE_ARMOR": - case "SHEARS": - return true; - default: - return false; - } - } + switch (split[split.length - 1]) { + case "HELMET": + case "CHESTPLATE": + case "LEGGINGS": + case "BOOTS": + case "SWORD": + case "AXE": + case "PICKAXE": + case "SHOVEL": + case "HOE": + case "ELYTRA": + case "TURTLE_HELMET": + case "TRIDENT": + case "HORSE_ARMOR": + case "SHEARS": + return true; + default: + return false; + } + } - public Material parseMaterial() { - Material mat = Material.matchMaterial(this.toString()); - return mat != null ? mat : Material.matchMaterial(m); - } + public Material parseMaterial() { + Material mat = Material.matchMaterial(this.toString()); + return mat != null ? mat : Material.matchMaterial(m); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java index 72f5376d..d689c6f0 100644 --- a/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/MyLocationTypeAdapter.java @@ -9,51 +9,51 @@ import java.util.logging.Level; public class MyLocationTypeAdapter implements JsonDeserializer, JsonSerializer { - private static final String WORLD = "world"; - private static final String X = "x"; - private static final String Y = "y"; - private static final String Z = "z"; - private static final String YAW = "yaw"; - private static final String PITCH = "pitch"; + private static final String WORLD = "world"; + private static final String X = "x"; + private static final String Y = "y"; + private static final String Z = "z"; + private static final String YAW = "yaw"; + private static final String PITCH = "pitch"; - @Override - public LazyLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - try { - JsonObject obj = json.getAsJsonObject(); + @Override + public LazyLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + JsonObject obj = json.getAsJsonObject(); - String worldName = obj.get(WORLD).getAsString(); - double x = obj.get(X).getAsDouble(); - double y = obj.get(Y).getAsDouble(); - double z = obj.get(Z).getAsDouble(); - float yaw = obj.get(YAW).getAsFloat(); - float pitch = obj.get(PITCH).getAsFloat(); + String worldName = obj.get(WORLD).getAsString(); + double x = obj.get(X).getAsDouble(); + double y = obj.get(Y).getAsDouble(); + double z = obj.get(Z).getAsDouble(); + float yaw = obj.get(YAW).getAsFloat(); + float pitch = obj.get(PITCH).getAsFloat(); - return new LazyLocation(worldName, x, y, z, yaw, pitch); + return new LazyLocation(worldName, x, y, z, yaw, pitch); - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a LazyLocation."); - return null; - } - } + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a LazyLocation."); + return null; + } + } - @Override - public JsonElement serialize(LazyLocation src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject obj = new JsonObject(); + @Override + public JsonElement serialize(LazyLocation src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); - try { - obj.addProperty(WORLD, src.getWorldName()); - obj.addProperty(X, src.getX()); - obj.addProperty(Y, src.getY()); - obj.addProperty(Z, src.getZ()); - obj.addProperty(YAW, src.getYaw()); - obj.addProperty(PITCH, src.getPitch()); + try { + obj.addProperty(WORLD, src.getWorldName()); + obj.addProperty(X, src.getX()); + obj.addProperty(Y, src.getY()); + obj.addProperty(Z, src.getZ()); + obj.addProperty(YAW, src.getYaw()); + obj.addProperty(PITCH, src.getPitch()); - return obj; - } catch (Exception ex) { - ex.printStackTrace(); - SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a LazyLocation."); - return obj; - } - } + return obj; + } catch (Exception ex) { + ex.printStackTrace(); + SavageFactions.plugin.log(Level.WARNING, "Error encountered while serializing a LazyLocation."); + return obj; + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java b/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java index ab152c08..cf4ff3b7 100644 --- a/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java +++ b/src/main/java/com/massivecraft/factions/util/Particles/ParticleEffect.java @@ -40,1559 +40,1559 @@ import java.util.Map.Entry; * @version 1.7 */ public enum ParticleEffect { - /** - * A particle effect which is displayed by exploding tnt and creepers: - *
      - *
    • It looks like a white cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - EXPLOSION_NORMAL("explode", 0, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by exploding ghast fireballs and wither skulls: - *
      - *
    • It looks like a gray ball which is fading away - *
    • The speed value slightly influences the size of this particle effect - *
    - */ - EXPLOSION_LARGE("largeexplode", 1, -1), - /** - * A particle effect which is displayed by exploding tnt and creepers: - *
      - *
    • It looks like a crowd of gray balls which are fading away - *
    • The speed value has no influence on this particle effect - *
    - */ - EXPLOSION_HUGE("hugeexplosion", 2, -1), - /** - * A particle effect which is displayed by launching fireworks: - *
      - *
    • It looks like a white star which is sparkling - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - FIREWORKS_SPARK("fireworksSpark", 3, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by swimming entities and arrows in water: - *
      - *
    • It looks like a bubble - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - WATER_BUBBLE("bubble", 4, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_WATER), - /** - * A particle effect which is displayed by swimming entities and shaking wolves: - *
      - *
    • It looks like a blue drop - *
    • The speed value has no influence on this particle effect - *
    - */ - WATER_SPLASH("splash", 5, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed on water when fishing: - *
      - *
    • It looks like a blue droplet - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - WATER_WAKE("wake", 6, 7, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by water: - *
      - *
    • It looks like a tiny blue square - *
    • The speed value has no influence on this particle effect - *
    - */ - SUSPENDED("suspended", 7, -1, ParticleProperty.REQUIRES_WATER), - /** - * A particle effect which is displayed by air when close to bedrock and the in the void: - *
      - *
    • It looks like a tiny gray square - *
    • The speed value has no influence on this particle effect - *
    - */ - SUSPENDED_DEPTH("depthSuspend", 8, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed when landing a critical hit and by arrows: - *
      - *
    • It looks like a light brown cross - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - CRIT("crit", 9, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed when landing a hit with an enchanted weapon: - *
      - *
    • It looks like a cyan star - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - CRIT_MAGIC("magicCrit", 10, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by primed tnt, torches, droppers, dispensers, end portals, brewing stands and monster spawners: - *
      - *
    • It looks like a little gray cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - SMOKE_NORMAL("smoke", 11, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by fire, minecarts with furnace and blazes: - *
      - *
    • It looks like a large gray cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - SMOKE_LARGE("largesmoke", 12, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed when splash potions or bottles o' enchanting hit something: - *
      - *
    • It looks like a white swirl - *
    • The speed value causes the particle to only move upwards when set to 0 - *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 - *
    - */ - SPELL("spell", 13, -1), - /** - * A particle effect which is displayed when instant splash potions hit something: - *
      - *
    • It looks like a white cross - *
    • The speed value causes the particle to only move upwards when set to 0 - *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 - *
    - */ - SPELL_INSTANT("instantSpell", 14, -1), - /** - * A particle effect which is displayed by entities with active potion effects: - *
      - *
    • It looks like a colored swirl - *
    • The speed value causes the particle to be colored black when set to 0 - *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed - *
    - */ - SPELL_MOB("mobSpell", 15, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed by entities with active potion effects applied through a beacon: - *
      - *
    • It looks like a transparent colored swirl - *
    • The speed value causes the particle to be always colored black when set to 0 - *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed - *
    - */ - SPELL_MOB_AMBIENT("mobSpellAmbient", 16, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed by witches: - *
      - *
    • It looks like a purple cross - *
    • The speed value causes the particle to only move upwards when set to 0 - *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 - *
    - */ - SPELL_WITCH("witchMagic", 17, -1), - /** - * A particle effect which is displayed by blocks beneath a water source: - *
      - *
    • It looks like a blue drip - *
    • The speed value has no influence on this particle effect - *
    - */ - DRIP_WATER("dripWater", 18, -1), - /** - * A particle effect which is displayed by blocks beneath a lava source: - *
      - *
    • It looks like an orange drip - *
    • The speed value has no influence on this particle effect - *
    - */ - DRIP_LAVA("dripLava", 19, -1), - /** - * A particle effect which is displayed when attacking a villager in a village: - *
      - *
    • It looks like a cracked gray heart - *
    • The speed value has no influence on this particle effect - *
    - */ - VILLAGER_ANGRY("angryVillager", 20, -1), - /** - * A particle effect which is displayed when using bone meal and trading with a villager in a village: - *
      - *
    • It looks like a green star - *
    • The speed value has no influence on this particle effect - *
    - */ - VILLAGER_HAPPY("happyVillager", 21, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by mycelium: - *
      - *
    • It looks like a tiny gray square - *
    • The speed value has no influence on this particle effect - *
    - */ - TOWN_AURA("townaura", 22, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by note blocks: - *
      - *
    • It looks like a colored note - *
    • The speed value causes the particle to be colored green when set to 0 - *
    - */ - NOTE("note", 23, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed by nether portals, endermen, ender pearls, eyes of ender, ender chests and dragon eggs: - *
      - *
    • It looks like a purple cloud - *
    • The speed value influences the spread of this particle effect - *
    - */ - PORTAL("portal", 24, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by enchantment tables which are nearby bookshelves: - *
      - *
    • It looks like a cryptic white letter - *
    • The speed value influences the spread of this particle effect - *
    - */ - ENCHANTMENT_TABLE("enchantmenttable", 25, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by torches, active furnaces, magma cubes and monster spawners: - *
      - *
    • It looks like a tiny flame - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - FLAME("flame", 26, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by lava: - *
      - *
    • It looks like a spark - *
    • The speed value has no influence on this particle effect - *
    - */ - LAVA("lava", 27, -1), - /** - * A particle effect which is currently unused: - *
      - *
    • It looks like a transparent gray square - *
    • The speed value has no influence on this particle effect - *
    - */ - FOOTSTEP("footstep", 28, -1), - /** - * A particle effect which is displayed when a mob dies: - *
      - *
    • It looks like a large white cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - CLOUD("cloud", 29, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by redstone ore, powered redstone, redstone torches and redstone repeaters: - *
      - *
    • It looks like a tiny colored cloud - *
    • The speed value causes the particle to be colored red when set to 0 - *
    - */ - REDSTONE("reddust", 30, -1, ParticleProperty.COLORABLE), - /** - * A particle effect which is displayed when snowballs hit a block: - *
      - *
    • It looks like a little piece with the snowball texture - *
    • The speed value has no influence on this particle effect - *
    - */ - SNOWBALL("snowballpoof", 31, -1), - /** - * A particle effect which is currently unused: - *
      - *
    • It looks like a tiny white cloud - *
    • The speed value influences the velocity at which the particle flies off - *
    - */ - SNOW_SHOVEL("snowshovel", 32, -1, ParticleProperty.DIRECTIONAL), - /** - * A particle effect which is displayed by slimes: - *
      - *
    • It looks like a tiny part of the slimeball icon - *
    • The speed value has no influence on this particle effect - *
    - */ - SLIME("slime", 33, -1), - /** - * A particle effect which is displayed when breeding and taming animals: - *
      - *
    • It looks like a red heart - *
    • The speed value has no influence on this particle effect - *
    - */ - HEART("heart", 34, -1), - /** - * A particle effect which is displayed by barriers: - *
      - *
    • It looks like a red box with a slash through it - *
    • The speed value has no influence on this particle effect - *
    - */ - BARRIER("barrier", 35, 8), - /** - * A particle effect which is displayed when breaking a tool or eggs hit a block: - *
      - *
    • It looks like a little piece with an item texture - *
    - */ - ITEM_CRACK("iconcrack", 36, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), - /** - * A particle effect which is displayed when breaking blocks or sprinting: - *
      - *
    • It looks like a little piece with a block texture - *
    • The speed value has no influence on this particle effect - *
    - */ - BLOCK_CRACK("blockcrack", 37, -1, ParticleProperty.REQUIRES_DATA), - /** - * A particle effect which is displayed when falling: - *
      - *
    • It looks like a little piece with a block texture - *
    - */ - BLOCK_DUST("blockdust", 38, 7, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), - /** - * A particle effect which is displayed when rain hits the ground: - *
      - *
    • It looks like a blue droplet - *
    • The speed value has no influence on this particle effect - *
    - */ - WATER_DROP("droplet", 39, 8), - /** - * A particle effect which is currently unused: - *
      - *
    • It has no visual effect - *
    - */ - ITEM_TAKE("take", 40, 8), - /** - * A particle effect which is displayed by elder guardians: - *
      - *
    • It looks like the shape of the elder guardian - *
    • The speed value has no influence on this particle effect - *
    • The offset values have no influence on this particle effect - *
    - */ - MOB_APPEARANCE("mobappearance", 41, 8); - - private static final Map NAME_MAP = new HashMap(); - private static final Map ID_MAP = new HashMap(); - - // Initialize map for quick name and id lookup - static { - for (ParticleEffect effect : values()) { - NAME_MAP.put(effect.name, effect); - ID_MAP.put(effect.id, effect); - } - } - - private final String name; - private final int id; - private final int requiredVersion; - private final List properties; - - /** - * Construct a new particle effect - * - * @param name Name of this particle effect - * @param id Id of this particle effect - * @param requiredVersion Version which is required (1.x) - * @param properties Properties of this particle effect - */ - ParticleEffect(String name, int id, int requiredVersion, ParticleProperty... properties) { - this.name = name; - this.id = id; - this.requiredVersion = requiredVersion; - this.properties = Arrays.asList(properties); - } - - /** - * Returns the particle effect with the given name - * - * @param name Name of the particle effect - * @return The particle effect - */ - public static ParticleEffect fromName(String name) { - for (Entry entry : NAME_MAP.entrySet()) { - if (!entry.getKey().equalsIgnoreCase(name)) { - continue; - } - return entry.getValue(); - } - return null; - } - - /** - * Returns the particle effect with the given id - * - * @param id Id of the particle effect - * @return The particle effect - */ - public static ParticleEffect fromId(int id) { - for (Entry entry : ID_MAP.entrySet()) { - if (entry.getKey() != id) { - continue; - } - return entry.getValue(); - } - return null; - } - - /** - * Determine if water is at a certain location - * - * @param location Location to check - * @return Whether water is at this location or not - */ - private static boolean isWater(Location location) { - Material material = location.getBlock().getType(); - return material == Material.WATER || material == SavageFactions.plugin.STATIONARY_WATER; - } - - /** - * Determine if the distance between @param location and one of the players exceeds 256 - * - * @param location Location to check - * @return Whether the distance exceeds 256 or not - */ - private static boolean isLongDistance(Location location, List players) { - String world = location.getWorld().getName(); - for (Player player : players) { - Location playerLocation = player.getLocation(); - if (!world.equals(playerLocation.getWorld().getName()) || playerLocation.distanceSquared(location) < 65536) { - continue; - } - return true; - } - return false; - } - - /** - * Determine if the data type for a particle effect is correct - * - * @param effect Particle effect - * @param data Particle data - * @return Whether the data type is correct or not - */ - private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) { - return ((effect == BLOCK_CRACK || effect == BLOCK_DUST) && data instanceof BlockData) || (effect == ITEM_CRACK && data instanceof ItemData); - } - - /** - * Determine if the color type for a particle effect is correct - * - * @param effect Particle effect - * @param color Particle color - * @return Whether the color type is correct or not - */ - private static boolean isColorCorrect(ParticleEffect effect, ParticleColor color) { - return ((effect == SPELL_MOB || effect == SPELL_MOB_AMBIENT || effect == REDSTONE) && color instanceof OrdinaryColor) || (effect == NOTE && color instanceof NoteColor); - } - - /** - * Returns the name of this particle effect - * - * @return The name - */ - public String getName() { - return name; - } - - /** - * Returns the id of this particle effect - * - * @return The id - */ - public int getId() { - return id; - } - - /** - * Returns the required version for this particle effect (1.x) - * - * @return The required version - */ - public int getRequiredVersion() { - return requiredVersion; - } - - /** - * Determine if this particle effect has a specific property - * - * @param property - property to check. - * @return Whether it has the property or not - */ - public boolean hasProperty(ParticleProperty property) { - return properties.contains(property); - } - - /** - * Determine if this particle effect is supported by your current server version - * - * @return Whether the particle effect is supported or not - */ - public boolean isSupported() { - if (requiredVersion == -1) { - return true; - } - return ParticlePacket.getVersion() >= requiredVersion; - } - - /** - * Displays a particle effect which is only visible for all players within a certain range in the world of @param center - * - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect requires water and none is at the center location - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, null).sendTo(center, range); - } - - /** - * Displays a particle effect which is only visible for the specified players - * - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect requires water and none is at the center location - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), null).sendTo(center, players); - } - - /** - * Displays a particle effect which is only visible for the specified players - * - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect requires water and none is at the center location - * @see #display(float, float, float, float, int, Location, List) - */ - public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - display(offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); - } - - /** - * Displays a single particle which flies into a determined direction and is only visible for all players within a certain range in the world of @param center - * - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location - * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (!hasProperty(ParticleProperty.DIRECTIONAL)) { - throw new IllegalArgumentException("This particle effect is not directional"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, direction, speed, range > 256, null).sendTo(center, range); - } - - /** - * Displays a single particle which flies into a determined direction and is only visible for the specified players - * - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location - * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect requires additional data"); - } - if (!hasProperty(ParticleProperty.DIRECTIONAL)) { - throw new IllegalArgumentException("This particle effect is not directional"); - } - if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { - throw new IllegalArgumentException("There is no water at the center location"); - } - new ParticlePacket(this, direction, speed, isLongDistance(center, players), null).sendTo(center, players); - } - - /** - * Displays a single particle which flies into a determined direction and is only visible for the specified players - * - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect requires additional data - * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location - * @see #display(Vector, float, Location, List) - */ - public void display(Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { - display(direction, speed, center, Arrays.asList(players)); - } - - /** - * Displays a single particle which is colored and only visible for all players within a certain range in the world of @param center - * - * @param color Color of the particle - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect - * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(ParticleColor color, Location center, double range) throws ParticleVersionException, ParticleColorException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.COLORABLE)) { - throw new ParticleColorException("This particle effect is not colorable"); - } - if (!isColorCorrect(this, color)) { - throw new ParticleColorException("The particle color type is incorrect"); - } - new ParticlePacket(this, color, range > 256).sendTo(center, range); - } - - /** - * Displays a single particle which is colored and only visible for the specified players - * - * @param color Color of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect - * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(ParticleColor color, Location center, List players) throws ParticleVersionException, ParticleColorException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.COLORABLE)) { - throw new ParticleColorException("This particle effect is not colorable"); - } - if (!isColorCorrect(this, color)) { - throw new ParticleColorException("The particle color type is incorrect"); - } - new ParticlePacket(this, color, isLongDistance(center, players)).sendTo(center, players); - } - - /** - * Displays a single particle which is colored and only visible for the specified players - * - * @param color Color of the particle - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect - * @see #display(ParticleColor, Location, List) - */ - public void display(ParticleColor color, Location center, Player... players) throws ParticleVersionException, ParticleColorException { - display(color, center, Arrays.asList(players)); - } - - /** - * Displays a particle effect which requires additional data and is only visible for all players within a certain range in the world of @param center - * - * @param data Data of the effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, data).sendTo(center, range); - } - - /** - * Displays a particle effect which requires additional data and is only visible for the specified players - * - * @param data Data of the effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), data).sendTo(center, players); - } - - /** - * Displays a particle effect which requires additional data and is only visible for the specified players - * - * @param data Data of the effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see #display(ParticleData, float, float, float, float, int, Location, List) - */ - public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException { - display(data, offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); - } - - /** - * Displays a single particle which requires additional data that flies into a determined direction and is only visible for all players within a certain range in the world of @param center - * - * @param data Data of the effect - * @param direction Direction of the particle - * @param speed Display speed of the particles - * @param center Center location of the effect - * @param range Range of the visibility - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, double) - */ - public void display(ParticleData data, Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, direction, speed, range > 256, data).sendTo(center, range); - } - - /** - * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players - * - * @param data Data of the effect - * @param direction Direction of the particle - * @param speed Display speed of the particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see ParticlePacket - * @see ParticlePacket#sendTo(Location, List) - */ - public void display(ParticleData data, Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException { - if (!isSupported()) { - throw new ParticleVersionException("This particle effect is not supported by your server version"); - } - if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { - throw new ParticleDataException("This particle effect does not require additional data"); - } - if (!isDataCorrect(this, data)) { - throw new ParticleDataException("The particle data type is incorrect"); - } - new ParticlePacket(this, direction, speed, isLongDistance(center, players), data).sendTo(center, players); - } - - /** - * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players - * - * @param data Data of the effect - * @param direction Direction of the particle - * @param speed Display speed of the particles - * @param center Center location of the effect - * @param players Receivers of the effect - * @throws ParticleVersionException If the particle effect is not supported by the server version - * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect - * @see #display(ParticleData, Vector, float, Location, List) - */ - public void display(ParticleData data, Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException { - display(data, direction, speed, center, Arrays.asList(players)); - } - - /** - * Represents the property of a particle effect - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public enum ParticleProperty { - /** - * The particle effect requires water to be displayed - */ - REQUIRES_WATER, - /** - * The particle effect requires block or item data to be displayed - */ - REQUIRES_DATA, - /** - * The particle effect uses the offsets as direction values - */ - DIRECTIONAL, - /** - * The particle effect uses the offsets as color values - */ - COLORABLE - } - - /** - * Represents the particle data for effects like {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - public static abstract class ParticleData { - private final Material material; - private final byte data; - private final int[] packetData; - - /** - * Construct a new particle data - * - * @param material Material of the item/block - * @param data Data value of the item/block - */ - @SuppressWarnings("deprecation") - public ParticleData(Material material, byte data) { - this.material = material; - this.data = data; - this.packetData = new int[]{material.getId(), data}; - } - - /** - * Returns the material of this data - * - * @return The material - */ - public Material getMaterial() { - return material; - } - - /** - * Returns the data value of this data - * - * @return The data value - */ - public byte getData() { - return data; - } - - /** - * Returns the data as an int array for packet construction - * - * @return The data for the packet - */ - public int[] getPacketData() { - return packetData; - } - - /** - * Returns the data as a string for pre 1.8 versions - * - * @return The data string for the packet - */ - public String getPacketDataString() { - return "_" + packetData[0] + "_" + packetData[1]; - } - } - - /** - * Represents the item data for the {@link ParticleEffect#ITEM_CRACK} effect - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - public static final class ItemData extends ParticleData { - /** - * Construct a new item data - * - * @param material Material of the item - * @param data Data value of the item - * @see ParticleData#ParticleData(Material, byte) - */ - public ItemData(Material material, byte data) { - super(material, data); - } - } - - /** - * Represents the block data for the {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} effects - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - public static final class BlockData extends ParticleData { - /** - * Construct a new block data - * - * @param material Material of the block - * @param data Data value of the block - * @throws IllegalArgumentException If the material is not a block - * @see ParticleData#ParticleData(Material, byte) - */ - public BlockData(Material material, byte data) throws IllegalArgumentException { - super(material, data); - if (!material.isBlock()) { - throw new IllegalArgumentException("The material is not a block"); - } - } - } - - /** - * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT}, {@link ParticleEffect#REDSTONE} and {@link ParticleEffect#NOTE} - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public static abstract class ParticleColor { - /** - * Returns the value for the offsetX field - * - * @return The offsetX value - */ - public abstract float getValueX(); - - /** - * Returns the value for the offsetY field - * - * @return The offsetY value - */ - public abstract float getValueY(); - - /** - * Returns the value for the offsetZ field - * - * @return The offsetZ value - */ - public abstract float getValueZ(); - } - - /** - * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT} and {@link ParticleEffect#NOTE} - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public static final class OrdinaryColor extends ParticleColor { - private final int red; - private final int green; - private final int blue; - - /** - * Construct a new ordinary color - * - * @param red Red value of the RGB format - * @param green Green value of the RGB format - * @param blue Blue value of the RGB format - * @throws IllegalArgumentException If one of the values is lower than 0 or higher than 255 - */ - public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException { - if (red < 0) { - throw new IllegalArgumentException("The red value is lower than 0"); - } - if (red > 255) { - throw new IllegalArgumentException("The red value is higher than 255"); - } - this.red = red; - if (green < 0) { - throw new IllegalArgumentException("The green value is lower than 0"); - } - if (green > 255) { - throw new IllegalArgumentException("The green value is higher than 255"); - } - this.green = green; - if (blue < 0) { - throw new IllegalArgumentException("The blue value is lower than 0"); - } - if (blue > 255) { - throw new IllegalArgumentException("The blue value is higher than 255"); - } - this.blue = blue; - } - - /** - * Construct a new ordinary color - * - * @param color Bukkit color - */ - public OrdinaryColor(Color color) { - this(color.getRed(), color.getGreen(), color.getBlue()); - } - - /** - * Returns the red value of the RGB format - * - * @return The red value - */ - public int getRed() { - return red; - } - - /** - * Returns the green value of the RGB format - * - * @return The green value - */ - public int getGreen() { - return green; - } - - /** - * Returns the blue value of the RGB format - * - * @return The blue value - */ - public int getBlue() { - return blue; - } - - /** - * Returns the red value divided by 255 - * - * @return The offsetX value - */ - @Override - public float getValueX() { - return (float) red / 255F; - } - - /** - * Returns the green value divided by 255 - * - * @return The offsetY value - */ - @Override - public float getValueY() { - return (float) green / 255F; - } - - /** - * Returns the blue value divided by 255 - * - * @return The offsetZ value - */ - @Override - public float getValueZ() { - return (float) blue / 255F; - } - } - - /** - * Represents the color for the {@link ParticleEffect#NOTE} effect - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - public static final class NoteColor extends ParticleColor { - private final int note; - - /** - * Construct a new note color - * - * @param note Note id which determines color - * @throws IllegalArgumentException If the note value is lower than 0 or higher than 24 - */ - public NoteColor(int note) throws IllegalArgumentException { - if (note < 0) { - throw new IllegalArgumentException("The note value is lower than 0"); - } - if (note > 24) { - throw new IllegalArgumentException("The note value is higher than 24"); - } - this.note = note; - } - - /** - * Returns the note value divided by 24 - * - * @return The offsetX value - */ - @Override - public float getValueX() { - return (float) note / 24F; - } - - /** - * Returns zero because the offsetY value is unused - * - * @return zero - */ - @Override - public float getValueY() { - return 0; - } - - /** - * Returns zero because the offsetZ value is unused - * - * @return zero - */ - @Override - public float getValueZ() { - return 0; - } - - } - - /** - * Represents a runtime exception that is thrown either if the displayed particle effect requires data and has none or vice-versa or if the data type is incorrect - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - private static final class ParticleDataException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new particle data exception - * - * @param message Message that will be logged - */ - public ParticleDataException(String message) { - super(message); - } - } - - /** - * Represents a runtime exception that is thrown either if the displayed particle effect is not colorable or if the particle color type is incorrect - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.7 - */ - private static final class ParticleColorException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new particle color exception - * - * @param message Message that will be logged - */ - public ParticleColorException(String message) { - super(message); - } - } - - /** - * Represents a runtime exception that is thrown if the displayed particle effect requires a newer version - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.6 - */ - private static final class ParticleVersionException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new particle version exception - * - * @param message Message that will be logged - */ - public ParticleVersionException(String message) { - super(message); - } - } - - /** - * Represents a particle effect packet with all attributes which is used for sending packets to the players - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.5 - */ - public static final class ParticlePacket { - private static int version; - private static Class enumParticle; - private static Constructor packetConstructor; - private static Method getHandle; - private static Field playerConnection; - private static Method sendPacket; - private static boolean initialized; - private final ParticleEffect effect; - private final float offsetY; - private final float offsetZ; - private final float speed; - private final int amount; - private final boolean longDistance; - private final ParticleData data; - private float offsetX; - private Object packet; - - /** - * Construct a new particle packet - * - * @param effect Particle effect - * @param offsetX Maximum distance particles can fly away from the center on the x-axis - * @param offsetY Maximum distance particles can fly away from the center on the y-axis - * @param offsetZ Maximum distance particles can fly away from the center on the z-axis - * @param speed Display speed of the particles - * @param amount Amount of particles - * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 - * @param data Data of the effect - * @throws IllegalArgumentException If the speed or amount is lower than 0 - * @see #initialize() - */ - public ParticlePacket(ParticleEffect effect, float offsetX, float offsetY, float offsetZ, float speed, int amount, boolean longDistance, ParticleData data) throws IllegalArgumentException { - initialize(); - if (speed < 0) { - throw new IllegalArgumentException("The speed is lower than 0"); - } - if (amount < 0) { - throw new IllegalArgumentException("The amount is lower than 0"); - } - this.effect = effect; - this.offsetX = offsetX; - this.offsetY = offsetY; - this.offsetZ = offsetZ; - this.speed = speed; - this.amount = amount; - this.longDistance = longDistance; - this.data = data; - } - - /** - * Construct a new particle packet of a single particle flying into a determined direction - * - * @param effect Particle effect - * @param direction Direction of the particle - * @param speed Display speed of the particle - * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 - * @param data Data of the effect - * @throws IllegalArgumentException If the speed is lower than 0 - */ - public ParticlePacket(ParticleEffect effect, Vector direction, float speed, boolean longDistance, ParticleData data) throws IllegalArgumentException { - this(effect, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), speed, 0, longDistance, data); - } - - /** - * Construct a new particle packet of a single colored particle - * - * @param effect Particle effect - * @param color Color of the particle - * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 - */ - public ParticlePacket(ParticleEffect effect, ParticleColor color, boolean longDistance) { - this(effect, color.getValueX(), color.getValueY(), color.getValueZ(), 1, 0, longDistance, null); - if (effect == ParticleEffect.REDSTONE && color instanceof OrdinaryColor && ((OrdinaryColor) color).getRed() == 0) { - offsetX = Float.MIN_NORMAL; - } - } - - /** - * Initializes {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} and sets {@link #initialized} to true if it succeeds - * - * Note: These fields only have to be initialized once, so it will return if {@link #initialized} is already set to true - * - * @throws VersionIncompatibleException if your bukkit version is not supported by this library - */ - public static void initialize() throws VersionIncompatibleException { - if (initialized) { - return; - } - try { - version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); - if (version > 7) { - enumParticle = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("EnumParticle"); - } - - Class packetClass = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass(version < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles"); - - packetConstructor = ReflectionUtils.getConstructor(packetClass); - getHandle = ReflectionUtils.getMethod("CraftPlayer", ReflectionUtils.PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); - playerConnection = ReflectionUtils.getField("EntityPlayer", ReflectionUtils.PackageType.MINECRAFT_SERVER, false, "playerConnection"); - sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("Packet")); - } catch (Exception exception) { - throw new VersionIncompatibleException("Your current bukkit version seems to be incompatible with this library", exception); - } - initialized = true; - } - - /** - * Returns the version of your server (1.x) - * - * @return The version number - */ - public static int getVersion() { - if (!initialized) { - initialize(); - } - return version; - } - - /** - * Determine if {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} are initialized - * - * @return Whether these fields are initialized or not - * @see #initialize() - */ - public static boolean isInitialized() { - return initialized; - } - - /** - * Initializes {@link #packet} with all set values - * - * @param center Center location of the effect - * @throws PacketInstantiationException If instantion fails due to an unknown error - */ - private void initializePacket(Location center) throws PacketInstantiationException { - if (packet != null) { - return; - } - try { - packet = packetConstructor.newInstance(); - if (version < 8) { - String name = effect.getName(); - if (data != null) { - name += data.getPacketDataString(); - } - ReflectionUtils.setValue(packet, true, "a", name); - } else { - ReflectionUtils.setValue(packet, true, "a", enumParticle.getEnumConstants()[effect.getId()]); - ReflectionUtils.setValue(packet, true, "j", longDistance); - if (data != null) { - int[] packetData = data.getPacketData(); - ReflectionUtils.setValue(packet, true, "k", effect == ParticleEffect.ITEM_CRACK ? packetData : new int[]{packetData[0] | (packetData[1] << 12)}); - } - } - ReflectionUtils.setValue(packet, true, "b", (float) center.getX()); - ReflectionUtils.setValue(packet, true, "c", (float) center.getY()); - ReflectionUtils.setValue(packet, true, "d", (float) center.getZ()); - ReflectionUtils.setValue(packet, true, "e", offsetX); - ReflectionUtils.setValue(packet, true, "f", offsetY); - ReflectionUtils.setValue(packet, true, "g", offsetZ); - ReflectionUtils.setValue(packet, true, "h", speed); - ReflectionUtils.setValue(packet, true, "i", amount); - } catch (Exception exception) { - throw new PacketInstantiationException("Packet instantiation failed", exception); - } - } - - /** - * Sends the packet to a single player and caches it - * - * @param center Center location of the effect - * @param player Receiver of the packet - * @throws PacketInstantiationException If instantion fails due to an unknown error - * @throws PacketSendingException If sending fails due to an unknown error - * @see #initializePacket(Location) - */ - public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException { - initializePacket(center); - try { - sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), packet); - } catch (Exception exception) { - throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception); - } - } - - /** - * Sends the packet to all players in the list - * - * @param center Center location of the effect - * @param players Receivers of the packet - * @throws IllegalArgumentException If the player list is empty - * @see #sendTo(Location center, Player player) - */ - public void sendTo(Location center, List players) throws IllegalArgumentException { - if (players.isEmpty()) { - throw new IllegalArgumentException("The player list is empty"); - } - for (Player player : players) { - sendTo(center, player); - } - } - - /** - * Sends the packet to all players in a certain range - * - * @param center Center location of the effect - * @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types) - * @throws IllegalArgumentException If the range is lower than 1 - * @see #sendTo(Location center, Player player) - */ - public void sendTo(Location center, double range) throws IllegalArgumentException { - if (range < 1) { - throw new IllegalArgumentException("The range is lower than 1"); - } - String worldName = center.getWorld().getName(); - double squared = range * range; - for (Player player : Bukkit.getOnlinePlayers()) { - if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) { - continue; - } - sendTo(center, player); - } - } - - /** - * Represents a runtime exception that is thrown if a bukkit version is not compatible with this library - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.5 - */ - private static final class VersionIncompatibleException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new version incompatible exception - * - * @param message Message that will be logged - * @param cause Cause of the exception - */ - public VersionIncompatibleException(String message, Throwable cause) { - super(message, cause); - } - } - - /** - * Represents a runtime exception that is thrown if packet instantiation fails - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.4 - */ - private static final class PacketInstantiationException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new packet instantiation exception - * - * @param message Message that will be logged - * @param cause Cause of the exception - */ - public PacketInstantiationException(String message, Throwable cause) { - super(message, cause); - } - } - - /** - * Represents a runtime exception that is thrown if packet sending fails - *

    - * This class is part of the ParticleEffect Library and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.4 - */ - private static final class PacketSendingException extends RuntimeException { - private static final long serialVersionUID = 3203085387160737484L; - - /** - * Construct a new packet sending exception - * - * @param message Message that will be logged - * @param cause Cause of the exception - */ - public PacketSendingException(String message, Throwable cause) { - super(message, cause); - } - } - } + /** + * A particle effect which is displayed by exploding tnt and creepers: + *

      + *
    • It looks like a white cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + EXPLOSION_NORMAL("explode", 0, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by exploding ghast fireballs and wither skulls: + *
      + *
    • It looks like a gray ball which is fading away + *
    • The speed value slightly influences the size of this particle effect + *
    + */ + EXPLOSION_LARGE("largeexplode", 1, -1), + /** + * A particle effect which is displayed by exploding tnt and creepers: + *
      + *
    • It looks like a crowd of gray balls which are fading away + *
    • The speed value has no influence on this particle effect + *
    + */ + EXPLOSION_HUGE("hugeexplosion", 2, -1), + /** + * A particle effect which is displayed by launching fireworks: + *
      + *
    • It looks like a white star which is sparkling + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + FIREWORKS_SPARK("fireworksSpark", 3, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by swimming entities and arrows in water: + *
      + *
    • It looks like a bubble + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + WATER_BUBBLE("bubble", 4, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_WATER), + /** + * A particle effect which is displayed by swimming entities and shaking wolves: + *
      + *
    • It looks like a blue drop + *
    • The speed value has no influence on this particle effect + *
    + */ + WATER_SPLASH("splash", 5, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed on water when fishing: + *
      + *
    • It looks like a blue droplet + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + WATER_WAKE("wake", 6, 7, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by water: + *
      + *
    • It looks like a tiny blue square + *
    • The speed value has no influence on this particle effect + *
    + */ + SUSPENDED("suspended", 7, -1, ParticleProperty.REQUIRES_WATER), + /** + * A particle effect which is displayed by air when close to bedrock and the in the void: + *
      + *
    • It looks like a tiny gray square + *
    • The speed value has no influence on this particle effect + *
    + */ + SUSPENDED_DEPTH("depthSuspend", 8, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed when landing a critical hit and by arrows: + *
      + *
    • It looks like a light brown cross + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + CRIT("crit", 9, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed when landing a hit with an enchanted weapon: + *
      + *
    • It looks like a cyan star + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + CRIT_MAGIC("magicCrit", 10, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by primed tnt, torches, droppers, dispensers, end portals, brewing stands and monster spawners: + *
      + *
    • It looks like a little gray cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + SMOKE_NORMAL("smoke", 11, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by fire, minecarts with furnace and blazes: + *
      + *
    • It looks like a large gray cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + SMOKE_LARGE("largesmoke", 12, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed when splash potions or bottles o' enchanting hit something: + *
      + *
    • It looks like a white swirl + *
    • The speed value causes the particle to only move upwards when set to 0 + *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 + *
    + */ + SPELL("spell", 13, -1), + /** + * A particle effect which is displayed when instant splash potions hit something: + *
      + *
    • It looks like a white cross + *
    • The speed value causes the particle to only move upwards when set to 0 + *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 + *
    + */ + SPELL_INSTANT("instantSpell", 14, -1), + /** + * A particle effect which is displayed by entities with active potion effects: + *
      + *
    • It looks like a colored swirl + *
    • The speed value causes the particle to be colored black when set to 0 + *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed + *
    + */ + SPELL_MOB("mobSpell", 15, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed by entities with active potion effects applied through a beacon: + *
      + *
    • It looks like a transparent colored swirl + *
    • The speed value causes the particle to be always colored black when set to 0 + *
    • The particle color gets lighter when increasing the speed and darker when decreasing the speed + *
    + */ + SPELL_MOB_AMBIENT("mobSpellAmbient", 16, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed by witches: + *
      + *
    • It looks like a purple cross + *
    • The speed value causes the particle to only move upwards when set to 0 + *
    • Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0 + *
    + */ + SPELL_WITCH("witchMagic", 17, -1), + /** + * A particle effect which is displayed by blocks beneath a water source: + *
      + *
    • It looks like a blue drip + *
    • The speed value has no influence on this particle effect + *
    + */ + DRIP_WATER("dripWater", 18, -1), + /** + * A particle effect which is displayed by blocks beneath a lava source: + *
      + *
    • It looks like an orange drip + *
    • The speed value has no influence on this particle effect + *
    + */ + DRIP_LAVA("dripLava", 19, -1), + /** + * A particle effect which is displayed when attacking a villager in a village: + *
      + *
    • It looks like a cracked gray heart + *
    • The speed value has no influence on this particle effect + *
    + */ + VILLAGER_ANGRY("angryVillager", 20, -1), + /** + * A particle effect which is displayed when using bone meal and trading with a villager in a village: + *
      + *
    • It looks like a green star + *
    • The speed value has no influence on this particle effect + *
    + */ + VILLAGER_HAPPY("happyVillager", 21, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by mycelium: + *
      + *
    • It looks like a tiny gray square + *
    • The speed value has no influence on this particle effect + *
    + */ + TOWN_AURA("townaura", 22, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by note blocks: + *
      + *
    • It looks like a colored note + *
    • The speed value causes the particle to be colored green when set to 0 + *
    + */ + NOTE("note", 23, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed by nether portals, endermen, ender pearls, eyes of ender, ender chests and dragon eggs: + *
      + *
    • It looks like a purple cloud + *
    • The speed value influences the spread of this particle effect + *
    + */ + PORTAL("portal", 24, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by enchantment tables which are nearby bookshelves: + *
      + *
    • It looks like a cryptic white letter + *
    • The speed value influences the spread of this particle effect + *
    + */ + ENCHANTMENT_TABLE("enchantmenttable", 25, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by torches, active furnaces, magma cubes and monster spawners: + *
      + *
    • It looks like a tiny flame + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + FLAME("flame", 26, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by lava: + *
      + *
    • It looks like a spark + *
    • The speed value has no influence on this particle effect + *
    + */ + LAVA("lava", 27, -1), + /** + * A particle effect which is currently unused: + *
      + *
    • It looks like a transparent gray square + *
    • The speed value has no influence on this particle effect + *
    + */ + FOOTSTEP("footstep", 28, -1), + /** + * A particle effect which is displayed when a mob dies: + *
      + *
    • It looks like a large white cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + CLOUD("cloud", 29, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by redstone ore, powered redstone, redstone torches and redstone repeaters: + *
      + *
    • It looks like a tiny colored cloud + *
    • The speed value causes the particle to be colored red when set to 0 + *
    + */ + REDSTONE("reddust", 30, -1, ParticleProperty.COLORABLE), + /** + * A particle effect which is displayed when snowballs hit a block: + *
      + *
    • It looks like a little piece with the snowball texture + *
    • The speed value has no influence on this particle effect + *
    + */ + SNOWBALL("snowballpoof", 31, -1), + /** + * A particle effect which is currently unused: + *
      + *
    • It looks like a tiny white cloud + *
    • The speed value influences the velocity at which the particle flies off + *
    + */ + SNOW_SHOVEL("snowshovel", 32, -1, ParticleProperty.DIRECTIONAL), + /** + * A particle effect which is displayed by slimes: + *
      + *
    • It looks like a tiny part of the slimeball icon + *
    • The speed value has no influence on this particle effect + *
    + */ + SLIME("slime", 33, -1), + /** + * A particle effect which is displayed when breeding and taming animals: + *
      + *
    • It looks like a red heart + *
    • The speed value has no influence on this particle effect + *
    + */ + HEART("heart", 34, -1), + /** + * A particle effect which is displayed by barriers: + *
      + *
    • It looks like a red box with a slash through it + *
    • The speed value has no influence on this particle effect + *
    + */ + BARRIER("barrier", 35, 8), + /** + * A particle effect which is displayed when breaking a tool or eggs hit a block: + *
      + *
    • It looks like a little piece with an item texture + *
    + */ + ITEM_CRACK("iconcrack", 36, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), + /** + * A particle effect which is displayed when breaking blocks or sprinting: + *
      + *
    • It looks like a little piece with a block texture + *
    • The speed value has no influence on this particle effect + *
    + */ + BLOCK_CRACK("blockcrack", 37, -1, ParticleProperty.REQUIRES_DATA), + /** + * A particle effect which is displayed when falling: + *
      + *
    • It looks like a little piece with a block texture + *
    + */ + BLOCK_DUST("blockdust", 38, 7, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA), + /** + * A particle effect which is displayed when rain hits the ground: + *
      + *
    • It looks like a blue droplet + *
    • The speed value has no influence on this particle effect + *
    + */ + WATER_DROP("droplet", 39, 8), + /** + * A particle effect which is currently unused: + *
      + *
    • It has no visual effect + *
    + */ + ITEM_TAKE("take", 40, 8), + /** + * A particle effect which is displayed by elder guardians: + *
      + *
    • It looks like the shape of the elder guardian + *
    • The speed value has no influence on this particle effect + *
    • The offset values have no influence on this particle effect + *
    + */ + MOB_APPEARANCE("mobappearance", 41, 8); + + private static final Map NAME_MAP = new HashMap(); + private static final Map ID_MAP = new HashMap(); + + // Initialize map for quick name and id lookup + static { + for (ParticleEffect effect : values()) { + NAME_MAP.put(effect.name, effect); + ID_MAP.put(effect.id, effect); + } + } + + private final String name; + private final int id; + private final int requiredVersion; + private final List properties; + + /** + * Construct a new particle effect + * + * @param name Name of this particle effect + * @param id Id of this particle effect + * @param requiredVersion Version which is required (1.x) + * @param properties Properties of this particle effect + */ + ParticleEffect(String name, int id, int requiredVersion, ParticleProperty... properties) { + this.name = name; + this.id = id; + this.requiredVersion = requiredVersion; + this.properties = Arrays.asList(properties); + } + + /** + * Returns the particle effect with the given name + * + * @param name Name of the particle effect + * @return The particle effect + */ + public static ParticleEffect fromName(String name) { + for (Entry entry : NAME_MAP.entrySet()) { + if (!entry.getKey().equalsIgnoreCase(name)) { + continue; + } + return entry.getValue(); + } + return null; + } + + /** + * Returns the particle effect with the given id + * + * @param id Id of the particle effect + * @return The particle effect + */ + public static ParticleEffect fromId(int id) { + for (Entry entry : ID_MAP.entrySet()) { + if (entry.getKey() != id) { + continue; + } + return entry.getValue(); + } + return null; + } + + /** + * Determine if water is at a certain location + * + * @param location Location to check + * @return Whether water is at this location or not + */ + private static boolean isWater(Location location) { + Material material = location.getBlock().getType(); + return material == Material.WATER || material == SavageFactions.plugin.STATIONARY_WATER; + } + + /** + * Determine if the distance between @param location and one of the players exceeds 256 + * + * @param location Location to check + * @return Whether the distance exceeds 256 or not + */ + private static boolean isLongDistance(Location location, List players) { + String world = location.getWorld().getName(); + for (Player player : players) { + Location playerLocation = player.getLocation(); + if (!world.equals(playerLocation.getWorld().getName()) || playerLocation.distanceSquared(location) < 65536) { + continue; + } + return true; + } + return false; + } + + /** + * Determine if the data type for a particle effect is correct + * + * @param effect Particle effect + * @param data Particle data + * @return Whether the data type is correct or not + */ + private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) { + return ((effect == BLOCK_CRACK || effect == BLOCK_DUST) && data instanceof BlockData) || (effect == ITEM_CRACK && data instanceof ItemData); + } + + /** + * Determine if the color type for a particle effect is correct + * + * @param effect Particle effect + * @param color Particle color + * @return Whether the color type is correct or not + */ + private static boolean isColorCorrect(ParticleEffect effect, ParticleColor color) { + return ((effect == SPELL_MOB || effect == SPELL_MOB_AMBIENT || effect == REDSTONE) && color instanceof OrdinaryColor) || (effect == NOTE && color instanceof NoteColor); + } + + /** + * Returns the name of this particle effect + * + * @return The name + */ + public String getName() { + return name; + } + + /** + * Returns the id of this particle effect + * + * @return The id + */ + public int getId() { + return id; + } + + /** + * Returns the required version for this particle effect (1.x) + * + * @return The required version + */ + public int getRequiredVersion() { + return requiredVersion; + } + + /** + * Determine if this particle effect has a specific property + * + * @param property - property to check. + * @return Whether it has the property or not + */ + public boolean hasProperty(ParticleProperty property) { + return properties.contains(property); + } + + /** + * Determine if this particle effect is supported by your current server version + * + * @return Whether the particle effect is supported or not + */ + public boolean isSupported() { + if (requiredVersion == -1) { + return true; + } + return ParticlePacket.getVersion() >= requiredVersion; + } + + /** + * Displays a particle effect which is only visible for all players within a certain range in the world of @param center + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, null).sendTo(center, range); + } + + /** + * Displays a particle effect which is only visible for the specified players + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), null).sendTo(center, players); + } + + /** + * Displays a particle effect which is only visible for the specified players + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see #display(float, float, float, float, int, Location, List) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + display(offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for all players within a certain range in the world of @param center + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location + * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (!hasProperty(ParticleProperty.DIRECTIONAL)) { + throw new IllegalArgumentException("This particle effect is not directional"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, direction, speed, range > 256, null).sendTo(center, range); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for the specified players + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location + * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData) + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect requires additional data"); + } + if (!hasProperty(ParticleProperty.DIRECTIONAL)) { + throw new IllegalArgumentException("This particle effect is not directional"); + } + if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, direction, speed, isLongDistance(center, players), null).sendTo(center, players); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for the specified players + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location + * @see #display(Vector, float, Location, List) + */ + public void display(Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + display(direction, speed, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which is colored and only visible for all players within a certain range in the world of @param center + * + * @param color Color of the particle + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect + * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleColor color, Location center, double range) throws ParticleVersionException, ParticleColorException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.COLORABLE)) { + throw new ParticleColorException("This particle effect is not colorable"); + } + if (!isColorCorrect(this, color)) { + throw new ParticleColorException("The particle color type is incorrect"); + } + new ParticlePacket(this, color, range > 256).sendTo(center, range); + } + + /** + * Displays a single particle which is colored and only visible for the specified players + * + * @param color Color of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect + * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean) + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleColor color, Location center, List players) throws ParticleVersionException, ParticleColorException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.COLORABLE)) { + throw new ParticleColorException("This particle effect is not colorable"); + } + if (!isColorCorrect(this, color)) { + throw new ParticleColorException("The particle color type is incorrect"); + } + new ParticlePacket(this, color, isLongDistance(center, players)).sendTo(center, players); + } + + /** + * Displays a single particle which is colored and only visible for the specified players + * + * @param color Color of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect + * @see #display(ParticleColor, Location, List) + */ + public void display(ParticleColor color, Location center, Player... players) throws ParticleVersionException, ParticleColorException { + display(color, center, Arrays.asList(players)); + } + + /** + * Displays a particle effect which requires additional data and is only visible for all players within a certain range in the world of @param center + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, data).sendTo(center, range); + } + + /** + * Displays a particle effect which requires additional data and is only visible for the specified players + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), data).sendTo(center, players); + } + + /** + * Displays a particle effect which requires additional data and is only visible for the specified players + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see #display(ParticleData, float, float, float, float, int, Location, List) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException { + display(data, offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for all players within a certain range in the world of @param center + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, direction, speed, range > 256, data).sendTo(center, range); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, List players) throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("This particle effect is not supported by your server version"); + } + if (!hasProperty(ParticleProperty.REQUIRES_DATA)) { + throw new ParticleDataException("This particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect"); + } + new ParticlePacket(this, direction, speed, isLongDistance(center, players), data).sendTo(center, players); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see #display(ParticleData, Vector, float, Location, List) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException { + display(data, direction, speed, center, Arrays.asList(players)); + } + + /** + * Represents the property of a particle effect + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public enum ParticleProperty { + /** + * The particle effect requires water to be displayed + */ + REQUIRES_WATER, + /** + * The particle effect requires block or item data to be displayed + */ + REQUIRES_DATA, + /** + * The particle effect uses the offsets as direction values + */ + DIRECTIONAL, + /** + * The particle effect uses the offsets as color values + */ + COLORABLE + } + + /** + * Represents the particle data for effects like {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static abstract class ParticleData { + private final Material material; + private final byte data; + private final int[] packetData; + + /** + * Construct a new particle data + * + * @param material Material of the item/block + * @param data Data value of the item/block + */ + @SuppressWarnings("deprecation") + public ParticleData(Material material, byte data) { + this.material = material; + this.data = data; + this.packetData = new int[]{material.getId(), data}; + } + + /** + * Returns the material of this data + * + * @return The material + */ + public Material getMaterial() { + return material; + } + + /** + * Returns the data value of this data + * + * @return The data value + */ + public byte getData() { + return data; + } + + /** + * Returns the data as an int array for packet construction + * + * @return The data for the packet + */ + public int[] getPacketData() { + return packetData; + } + + /** + * Returns the data as a string for pre 1.8 versions + * + * @return The data string for the packet + */ + public String getPacketDataString() { + return "_" + packetData[0] + "_" + packetData[1]; + } + } + + /** + * Represents the item data for the {@link ParticleEffect#ITEM_CRACK} effect + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static final class ItemData extends ParticleData { + /** + * Construct a new item data + * + * @param material Material of the item + * @param data Data value of the item + * @see ParticleData#ParticleData(Material, byte) + */ + public ItemData(Material material, byte data) { + super(material, data); + } + } + + /** + * Represents the block data for the {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} effects + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static final class BlockData extends ParticleData { + /** + * Construct a new block data + * + * @param material Material of the block + * @param data Data value of the block + * @throws IllegalArgumentException If the material is not a block + * @see ParticleData#ParticleData(Material, byte) + */ + public BlockData(Material material, byte data) throws IllegalArgumentException { + super(material, data); + if (!material.isBlock()) { + throw new IllegalArgumentException("The material is not a block"); + } + } + } + + /** + * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT}, {@link ParticleEffect#REDSTONE} and {@link ParticleEffect#NOTE} + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public static abstract class ParticleColor { + /** + * Returns the value for the offsetX field + * + * @return The offsetX value + */ + public abstract float getValueX(); + + /** + * Returns the value for the offsetY field + * + * @return The offsetY value + */ + public abstract float getValueY(); + + /** + * Returns the value for the offsetZ field + * + * @return The offsetZ value + */ + public abstract float getValueZ(); + } + + /** + * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT} and {@link ParticleEffect#NOTE} + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public static final class OrdinaryColor extends ParticleColor { + private final int red; + private final int green; + private final int blue; + + /** + * Construct a new ordinary color + * + * @param red Red value of the RGB format + * @param green Green value of the RGB format + * @param blue Blue value of the RGB format + * @throws IllegalArgumentException If one of the values is lower than 0 or higher than 255 + */ + public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException { + if (red < 0) { + throw new IllegalArgumentException("The red value is lower than 0"); + } + if (red > 255) { + throw new IllegalArgumentException("The red value is higher than 255"); + } + this.red = red; + if (green < 0) { + throw new IllegalArgumentException("The green value is lower than 0"); + } + if (green > 255) { + throw new IllegalArgumentException("The green value is higher than 255"); + } + this.green = green; + if (blue < 0) { + throw new IllegalArgumentException("The blue value is lower than 0"); + } + if (blue > 255) { + throw new IllegalArgumentException("The blue value is higher than 255"); + } + this.blue = blue; + } + + /** + * Construct a new ordinary color + * + * @param color Bukkit color + */ + public OrdinaryColor(Color color) { + this(color.getRed(), color.getGreen(), color.getBlue()); + } + + /** + * Returns the red value of the RGB format + * + * @return The red value + */ + public int getRed() { + return red; + } + + /** + * Returns the green value of the RGB format + * + * @return The green value + */ + public int getGreen() { + return green; + } + + /** + * Returns the blue value of the RGB format + * + * @return The blue value + */ + public int getBlue() { + return blue; + } + + /** + * Returns the red value divided by 255 + * + * @return The offsetX value + */ + @Override + public float getValueX() { + return (float) red / 255F; + } + + /** + * Returns the green value divided by 255 + * + * @return The offsetY value + */ + @Override + public float getValueY() { + return (float) green / 255F; + } + + /** + * Returns the blue value divided by 255 + * + * @return The offsetZ value + */ + @Override + public float getValueZ() { + return (float) blue / 255F; + } + } + + /** + * Represents the color for the {@link ParticleEffect#NOTE} effect + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + public static final class NoteColor extends ParticleColor { + private final int note; + + /** + * Construct a new note color + * + * @param note Note id which determines color + * @throws IllegalArgumentException If the note value is lower than 0 or higher than 24 + */ + public NoteColor(int note) throws IllegalArgumentException { + if (note < 0) { + throw new IllegalArgumentException("The note value is lower than 0"); + } + if (note > 24) { + throw new IllegalArgumentException("The note value is higher than 24"); + } + this.note = note; + } + + /** + * Returns the note value divided by 24 + * + * @return The offsetX value + */ + @Override + public float getValueX() { + return (float) note / 24F; + } + + /** + * Returns zero because the offsetY value is unused + * + * @return zero + */ + @Override + public float getValueY() { + return 0; + } + + /** + * Returns zero because the offsetZ value is unused + * + * @return zero + */ + @Override + public float getValueZ() { + return 0; + } + + } + + /** + * Represents a runtime exception that is thrown either if the displayed particle effect requires data and has none or vice-versa or if the data type is incorrect + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + private static final class ParticleDataException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle data exception + * + * @param message Message that will be logged + */ + public ParticleDataException(String message) { + super(message); + } + } + + /** + * Represents a runtime exception that is thrown either if the displayed particle effect is not colorable or if the particle color type is incorrect + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.7 + */ + private static final class ParticleColorException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle color exception + * + * @param message Message that will be logged + */ + public ParticleColorException(String message) { + super(message); + } + } + + /** + * Represents a runtime exception that is thrown if the displayed particle effect requires a newer version + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + private static final class ParticleVersionException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle version exception + * + * @param message Message that will be logged + */ + public ParticleVersionException(String message) { + super(message); + } + } + + /** + * Represents a particle effect packet with all attributes which is used for sending packets to the players + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.5 + */ + public static final class ParticlePacket { + private static int version; + private static Class enumParticle; + private static Constructor packetConstructor; + private static Method getHandle; + private static Field playerConnection; + private static Method sendPacket; + private static boolean initialized; + private final ParticleEffect effect; + private final float offsetY; + private final float offsetZ; + private final float speed; + private final int amount; + private final boolean longDistance; + private final ParticleData data; + private float offsetX; + private Object packet; + + /** + * Construct a new particle packet + * + * @param effect Particle effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + * @param data Data of the effect + * @throws IllegalArgumentException If the speed or amount is lower than 0 + * @see #initialize() + */ + public ParticlePacket(ParticleEffect effect, float offsetX, float offsetY, float offsetZ, float speed, int amount, boolean longDistance, ParticleData data) throws IllegalArgumentException { + initialize(); + if (speed < 0) { + throw new IllegalArgumentException("The speed is lower than 0"); + } + if (amount < 0) { + throw new IllegalArgumentException("The amount is lower than 0"); + } + this.effect = effect; + this.offsetX = offsetX; + this.offsetY = offsetY; + this.offsetZ = offsetZ; + this.speed = speed; + this.amount = amount; + this.longDistance = longDistance; + this.data = data; + } + + /** + * Construct a new particle packet of a single particle flying into a determined direction + * + * @param effect Particle effect + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + * @param data Data of the effect + * @throws IllegalArgumentException If the speed is lower than 0 + */ + public ParticlePacket(ParticleEffect effect, Vector direction, float speed, boolean longDistance, ParticleData data) throws IllegalArgumentException { + this(effect, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), speed, 0, longDistance, data); + } + + /** + * Construct a new particle packet of a single colored particle + * + * @param effect Particle effect + * @param color Color of the particle + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + */ + public ParticlePacket(ParticleEffect effect, ParticleColor color, boolean longDistance) { + this(effect, color.getValueX(), color.getValueY(), color.getValueZ(), 1, 0, longDistance, null); + if (effect == ParticleEffect.REDSTONE && color instanceof OrdinaryColor && ((OrdinaryColor) color).getRed() == 0) { + offsetX = Float.MIN_NORMAL; + } + } + + /** + * Initializes {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} and sets {@link #initialized} to true if it succeeds + * + * Note: These fields only have to be initialized once, so it will return if {@link #initialized} is already set to true + * + * @throws VersionIncompatibleException if your bukkit version is not supported by this library + */ + public static void initialize() throws VersionIncompatibleException { + if (initialized) { + return; + } + try { + version = Integer.parseInt(ReflectionUtils.PackageType.getServerVersion().split("_")[1]); + if (version > 7) { + enumParticle = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("EnumParticle"); + } + + Class packetClass = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass(version < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles"); + + packetConstructor = ReflectionUtils.getConstructor(packetClass); + getHandle = ReflectionUtils.getMethod("CraftPlayer", ReflectionUtils.PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); + playerConnection = ReflectionUtils.getField("EntityPlayer", ReflectionUtils.PackageType.MINECRAFT_SERVER, false, "playerConnection"); + sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("Packet")); + } catch (Exception exception) { + throw new VersionIncompatibleException("Your current bukkit version seems to be incompatible with this library", exception); + } + initialized = true; + } + + /** + * Returns the version of your server (1.x) + * + * @return The version number + */ + public static int getVersion() { + if (!initialized) { + initialize(); + } + return version; + } + + /** + * Determine if {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} are initialized + * + * @return Whether these fields are initialized or not + * @see #initialize() + */ + public static boolean isInitialized() { + return initialized; + } + + /** + * Initializes {@link #packet} with all set values + * + * @param center Center location of the effect + * @throws PacketInstantiationException If instantion fails due to an unknown error + */ + private void initializePacket(Location center) throws PacketInstantiationException { + if (packet != null) { + return; + } + try { + packet = packetConstructor.newInstance(); + if (version < 8) { + String name = effect.getName(); + if (data != null) { + name += data.getPacketDataString(); + } + ReflectionUtils.setValue(packet, true, "a", name); + } else { + ReflectionUtils.setValue(packet, true, "a", enumParticle.getEnumConstants()[effect.getId()]); + ReflectionUtils.setValue(packet, true, "j", longDistance); + if (data != null) { + int[] packetData = data.getPacketData(); + ReflectionUtils.setValue(packet, true, "k", effect == ParticleEffect.ITEM_CRACK ? packetData : new int[]{packetData[0] | (packetData[1] << 12)}); + } + } + ReflectionUtils.setValue(packet, true, "b", (float) center.getX()); + ReflectionUtils.setValue(packet, true, "c", (float) center.getY()); + ReflectionUtils.setValue(packet, true, "d", (float) center.getZ()); + ReflectionUtils.setValue(packet, true, "e", offsetX); + ReflectionUtils.setValue(packet, true, "f", offsetY); + ReflectionUtils.setValue(packet, true, "g", offsetZ); + ReflectionUtils.setValue(packet, true, "h", speed); + ReflectionUtils.setValue(packet, true, "i", amount); + } catch (Exception exception) { + throw new PacketInstantiationException("Packet instantiation failed", exception); + } + } + + /** + * Sends the packet to a single player and caches it + * + * @param center Center location of the effect + * @param player Receiver of the packet + * @throws PacketInstantiationException If instantion fails due to an unknown error + * @throws PacketSendingException If sending fails due to an unknown error + * @see #initializePacket(Location) + */ + public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException { + initializePacket(center); + try { + sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), packet); + } catch (Exception exception) { + throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception); + } + } + + /** + * Sends the packet to all players in the list + * + * @param center Center location of the effect + * @param players Receivers of the packet + * @throws IllegalArgumentException If the player list is empty + * @see #sendTo(Location center, Player player) + */ + public void sendTo(Location center, List players) throws IllegalArgumentException { + if (players.isEmpty()) { + throw new IllegalArgumentException("The player list is empty"); + } + for (Player player : players) { + sendTo(center, player); + } + } + + /** + * Sends the packet to all players in a certain range + * + * @param center Center location of the effect + * @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types) + * @throws IllegalArgumentException If the range is lower than 1 + * @see #sendTo(Location center, Player player) + */ + public void sendTo(Location center, double range) throws IllegalArgumentException { + if (range < 1) { + throw new IllegalArgumentException("The range is lower than 1"); + } + String worldName = center.getWorld().getName(); + double squared = range * range; + for (Player player : Bukkit.getOnlinePlayers()) { + if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) { + continue; + } + sendTo(center, player); + } + } + + /** + * Represents a runtime exception that is thrown if a bukkit version is not compatible with this library + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.5 + */ + private static final class VersionIncompatibleException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new version incompatible exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public VersionIncompatibleException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Represents a runtime exception that is thrown if packet instantiation fails + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.4 + */ + private static final class PacketInstantiationException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new packet instantiation exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public PacketInstantiationException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Represents a runtime exception that is thrown if packet sending fails + *

    + * This class is part of the ParticleEffect Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.4 + */ + private static final class PacketSendingException extends RuntimeException { + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new packet sending exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public PacketSendingException(String message, Throwable cause) { + super(message, cause); + } + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java b/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java index e3923367..4184eb08 100644 --- a/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java +++ b/src/main/java/com/massivecraft/factions/util/Particles/ReflectionUtils.java @@ -26,583 +26,583 @@ import java.util.Map; * @version 1.1 */ public final class ReflectionUtils { - // Prevent accidental construction - private ReflectionUtils() { - } + // Prevent accidental construction + private ReflectionUtils() { + } - /** - * Returns the constructor of a given class with the given parameter types - * - * @param clazz Target class - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @see DataType - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Constructor constructor : clazz.getConstructors()) { - if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { - continue; - } - return constructor; - } - throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); - } + /** + * Returns the constructor of a given class with the given parameter types + * + * @param clazz Target class + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @see DataType + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Constructor constructor : clazz.getConstructors()) { + if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { + continue; + } + return constructor; + } + throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); + } - /** - * Returns the constructor of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the desired target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #getConstructor(Class, Class...) - */ - public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getConstructor(packageType.getClass(className), parameterTypes); - } + /** + * Returns the constructor of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the desired target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #getConstructor(Class, Class...) + */ + public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getConstructor(packageType.getClass(className), parameterTypes); + } - /** - * Returns an instance of a class with the given arguments - * - * @param clazz Target class - * @param arguments Arguments which are used to construct an object of the target class - * @return The instance of the target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - */ - public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); - } + /** + * Returns an instance of a class with the given arguments + * + * @param clazz Target class + * @param arguments Arguments which are used to construct an object of the target class + * @return The instance of the target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + */ + public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); + } - /** - * Returns an instance of a desired class with the given arguments - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param arguments Arguments which are used to construct an object of the desired target class - * @return The instance of the desired target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #instantiateObject(Class, Object...) - */ - public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return instantiateObject(packageType.getClass(className), arguments); - } + /** + * Returns an instance of a desired class with the given arguments + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param arguments Arguments which are used to construct an object of the desired target class + * @return The instance of the desired target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #instantiateObject(Class, Object...) + */ + public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return instantiateObject(packageType.getClass(className), arguments); + } - /** - * Returns a method of a class with the given parameter types - * - * @param clazz Target class - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Method method : clazz.getMethods()) { - if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { - continue; - } - return method; - } - throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); - } + /** + * Returns a method of a class with the given parameter types + * + * @param clazz Target class + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Method method : clazz.getMethods()) { + if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { + continue; + } + return method; + } + throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); + } - /** - * Returns a method of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the desired target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #getMethod(Class, String, Class...) - */ - public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getMethod(packageType.getClass(className), methodName, parameterTypes); - } + /** + * Returns a method of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the desired target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #getMethod(Class, String, Class...) + */ + public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getMethod(packageType.getClass(className), methodName, parameterTypes); + } - /** - * Invokes a method on an object with the given arguments - * - * @param instance Target object - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } + /** + * Invokes a method on an object with the given arguments + * + * @param instance Target object + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } - /** - * Invokes a method of the target class on an object with the given arguments - * - * @param instance Target object - * @param clazz Target class - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } + /** + * Invokes a method of the target class on an object with the given arguments + * + * @param instance Target object + * @param clazz Target class + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } - /** - * Invokes a method of a desired class on an object with the given arguments - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass() (String, PackageType) - * @see #invokeMethod(Object, Class, String, Object...) - */ - public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return invokeMethod(instance, packageType.getClass(className), methodName, arguments); - } + /** + * Invokes a method of a desired class on an object with the given arguments + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass() (String, PackageType) + * @see #invokeMethod(Object, Class, String, Object...) + */ + public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return invokeMethod(instance, packageType.getClass(className), methodName, arguments); + } - /** - * Returns a field of the target class with the given name - * - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the target class with the specified name - * @throws NoSuchFieldException If the desired field of the given class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - */ - public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { - Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); - field.setAccessible(true); - return field; - } + /** + * Returns a field of the target class with the given name + * + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the target class with the specified name + * @throws NoSuchFieldException If the desired field of the given class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + */ + public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { + Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); + field.setAccessible(true); + return field; + } - /** - * Returns a field of a desired class with the given name - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the desired target class with the specified name - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getField(Class, boolean, String) - */ - public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { - return getField(packageType.getClass(className), declared, fieldName); - } + /** + * Returns a field of a desired class with the given name + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the desired target class with the specified name + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getField(Class, boolean, String) + */ + public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { + return getField(packageType.getClass(className), declared, fieldName); + } - /** - * Returns the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getField(Class, boolean, String) - */ - public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getField(clazz, declared, fieldName).get(instance); - } + /** + * Returns the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getField(clazz, declared, fieldName).get(instance); + } - /** - * Returns the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - return getValue(instance, packageType.getClass(className), declared, fieldName); - } + /** + * Returns the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + return getValue(instance, packageType.getClass(className), declared, fieldName); + } - /** - * Returns the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getValue(instance, instance.getClass(), declared, fieldName); - } + /** + * Returns the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getValue(instance, instance.getClass(), declared, fieldName); + } - /** - * Sets the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getField(Class, boolean, String) - */ - public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - getField(clazz, declared, fieldName).set(instance, value); - } + /** + * Sets the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + getField(clazz, declared, fieldName).set(instance, value); + } - /** - * Sets the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - setValue(instance, packageType.getClass(className), declared, fieldName, value); - } + /** + * Sets the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + setValue(instance, packageType.getClass(className), declared, fieldName, value); + } - /** - * Sets the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - setValue(instance, instance.getClass(), declared, fieldName, value); - } + /** + * Sets the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + setValue(instance, instance.getClass(), declared, fieldName, value); + } - /** - * Represents an enumeration of dynamic packages of NMS and CraftBukkit - *

    - * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum PackageType { - MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), - CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), - CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), - CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), - CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), - CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), - CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), - CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), - CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), - CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), - CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), - CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), - CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), - CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), - CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), - CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), - CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), - CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), - CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), - CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); + /** + * Represents an enumeration of dynamic packages of NMS and CraftBukkit + *

    + * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum PackageType { + MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), + CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), + CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), + CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), + CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), + CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), + CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), + CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), + CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), + CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), + CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), + CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), + CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), + CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), + CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), + CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), + CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), + CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), + CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), + CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); - private final String path; + private final String path; - /** - * Construct a new package type - * - * @param path Path of the package - */ - PackageType(String path) { - this.path = path; - } + /** + * Construct a new package type + * + * @param path Path of the package + */ + PackageType(String path) { + this.path = path; + } - /** - * Construct a new package type - * - * @param parent Parent package of the package - * @param path Path of the package - */ - PackageType(PackageType parent, String path) { - this(parent + "." + path); - } + /** + * Construct a new package type + * + * @param parent Parent package of the package + * @param path Path of the package + */ + PackageType(PackageType parent, String path) { + this(parent + "." + path); + } - /** - * Returns the version of your server - * - * @return The server version - */ - public static String getServerVersion() { - return Bukkit.getServer().getClass().getName().split("\\.")[3]; - } + /** + * Returns the version of your server + * + * @return The server version + */ + public static String getServerVersion() { + return Bukkit.getServer().getClass().getName().split("\\.")[3]; + } - /** - * Returns the path of this package type - * - * @return The path - */ - public String getPath() { - return path; - } + /** + * Returns the path of this package type + * + * @return The path + */ + public String getPath() { + return path; + } - /** - * Returns the class with the given name - * - * @param className Name of the desired class - * @return The class with the specified name - * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found - */ - public Class getClass(String className) throws ClassNotFoundException { - return Class.forName(this + "." + className); - } + /** + * Returns the class with the given name + * + * @param className Name of the desired class + * @return The class with the specified name + * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found + */ + public Class getClass(String className) throws ClassNotFoundException { + return Class.forName(this + "." + className); + } - // Override for convenience - @Override - public String toString() { - return path; - } - } + // Override for convenience + @Override + public String toString() { + return path; + } + } - /** - * Represents an enumeration of Java data types with corresponding classes - *

    - * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum DataType { - BYTE(byte.class, Byte.class), - SHORT(short.class, Short.class), - INTEGER(int.class, Integer.class), - LONG(long.class, Long.class), - CHARACTER(char.class, Character.class), - FLOAT(float.class, Float.class), - DOUBLE(double.class, Double.class), - BOOLEAN(boolean.class, Boolean.class); + /** + * Represents an enumeration of Java data types with corresponding classes + *

    + * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum DataType { + BYTE(byte.class, Byte.class), + SHORT(short.class, Short.class), + INTEGER(int.class, Integer.class), + LONG(long.class, Long.class), + CHARACTER(char.class, Character.class), + FLOAT(float.class, Float.class), + DOUBLE(double.class, Double.class), + BOOLEAN(boolean.class, Boolean.class); - private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); + private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); - // Initialize map for quick class lookup - static { - for (DataType type : values()) { - CLASS_MAP.put(type.primitive, type); - CLASS_MAP.put(type.reference, type); - } - } + // Initialize map for quick class lookup + static { + for (DataType type : values()) { + CLASS_MAP.put(type.primitive, type); + CLASS_MAP.put(type.reference, type); + } + } - private final Class primitive; - private final Class reference; + private final Class primitive; + private final Class reference; - /** - * Construct a new data type - * - * @param primitive Primitive class of this data type - * @param reference Reference class of this data type - */ - DataType(Class primitive, Class reference) { - this.primitive = primitive; - this.reference = reference; - } + /** + * Construct a new data type + * + * @param primitive Primitive class of this data type + * @param reference Reference class of this data type + */ + DataType(Class primitive, Class reference) { + this.primitive = primitive; + this.reference = reference; + } - /** - * Returns the data type with the given primitive/reference class - * - * @param clazz Primitive/Reference class of the data type - * @return The data type - */ - public static DataType fromClass(Class clazz) { - return CLASS_MAP.get(clazz); - } + /** + * Returns the data type with the given primitive/reference class + * + * @param clazz Primitive/Reference class of the data type + * @return The data type + */ + public static DataType fromClass(Class clazz) { + return CLASS_MAP.get(clazz); + } - /** - * Returns the primitive class of the data type with the given reference class - * - * @param clazz Reference class of the data type - * @return The primitive class - */ - public static Class getPrimitive(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getPrimitive(); - } + /** + * Returns the primitive class of the data type with the given reference class + * + * @param clazz Reference class of the data type + * @return The primitive class + */ + public static Class getPrimitive(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getPrimitive(); + } - /** - * Returns the reference class of the data type with the given primitive class - * - * @param clazz Primitive class of the data type - * @return The reference class - */ - public static Class getReference(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getReference(); - } + /** + * Returns the reference class of the data type with the given primitive class + * + * @param clazz Primitive class of the data type + * @return The reference class + */ + public static Class getReference(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getReference(); + } - /** - * Returns the primitive class array of the given class array - * - * @param classes Given class array - * @return The primitive class array - */ - public static Class[] getPrimitive(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(classes[index]); - } - return types; - } + /** + * Returns the primitive class array of the given class array + * + * @param classes Given class array + * @return The primitive class array + */ + public static Class[] getPrimitive(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(classes[index]); + } + return types; + } - /** - * Returns the reference class array of the given class array - * - * @param classes Given class array - * @return The reference class array - */ - public static Class[] getReference(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(classes[index]); - } - return types; - } + /** + * Returns the reference class array of the given class array + * + * @param classes Given class array + * @return The reference class array + */ + public static Class[] getReference(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(classes[index]); + } + return types; + } - /** - * Returns the primitive class array of the given object array - * - * @param objects Given object array - * @return The primitive class array - */ - public static Class[] getPrimitive(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(objects[index].getClass()); - } - return types; - } + /** + * Returns the primitive class array of the given object array + * + * @param objects Given object array + * @return The primitive class array + */ + public static Class[] getPrimitive(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(objects[index].getClass()); + } + return types; + } - /** - * Returns the reference class array of the given object array - * - * @param objects Given object array - * @return The reference class array - */ - public static Class[] getReference(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(objects[index].getClass()); - } - return types; - } + /** + * Returns the reference class array of the given object array + * + * @param objects Given object array + * @return The reference class array + */ + public static Class[] getReference(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(objects[index].getClass()); + } + return types; + } - /** - * Compares two class arrays on equivalence - * - * @param primary Primary class array - * @param secondary Class array which is compared to the primary array - * @return Whether these arrays are equal or not - */ - public static boolean compare(Class[] primary, Class[] secondary) { - if (primary == null || secondary == null || primary.length != secondary.length) { - return false; - } - for (int index = 0; index < primary.length; index++) { - Class primaryClass = primary[index]; - Class secondaryClass = secondary[index]; - if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { - continue; - } - return false; - } - return true; - } + /** + * Compares two class arrays on equivalence + * + * @param primary Primary class array + * @param secondary Class array which is compared to the primary array + * @return Whether these arrays are equal or not + */ + public static boolean compare(Class[] primary, Class[] secondary) { + if (primary == null || secondary == null || primary.length != secondary.length) { + return false; + } + for (int index = 0; index < primary.length; index++) { + Class primaryClass = primary[index]; + Class secondaryClass = secondary[index]; + if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { + continue; + } + return false; + } + return true; + } - /** - * Returns the primitive class of this data type - * - * @return The primitive class - */ - public Class getPrimitive() { - return primitive; - } + /** + * Returns the primitive class of this data type + * + * @return The primitive class + */ + public Class getPrimitive() { + return primitive; + } - /** - * Returns the reference class of this data type - * - * @return The reference class - */ - public Class getReference() { - return reference; - } - } + /** + * Returns the reference class of this data type + * + * @return The reference class + */ + public Class getReference() { + return reference; + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java b/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java index aeb8de97..efd66b29 100644 --- a/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java +++ b/src/main/java/com/massivecraft/factions/util/PermissionsMapTypeAdapter.java @@ -17,82 +17,82 @@ import java.util.logging.Level; public class PermissionsMapTypeAdapter implements JsonDeserializer>> { - @Override - public Map> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { + @Override + public Map> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { - try { - JsonObject obj = json.getAsJsonObject(); - if (obj == null) { - return null; - } + try { + JsonObject obj = json.getAsJsonObject(); + if (obj == null) { + return null; + } - Map> permissionsMap = new ConcurrentHashMap<>(); + Map> permissionsMap = new ConcurrentHashMap<>(); - // Top level is Relation - for (Map.Entry entry : obj.entrySet()) { - Permissable permissable = getPermissable(entry.getKey()); + // Top level is Relation + for (Map.Entry entry : obj.entrySet()) { + Permissable permissable = getPermissable(entry.getKey()); - if (permissable == null) { - continue; - } + if (permissable == null) { + continue; + } - // Second level is the map between action -> access - Map accessMap = new HashMap<>(); - for (Map.Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { - PermissableAction permissableAction = PermissableAction.fromString(entry2.getKey()); - if (permissableAction == null) { - switch (entry2.getKey()) { - case "frostwalk": - permissableAction = PermissableAction.FROST_WALK; - break; - case "painbuild": - permissableAction = PermissableAction.PAIN_BUILD; - break; - case "items": - permissableAction = PermissableAction.ITEM; - break; - } - } - Access access = Access.fromString(entry2.getValue().getAsString()); - accessMap.put(permissableAction, access); - } - permissionsMap.put(permissable, accessMap); - } + // Second level is the map between action -> access + Map accessMap = new HashMap<>(); + for (Map.Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { + PermissableAction permissableAction = PermissableAction.fromString(entry2.getKey()); + if (permissableAction == null) { + switch (entry2.getKey()) { + case "frostwalk": + permissableAction = PermissableAction.FROST_WALK; + break; + case "painbuild": + permissableAction = PermissableAction.PAIN_BUILD; + break; + case "items": + permissableAction = PermissableAction.ITEM; + break; + } + } + Access access = Access.fromString(entry2.getValue().getAsString()); + accessMap.put(permissableAction, access); + } + permissionsMap.put(permissable, accessMap); + } - return permissionsMap; + return permissionsMap; - } catch (Exception ex) { - SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a PermissionsMap."); - ex.printStackTrace(); - return null; - } - } + } catch (Exception ex) { + SavageFactions.plugin.log(Level.WARNING, "Error encountered while deserializing a PermissionsMap."); + ex.printStackTrace(); + return null; + } + } - private Permissable getPermissable(String name) { - // If name is uppercase then it is (probably, no way to completely know) valid if not begin conversion - if (name.equals(name.toUpperCase())) { - if (Role.fromString(name.toUpperCase()) != null) { - return Role.fromString(name.toUpperCase()); - } else if (Relation.fromString(name.toUpperCase()) != null) { - return Relation.fromString(name.toUpperCase()); - } else { - return null; - } - } else { - if (name.equals(TL.ROLE_RECRUIT.toString())) { - return Role.RECRUIT; - } else if (name.equals(TL.ROLE_NORMAL.toString())) { - return Role.NORMAL; - } else if (name.equals(TL.ROLE_MODERATOR.toString())) { - return Role.MODERATOR; - } else { - // If it is explicitly member and its old data then it refers to relation member not role, skip it - if (name.equals("member")) { - return null; - } - return Relation.fromString(name); - } - } - } + private Permissable getPermissable(String name) { + // If name is uppercase then it is (probably, no way to completely know) valid if not begin conversion + if (name.equals(name.toUpperCase())) { + if (Role.fromString(name.toUpperCase()) != null) { + return Role.fromString(name.toUpperCase()); + } else if (Relation.fromString(name.toUpperCase()) != null) { + return Relation.fromString(name.toUpperCase()); + } else { + return null; + } + } else { + if (name.equals(TL.ROLE_RECRUIT.toString())) { + return Role.RECRUIT; + } else if (name.equals(TL.ROLE_NORMAL.toString())) { + return Role.NORMAL; + } else if (name.equals(TL.ROLE_MODERATOR.toString())) { + return Role.MODERATOR; + } else { + // If it is explicitly member and its old data then it refers to relation member not role, skip it + if (name.equals("member")) { + return null; + } + return Relation.fromString(name); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/util/RelationUtil.java b/src/main/java/com/massivecraft/factions/util/RelationUtil.java index 4c656f84..0912b81c 100644 --- a/src/main/java/com/massivecraft/factions/util/RelationUtil.java +++ b/src/main/java/com/massivecraft/factions/util/RelationUtil.java @@ -11,101 +11,101 @@ import org.bukkit.ChatColor; public class RelationUtil { - public static String describeThatToMe(RelationParticipator that, RelationParticipator me, boolean ucfirst) { - String ret = ""; + public static String describeThatToMe(RelationParticipator that, RelationParticipator me, boolean ucfirst) { + String ret = ""; - Faction thatFaction = getFaction(that); - if (thatFaction == null) { - return "ERROR"; // ERROR - } + Faction thatFaction = getFaction(that); + if (thatFaction == null) { + return "ERROR"; // ERROR + } - Faction myFaction = getFaction(me); + Faction myFaction = getFaction(me); // if (myFaction == null) return that.describeTo(null); // no relation, but can show basic name or tag - if (that instanceof Faction) { - if (me instanceof FPlayer && myFaction == thatFaction) { - ret = TL.GENERIC_YOURFACTION.toString(); - } else { - ret = thatFaction.getTag(); - } - } else if (that instanceof FPlayer) { - FPlayer fplayerthat = (FPlayer) that; - if (that == me) { - ret = TL.GENERIC_YOU.toString(); - } else if (thatFaction == myFaction) { - ret = fplayerthat.getNameAndTitle(); - } else { - ret = fplayerthat.getNameAndTag(); - } - } + if (that instanceof Faction) { + if (me instanceof FPlayer && myFaction == thatFaction) { + ret = TL.GENERIC_YOURFACTION.toString(); + } else { + ret = thatFaction.getTag(); + } + } else if (that instanceof FPlayer) { + FPlayer fplayerthat = (FPlayer) that; + if (that == me) { + ret = TL.GENERIC_YOU.toString(); + } else if (thatFaction == myFaction) { + ret = fplayerthat.getNameAndTitle(); + } else { + ret = fplayerthat.getNameAndTag(); + } + } - if (ucfirst) { - ret = TextUtil.upperCaseFirst(ret); - } + if (ucfirst) { + ret = TextUtil.upperCaseFirst(ret); + } - return "" + getColorOfThatToMe(that, me) + ret; - } + return "" + getColorOfThatToMe(that, me) + ret; + } - public static String describeThatToMe(RelationParticipator that, RelationParticipator me) { - return describeThatToMe(that, me, false); - } + public static String describeThatToMe(RelationParticipator that, RelationParticipator me) { + return describeThatToMe(that, me, false); + } - public static Relation getRelationTo(RelationParticipator me, RelationParticipator that) { - return getRelationTo(that, me, false); - } + public static Relation getRelationTo(RelationParticipator me, RelationParticipator that) { + return getRelationTo(that, me, false); + } - public static Relation getRelationTo(RelationParticipator me, RelationParticipator that, boolean ignorePeaceful) { - Faction fthat = getFaction(that); - Faction fme = getFaction(me); + public static Relation getRelationTo(RelationParticipator me, RelationParticipator that, boolean ignorePeaceful) { + Faction fthat = getFaction(that); + Faction fme = getFaction(me); - if (fthat == null || fme == null) { - return Relation.NEUTRAL; // ERROR - } + if (fthat == null || fme == null) { + return Relation.NEUTRAL; // ERROR + } - if (!fthat.isNormal() || !fme.isNormal()) { - return Relation.NEUTRAL; - } + if (!fthat.isNormal() || !fme.isNormal()) { + return Relation.NEUTRAL; + } - if (fthat.equals(fme)) { - return Relation.MEMBER; - } + if (fthat.equals(fme)) { + return Relation.MEMBER; + } - if (!ignorePeaceful && (fme.isPeaceful() || fthat.isPeaceful())) { - return Relation.NEUTRAL; - } + if (!ignorePeaceful && (fme.isPeaceful() || fthat.isPeaceful())) { + return Relation.NEUTRAL; + } - if (fme.getRelationWish(fthat).value >= fthat.getRelationWish(fme).value) { - return fthat.getRelationWish(fme); - } + if (fme.getRelationWish(fthat).value >= fthat.getRelationWish(fme).value) { + return fthat.getRelationWish(fme); + } - return fme.getRelationWish(fthat); - } + return fme.getRelationWish(fthat); + } - public static Faction getFaction(RelationParticipator rp) { - if (rp instanceof Faction) { - return (Faction) rp; - } + public static Faction getFaction(RelationParticipator rp) { + if (rp instanceof Faction) { + return (Faction) rp; + } - if (rp instanceof FPlayer) { - return ((FPlayer) rp).getFaction(); - } + if (rp instanceof FPlayer) { + return ((FPlayer) rp).getFaction(); + } - // ERROR - return null; - } + // ERROR + return null; + } - public static ChatColor getColorOfThatToMe(RelationParticipator that, RelationParticipator me) { - Faction thatFaction = getFaction(that); + public static ChatColor getColorOfThatToMe(RelationParticipator that, RelationParticipator me) { + Faction thatFaction = getFaction(that); - if (thatFaction != null && thatFaction != getFaction(me)) { - if (thatFaction.isPeaceful()) - return Conf.colorPeaceful; - else if (thatFaction.isSafeZone()) - return Conf.colorPeaceful; - else if (thatFaction.isWarZone()) - return Conf.colorWar; - } + if (thatFaction != null && thatFaction != getFaction(me)) { + if (thatFaction.isPeaceful()) + return Conf.colorPeaceful; + else if (thatFaction.isSafeZone()) + return Conf.colorPeaceful; + else if (thatFaction.isWarZone()) + return Conf.colorWar; + } - return getRelationTo(that, me).getColor(); - } + return getRelationTo(that, me).getColor(); + } } diff --git a/src/main/java/com/massivecraft/factions/util/SpiralTask.java b/src/main/java/com/massivecraft/factions/util/SpiralTask.java index 1124bf8b..1b209fd4 100644 --- a/src/main/java/com/massivecraft/factions/util/SpiralTask.java +++ b/src/main/java/com/massivecraft/factions/util/SpiralTask.java @@ -24,186 +24,186 @@ import java.util.logging.Level; public abstract class SpiralTask implements Runnable { - // general task-related reference data - private transient World world = null; - private transient boolean readyToGo = false; - private transient int taskID = -1; - private transient int limit = 0; + // general task-related reference data + private transient World world = null; + private transient boolean readyToGo = false; + private transient int taskID = -1; + private transient int limit = 0; - // values for the spiral pattern routine - private transient int x = 0; - private transient int z = 0; - private transient boolean isZLeg = false; - private transient boolean isNeg = false; - private transient int length = -1; - private transient int current = 0; + // values for the spiral pattern routine + private transient int x = 0; + private transient int z = 0; + private transient boolean isZLeg = false; + private transient boolean isNeg = false; + private transient int length = -1; + private transient int current = 0; - @SuppressWarnings("LeakingThisInConstructor") - public SpiralTask(FLocation fLocation, int radius) { - // limit is determined based on spiral leg length for given radius; see insideRadius() - this.limit = (radius - 1) * 2; + @SuppressWarnings("LeakingThisInConstructor") + public SpiralTask(FLocation fLocation, int radius) { + // limit is determined based on spiral leg length for given radius; see insideRadius() + this.limit = (radius - 1) * 2; - this.world = Bukkit.getWorld(fLocation.getWorldName()); - if (this.world == null) { - SavageFactions.plugin.log(Level.WARNING, "[SpiralTask] A valid world must be specified!"); - this.stop(); - return; - } + this.world = Bukkit.getWorld(fLocation.getWorldName()); + if (this.world == null) { + SavageFactions.plugin.log(Level.WARNING, "[SpiralTask] A valid world must be specified!"); + this.stop(); + return; + } - this.x = (int) fLocation.getX(); - this.z = (int) fLocation.getZ(); + this.x = (int) fLocation.getX(); + this.z = (int) fLocation.getZ(); - this.readyToGo = true; + this.readyToGo = true; - // get this party started - this.setTaskID(Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, this, 2, 2)); - } + // get this party started + this.setTaskID(Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, this, 2, 2)); + } - private static long now() { - return System.currentTimeMillis(); - } + private static long now() { + return System.currentTimeMillis(); + } - /* - * This is where the necessary work is done; you'll need to override this method with whatever you want - * done at each chunk in the spiral pattern. - * Return false if the entire task needs to be aborted, otherwise return true to continue. - */ - public abstract boolean work(); + /* + * This is where the necessary work is done; you'll need to override this method with whatever you want + * done at each chunk in the spiral pattern. + * Return false if the entire task needs to be aborted, otherwise return true to continue. + */ + public abstract boolean work(); - /* - * Returns an FLocation pointing at the current chunk X and Z values. - */ - public final FLocation currentFLocation() { - return new FLocation(world.getName(), x, z); - } + /* + * Returns an FLocation pointing at the current chunk X and Z values. + */ + public final FLocation currentFLocation() { + return new FLocation(world.getName(), x, z); + } - /* - * Returns a Location pointing at the current chunk X and Z values. - * note that the Location is at the corner of the chunk, not the center. - */ - public final Location currentLocation() { - return new Location(world, FLocation.chunkToBlock(x), 65.0, FLocation.chunkToBlock(z)); - } + /* + * Returns a Location pointing at the current chunk X and Z values. + * note that the Location is at the corner of the chunk, not the center. + */ + public final Location currentLocation() { + return new Location(world, FLocation.chunkToBlock(x), 65.0, FLocation.chunkToBlock(z)); + } - /* - * Returns current chunk X and Z values. - */ - public final int getX() { - return x; - } + /* + * Returns current chunk X and Z values. + */ + public final int getX() { + return x; + } - /* - * Below are the guts of the class, which you normally wouldn't need to mess with. - */ + /* + * Below are the guts of the class, which you normally wouldn't need to mess with. + */ - public final int getZ() { - return z; - } + public final int getZ() { + return z; + } - public final void setTaskID(int ID) { - if (ID == -1) { - this.stop(); - } - taskID = ID; - } + public final void setTaskID(int ID) { + if (ID == -1) { + this.stop(); + } + taskID = ID; + } - public final void run() { - if (!this.valid() || !readyToGo) { - return; - } + public final void run() { + if (!this.valid() || !readyToGo) { + return; + } - // this is set so it only does one iteration at a time, no matter how frequently the timer fires - readyToGo = false; + // this is set so it only does one iteration at a time, no matter how frequently the timer fires + readyToGo = false; - // make sure we're still inside the specified radius - if (!this.insideRadius()) { - return; - } + // make sure we're still inside the specified radius + if (!this.insideRadius()) { + return; + } - // track this to keep one iteration from dragging on too long and possibly choking the system - long loopStartTime = now(); + // track this to keep one iteration from dragging on too long and possibly choking the system + long loopStartTime = now(); - // keep going until the task has been running for 20ms or more, then stop to take a breather - while (now() < loopStartTime + 20) { - // run the primary task on the current X/Z coordinates - if (!this.work()) { - this.finish(); - return; - } + // keep going until the task has been running for 20ms or more, then stop to take a breather + while (now() < loopStartTime + 20) { + // run the primary task on the current X/Z coordinates + if (!this.work()) { + this.finish(); + return; + } - // move on to next chunk in spiral - if (!this.moveToNext()) { - return; - } - } + // move on to next chunk in spiral + if (!this.moveToNext()) { + return; + } + } - // ready for the next iteration to run - readyToGo = true; - } + // ready for the next iteration to run + readyToGo = true; + } - // step through chunks in spiral pattern from center; returns false if we're done, otherwise returns true - public final boolean moveToNext() { - if (!this.valid()) { - return false; - } + // step through chunks in spiral pattern from center; returns false if we're done, otherwise returns true + public final boolean moveToNext() { + if (!this.valid()) { + return false; + } - // make sure we don't need to turn down the next leg of the spiral - if (current < length) { - current++; + // make sure we don't need to turn down the next leg of the spiral + if (current < length) { + current++; - // if we're outside the radius, we're done - if (!this.insideRadius()) { - return false; - } - } else { // one leg/side of the spiral down... - current = 0; - isZLeg ^= true; - // every second leg (between X and Z legs, negative or positive), length increases - if (isZLeg) { - isNeg ^= true; - length++; - } - } + // if we're outside the radius, we're done + if (!this.insideRadius()) { + return false; + } + } else { // one leg/side of the spiral down... + current = 0; + isZLeg ^= true; + // every second leg (between X and Z legs, negative or positive), length increases + if (isZLeg) { + isNeg ^= true; + length++; + } + } - // move one chunk further in the appropriate direction - if (isZLeg) { - z += (isNeg) ? -1 : 1; - } else { - x += (isNeg) ? -1 : 1; - } + // move one chunk further in the appropriate direction + if (isZLeg) { + z += (isNeg) ? -1 : 1; + } else { + x += (isNeg) ? -1 : 1; + } - return true; - } + return true; + } - public final boolean insideRadius() { - boolean inside = current < limit; - if (!inside) { - this.finish(); - } - return inside; - } + public final boolean insideRadius() { + boolean inside = current < limit; + if (!inside) { + this.finish(); + } + return inside; + } - // for successful completion - public void finish() { + // for successful completion + public void finish() { // SavageFactions.plugin.log("SpiralTask successfully completed!"); - this.stop(); - } + this.stop(); + } - // we're done, whether finished or cancelled - public final void stop() { - if (!this.valid()) { - return; - } + // we're done, whether finished or cancelled + public final void stop() { + if (!this.valid()) { + return; + } - readyToGo = false; - Bukkit.getServer().getScheduler().cancelTask(taskID); - taskID = -1; - } + readyToGo = false; + Bukkit.getServer().getScheduler().cancelTask(taskID); + taskID = -1; + } - // is this task still valid/workable? - public final boolean valid() { - return taskID != -1; - } + // is this task still valid/workable? + public final boolean valid() { + return taskID != -1; + } } diff --git a/src/main/java/com/massivecraft/factions/util/UtilFly.java b/src/main/java/com/massivecraft/factions/util/UtilFly.java index 4a8a11f0..c8acf539 100644 --- a/src/main/java/com/massivecraft/factions/util/UtilFly.java +++ b/src/main/java/com/massivecraft/factions/util/UtilFly.java @@ -12,103 +12,103 @@ import java.util.Iterator; public class UtilFly { - public static ArrayList playersFlying; + public static ArrayList playersFlying; - static { - playersFlying = SavageFactions.playersFlying; - } + static { + playersFlying = SavageFactions.playersFlying; + } - public UtilFly() { - } + public UtilFly() { + } - public static void run() { - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - playersFlying.clear(); - Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { - public void run() { - Iterator var2 = UtilFly.playersFlying.iterator(); + public static void run() { + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + playersFlying.clear(); + Bukkit.getScheduler().scheduleSyncRepeatingTask(SavageFactions.plugin, new Runnable() { + public void run() { + Iterator var2 = UtilFly.playersFlying.iterator(); - while (var2.hasNext()) { - FPlayer fp = (FPlayer) var2.next(); - if (fp != null) { - fp.checkIfNearbyEnemies(); - } - } + while (var2.hasNext()) { + FPlayer fp = (FPlayer) var2.next(); + if (fp != null) { + fp.checkIfNearbyEnemies(); + } + } - } - }, 0L, (long) SavageFactions.plugin.getConfig().getInt("fly-task-interval", 10)); - } - } + } + }, 0L, (long) SavageFactions.plugin.getConfig().getInt("fly-task-interval", 10)); + } + } - public static void setFly(FPlayer fp, boolean fly, boolean silent, boolean damage) { - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - fp.getPlayer().setAllowFlight(fly); - fp.getPlayer().setFlying(fly); - fp.setFlying(fly); - if (fly) { - playersFlying.add(fp); - } else { - playersFlying.remove(fp); - } + public static void setFly(FPlayer fp, boolean fly, boolean silent, boolean damage) { + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + fp.getPlayer().setAllowFlight(fly); + fp.getPlayer().setFlying(fly); + fp.setFlying(fly); + if (fly) { + playersFlying.add(fp); + } else { + playersFlying.remove(fp); + } - if (!silent) { - if (!damage) { - fp.msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); - } else { - fp.msg(TL.COMMAND_FLY_DAMAGE); - } - } + if (!silent) { + if (!damage) { + fp.msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); + } else { + fp.msg(TL.COMMAND_FLY_DAMAGE); + } + } - setFallDamage(fp, fly, damage); - } - } + setFallDamage(fp, fly, damage); + } + } - public static void checkFly(FPlayer me, Faction factionTo) { - if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { - if (!me.isAdminBypassing() || !me.isFlying()) { - Relation relationTo; - if (!me.isFlying()) { - if (me.isAdminBypassing()) { - setFly(me, true, false, false); - return; - } + public static void checkFly(FPlayer me, Faction factionTo) { + if (SavageFactions.plugin.getConfig().getBoolean("enable-faction-flight")) { + if (!me.isAdminBypassing() || !me.isFlying()) { + Relation relationTo; + if (!me.isFlying()) { + if (me.isAdminBypassing()) { + setFly(me, true, false, false); + return; + } - if (factionTo == me.getFaction() && me.getPlayer().hasPermission("factions.fly")) { - setFly(me, true, false, false); - } else { - relationTo = factionTo.getRelationTo(me); - if (factionTo.isWilderness() && me.canflyinWilderness() || factionTo.isWarZone() && me.canflyinWarzone() || factionTo.isSafeZone() && me.canflyinSafezone() || relationTo == Relation.ENEMY && me.canflyinEnemy() || relationTo == Relation.ALLY && me.canflyinAlly() || relationTo == Relation.TRUCE && me.canflyinTruce() || relationTo == Relation.NEUTRAL && me.canflyinNeutral()) { - setFly(me, true, false, false); - } - } - } else { - relationTo = factionTo.getRelationTo(me); - if (factionTo.equals(me.getFaction()) && !me.getPlayer().hasPermission("factions.fly") || factionTo.isWilderness() && !me.canflyinWilderness() || factionTo.isWarZone() && !me.canflyinWarzone() || factionTo.isSafeZone() && !me.canflyinSafezone() || relationTo == Relation.ENEMY && !me.canflyinEnemy() || relationTo == Relation.ALLY && !me.canflyinAlly() || relationTo == Relation.TRUCE && !me.canflyinTruce() || relationTo == Relation.NEUTRAL && !me.canflyinNeutral()) { - setFly(me, false, false, false); - } - } + if (factionTo == me.getFaction() && me.getPlayer().hasPermission("factions.fly")) { + setFly(me, true, false, false); + } else { + relationTo = factionTo.getRelationTo(me); + if (factionTo.isWilderness() && me.canflyinWilderness() || factionTo.isWarZone() && me.canflyinWarzone() || factionTo.isSafeZone() && me.canflyinSafezone() || relationTo == Relation.ENEMY && me.canflyinEnemy() || relationTo == Relation.ALLY && me.canflyinAlly() || relationTo == Relation.TRUCE && me.canflyinTruce() || relationTo == Relation.NEUTRAL && me.canflyinNeutral()) { + setFly(me, true, false, false); + } + } + } else { + relationTo = factionTo.getRelationTo(me); + if (factionTo.equals(me.getFaction()) && !me.getPlayer().hasPermission("factions.fly") || factionTo.isWilderness() && !me.canflyinWilderness() || factionTo.isWarZone() && !me.canflyinWarzone() || factionTo.isSafeZone() && !me.canflyinSafezone() || relationTo == Relation.ENEMY && !me.canflyinEnemy() || relationTo == Relation.ALLY && !me.canflyinAlly() || relationTo == Relation.TRUCE && !me.canflyinTruce() || relationTo == Relation.NEUTRAL && !me.canflyinNeutral()) { + setFly(me, false, false, false); + } + } - } - } - } + } + } + } - public static void setFallDamage(final FPlayer fp, boolean fly, boolean damage) { - if (!fly) { - if (!damage) { - fp.sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", String.valueOf(SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3)))); - } + public static void setFallDamage(final FPlayer fp, boolean fly, boolean damage) { + if (!fly) { + if (!damage) { + fp.sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", String.valueOf(SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3)))); + } - int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); - if (cooldown > 0) { - fp.setTakeFallDamage(false); - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - public void run() { - fp.setTakeFallDamage(true); - } - }, 20L * (long) cooldown); - } - } + int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); + if (cooldown > 0) { + fp.setTakeFallDamage(false); + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + public void run() { + fp.setTakeFallDamage(true); + } + }, 20L * (long) cooldown); + } + } - } + } } diff --git a/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java b/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java index a817e166..f786900e 100644 --- a/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java +++ b/src/main/java/com/massivecraft/factions/util/VisualizeUtil.java @@ -9,64 +9,64 @@ import java.util.*; public class VisualizeUtil { - protected static Map> playerLocations = new HashMap<>(); + protected static Map> playerLocations = new HashMap<>(); - public static Set getPlayerLocations(Player player) { - return getPlayerLocations(player.getUniqueId()); - } + public static Set getPlayerLocations(Player player) { + return getPlayerLocations(player.getUniqueId()); + } - public static Set getPlayerLocations(UUID uuid) { - Set ret = playerLocations.get(uuid); - if (ret == null) { - ret = new HashSet<>(); - playerLocations.put(uuid, ret); - } - return ret; - } + public static Set getPlayerLocations(UUID uuid) { + Set ret = playerLocations.get(uuid); + if (ret == null) { + ret = new HashSet<>(); + playerLocations.put(uuid, ret); + } + return ret; + } - @SuppressWarnings("deprecation") - public static void addLocation(Player player, Location location, Material type, byte data) { - getPlayerLocations(player).add(location); - player.sendBlockChange(location, type, data); - } + @SuppressWarnings("deprecation") + public static void addLocation(Player player, Location location, Material type, byte data) { + getPlayerLocations(player).add(location); + player.sendBlockChange(location, type, data); + } - @SuppressWarnings("deprecation") - public static void addLocation(Player player, Location location, Material material) { - getPlayerLocations(player).add(location); - player.sendBlockChange(location, material, (byte) 0); - } + @SuppressWarnings("deprecation") + public static void addLocation(Player player, Location location, Material material) { + getPlayerLocations(player).add(location); + player.sendBlockChange(location, material, (byte) 0); + } - @SuppressWarnings("deprecation") - public static void addLocations(Player player, Collection locations, Material material) { - Set ploc = getPlayerLocations(player); - for (Location location : locations) { - ploc.add(location); - player.sendBlockChange(location, material, (byte) 0); - } - } + @SuppressWarnings("deprecation") + public static void addLocations(Player player, Collection locations, Material material) { + Set ploc = getPlayerLocations(player); + for (Location location : locations) { + ploc.add(location); + player.sendBlockChange(location, material, (byte) 0); + } + } - @SuppressWarnings("deprecation") - public static void addBlocks(Player player, Collection blocks, Material material) { - Set ploc = getPlayerLocations(player); - for (Block block : blocks) { - Location location = block.getLocation(); - ploc.add(location); - player.sendBlockChange(location, material, (byte) 0); - } - } + @SuppressWarnings("deprecation") + public static void addBlocks(Player player, Collection blocks, Material material) { + Set ploc = getPlayerLocations(player); + for (Block block : blocks) { + Location location = block.getLocation(); + ploc.add(location); + player.sendBlockChange(location, material, (byte) 0); + } + } - @SuppressWarnings("deprecation") - public static void clear(Player player) { - Set locations = getPlayerLocations(player); - if (locations == null) { - return; - } - for (Location location : locations) { - Block block = location.getWorld().getBlockAt(location); - player.sendBlockChange(location, block.getType(), block.getData()); - } - locations.clear(); - } + @SuppressWarnings("deprecation") + public static void clear(Player player) { + Set locations = getPlayerLocations(player); + if (locations == null) { + return; + } + for (Location location : locations) { + Block block = location.getWorld().getBlockAt(location); + player.sendBlockChange(location, block.getType(), block.getData()); + } + locations.clear(); + } } diff --git a/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java b/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java index 8de53dff..bfd08ef6 100644 --- a/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java +++ b/src/main/java/com/massivecraft/factions/util/WarmUpUtil.java @@ -6,37 +6,37 @@ import com.massivecraft.factions.zcore.util.TL; public class WarmUpUtil { - /** - * @param player The player to notify. - * @param translationKey The translation key used for notifying. - * @param action The action, inserted into the notification message. - * @param runnable The task to run after the delay. If the delay is 0, the task is instantly ran. - * @param delay The time used, in seconds, for the delay. - *

    - * note: for translations: %s = action, %d = delay - */ - public static void process(final FPlayer player, Warmup warmup, TL translationKey, String action, final Runnable runnable, long delay) { - if (delay > 0) { - if (player.isWarmingUp()) { - player.msg(TL.WARMUPS_ALREADY); - } else { - player.msg(translationKey.format(action, delay)); - int id = SavageFactions.plugin.getServer().getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - player.stopWarmup(); - runnable.run(); - } - }, delay * 20).getTaskId(); - player.addWarmup(warmup, id); - } - } else { - runnable.run(); - } - } + /** + * @param player The player to notify. + * @param translationKey The translation key used for notifying. + * @param action The action, inserted into the notification message. + * @param runnable The task to run after the delay. If the delay is 0, the task is instantly ran. + * @param delay The time used, in seconds, for the delay. + *

    + * note: for translations: %s = action, %d = delay + */ + public static void process(final FPlayer player, Warmup warmup, TL translationKey, String action, final Runnable runnable, long delay) { + if (delay > 0) { + if (player.isWarmingUp()) { + player.msg(TL.WARMUPS_ALREADY); + } else { + player.msg(translationKey.format(action, delay)); + int id = SavageFactions.plugin.getServer().getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + player.stopWarmup(); + runnable.run(); + } + }, delay * 20).getTaskId(); + player.addWarmup(warmup, id); + } + } else { + runnable.run(); + } + } - public enum Warmup { - HOME, WARP, FLIGHT, BANNER, CHECKPOINT - } + public enum Warmup { + HOME, WARP, FLIGHT, BANNER, CHECKPOINT + } } diff --git a/src/main/java/com/massivecraft/factions/util/WarpGUI.java b/src/main/java/com/massivecraft/factions/util/WarpGUI.java index 7936ffe1..702c7a6f 100644 --- a/src/main/java/com/massivecraft/factions/util/WarpGUI.java +++ b/src/main/java/com/massivecraft/factions/util/WarpGUI.java @@ -24,241 +24,241 @@ import java.util.logging.Level; public class WarpGUI implements InventoryHolder, FactionGUI { - private final ConfigurationSection section; - int guiSize; - private Inventory warpGUI; - private FPlayer fme; - private HashMap warpSlots = new HashMap<>(); - private int maxWarps; - private List dummySlots = new ArrayList<>(); + private final ConfigurationSection section; + int guiSize; + private Inventory warpGUI; + private FPlayer fme; + private HashMap warpSlots = new HashMap<>(); + private int maxWarps; + private List dummySlots = new ArrayList<>(); - public WarpGUI(FPlayer fme) { - this.fme = fme; - this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fwarp-gui"); - } + public WarpGUI(FPlayer fme) { + this.fme = fme; + this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fwarp-gui"); + } - @Override - public void build() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + @Override + public void build() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - // Build basic Inventory info - guiSize = section.getInt("rows", 3); - if (guiSize > 6) { - guiSize = 6; - SavageFactions.plugin.log(Level.INFO, "Warp GUI size out of bounds, defaulting to 6"); - } + // Build basic Inventory info + guiSize = section.getInt("rows", 3); + if (guiSize > 6) { + guiSize = 6; + SavageFactions.plugin.log(Level.INFO, "Warp GUI size out of bounds, defaulting to 6"); + } - guiSize *= 9; - String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); - warpGUI = Bukkit.createInventory(this, guiSize, guiName); + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); + warpGUI = Bukkit.createInventory(this, guiSize, guiName); - maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); + maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); - Set factionWarps = fme.getFaction().getWarps().keySet(); - List warpOpenSlots = section.getIntegerList("warp-slots"); + Set factionWarps = fme.getFaction().getWarps().keySet(); + List warpOpenSlots = section.getIntegerList("warp-slots"); - buildDummyItems(); + buildDummyItems(); - if (maxWarps != warpOpenSlots.size()) { - SavageFactions.plugin.log(Level.SEVERE, "Invalid warp slots for GUI, Please use same value as max warps"); - return; - } + if (maxWarps != warpOpenSlots.size()) { + SavageFactions.plugin.log(Level.SEVERE, "Invalid warp slots for GUI, Please use same value as max warps"); + return; + } - int warpSlotIndex = 0; - for (String warp : factionWarps) { - warpSlots.put(warpOpenSlots.get(warpSlotIndex), warp); - warpSlotIndex++; - } + int warpSlotIndex = 0; + for (String warp : factionWarps) { + warpSlots.put(warpOpenSlots.get(warpSlotIndex), warp); + warpSlotIndex++; + } - buildItems(); - } + buildItems(); + } - @Override - public Inventory getInventory() { - return warpGUI; - } + @Override + public Inventory getInventory() { + return warpGUI; + } - private void buildItems() { - for (Map.Entry entry : warpSlots.entrySet()) { - warpGUI.setItem(entry.getKey(), buildItem(entry.getValue())); - } - } + private void buildItems() { + for (Map.Entry entry : warpSlots.entrySet()) { + warpGUI.setItem(entry.getKey(), buildItem(entry.getValue())); + } + } - @Override - public void onClick(int slot, ClickType action) { - if (warpSlots.containsKey(slot)) { - fme.getPlayer().closeInventory(); + @Override + public void onClick(int slot, ClickType action) { + if (warpSlots.containsKey(slot)) { + fme.getPlayer().closeInventory(); - // All clear lets TP them or ask for password - String warp = warpSlots.get(slot); - if (!fme.getFaction().hasWarpPassword(warp)) { - if (transact(fme)) { - doWarmup(warp); - } - } else { - fme.setEnteringPassword(true, warp); - fme.msg(TL.COMMAND_FWARP_PASSWORD_REQUIRED); - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - if (fme.isEnteringPassword()) { - fme.msg(TL.COMMAND_FWARP_PASSWORD_TIMEOUT); - fme.setEnteringPassword(false, ""); - } - } - }, SavageFactions.plugin.getConfig().getInt("fwarp-gui.password-timeout", 5) * 20); - } - } - } + // All clear lets TP them or ask for password + String warp = warpSlots.get(slot); + if (!fme.getFaction().hasWarpPassword(warp)) { + if (transact(fme)) { + doWarmup(warp); + } + } else { + fme.setEnteringPassword(true, warp); + fme.msg(TL.COMMAND_FWARP_PASSWORD_REQUIRED); + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + if (fme.isEnteringPassword()) { + fme.msg(TL.COMMAND_FWARP_PASSWORD_TIMEOUT); + fme.setEnteringPassword(false, ""); + } + } + }, SavageFactions.plugin.getConfig().getInt("fwarp-gui.password-timeout", 5) * 20); + } + } + } - private void doWarmup(final String warp) { - WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); - if (player != null) { - player.teleport(fme.getFaction().getWarp(warp).getLocation()); - fme.msg(TL.COMMAND_FWARP_WARPED, warp); - } - } - }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); - } + private void doWarmup(final String warp) { + WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { + @Override + public void run() { + Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); + if (player != null) { + player.teleport(fme.getFaction().getWarp(warp).getLocation()); + fme.msg(TL.COMMAND_FWARP_WARPED, warp); + } + } + }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); + } - private boolean transact(FPlayer player) { - if (!SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing()) { - return true; - } + private boolean transact(FPlayer player) { + if (!SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing()) { + return true; + } - double cost = SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5); + double cost = SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5); - if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { - return true; - } + if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { + return true; + } - if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { - return Econ.modifyMoney(fme.getFaction(), -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); - } else { - return Econ.modifyMoney(fme, -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); - } - } + if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { + return Econ.modifyMoney(fme.getFaction(), -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); + } else { + return Econ.modifyMoney(fme, -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); + } + } - private ItemStack buildItem(String warp) { - ConfigurationSection warpItemSection = section.getConfigurationSection("warp-item"); - if (warpItemSection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + private ItemStack buildItem(String warp) { + ConfigurationSection warpItemSection = section.getConfigurationSection("warp-item"); + if (warpItemSection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - String displayName = replacePlaceholers(warpItemSection.getString("name"), warp, fme.getFaction()); - List lore = new ArrayList<>(); + String displayName = replacePlaceholers(warpItemSection.getString("name"), warp, fme.getFaction()); + List lore = new ArrayList<>(); - if (warpItemSection.getString("material") == null) { - return null; - } - Material material = Material.matchMaterial(warpItemSection.getString("material")); - if (material == null) { - material = Material.STONE; - } + if (warpItemSection.getString("material") == null) { + return null; + } + Material material = Material.matchMaterial(warpItemSection.getString("material")); + if (material == null) { + material = Material.STONE; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - for (String loreLine : warpItemSection.getStringList("lore")) { - lore.add(replacePlaceholers(loreLine, warp, fme.getFaction())); - } + for (String loreLine : warpItemSection.getStringList("lore")) { + lore.add(replacePlaceholers(loreLine, warp, fme.getFaction())); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - private String replacePlaceholers(String string, String warp, Faction faction) { - string = ChatColor.translateAlternateColorCodes('&', string); - string = string.replace("{warp}", warp); - string = string.replace("{warp-protected}", faction.hasWarpPassword(warp) ? "Enabled" : "Disabled"); - string = string.replace("{warp-cost}", !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) ? "Disabled" : Integer.toString(SavageFactions.plugin.getConfig().getInt("warp-cost.warp", 5))); - return string; - } + private String replacePlaceholers(String string, String warp, Faction faction) { + string = ChatColor.translateAlternateColorCodes('&', string); + string = string.replace("{warp}", warp); + string = string.replace("{warp-protected}", faction.hasWarpPassword(warp) ? "Enabled" : "Disabled"); + string = string.replace("{warp-cost}", !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) ? "Disabled" : Integer.toString(SavageFactions.plugin.getConfig().getInt("warp-cost.warp", 5))); + return string; + } - private void buildDummyItems() { - for (String key : section.getConfigurationSection("dummy-slots").getKeys(false)) { - int dummyId; - try { - dummyId = Integer.parseInt(key); - } catch (NumberFormatException exception) { - SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); - continue; - } + private void buildDummyItems() { + for (String key : section.getConfigurationSection("dummy-slots").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } - ItemStack dummyItem = buildDummyItem(dummyId); - if (dummyItem == null) { - continue; - } + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } - List dummyIdSlots = section.getIntegerList("dummy-slots." + key); - for (Integer slot : dummyIdSlots) { - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); - continue; - } - dummySlots.add(slot); - warpGUI.setItem(slot, dummyItem); - } - } - } + List dummyIdSlots = section.getIntegerList("dummy-slots." + key); + for (Integer slot : dummyIdSlots) { + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + dummySlots.add(slot); + warpGUI.setItem(slot, dummyItem); + } + } + } - private ItemStack buildDummyItem(int id) { - final ConfigurationSection dummySection = section.getConfigurationSection("dummy-items." + id); + private ItemStack buildDummyItem(int id) { + final ConfigurationSection dummySection = section.getConfigurationSection("dummy-items." + id); - if (dummySection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (dummySection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - Material material = Material.matchMaterial(dummySection.getString("material", "")); - if (material == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); - return null; - } + Material material = Material.matchMaterial(dummySection.getString("material", "")); + if (material == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } - ItemStack itemStack = new ItemStack(material); + ItemStack itemStack = new ItemStack(material); - DyeColor color; - try { - color = DyeColor.valueOf(dummySection.getString("color", "")); - } catch (Exception exception) { - color = null; - } - if (color != null) { - itemStack.setDurability(color.getWoolData()); - } + DyeColor color; + try { + color = DyeColor.valueOf(dummySection.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } - ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta itemMeta = itemStack.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); - List lore = new ArrayList<>(); - for (String loreLine : dummySection.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } - itemMeta.setLore(lore); + List lore = new ArrayList<>(); + for (String loreLine : dummySection.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + itemMeta.setLore(lore); - itemStack.setItemMeta(itemMeta); + itemStack.setItemMeta(itemMeta); - return itemStack; - } + return itemStack; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java b/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java index bed3cb90..2bc4a19d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java +++ b/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java @@ -1,7 +1,7 @@ -package com.massivecraft.factions.zcore; - -public enum CommandVisibility { - VISIBLE, // Visible commands are visible to anyone. Even those who don't have permission to use it or is of invalid sender type. - SECRET, // Secret commands are visible only to those who can use the command. These commands are usually some kind of admin commands. - INVISIBLE // Invisible commands are invisible to everyone, even those who can use the command. -} +package com.massivecraft.factions.zcore; + +public enum CommandVisibility { + VISIBLE, // Visible commands are visible to anyone. Even those who don't have permission to use it or is of invalid sender type. + SECRET, // Secret commands are visible only to those who can use the command. These commands are usually some kind of admin commands. + INVISIBLE // Invisible commands are invisible to everyone, even those who can use the command. +} diff --git a/src/main/java/com/massivecraft/factions/zcore/MCommand.java b/src/main/java/com/massivecraft/factions/zcore/MCommand.java index 94919da4..013e3ae9 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MCommand.java +++ b/src/main/java/com/massivecraft/factions/zcore/MCommand.java @@ -23,463 +23,463 @@ import java.util.UUID; public abstract class MCommand { - public T p; - - // The sub-commands to this command - public List> subCommands; - // The different names this commands will react to - public List aliases; - public boolean allowNoSlashAccess; - // Information on the args - public List requiredArgs; - public LinkedHashMap optionalArgs; - public boolean errorOnToManyArgs = true; - public List helpLong; - public CommandVisibility visibility; - // Some information on permissions - public boolean senderMustBePlayer; - public boolean senderMustHaveFaction; - public String permission; - // Information available on execution of the command - public CommandSender sender; // Will always be set - public Player me; // Will only be set when the sender is a player - public boolean senderIsConsole; - public List args; // Will contain the arguments, or and empty list if there are none. - public List> commandChain = new ArrayList<>(); // The command chain used to execute this command - // FIELD: Help Short - // This field may be left blank and will in such case be loaded from the permissions node instead. - // Thus make sure the permissions node description is an action description like "eat hamburgers" or "do admin stuff". - private String helpShort; - - public MCommand(T p) { - this.p = p; - - this.permission = null; - - this.allowNoSlashAccess = false; - - this.subCommands = new ArrayList<>(); - this.aliases = new ArrayList<>(); - - this.requiredArgs = new ArrayList<>(); - this.optionalArgs = new LinkedHashMap<>(); - - this.helpShort = null; - this.helpLong = new ArrayList<>(); - this.visibility = CommandVisibility.VISIBLE; - } - - public void addSubCommand(MCommand subCommand) { - subCommand.commandChain.addAll(this.commandChain); - subCommand.commandChain.add(this); - this.subCommands.add(subCommand); - } - - public String getHelpShort() { - return this.helpShort != null ? this.helpShort : getUsageTranslation().toString(); - } - - public void setHelpShort(String val) { - this.helpShort = val; - } - - public abstract TL getUsageTranslation(); - - public void setCommandSender(CommandSender sender) { - this.sender = sender; - if (sender instanceof Player) { - this.me = (Player) sender; - this.senderIsConsole = false; - } else { - this.me = null; - this.senderIsConsole = true; - } - } - - // The commandChain is a list of the parent command chain used to get to this command. - public void execute(CommandSender sender, List args, List> commandChain) { - // Set the execution-time specific variables - setCommandSender(sender); - this.args = args; - this.commandChain = commandChain; - - // Is there a matching sub command? - if (args.size() > 0) { - for (MCommand subCommand : this.subCommands) { - if (subCommand.aliases.contains(args.get(0).toLowerCase())) { - args.remove(0); - commandChain.add(this); - subCommand.execute(sender, args, commandChain); - return; - } - } - } - - if (!validCall(this.sender, this.args)) { - return; - } - - if (!this.isEnabled()) { - return; - } - - perform(); - } - - public void execute(CommandSender sender, List args) { - execute(sender, args, new ArrayList>()); - } - - // This is where the command action is performed. - public abstract void perform(); - - - // -------------------------------------------- // - // Call Validation - // -------------------------------------------- // - - /** - * In this method we validate that all prerequisites to perform this command has been met. - * - * @param sender of the command - * @param args of the command - * @return true if valid, false if not. - */ - // TODO: There should be a boolean for silence - public boolean validCall(CommandSender sender, List args) { - return validSenderType(sender, true) && validSenderPermissions(sender, true) && validArgs(args, sender); - } - - public boolean isEnabled() { - return true; - } - - - public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { - if (this.senderMustBePlayer && !(sender instanceof Player)) { - if (informSenderIfNot) { - msg(TL.GENERIC_PLAYERONLY); - } - return false; - - } - return !this.senderMustHaveFaction || !FPlayers.getInstance().getByPlayer((Player) sender).hasFaction(); - } - - public boolean validSenderPermissions(CommandSender sender, boolean informSenderIfNot) { - return this.permission == null || p.perm.has(sender, this.permission, informSenderIfNot); - } - - public boolean validArgs(List args, CommandSender sender) { - if (args.size() < this.requiredArgs.size()) { - if (sender != null) { - msg(TL.GENERIC_ARGS_TOOFEW); - sender.sendMessage(this.getUseageTemplate()); - } - return false; - } - - if (args.size() > this.requiredArgs.size() + this.optionalArgs.size() && this.errorOnToManyArgs) { - if (sender != null) { - // Get the to many string slice - List theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size()); - msg(TL.GENERIC_ARGS_TOOMANY, TextUtil.implode(theToMany, " ")); - sender.sendMessage(this.getUseageTemplate()); - } - return false; - } - return true; - } - - public boolean validArgs(List args) { - return this.validArgs(args, null); - } - - // -------------------------------------------- // - // Help and Usage information - // -------------------------------------------- // - - public String getUseageTemplate(List> commandChain, boolean addShortHelp) { - StringBuilder ret = new StringBuilder(); - ret.append(p.txt.parseTags("")); - ret.append('/'); - - for (MCommand mc : commandChain) { - ret.append(TextUtil.implode(mc.aliases, ",")); - ret.append(' '); - } - - ret.append(TextUtil.implode(this.aliases, ",")); - - List args = new ArrayList<>(); - - for (String requiredArg : this.requiredArgs) { - args.add("<" + requiredArg + ">"); - } - - for (Entry optionalArg : this.optionalArgs.entrySet()) { - String val = optionalArg.getValue(); - if (val == null) { - val = ""; - } else { - val = "=" + val; - } - args.add("[" + optionalArg.getKey() + val + "]"); - } - - if (args.size() > 0) { - ret.append(p.txt.parseTags(" ")); - ret.append(TextUtil.implode(args, " ")); - } - - if (addShortHelp) { - ret.append(p.txt.parseTags(" ")); - ret.append(this.getHelpShort()); - } - - return ret.toString(); - } - - public String getUseageTemplate(boolean addShortHelp) { - return getUseageTemplate(this.commandChain, addShortHelp); - } - - public String getUseageTemplate() { - return getUseageTemplate(false); - } - - // -------------------------------------------- // - // Message Sending Helpers - // -------------------------------------------- // - - public void msg(String str, Object... args) { - sender.sendMessage(p.txt.parse(str, args)); - } - - public void msg(TL translation, Object... args) { - sender.sendMessage(p.txt.parse(translation.toString(), args)); - } - - public void sendMessage(String msg) { - sender.sendMessage(msg); - } - - public void sendMessage(List msgs) { - for (String msg : msgs) { - this.sendMessage(msg); - } - } - - public void sendFancyMessage(FancyMessage message) { - message.send(sender); - } - - public void sendFancyMessage(List messages) { - for (FancyMessage m : messages) { - sendFancyMessage(m); - } - } - - public List getToolTips(FPlayer player) { - List lines = new ArrayList<>(); - for (String s : p.getConfig().getStringList("tooltips.show")) { - lines.add(ChatColor.translateAlternateColorCodes('&', replaceFPlayerTags(s, player))); - } - return lines; - } - - public List getToolTips(Faction faction) { - List lines = new ArrayList<>(); - for (String s : p.getConfig().getStringList("tooltips.list")) { - lines.add(ChatColor.translateAlternateColorCodes('&', replaceFactionTags(s, faction))); - } - return lines; - } - - public String replaceFPlayerTags(String s, FPlayer player) { - if (s.contains("{balance}")) { - String balance = Econ.isSetup() ? Econ.getFriendlyBalance(player) : "no balance"; - s = s.replace("{balance}", balance); - } - if (s.contains("{lastSeen}")) { - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - player.getLastLoginTime(), true, true) + " ago"; - String lastSeen = player.isOnline() ? ChatColor.GREEN + "Online" : (System.currentTimeMillis() - player.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - s = s.replace("{lastSeen}", lastSeen); - } - if (s.contains("{power}")) { - String power = player.getPowerRounded() + "/" + player.getPowerMaxRounded(); - s = s.replace("{power}", power); - } - if (s.contains("{group}")) { - String group = SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(player.getId()))); - s = s.replace("{group}", group); - } - return s; - } - - public String replaceFactionTags(String s, Faction faction) { - if (s.contains("{power}")) { - s = s.replace("{power}", String.valueOf(faction.getPowerRounded())); - } - if (s.contains("{maxPower}")) { - s = s.replace("{maxPower}", String.valueOf(faction.getPowerMaxRounded())); - } - if (s.contains("{leader}")) { - FPlayer fLeader = faction.getFPlayerAdmin(); - String leader = fLeader == null ? "Server" : fLeader.getName().substring(0, fLeader.getName().length() > 14 ? 13 : fLeader.getName().length()); - s = s.replace("{leader}", leader); - } - if (s.contains("{chunks}")) { - s = s.replace("{chunks}", String.valueOf(faction.getLandRounded())); - } - if (s.contains("{members}")) { - s = s.replace("{members}", String.valueOf(faction.getSize())); - - } - if (s.contains("{online}")) { - s = s.replace("{online}", String.valueOf(faction.getOnlinePlayers().size())); - } - return s; - } - - // -------------------------------------------- // - // Argument Readers - // -------------------------------------------- // - - // Is set? ====================== - public boolean argIsSet(int idx) { - return this.args.size() >= idx + 1; - } - - // STRING ====================== - public String argAsString(int idx, String def) { - if (this.args.size() < idx + 1) { - return def; - } - return this.args.get(idx); - } - - public String argAsString(int idx) { - return this.argAsString(idx, null); - } - - // INT ====================== - public Integer strAsInt(String str, Integer def) { - if (str == null) { - return def; - } - try { - return Integer.parseInt(str); - } catch (Exception e) { - return def; - } - } - - public Integer argAsInt(int idx, Integer def) { - return strAsInt(this.argAsString(idx), def); - } - - public Integer argAsInt(int idx) { - return this.argAsInt(idx, null); - } - - // Double ====================== - public Double strAsDouble(String str, Double def) { - if (str == null) { - return def; - } - try { - return Double.parseDouble(str); - } catch (Exception e) { - return def; - } - } - - public Double argAsDouble(int idx, Double def) { - return strAsDouble(this.argAsString(idx), def); - } - - public Double argAsDouble(int idx) { - return this.argAsDouble(idx, null); - } - - // TODO: Go through the str conversion for the other arg-readers as well. - // Boolean ====================== - public Boolean strAsBool(String str) { - str = str.toLowerCase(); - return str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"); - } - - public Boolean argAsBool(int idx, boolean def) { - String str = this.argAsString(idx); - if (str == null) { - return def; - } - - return strAsBool(str); - } - - public Boolean argAsBool(int idx) { - return this.argAsBool(idx, false); - } - - // PLAYER ====================== - public Player strAsPlayer(String name, Player def, boolean msg) { - Player ret = def; - - if (name != null) { - Player player = Bukkit.getServer().getPlayer(name); - if (player != null) { - ret = player; - } - } - - if (msg && ret == null) { - this.msg(TL.GENERIC_NOPLAYERFOUND, name); - } - - return ret; - } - - public Player argAsPlayer(int idx, Player def, boolean msg) { - return this.strAsPlayer(this.argAsString(idx), def, msg); - } - - public Player argAsPlayer(int idx, Player def) { - return this.argAsPlayer(idx, def, true); - } - - public Player argAsPlayer(int idx) { - return this.argAsPlayer(idx, null); - } - - // BEST PLAYER MATCH ====================== - public Player strAsBestPlayerMatch(String name, Player def, boolean msg) { - Player ret = def; - - if (name != null) { - List players = Bukkit.getServer().matchPlayer(name); - if (players.size() > 0) { - ret = players.get(0); - } - } - - if (msg && ret == null) { - this.msg(TL.GENERIC_NOPLAYERMATCH, name); - } - - return ret; - } - - public Player argAsBestPlayerMatch(int idx, Player def, boolean msg) { - return this.strAsBestPlayerMatch(this.argAsString(idx), def, msg); - } - - public Player argAsBestPlayerMatch(int idx, Player def) { - return this.argAsBestPlayerMatch(idx, def, true); - } - - public Player argAsBestPlayerMatch(int idx) { - return this.argAsPlayer(idx, null); - } + public T p; + + // The sub-commands to this command + public List> subCommands; + // The different names this commands will react to + public List aliases; + public boolean allowNoSlashAccess; + // Information on the args + public List requiredArgs; + public LinkedHashMap optionalArgs; + public boolean errorOnToManyArgs = true; + public List helpLong; + public CommandVisibility visibility; + // Some information on permissions + public boolean senderMustBePlayer; + public boolean senderMustHaveFaction; + public String permission; + // Information available on execution of the command + public CommandSender sender; // Will always be set + public Player me; // Will only be set when the sender is a player + public boolean senderIsConsole; + public List args; // Will contain the arguments, or and empty list if there are none. + public List> commandChain = new ArrayList<>(); // The command chain used to execute this command + // FIELD: Help Short + // This field may be left blank and will in such case be loaded from the permissions node instead. + // Thus make sure the permissions node description is an action description like "eat hamburgers" or "do admin stuff". + private String helpShort; + + public MCommand(T p) { + this.p = p; + + this.permission = null; + + this.allowNoSlashAccess = false; + + this.subCommands = new ArrayList<>(); + this.aliases = new ArrayList<>(); + + this.requiredArgs = new ArrayList<>(); + this.optionalArgs = new LinkedHashMap<>(); + + this.helpShort = null; + this.helpLong = new ArrayList<>(); + this.visibility = CommandVisibility.VISIBLE; + } + + public void addSubCommand(MCommand subCommand) { + subCommand.commandChain.addAll(this.commandChain); + subCommand.commandChain.add(this); + this.subCommands.add(subCommand); + } + + public String getHelpShort() { + return this.helpShort != null ? this.helpShort : getUsageTranslation().toString(); + } + + public void setHelpShort(String val) { + this.helpShort = val; + } + + public abstract TL getUsageTranslation(); + + public void setCommandSender(CommandSender sender) { + this.sender = sender; + if (sender instanceof Player) { + this.me = (Player) sender; + this.senderIsConsole = false; + } else { + this.me = null; + this.senderIsConsole = true; + } + } + + // The commandChain is a list of the parent command chain used to get to this command. + public void execute(CommandSender sender, List args, List> commandChain) { + // Set the execution-time specific variables + setCommandSender(sender); + this.args = args; + this.commandChain = commandChain; + + // Is there a matching sub command? + if (args.size() > 0) { + for (MCommand subCommand : this.subCommands) { + if (subCommand.aliases.contains(args.get(0).toLowerCase())) { + args.remove(0); + commandChain.add(this); + subCommand.execute(sender, args, commandChain); + return; + } + } + } + + if (!validCall(this.sender, this.args)) { + return; + } + + if (!this.isEnabled()) { + return; + } + + perform(); + } + + public void execute(CommandSender sender, List args) { + execute(sender, args, new ArrayList>()); + } + + // This is where the command action is performed. + public abstract void perform(); + + + // -------------------------------------------- // + // Call Validation + // -------------------------------------------- // + + /** + * In this method we validate that all prerequisites to perform this command has been met. + * + * @param sender of the command + * @param args of the command + * @return true if valid, false if not. + */ + // TODO: There should be a boolean for silence + public boolean validCall(CommandSender sender, List args) { + return validSenderType(sender, true) && validSenderPermissions(sender, true) && validArgs(args, sender); + } + + public boolean isEnabled() { + return true; + } + + + public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { + if (this.senderMustBePlayer && !(sender instanceof Player)) { + if (informSenderIfNot) { + msg(TL.GENERIC_PLAYERONLY); + } + return false; + + } + return !this.senderMustHaveFaction || !FPlayers.getInstance().getByPlayer((Player) sender).hasFaction(); + } + + public boolean validSenderPermissions(CommandSender sender, boolean informSenderIfNot) { + return this.permission == null || p.perm.has(sender, this.permission, informSenderIfNot); + } + + public boolean validArgs(List args, CommandSender sender) { + if (args.size() < this.requiredArgs.size()) { + if (sender != null) { + msg(TL.GENERIC_ARGS_TOOFEW); + sender.sendMessage(this.getUseageTemplate()); + } + return false; + } + + if (args.size() > this.requiredArgs.size() + this.optionalArgs.size() && this.errorOnToManyArgs) { + if (sender != null) { + // Get the to many string slice + List theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size()); + msg(TL.GENERIC_ARGS_TOOMANY, TextUtil.implode(theToMany, " ")); + sender.sendMessage(this.getUseageTemplate()); + } + return false; + } + return true; + } + + public boolean validArgs(List args) { + return this.validArgs(args, null); + } + + // -------------------------------------------- // + // Help and Usage information + // -------------------------------------------- // + + public String getUseageTemplate(List> commandChain, boolean addShortHelp) { + StringBuilder ret = new StringBuilder(); + ret.append(p.txt.parseTags("")); + ret.append('/'); + + for (MCommand mc : commandChain) { + ret.append(TextUtil.implode(mc.aliases, ",")); + ret.append(' '); + } + + ret.append(TextUtil.implode(this.aliases, ",")); + + List args = new ArrayList<>(); + + for (String requiredArg : this.requiredArgs) { + args.add("<" + requiredArg + ">"); + } + + for (Entry optionalArg : this.optionalArgs.entrySet()) { + String val = optionalArg.getValue(); + if (val == null) { + val = ""; + } else { + val = "=" + val; + } + args.add("[" + optionalArg.getKey() + val + "]"); + } + + if (args.size() > 0) { + ret.append(p.txt.parseTags(" ")); + ret.append(TextUtil.implode(args, " ")); + } + + if (addShortHelp) { + ret.append(p.txt.parseTags(" ")); + ret.append(this.getHelpShort()); + } + + return ret.toString(); + } + + public String getUseageTemplate(boolean addShortHelp) { + return getUseageTemplate(this.commandChain, addShortHelp); + } + + public String getUseageTemplate() { + return getUseageTemplate(false); + } + + // -------------------------------------------- // + // Message Sending Helpers + // -------------------------------------------- // + + public void msg(String str, Object... args) { + sender.sendMessage(p.txt.parse(str, args)); + } + + public void msg(TL translation, Object... args) { + sender.sendMessage(p.txt.parse(translation.toString(), args)); + } + + public void sendMessage(String msg) { + sender.sendMessage(msg); + } + + public void sendMessage(List msgs) { + for (String msg : msgs) { + this.sendMessage(msg); + } + } + + public void sendFancyMessage(FancyMessage message) { + message.send(sender); + } + + public void sendFancyMessage(List messages) { + for (FancyMessage m : messages) { + sendFancyMessage(m); + } + } + + public List getToolTips(FPlayer player) { + List lines = new ArrayList<>(); + for (String s : p.getConfig().getStringList("tooltips.show")) { + lines.add(ChatColor.translateAlternateColorCodes('&', replaceFPlayerTags(s, player))); + } + return lines; + } + + public List getToolTips(Faction faction) { + List lines = new ArrayList<>(); + for (String s : p.getConfig().getStringList("tooltips.list")) { + lines.add(ChatColor.translateAlternateColorCodes('&', replaceFactionTags(s, faction))); + } + return lines; + } + + public String replaceFPlayerTags(String s, FPlayer player) { + if (s.contains("{balance}")) { + String balance = Econ.isSetup() ? Econ.getFriendlyBalance(player) : "no balance"; + s = s.replace("{balance}", balance); + } + if (s.contains("{lastSeen}")) { + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - player.getLastLoginTime(), true, true) + " ago"; + String lastSeen = player.isOnline() ? ChatColor.GREEN + "Online" : (System.currentTimeMillis() - player.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + s = s.replace("{lastSeen}", lastSeen); + } + if (s.contains("{power}")) { + String power = player.getPowerRounded() + "/" + player.getPowerMaxRounded(); + s = s.replace("{power}", power); + } + if (s.contains("{group}")) { + String group = SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(player.getId()))); + s = s.replace("{group}", group); + } + return s; + } + + public String replaceFactionTags(String s, Faction faction) { + if (s.contains("{power}")) { + s = s.replace("{power}", String.valueOf(faction.getPowerRounded())); + } + if (s.contains("{maxPower}")) { + s = s.replace("{maxPower}", String.valueOf(faction.getPowerMaxRounded())); + } + if (s.contains("{leader}")) { + FPlayer fLeader = faction.getFPlayerAdmin(); + String leader = fLeader == null ? "Server" : fLeader.getName().substring(0, fLeader.getName().length() > 14 ? 13 : fLeader.getName().length()); + s = s.replace("{leader}", leader); + } + if (s.contains("{chunks}")) { + s = s.replace("{chunks}", String.valueOf(faction.getLandRounded())); + } + if (s.contains("{members}")) { + s = s.replace("{members}", String.valueOf(faction.getSize())); + + } + if (s.contains("{online}")) { + s = s.replace("{online}", String.valueOf(faction.getOnlinePlayers().size())); + } + return s; + } + + // -------------------------------------------- // + // Argument Readers + // -------------------------------------------- // + + // Is set? ====================== + public boolean argIsSet(int idx) { + return this.args.size() >= idx + 1; + } + + // STRING ====================== + public String argAsString(int idx, String def) { + if (this.args.size() < idx + 1) { + return def; + } + return this.args.get(idx); + } + + public String argAsString(int idx) { + return this.argAsString(idx, null); + } + + // INT ====================== + public Integer strAsInt(String str, Integer def) { + if (str == null) { + return def; + } + try { + return Integer.parseInt(str); + } catch (Exception e) { + return def; + } + } + + public Integer argAsInt(int idx, Integer def) { + return strAsInt(this.argAsString(idx), def); + } + + public Integer argAsInt(int idx) { + return this.argAsInt(idx, null); + } + + // Double ====================== + public Double strAsDouble(String str, Double def) { + if (str == null) { + return def; + } + try { + return Double.parseDouble(str); + } catch (Exception e) { + return def; + } + } + + public Double argAsDouble(int idx, Double def) { + return strAsDouble(this.argAsString(idx), def); + } + + public Double argAsDouble(int idx) { + return this.argAsDouble(idx, null); + } + + // TODO: Go through the str conversion for the other arg-readers as well. + // Boolean ====================== + public Boolean strAsBool(String str) { + str = str.toLowerCase(); + return str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"); + } + + public Boolean argAsBool(int idx, boolean def) { + String str = this.argAsString(idx); + if (str == null) { + return def; + } + + return strAsBool(str); + } + + public Boolean argAsBool(int idx) { + return this.argAsBool(idx, false); + } + + // PLAYER ====================== + public Player strAsPlayer(String name, Player def, boolean msg) { + Player ret = def; + + if (name != null) { + Player player = Bukkit.getServer().getPlayer(name); + if (player != null) { + ret = player; + } + } + + if (msg && ret == null) { + this.msg(TL.GENERIC_NOPLAYERFOUND, name); + } + + return ret; + } + + public Player argAsPlayer(int idx, Player def, boolean msg) { + return this.strAsPlayer(this.argAsString(idx), def, msg); + } + + public Player argAsPlayer(int idx, Player def) { + return this.argAsPlayer(idx, def, true); + } + + public Player argAsPlayer(int idx) { + return this.argAsPlayer(idx, null); + } + + // BEST PLAYER MATCH ====================== + public Player strAsBestPlayerMatch(String name, Player def, boolean msg) { + Player ret = def; + + if (name != null) { + List players = Bukkit.getServer().matchPlayer(name); + if (players.size() > 0) { + ret = players.get(0); + } + } + + if (msg && ret == null) { + this.msg(TL.GENERIC_NOPLAYERMATCH, name); + } + + return ret; + } + + public Player argAsBestPlayerMatch(int idx, Player def, boolean msg) { + return this.strAsBestPlayerMatch(this.argAsString(idx), def, msg); + } + + public Player argAsBestPlayerMatch(int idx, Player def) { + return this.argAsBestPlayerMatch(idx, def, true); + } + + public Player argAsBestPlayerMatch(int idx) { + return this.argAsPlayer(idx, null); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/MPlugin.java b/src/main/java/com/massivecraft/factions/zcore/MPlugin.java index 1b6bdac2..865a7a4d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MPlugin.java +++ b/src/main/java/com/massivecraft/factions/zcore/MPlugin.java @@ -27,313 +27,313 @@ import java.util.logging.Level; public abstract class MPlugin extends JavaPlugin { - // Persist related - public final Gson gson = this.getGsonBuilder().create(); - // Some utils - public Persist persist; - public TextUtil txt; - public PermUtil perm; - public String refCommand = ""; - //holds f stuck taskids - public Map stuckMap = new HashMap<>(); - // These are not supposed to be used directly. - // They are loaded and used through the TextUtil instance for the plugin. - public Map rawTags = new LinkedHashMap<>(); - protected boolean loadSuccessful = false; - private Integer saveTask = null; - private boolean autoSave = true; - // Listeners - private MPluginSecretPlayerListener mPluginSecretPlayerListener; + // Persist related + public final Gson gson = this.getGsonBuilder().create(); + // Some utils + public Persist persist; + public TextUtil txt; + public PermUtil perm; + public String refCommand = ""; + //holds f stuck taskids + public Map stuckMap = new HashMap<>(); + // These are not supposed to be used directly. + // They are loaded and used through the TextUtil instance for the plugin. + public Map rawTags = new LinkedHashMap<>(); + protected boolean loadSuccessful = false; + private Integer saveTask = null; + private boolean autoSave = true; + // Listeners + private MPluginSecretPlayerListener mPluginSecretPlayerListener; - // Our stored base commands - private List> baseCommands = new ArrayList<>(); - // holds f stuck start times - private Map timers = new HashMap<>(); - // -------------------------------------------- // - // ENABLE - // -------------------------------------------- // - private long timeEnableStart; + // Our stored base commands + private List> baseCommands = new ArrayList<>(); + // holds f stuck start times + private Map timers = new HashMap<>(); + // -------------------------------------------- // + // ENABLE + // -------------------------------------------- // + private long timeEnableStart; - public boolean getAutoSave() { - return this.autoSave; - } + public boolean getAutoSave() { + return this.autoSave; + } - public void setAutoSave(boolean val) { - this.autoSave = val; - } + public void setAutoSave(boolean val) { + this.autoSave = val; + } - public List> getBaseCommands() { - return this.baseCommands; - } + public List> getBaseCommands() { + return this.baseCommands; + } - public boolean preEnable() { - log("=== ENABLE START ==="); - timeEnableStart = System.currentTimeMillis(); + public boolean preEnable() { + log("=== ENABLE START ==="); + timeEnableStart = System.currentTimeMillis(); - // Ensure basefolder exists! - this.getDataFolder().mkdirs(); + // Ensure basefolder exists! + this.getDataFolder().mkdirs(); - // Create Utility Instances - this.perm = new PermUtil(this); - this.persist = new Persist(this); + // Create Utility Instances + this.perm = new PermUtil(this); + this.persist = new Persist(this); - this.txt = new TextUtil(); - initTXT(); + this.txt = new TextUtil(); + initTXT(); - // attempt to get first command defined in plugin.yml as reference command, if any commands are defined in there - // reference command will be used to prevent "unknown command" console messages - try { - Map> refCmd = this.getDescription().getCommands(); - if (refCmd != null && !refCmd.isEmpty()) { - this.refCommand = (String) (refCmd.keySet().toArray()[0]); - } - } catch (ClassCastException ex) { - } + // attempt to get first command defined in plugin.yml as reference command, if any commands are defined in there + // reference command will be used to prevent "unknown command" console messages + try { + Map> refCmd = this.getDescription().getCommands(); + if (refCmd != null && !refCmd.isEmpty()) { + this.refCommand = (String) (refCmd.keySet().toArray()[0]); + } + } catch (ClassCastException ex) { + } - // Create and register player command listener - this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this); - getServer().getPluginManager().registerEvents(this.mPluginSecretPlayerListener, this); + // Create and register player command listener + this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this); + getServer().getPluginManager().registerEvents(this.mPluginSecretPlayerListener, this); - // Register recurring tasks - if (saveTask == null && Conf.saveToFileEveryXMinutes > 0.0) { - long saveTicks = (long) (20 * 60 * Conf.saveToFileEveryXMinutes); // Approximately every 30 min by default - saveTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(this), saveTicks, saveTicks); - } + // Register recurring tasks + if (saveTask == null && Conf.saveToFileEveryXMinutes > 0.0) { + long saveTicks = (long) (20 * 60 * Conf.saveToFileEveryXMinutes); // Approximately every 30 min by default + saveTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(this), saveTicks, saveTicks); + } - loadLang(); + loadLang(); - loadSuccessful = true; - return true; - } + loadSuccessful = true; + return true; + } - public void postEnable() { - log("=== ENABLE DONE (Took " + (System.currentTimeMillis() - timeEnableStart) + "ms) ==="); - } + public void postEnable() { + log("=== ENABLE DONE (Took " + (System.currentTimeMillis() - timeEnableStart) + "ms) ==="); + } - public void loadLang() { - File lang = new File(getDataFolder(), "lang.yml"); - OutputStream out = null; - InputStream defLangStream = this.getResource("lang.yml"); - if (!lang.exists()) { - try { - getDataFolder().mkdir(); - lang.createNewFile(); - if (defLangStream != null) { - out = new FileOutputStream(lang); - int read; - byte[] bytes = new byte[1024]; + public void loadLang() { + File lang = new File(getDataFolder(), "lang.yml"); + OutputStream out = null; + InputStream defLangStream = this.getResource("lang.yml"); + if (!lang.exists()) { + try { + getDataFolder().mkdir(); + lang.createNewFile(); + if (defLangStream != null) { + out = new FileOutputStream(lang); + int read; + byte[] bytes = new byte[1024]; - while ((read = defLangStream.read(bytes)) != -1) { - out.write(bytes, 0, read); - } - YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(new BufferedReader(new InputStreamReader(defLangStream))); - TL.setFile(defConfig); - } - } catch (IOException e) { - e.printStackTrace(); // So they notice - getLogger().severe("[Factions] Couldn't create language file."); - getLogger().severe("[Factions] This is a fatal error. Now disabling"); - this.setEnabled(false); // Without it loaded, we can't send them messages - } finally { - if (defLangStream != null) { - try { - defLangStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (out != null) { - try { - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } + while ((read = defLangStream.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(new BufferedReader(new InputStreamReader(defLangStream))); + TL.setFile(defConfig); + } + } catch (IOException e) { + e.printStackTrace(); // So they notice + getLogger().severe("[Factions] Couldn't create language file."); + getLogger().severe("[Factions] This is a fatal error. Now disabling"); + this.setEnabled(false); // Without it loaded, we can't send them messages + } finally { + if (defLangStream != null) { + try { + defLangStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } - } - } - } + } + } + } - YamlConfiguration conf = YamlConfiguration.loadConfiguration(lang); - for (TL item : TL.values()) { - if (conf.getString(item.getPath()) == null) { - conf.set(item.getPath(), item.getDefault()); - } - } + YamlConfiguration conf = YamlConfiguration.loadConfiguration(lang); + for (TL item : TL.values()) { + if (conf.getString(item.getPath()) == null) { + conf.set(item.getPath(), item.getDefault()); + } + } - // Remove this here because I'm sick of dealing with bug reports due to bad decisions on my part. - if (conf.getString(TL.COMMAND_SHOW_POWER.getPath(), "").contains("%5$s")) { - conf.set(TL.COMMAND_SHOW_POWER.getPath(), TL.COMMAND_SHOW_POWER.getDefault()); - log(Level.INFO, "Removed errant format specifier from f show power."); - } + // Remove this here because I'm sick of dealing with bug reports due to bad decisions on my part. + if (conf.getString(TL.COMMAND_SHOW_POWER.getPath(), "").contains("%5$s")) { + conf.set(TL.COMMAND_SHOW_POWER.getPath(), TL.COMMAND_SHOW_POWER.getDefault()); + log(Level.INFO, "Removed errant format specifier from f show power."); + } - TL.setFile(conf); - try { - conf.save(lang); - } catch (IOException e) { - getLogger().log(Level.WARNING, "Factions: Failed to save lang.yml."); - getLogger().log(Level.WARNING, "Factions: Report this stack trace to prosavage."); - e.printStackTrace(); - } - } + TL.setFile(conf); + try { + conf.save(lang); + } catch (IOException e) { + getLogger().log(Level.WARNING, "Factions: Failed to save lang.yml."); + getLogger().log(Level.WARNING, "Factions: Report this stack trace to prosavage."); + e.printStackTrace(); + } + } - public void onDisable() { - if (saveTask != null) { - this.getServer().getScheduler().cancelTask(saveTask); - saveTask = null; - } - // only save data if plugin actually loaded successfully - if (loadSuccessful) { - Factions.getInstance().forceSave(); - FPlayers.getInstance().forceSave(); - Board.getInstance().forceSave(); - } - log("Disabled"); - } + public void onDisable() { + if (saveTask != null) { + this.getServer().getScheduler().cancelTask(saveTask); + saveTask = null; + } + // only save data if plugin actually loaded successfully + if (loadSuccessful) { + Factions.getInstance().forceSave(); + FPlayers.getInstance().forceSave(); + Board.getInstance().forceSave(); + } + log("Disabled"); + } - // -------------------------------------------- // - // Some inits... - // You are supposed to override these in the plugin if you aren't satisfied with the defaults - // The goal is that you always will be satisfied though. - // -------------------------------------------- // + // -------------------------------------------- // + // Some inits... + // You are supposed to override these in the plugin if you aren't satisfied with the defaults + // The goal is that you always will be satisfied though. + // -------------------------------------------- // - public void suicide() { - log("Now I suicide!"); - this.getServer().getPluginManager().disablePlugin(this); - } + public void suicide() { + log("Now I suicide!"); + this.getServer().getPluginManager().disablePlugin(this); + } - // -------------------------------------------- // - // LANG AND TAGS - // -------------------------------------------- // + // -------------------------------------------- // + // LANG AND TAGS + // -------------------------------------------- // - public GsonBuilder getGsonBuilder() { - return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE); - } + public GsonBuilder getGsonBuilder() { + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE); + } - public void addRawTags() { - this.rawTags.put("l", ""); // logo - this.rawTags.put("a", ""); // art - this.rawTags.put("n", ""); // notice - this.rawTags.put("i", ""); // info - this.rawTags.put("g", ""); // good - this.rawTags.put("b", ""); // bad - this.rawTags.put("h", ""); // highligh - this.rawTags.put("c", ""); // command - this.rawTags.put("plugin", ""); // parameter - } + public void addRawTags() { + this.rawTags.put("l", ""); // logo + this.rawTags.put("a", ""); // art + this.rawTags.put("n", ""); // notice + this.rawTags.put("i", ""); // info + this.rawTags.put("g", ""); // good + this.rawTags.put("b", ""); // bad + this.rawTags.put("h", ""); // highligh + this.rawTags.put("c", ""); // command + this.rawTags.put("plugin", ""); // parameter + } - public void initTXT() { - this.addRawTags(); + public void initTXT() { + this.addRawTags(); - Type type = new TypeToken>() { - }.getType(); + Type type = new TypeToken>() { + }.getType(); - Map tagsFromFile = this.persist.load(type, "tags"); - if (tagsFromFile != null) { - this.rawTags.putAll(tagsFromFile); - } - this.persist.save(this.rawTags, "tags"); + Map tagsFromFile = this.persist.load(type, "tags"); + if (tagsFromFile != null) { + this.rawTags.putAll(tagsFromFile); + } + this.persist.save(this.rawTags, "tags"); - for (Entry rawTag : this.rawTags.entrySet()) { - this.txt.tags.put(rawTag.getKey(), TextUtil.parseColor(rawTag.getValue())); - } - } + for (Entry rawTag : this.rawTags.entrySet()) { + this.txt.tags.put(rawTag.getKey(), TextUtil.parseColor(rawTag.getValue())); + } + } - // -------------------------------------------- // - // COMMAND HANDLING - // -------------------------------------------- // + // -------------------------------------------- // + // COMMAND HANDLING + // -------------------------------------------- // - // can be overridden by SavageFactions method, to provide option - public boolean logPlayerCommands() { - return true; - } + // can be overridden by SavageFactions method, to provide option + public boolean logPlayerCommands() { + return true; + } - public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { - return handleCommand(sender, commandString, testOnly, false); - } + public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { + return handleCommand(sender, commandString, testOnly, false); + } - public boolean handleCommand(final CommandSender sender, String commandString, boolean testOnly, boolean async) { - boolean noSlash = true; - if (commandString.startsWith("/")) { - noSlash = false; - commandString = commandString.substring(1); - } + public boolean handleCommand(final CommandSender sender, String commandString, boolean testOnly, boolean async) { + boolean noSlash = true; + if (commandString.startsWith("/")) { + noSlash = false; + commandString = commandString.substring(1); + } - for (final MCommand command : this.getBaseCommands()) { - if (noSlash && !command.allowNoSlashAccess) { - continue; - } + for (final MCommand command : this.getBaseCommands()) { + if (noSlash && !command.allowNoSlashAccess) { + continue; + } - for (String alias : command.aliases) { - // disallow double-space after alias, so specific commands can be prevented (preventing "f home" won't prevent "f home") - if (commandString.startsWith(alias + " ")) { - return false; - } + for (String alias : command.aliases) { + // disallow double-space after alias, so specific commands can be prevented (preventing "f home" won't prevent "f home") + if (commandString.startsWith(alias + " ")) { + return false; + } - if (commandString.startsWith(alias + " ") || commandString.equals(alias)) { - final List args = new ArrayList<>(Arrays.asList(commandString.split("\\s+"))); - args.remove(0); + if (commandString.startsWith(alias + " ") || commandString.equals(alias)) { + final List args = new ArrayList<>(Arrays.asList(commandString.split("\\s+"))); + args.remove(0); - if (testOnly) { - return true; - } + if (testOnly) { + return true; + } - if (async) { - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { - @Override - public void run() { - command.execute(sender, args); - } - }); - } else { - command.execute(sender, args); - } + if (async) { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { + @Override + public void run() { + command.execute(sender, args); + } + }); + } else { + command.execute(sender, args); + } - return true; - } - } - } - return false; - } + return true; + } + } + } + return false; + } - public boolean handleCommand(CommandSender sender, String commandString) { - return this.handleCommand(sender, commandString, false); - } + public boolean handleCommand(CommandSender sender, String commandString) { + return this.handleCommand(sender, commandString, false); + } - // -------------------------------------------- // - // HOOKS - // -------------------------------------------- // - public void preAutoSave() { + // -------------------------------------------- // + // HOOKS + // -------------------------------------------- // + public void preAutoSave() { - } + } - public void postAutoSave() { + public void postAutoSave() { - } + } - public Map getStuckMap() { - return this.stuckMap; - } + public Map getStuckMap() { + return this.stuckMap; + } - public Map getTimers() { - return this.timers; - } + public Map getTimers() { + return this.timers; + } - // -------------------------------------------- // - // LOGGING - // -------------------------------------------- // - public void log(Object msg) { - log(Level.INFO, msg); - } + // -------------------------------------------- // + // LOGGING + // -------------------------------------------- // + public void log(Object msg) { + log(Level.INFO, msg); + } - public void log(String str, Object... args) { - log(Level.INFO, this.txt.parse(str, args)); - } + public void log(String str, Object... args) { + log(Level.INFO, this.txt.parse(str, args)); + } - public void log(Level level, String str, Object... args) { - log(level, this.txt.parse(str, args)); - } + public void log(Level level, String str, Object... args) { + log(level, this.txt.parse(str, args)); + } - public void log(Level level, Object msg) { - getLogger().log(level, "[" + this.getDescription().getFullName() + "] " + msg); - } + public void log(Level level, Object msg) { + getLogger().log(level, "[" + this.getDescription().getFullName() + "] " + msg); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java b/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java index ea4474c9..e82bae1d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java @@ -12,30 +12,30 @@ import org.bukkit.event.player.PlayerLoginEvent; public class MPluginSecretPlayerListener implements Listener { - private MPlugin p; + private MPlugin p; - public MPluginSecretPlayerListener(MPlugin p) { - this.p = p; - } + public MPluginSecretPlayerListener(MPlugin p) { + this.p = p; + } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - if (FactionsPlayerListener.preventCommand(event.getMessage(), event.getPlayer())) { - if (p.logPlayerCommands()) { - Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); - } - event.setCancelled(true); - } - } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + if (FactionsPlayerListener.preventCommand(event.getMessage(), event.getPlayer())) { + if (p.logPlayerCommands()) { + Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); + } + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerChat(AsyncPlayerChatEvent event) { - if (p.handleCommand(event.getPlayer(), event.getMessage(), false, true)) { - if (p.logPlayerCommands()) { - Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); - } - event.setCancelled(true); - } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerChat(AsyncPlayerChatEvent event) { + if (p.handleCommand(event.getPlayer(), event.getMessage(), false, true)) { + if (p.logPlayerCommands()) { + Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); + } + event.setCancelled(true); + } /* Should be handled by stuff in FactionsChatListener Player speaker = event.getPlayer(); @@ -43,10 +43,10 @@ public class MPluginSecretPlayerListener implements Listener { format = format.replace(Conf.chatTagReplaceString, SavageFactions.plugin.getPlayerFactionTag(speaker)).replace("[FACTION_TITLE]", SavageFactions.plugin.getPlayerTitle(speaker)); event.setFormat(format); */ - } + } - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerPreLogin(PlayerLoginEvent event) { - FPlayers.getInstance().getByPlayer(event.getPlayer()); - } + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerPreLogin(PlayerLoginEvent event) { + FPlayers.getInstance().getByPlayer(event.getPlayer()); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java b/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java index 87243fc2..ed6c607b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java @@ -3,41 +3,41 @@ package com.massivecraft.factions.zcore.fperms; import org.bukkit.ChatColor; public enum Access { - ALLOW("Allow", ChatColor.GREEN), - DENY("Deny", ChatColor.DARK_RED), - UNDEFINED("Undefined", ChatColor.GRAY); + ALLOW("Allow", ChatColor.GREEN), + DENY("Deny", ChatColor.DARK_RED), + UNDEFINED("Undefined", ChatColor.GRAY); - private final String name; - private final ChatColor color; + private final String name; + private final ChatColor color; - Access(String name, ChatColor color) { - this.name = name; - this.color = color; - } + Access(String name, ChatColor color) { + this.name = name; + this.color = color; + } - /** - * Case insensitive check for access. - * - * @param check - * @return - */ - public static Access fromString(String check) { - for (Access access : values()) - if (access.name().equalsIgnoreCase(check)) - return access; - return null; - } + /** + * Case insensitive check for access. + * + * @param check + * @return + */ + public static Access fromString(String check) { + for (Access access : values()) + if (access.name().equalsIgnoreCase(check)) + return access; + return null; + } - public String getName() { - return this.name; - } + public String getName() { + return this.name; + } - public ChatColor getColor() { - return color; - } + public ChatColor getColor() { + return color; + } - @Override - public String toString() { - return name(); - } + @Override + public String toString() { + return name(); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java b/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java index be3f7f3c..b1d472b4 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java @@ -1,147 +1,152 @@ package com.massivecraft.factions.zcore.fperms; public class DefaultPermissions { - public DefaultPermissions() { } - public DefaultPermissions(boolean def) { - this.ban = def; - this.build = def; - this.destroy = def; - this.frostwalk = def; - this.painbuild = def; - this.door = def; - this.button = def; - this.lever = def; - this.container = def; - this.invite = def; - this.kick = def; - this.items = def; - this.sethome = def; - this.territory = def; - this.access = def; - this.home = def; - this.disband = def; - this.promote = def; - this.setwarp = def; - this.warp = def; - this.fly = def; - this.vault = def; - this.tntbank = def; - this.tntfill = def; - this.withdraw = def; - this.chest = def; - this.spawner = def; - } - public DefaultPermissions(boolean canBan, - boolean canBuild, - boolean canDestory, - boolean canFrostwalk, - boolean canPainbuild, - boolean canDoor, - boolean canButton, - boolean canLever, - boolean canContainer, - boolean canInvite, - boolean canKick, - boolean canItems, - boolean canSethome, - boolean canTerritory, - boolean canAccess, - boolean canHome, - boolean canDisband, - boolean canPromote, - boolean canSetwarp, - boolean canWarp, - boolean canFly, - boolean canVault, - boolean canTntbank, - boolean canTntfill, - boolean canWithdraw, - boolean canChest, - boolean canSpawners) { - this.ban = canBan; - this.build = canBuild; - this.destroy = canDestory; - this.frostwalk = canFrostwalk; - this.painbuild = canPainbuild; - this.door = canDoor; - this.button = canButton; - this.lever = canLever; - this.container = canContainer; - this.invite = canInvite; - this.kick = canKick; - this.items = canItems; - this.sethome = canSethome; - this.territory = canTerritory; - this.access = canAccess; - this.home = canHome; - this.disband = canDisband; - this.promote = canPromote; - this.setwarp = canSetwarp; - this.warp = canWarp; - this.fly = canFly; - this.vault = canVault; - this.tntbank = canTntbank; - this.tntfill = canTntfill; - this.withdraw = canWithdraw; - this.chest = canChest; - this.spawner = canSpawners; - } - public boolean ban; - public boolean build; - public boolean destroy; - public boolean frostwalk; - public boolean painbuild; - public boolean door; - public boolean button; - public boolean lever; - public boolean container; - public boolean invite; - public boolean kick; - public boolean items; - public boolean sethome; - public boolean territory; - public boolean access; - public boolean home; - public boolean disband; - public boolean promote; - public boolean setwarp; - public boolean warp; - public boolean fly; - public boolean vault; - public boolean tntbank; - public boolean tntfill; - public boolean withdraw; - public boolean chest; - public boolean spawner; - @Deprecated - public boolean getbyName(String name) { - if (name == "ban") return this.ban; - else if (name == "build") return this.build; - else if (name == "destroy") return this.destroy; - else if (name == "frostwalk") return this.frostwalk; - else if (name == "painbuild") return this.painbuild; - else if (name == "door") return this.door; - else if (name == "button") return this.button; - else if (name == "lever") return this.lever; - else if (name == "container") return this.container; - else if (name == "invite") return this.invite; - else if (name == "kick") return this.kick; - else if (name == "items") return this.items; - else if (name == "sethome") return this.sethome; - else if (name == "territory") return this.territory; - else if (name == "access") return this.access; - else if (name == "home") return this.disband; - else if (name == "disband") return this.disband; - else if (name == "promote") return this.promote; - else if (name == "setwarp") return this.setwarp; - else if (name == "warp") return this.warp; - else if (name == "fly") return this.fly; - else if (name == "vault") return this.vault; - else if (name == "tntbank") return this.tntbank; - else if (name == "tntfill") return this.tntfill; - else if (name == "withdraw") return this.withdraw; - else if (name == "chest") return this.chest; - else if (name == "spawner") return this.spawner; - else return false; - } + public DefaultPermissions() { + } + + public DefaultPermissions(boolean def) { + this.ban = def; + this.build = def; + this.destroy = def; + this.frostwalk = def; + this.painbuild = def; + this.door = def; + this.button = def; + this.lever = def; + this.container = def; + this.invite = def; + this.kick = def; + this.items = def; + this.sethome = def; + this.territory = def; + this.access = def; + this.home = def; + this.disband = def; + this.promote = def; + this.setwarp = def; + this.warp = def; + this.fly = def; + this.vault = def; + this.tntbank = def; + this.tntfill = def; + this.withdraw = def; + this.chest = def; + this.spawner = def; + } + + public DefaultPermissions(boolean canBan, + boolean canBuild, + boolean canDestory, + boolean canFrostwalk, + boolean canPainbuild, + boolean canDoor, + boolean canButton, + boolean canLever, + boolean canContainer, + boolean canInvite, + boolean canKick, + boolean canItems, + boolean canSethome, + boolean canTerritory, + boolean canAccess, + boolean canHome, + boolean canDisband, + boolean canPromote, + boolean canSetwarp, + boolean canWarp, + boolean canFly, + boolean canVault, + boolean canTntbank, + boolean canTntfill, + boolean canWithdraw, + boolean canChest, + boolean canSpawners) { + this.ban = canBan; + this.build = canBuild; + this.destroy = canDestory; + this.frostwalk = canFrostwalk; + this.painbuild = canPainbuild; + this.door = canDoor; + this.button = canButton; + this.lever = canLever; + this.container = canContainer; + this.invite = canInvite; + this.kick = canKick; + this.items = canItems; + this.sethome = canSethome; + this.territory = canTerritory; + this.access = canAccess; + this.home = canHome; + this.disband = canDisband; + this.promote = canPromote; + this.setwarp = canSetwarp; + this.warp = canWarp; + this.fly = canFly; + this.vault = canVault; + this.tntbank = canTntbank; + this.tntfill = canTntfill; + this.withdraw = canWithdraw; + this.chest = canChest; + this.spawner = canSpawners; + } + + public boolean ban; + public boolean build; + public boolean destroy; + public boolean frostwalk; + public boolean painbuild; + public boolean door; + public boolean button; + public boolean lever; + public boolean container; + public boolean invite; + public boolean kick; + public boolean items; + public boolean sethome; + public boolean territory; + public boolean access; + public boolean home; + public boolean disband; + public boolean promote; + public boolean setwarp; + public boolean warp; + public boolean fly; + public boolean vault; + public boolean tntbank; + public boolean tntfill; + public boolean withdraw; + public boolean chest; + public boolean spawner; + + @Deprecated + public boolean getbyName(String name) { + if (name == "ban") return this.ban; + else if (name == "build") return this.build; + else if (name == "destroy") return this.destroy; + else if (name == "frostwalk") return this.frostwalk; + else if (name == "painbuild") return this.painbuild; + else if (name == "door") return this.door; + else if (name == "button") return this.button; + else if (name == "lever") return this.lever; + else if (name == "container") return this.container; + else if (name == "invite") return this.invite; + else if (name == "kick") return this.kick; + else if (name == "items") return this.items; + else if (name == "sethome") return this.sethome; + else if (name == "territory") return this.territory; + else if (name == "access") return this.access; + else if (name == "home") return this.disband; + else if (name == "disband") return this.disband; + else if (name == "promote") return this.promote; + else if (name == "setwarp") return this.setwarp; + else if (name == "warp") return this.warp; + else if (name == "fly") return this.fly; + else if (name == "vault") return this.vault; + else if (name == "tntbank") return this.tntbank; + else if (name == "tntfill") return this.tntfill; + else if (name == "withdraw") return this.withdraw; + else if (name == "chest") return this.chest; + else if (name == "spawner") return this.spawner; + else return false; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java b/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java index 3441f9d3..3412581b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java @@ -4,10 +4,10 @@ import org.bukkit.inventory.ItemStack; public interface Permissable { - ItemStack buildItem(); + ItemStack buildItem(); - String replacePlaceholders(String string); + String replacePlaceholders(String string); - String name(); + String name(); } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java index 3fc99e83..3c5c32e7 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java @@ -16,169 +16,169 @@ import java.util.Map; import java.util.logging.Level; public enum PermissableAction { - BAN("ban"), - BUILD("build"), - DESTROY("destroy"), - FROST_WALK("frostwalk"), - PAIN_BUILD("painbuild"), - DOOR("door"), - BUTTON("button"), - LEVER("lever"), - CONTAINER("container"), - INVITE("invite"), - KICK("kick"), - ITEM("items"), // generic for most items - SETHOME("sethome"), - TERRITORY("territory"), - ACCESS("access"), - HOME("home"), - DISBAND("disband"), - PROMOTE("promote"), - SETWARP("setwarp"), - WARP("warp"), - FLY("fly"), - VAULT("vault"), - TNTBANK("tntbank"), - TNTFILL("tntfill"), - WITHDRAW("withdraw"), - CHEST("chest"), - SPAWNER("spawner"); + BAN("ban"), + BUILD("build"), + DESTROY("destroy"), + FROST_WALK("frostwalk"), + PAIN_BUILD("painbuild"), + DOOR("door"), + BUTTON("button"), + LEVER("lever"), + CONTAINER("container"), + INVITE("invite"), + KICK("kick"), + ITEM("items"), // generic for most items + SETHOME("sethome"), + TERRITORY("territory"), + ACCESS("access"), + HOME("home"), + DISBAND("disband"), + PROMOTE("promote"), + SETWARP("setwarp"), + WARP("warp"), + FLY("fly"), + VAULT("vault"), + TNTBANK("tntbank"), + TNTFILL("tntfill"), + WITHDRAW("withdraw"), + CHEST("chest"), + SPAWNER("spawner"); - private String name; + private String name; - PermissableAction(String name) { - this.name = name; - } + PermissableAction(String name) { + this.name = name; + } - /** - * Case insensitive check for action. - * - * @param check - * @return - action - */ - public static PermissableAction fromString(String check) { - for (PermissableAction permissableAction : values()) { - if (permissableAction.name().equalsIgnoreCase(check)) { - return permissableAction; - } - } + /** + * Case insensitive check for action. + * + * @param check + * @return - action + */ + public static PermissableAction fromString(String check) { + for (PermissableAction permissableAction : values()) { + if (permissableAction.name().equalsIgnoreCase(check)) { + return permissableAction; + } + } - return null; - } + return null; + } - /** - * Get the friendly name of this action. Used for editing in commands. - * - * @return friendly name of the action as a String. - */ - public String getName() { - return this.name; - } + /** + * Get the friendly name of this action. Used for editing in commands. + * + * @return friendly name of the action as a String. + */ + public String getName() { + return this.name; + } - @Override - public String toString() { - return name; - } + @Override + public String toString() { + return name; + } - // Utility method to build items for F Perm GUI - public ItemStack buildItem(FPlayer fme, Permissable permissable) { - final ConfigurationSection section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); + // Utility method to build items for F Perm GUI + public ItemStack buildItem(FPlayer fme, Permissable permissable) { + final ConfigurationSection section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - String displayName = replacePlaceholders(section.getString("placeholder-item.name"), fme, permissable); - List lore = new ArrayList<>(); + String displayName = replacePlaceholders(section.getString("placeholder-item.name"), fme, permissable); + List lore = new ArrayList<>(); - if (section.getString("materials." + name().toLowerCase().replace('_', '-')) == null) { - return null; - } - Material material = Material.matchMaterial(section.getString("materials." + name().toLowerCase().replace('_', '-'))); - if (material == null) { - material = SavageFactions.plugin.STAINED_CLAY; - } + if (section.getString("materials." + name().toLowerCase().replace('_', '-')) == null) { + return null; + } + Material material = Material.matchMaterial(section.getString("materials." + name().toLowerCase().replace('_', '-'))); + if (material == null) { + material = SavageFactions.plugin.STAINED_CLAY; + } - Access access = fme.getFaction().getAccess(permissable, this); - if (access == null) { - access = Access.UNDEFINED; - } + Access access = fme.getFaction().getAccess(permissable, this); + if (access == null) { + access = Access.UNDEFINED; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - String accessValue = null; + String accessValue = null; - switch (access) { - case ALLOW: - accessValue = "allow"; - break; - case DENY: - accessValue = "deny"; - break; - case UNDEFINED: - accessValue = "undefined"; - break; - } + switch (access) { + case ALLOW: + accessValue = "allow"; + break; + case DENY: + accessValue = "deny"; + break; + case UNDEFINED: + accessValue = "undefined"; + break; + } - // If under the 1.13 version we will use the colorable option. - if (!SavageFactions.plugin.mc113) { - DyeColor dyeColor = null; + // If under the 1.13 version we will use the colorable option. + if (!SavageFactions.plugin.mc113) { + DyeColor dyeColor = null; - try { - dyeColor = DyeColor.valueOf(section.getString("access." + access.name().toLowerCase())); - } catch (Exception exception) { - } + try { + dyeColor = DyeColor.valueOf(section.getString("access." + access.name().toLowerCase())); + } catch (Exception exception) { + } - if (dyeColor != null) { - item.setDurability(dyeColor.getWoolData()); - } - } else { - // so this is in 1.13 mode, our config will automatically be updated to a material instead of color because of it being removed in the new api - item.setType(Material.valueOf(SavageFactions.plugin.getConfig().getString("fperm-gui.action.access." + accessValue))); - } + if (dyeColor != null) { + item.setDurability(dyeColor.getWoolData()); + } + } else { + // so this is in 1.13 mode, our config will automatically be updated to a material instead of color because of it being removed in the new api + item.setType(Material.valueOf(SavageFactions.plugin.getConfig().getString("fperm-gui.action.access." + accessValue))); + } - for (String loreLine : section.getStringList("placeholder-item.lore")) { - lore.add(replacePlaceholders(loreLine, fme, permissable)); - } + for (String loreLine : section.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine, fme, permissable)); + } - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - public String replacePlaceholders(String string, FPlayer fme, Permissable permissable) { - // Run Permissable placeholders - string = permissable.replacePlaceholders(string); + public String replacePlaceholders(String string, FPlayer fme, Permissable permissable) { + // Run Permissable placeholders + string = permissable.replacePlaceholders(string); - String actionName = name.substring(0, 1).toUpperCase() + name.substring(1); - string = string.replace("{action}", actionName); + String actionName = name.substring(0, 1).toUpperCase() + name.substring(1); + string = string.replace("{action}", actionName); - Access access = fme.getFaction().getAccess(permissable, this); - if (access == null) { - access = Access.UNDEFINED; - } - String actionAccess = access.getName(); - string = string.replace("{action-access}", actionAccess); - string = string.replace("{action-access-color}", access.getColor().toString()); + Access access = fme.getFaction().getAccess(permissable, this); + if (access == null) { + access = Access.UNDEFINED; + } + String actionAccess = access.getName(); + string = string.replace("{action-access}", actionAccess); + string = string.replace("{action-access-color}", access.getColor().toString()); - return string; - } + return string; + } - public static Map fromDefaults(DefaultPermissions defaultPermissions) { - Map defaultMap = new HashMap<>(); - for (PermissableAction permissableAction : PermissableAction.values()) { - defaultMap.put(permissableAction, defaultPermissions.getbyName(permissableAction.name) ? Access.ALLOW : Access.DENY); - } - return defaultMap; - } + public static Map fromDefaults(DefaultPermissions defaultPermissions) { + Map defaultMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + defaultMap.put(permissableAction, defaultPermissions.getbyName(permissableAction.name) ? Access.ALLOW : Access.DENY); + } + return defaultMap; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java index c26ad9a4..5608e972 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java @@ -24,291 +24,291 @@ import java.util.logging.Level; public class PermissableActionGUI implements InventoryHolder, FactionGUI { - private final ConfigurationSection section; - private Inventory actionGUI; - private FPlayer fme; - private int guiSize; - private Permissable permissable; - private HashMap actionSlots = new HashMap<>(); - private HashMap specialSlots = new HashMap<>(); - private ArrayList usedDummySlots = new ArrayList<>(); + private final ConfigurationSection section; + private Inventory actionGUI; + private FPlayer fme; + private int guiSize; + private Permissable permissable; + private HashMap actionSlots = new HashMap<>(); + private HashMap specialSlots = new HashMap<>(); + private ArrayList usedDummySlots = new ArrayList<>(); - public PermissableActionGUI(FPlayer fme, Permissable permissable) { - this.fme = fme; - this.permissable = permissable; - this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); - } + public PermissableActionGUI(FPlayer fme, Permissable permissable) { + this.fme = fme; + this.permissable = permissable; + this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); + } - public void build() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + public void build() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - guiSize = section.getInt("rows", 3); - if (guiSize > 6) { - guiSize = 6; - SavageFactions.plugin.log(Level.INFO, "Action GUI size out of bounds, defaulting to 6"); - } + guiSize = section.getInt("rows", 3); + if (guiSize > 6) { + guiSize = 6; + SavageFactions.plugin.log(Level.INFO, "Action GUI size out of bounds, defaulting to 6"); + } - guiSize *= 9; - String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPerms")); - actionGUI = Bukkit.createInventory(this, guiSize, guiName); - boolean disabled = false; - for (String key : section.getConfigurationSection("slots").getKeys(false)) { - int slot = section.getInt("slots." + key); - if (slot == -1) { - disabled = true; - continue; - } - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot for: " + key.toUpperCase()); - continue; - } + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPerms")); + actionGUI = Bukkit.createInventory(this, guiSize, guiName); + boolean disabled = false; + for (String key : section.getConfigurationSection("slots").getKeys(false)) { + int slot = section.getInt("slots." + key); + if (slot == -1) { + disabled = true; + continue; + } + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot for: " + key.toUpperCase()); + continue; + } - if (SpecialItem.isSpecial(key)) { - specialSlots.put(slot, SpecialItem.fromString(key)); - continue; - } + if (SpecialItem.isSpecial(key)) { + specialSlots.put(slot, SpecialItem.fromString(key)); + continue; + } - PermissableAction permissableAction = PermissableAction.fromString(key.toUpperCase().replace('-', '_')); - if (permissableAction == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid permissable action: " + key.toUpperCase()); - continue; - } + PermissableAction permissableAction = PermissableAction.fromString(key.toUpperCase().replace('-', '_')); + if (permissableAction == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid permissable action: " + key.toUpperCase()); + continue; + } - actionSlots.put(section.getInt("slots." + key), permissableAction); - } + actionSlots.put(section.getInt("slots." + key), permissableAction); + } - buildDummyItems(); + buildDummyItems(); - if (actionSlots.values().toArray().length != PermissableAction.values().length) { - // Missing actions add them forcefully to the GUI and log error - Set missingActions = new HashSet<>(Arrays.asList(PermissableAction.values())); - missingActions.removeAll(actionSlots.values()); + if (actionSlots.values().toArray().length != PermissableAction.values().length) { + // Missing actions add them forcefully to the GUI and log error + Set missingActions = new HashSet<>(Arrays.asList(PermissableAction.values())); + missingActions.removeAll(actionSlots.values()); - for (PermissableAction action : missingActions) { - if (disabled) { - break; - } - if (!usedDummySlots.isEmpty()) { - int slot = usedDummySlots.get(0); - actionSlots.put(slot, action); - } else { - int slot = actionGUI.firstEmpty(); - if (slot != -1) { - actionSlots.put(slot, action); - } - } - SavageFactions.plugin.log(Level.WARNING, "Missing action: " + action.name()); - } + for (PermissableAction action : missingActions) { + if (disabled) { + break; + } + if (!usedDummySlots.isEmpty()) { + int slot = usedDummySlots.get(0); + actionSlots.put(slot, action); + } else { + int slot = actionGUI.firstEmpty(); + if (slot != -1) { + actionSlots.put(slot, action); + } + } + SavageFactions.plugin.log(Level.WARNING, "Missing action: " + action.name()); + } - } + } - buildSpecialItems(); - buildItems(); - } + buildSpecialItems(); + buildItems(); + } - @Override - public Inventory getInventory() { - return actionGUI; - } + @Override + public Inventory getInventory() { + return actionGUI; + } - @Override - public void onClick(int slot, ClickType click) { - if (specialSlots.containsKey(slot)) { - if (specialSlots.get(slot) == SpecialItem.BACK) { - PermissableRelationGUI relationGUI = new PermissableRelationGUI(fme); - relationGUI.build(); + @Override + public void onClick(int slot, ClickType click) { + if (specialSlots.containsKey(slot)) { + if (specialSlots.get(slot) == SpecialItem.BACK) { + PermissableRelationGUI relationGUI = new PermissableRelationGUI(fme); + relationGUI.build(); - fme.getPlayer().openInventory(relationGUI.getInventory()); - } - return; - } - if (!actionSlots.containsKey(slot)) { - return; - } + fme.getPlayer().openInventory(relationGUI.getInventory()); + } + return; + } + if (!actionSlots.containsKey(slot)) { + return; + } - PermissableAction action = actionSlots.get(slot); - Access access; - if (click == ClickType.LEFT) { - access = Access.ALLOW; - fme.getFaction().setPermission(permissable, action, access); - } else if (click == ClickType.RIGHT) { - access = Access.DENY; - fme.getFaction().setPermission(permissable, action, access); - } else if (click == ClickType.MIDDLE) { - access = Access.UNDEFINED; - fme.getFaction().setPermission(permissable, action, access); - } else { - return; - } + PermissableAction action = actionSlots.get(slot); + Access access; + if (click == ClickType.LEFT) { + access = Access.ALLOW; + fme.getFaction().setPermission(permissable, action, access); + } else if (click == ClickType.RIGHT) { + access = Access.DENY; + fme.getFaction().setPermission(permissable, action, access); + } else if (click == ClickType.MIDDLE) { + access = Access.UNDEFINED; + fme.getFaction().setPermission(permissable, action, access); + } else { + return; + } - actionGUI.setItem(slot, action.buildItem(fme, permissable)); - fme.msg(TL.COMMAND_PERM_SET, action.name(), access.name(), permissable.name()); - SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), action.name(), access.name(), permissable.name()) + " for faction " + fme.getTag()); - } + actionGUI.setItem(slot, action.buildItem(fme, permissable)); + fme.msg(TL.COMMAND_PERM_SET, action.name(), access.name(), permissable.name()); + SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), action.name(), access.name(), permissable.name()) + " for faction " + fme.getTag()); + } - private void buildItems() { - for (Map.Entry entry : actionSlots.entrySet()) { - PermissableAction permissableAction = entry.getValue(); + private void buildItems() { + for (Map.Entry entry : actionSlots.entrySet()) { + PermissableAction permissableAction = entry.getValue(); - ItemStack item = permissableAction.buildItem(fme, permissable); + ItemStack item = permissableAction.buildItem(fme, permissable); - if (item == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid item for: " + permissableAction.toString().toUpperCase()); - continue; - } + if (item == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid item for: " + permissableAction.toString().toUpperCase()); + continue; + } - actionGUI.setItem(entry.getKey(), item); - } - } + actionGUI.setItem(entry.getKey(), item); + } + } - private void buildSpecialItems() { - for (Map.Entry entry : specialSlots.entrySet()) { - actionGUI.setItem(entry.getKey(), getSpecialItem(entry.getValue())); - } - } + private void buildSpecialItems() { + for (Map.Entry entry : specialSlots.entrySet()) { + actionGUI.setItem(entry.getKey(), getSpecialItem(entry.getValue())); + } + } - private ItemStack getSpecialItem(SpecialItem specialItem) { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + private ItemStack getSpecialItem(SpecialItem specialItem) { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - switch (specialItem) { - case RELATION: - return permissable.buildItem(); - case BACK: - ConfigurationSection backButtonConfig = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.back-item"); + switch (specialItem) { + case RELATION: + return permissable.buildItem(); + case BACK: + ConfigurationSection backButtonConfig = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.back-item"); - ItemStack backButton = new ItemStack(Material.matchMaterial(backButtonConfig.getString("material"))); - ItemMeta backButtonMeta = backButton.getItemMeta(); + ItemStack backButton = new ItemStack(Material.matchMaterial(backButtonConfig.getString("material"))); + ItemMeta backButtonMeta = backButton.getItemMeta(); - backButtonMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', backButtonConfig.getString("name"))); - List lore = new ArrayList<>(); - for (String loreLine : backButtonConfig.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } + backButtonMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', backButtonConfig.getString("name"))); + List lore = new ArrayList<>(); + for (String loreLine : backButtonConfig.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } - backButtonMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - backButtonMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + backButtonMeta.setLore(lore); + if (!SavageFactions.plugin.mc17) { + backButtonMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - backButton.setItemMeta(backButtonMeta); + backButton.setItemMeta(backButtonMeta); - return backButton; - default: - return null; - } - } + return backButton; + default: + return null; + } + } - private void buildDummyItems() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + private void buildDummyItems() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { - int dummyId; - try { - dummyId = Integer.parseInt(key); - } catch (NumberFormatException exception) { - SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); - continue; - } + for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } - ItemStack dummyItem = buildDummyItem(dummyId); - if (dummyItem == null) { - continue; - } + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } - ItemMeta meta = dummyItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + ItemMeta meta = dummyItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - dummyItem.setItemMeta(meta); + dummyItem.setItemMeta(meta); - List dummySlots = section.getIntegerList("dummy-items." + key); - for (Integer slot : dummySlots) { - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); - continue; - } - usedDummySlots.add(slot); - actionGUI.setItem(slot, dummyItem); - } - } - } + List dummySlots = section.getIntegerList("dummy-items." + key); + for (Integer slot : dummySlots) { + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + usedDummySlots.add(slot); + actionGUI.setItem(slot, dummyItem); + } + } + } - private ItemStack buildDummyItem(int id) { - final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); + private ItemStack buildDummyItem(int id) { + final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); - if (dummySection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build dummy items for F PERM GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (dummySection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build dummy items for F PERM GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - Material material = Material.matchMaterial(dummySection.getString("material", "")); - if (material == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); - return null; - } + Material material = Material.matchMaterial(dummySection.getString("material", "")); + if (material == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } - ItemStack itemStack = new ItemStack(material); + ItemStack itemStack = new ItemStack(material); - DyeColor color; - try { - color = DyeColor.valueOf(dummySection.getString("color", "")); - } catch (Exception exception) { - color = null; - } - if (color != null) { - itemStack.setDurability(color.getWoolData()); - } + DyeColor color; + try { + color = DyeColor.valueOf(dummySection.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } - ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); - List lore = new ArrayList<>(); - for (String loreLine : dummySection.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } + List lore = new ArrayList<>(); + for (String loreLine : dummySection.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } - itemMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + itemMeta.setLore(lore); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemStack.setItemMeta(itemMeta); + itemStack.setItemMeta(itemMeta); - return itemStack; - } + return itemStack; + } - public enum SpecialItem { - BACK, - RELATION; + public enum SpecialItem { + BACK, + RELATION; - static boolean isSpecial(String string) { - return fromString(string) != null; - } + static boolean isSpecial(String string) { + return fromString(string) != null; + } - static SpecialItem fromString(String string) { - for (SpecialItem specialItem : SpecialItem.values()) { - if (string.equalsIgnoreCase(specialItem.name())) { - return specialItem; - } - } - return null; - } - } + static SpecialItem fromString(String string) { + for (SpecialItem specialItem : SpecialItem.values()) { + if (string.equalsIgnoreCase(specialItem.name())) { + return specialItem; + } + } + return null; + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java index 871ee281..200af74d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java @@ -26,184 +26,184 @@ import java.util.logging.Level; public class PermissableRelationGUI implements InventoryHolder, FactionGUI { - private final ConfigurationSection section; - private Inventory relationGUI; - private FPlayer fme; - private int guiSize; - private HashMap relationSlots = new HashMap<>(); + private final ConfigurationSection section; + private Inventory relationGUI; + private FPlayer fme; + private int guiSize; + private HashMap relationSlots = new HashMap<>(); - public PermissableRelationGUI(FPlayer fme) { - this.fme = fme; - this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); - } + public PermissableRelationGUI(FPlayer fme) { + this.fme = fme; + this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); + } - public void build() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + public void build() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - // Build basic Inventory info - guiSize = section.getInt("rows", 3); - if (guiSize > 5) { - guiSize = 5; - SavageFactions.plugin.log(Level.INFO, "Relation GUI size out of bounds, defaulting to 5"); - } + // Build basic Inventory info + guiSize = section.getInt("rows", 3); + if (guiSize > 5) { + guiSize = 5; + SavageFactions.plugin.log(Level.INFO, "Relation GUI size out of bounds, defaulting to 5"); + } - guiSize *= 9; - String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); - relationGUI = Bukkit.createInventory(this, guiSize, guiName); + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); + relationGUI = Bukkit.createInventory(this, guiSize, guiName); - for (String key : section.getConfigurationSection("slots").getKeys(false)) { - int slot = section.getInt("slots." + key); - if (slot == -1) { - continue; - } - if (slot + 1 > guiSize && slot > 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot of " + key.toUpperCase() + " in relation GUI skipping it"); - continue; - } + for (String key : section.getConfigurationSection("slots").getKeys(false)) { + int slot = section.getInt("slots." + key); + if (slot == -1) { + continue; + } + if (slot + 1 > guiSize && slot > 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot of " + key.toUpperCase() + " in relation GUI skipping it"); + continue; + } - if (getPermissable(key) == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid permissable " + key.toUpperCase() + " skipping it"); - continue; - } + if (getPermissable(key) == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid permissable " + key.toUpperCase() + " skipping it"); + continue; + } - relationSlots.put(slot, getPermissable(key)); - } + relationSlots.put(slot, getPermissable(key)); + } - buildDummyItems(); - buildItems(); - } + buildDummyItems(); + buildItems(); + } - @Override - public Inventory getInventory() { - return relationGUI; - } + @Override + public Inventory getInventory() { + return relationGUI; + } - @Override - public void onClick(int slot, ClickType clickType) { - if (!relationSlots.containsKey(slot)) { - return; - } + @Override + public void onClick(int slot, ClickType clickType) { + if (!relationSlots.containsKey(slot)) { + return; + } - PermissableActionGUI actionGUI = new PermissableActionGUI(fme, relationSlots.get(slot)); - actionGUI.build(); + PermissableActionGUI actionGUI = new PermissableActionGUI(fme, relationSlots.get(slot)); + actionGUI.build(); - fme.getPlayer().openInventory(actionGUI.getInventory()); - } + fme.getPlayer().openInventory(actionGUI.getInventory()); + } - private Permissable getPermissable(String name) { - if (Role.fromString(name.toUpperCase()) != null) { - return Role.fromString(name.toUpperCase()); - } else if (Relation.fromString(name.toUpperCase()) != null) { - return Relation.fromString(name.toUpperCase()); - } else { - return null; - } - } + private Permissable getPermissable(String name) { + if (Role.fromString(name.toUpperCase()) != null) { + return Role.fromString(name.toUpperCase()); + } else if (Relation.fromString(name.toUpperCase()) != null) { + return Relation.fromString(name.toUpperCase()); + } else { + return null; + } + } - private void buildItems() { - for (Map.Entry entry : relationSlots.entrySet()) { - Permissable permissable = entry.getValue(); + private void buildItems() { + for (Map.Entry entry : relationSlots.entrySet()) { + Permissable permissable = entry.getValue(); - ItemStack item = permissable.buildItem(); + ItemStack item = permissable.buildItem(); - if (item == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for " + permissable.toString().toUpperCase() + " skipping it"); - continue; - } + if (item == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for " + permissable.toString().toUpperCase() + " skipping it"); + continue; + } - relationGUI.setItem(entry.getKey(), item); - } - } + relationGUI.setItem(entry.getKey(), item); + } + } - private void buildDummyItems() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + private void buildDummyItems() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { - int dummyId; - try { - dummyId = Integer.parseInt(key); - } catch (NumberFormatException exception) { - SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); - continue; - } + for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } - ItemStack dummyItem = buildDummyItem(dummyId); - if (dummyItem == null) { - continue; - } + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } - ItemMeta meta = dummyItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + ItemMeta meta = dummyItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - dummyItem.setItemMeta(meta); + dummyItem.setItemMeta(meta); - List dummySlots = section.getIntegerList("dummy-items." + key); - for (Integer slot : dummySlots) { - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); - continue; - } - relationGUI.setItem(slot, dummyItem); - } - } - } + List dummySlots = section.getIntegerList("dummy-items." + key); + for (Integer slot : dummySlots) { + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + relationGUI.setItem(slot, dummyItem); + } + } + } - private ItemStack buildDummyItem(int id) { - final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); + private ItemStack buildDummyItem(int id) { + final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); - if (dummySection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (dummySection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - Material material = Material.matchMaterial(dummySection.getString("material", "")); - if (material == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); - return null; - } + Material material = Material.matchMaterial(dummySection.getString("material", "")); + if (material == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } - ItemStack itemStack = new ItemStack(material); + ItemStack itemStack = new ItemStack(material); - DyeColor color; - try { - color = DyeColor.valueOf(dummySection.getString("color", "")); - } catch (Exception exception) { - color = null; - } - if (color != null) { - itemStack.setDurability(color.getWoolData()); - } + DyeColor color; + try { + color = DyeColor.valueOf(dummySection.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } - ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); - List lore = new ArrayList<>(); - for (String loreLine : dummySection.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } - itemMeta.setLore(lore); + List lore = new ArrayList<>(); + for (String loreLine : dummySection.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + itemMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemStack.setItemMeta(itemMeta); + itemStack.setItemMeta(itemMeta); - return itemStack; - } + return itemStack; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java index a12f496d..a98490ac 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java @@ -17,62 +17,62 @@ import java.util.concurrent.ThreadLocalRandom; public class CropUpgrades implements Listener { - @EventHandler - public void onCropGrow(BlockGrowEvent e) { - FLocation floc = new FLocation(e.getBlock().getLocation()); - Faction factionAtLoc = Board.getInstance().getFactionAt(floc); + @EventHandler + public void onCropGrow(BlockGrowEvent e) { + FLocation floc = new FLocation(e.getBlock().getLocation()); + Faction factionAtLoc = Board.getInstance().getFactionAt(floc); - if (!factionAtLoc.isWilderness()) { - int level = factionAtLoc.getUpgrade(Upgrade.CROP); - if (level != 0) { - int chance = -1; + if (!factionAtLoc.isWilderness()) { + int level = factionAtLoc.getUpgrade(Upgrade.CROP); + if (level != 0) { + int chance = -1; - switch (level) { - case 1: - chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-1"); - break; - case 2: - chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-2"); - break; - case 3: - chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-3"); - break; - } + switch (level) { + case 1: + chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-1"); + break; + case 2: + chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-2"); + break; + case 3: + chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-3"); + break; + } - if (chance >= 0) { - int randomNum = ThreadLocalRandom.current().nextInt(1, 100 + 1); - if (randomNum <= chance) - growCrop(e); - } - } - } - } + if (chance >= 0) { + int randomNum = ThreadLocalRandom.current().nextInt(1, 100 + 1); + if (randomNum <= chance) + growCrop(e); + } + } + } + } - private void growCrop(BlockGrowEvent e) { + private void growCrop(BlockGrowEvent e) { - if (e.getBlock().getType().equals(SavageFactions.plugin.CROPS)) { - e.setCancelled(true); - Crops c = new Crops(CropState.RIPE); - BlockState bs = e.getBlock().getState(); - bs.setData(c); - bs.update(); - } + if (e.getBlock().getType().equals(SavageFactions.plugin.CROPS)) { + e.setCancelled(true); + Crops c = new Crops(CropState.RIPE); + BlockState bs = e.getBlock().getState(); + bs.setData(c); + bs.update(); + } - Block below = e.getBlock().getLocation().subtract(0, 1, 0).getBlock(); + Block below = e.getBlock().getLocation().subtract(0, 1, 0).getBlock(); - if (below.getType() == SavageFactions.plugin.SUGAR_CANE_BLOCK) { - Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); + if (below.getType() == SavageFactions.plugin.SUGAR_CANE_BLOCK) { + Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); - if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { - above.setType(SavageFactions.plugin.SUGAR_CANE_BLOCK); - } + if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { + above.setType(SavageFactions.plugin.SUGAR_CANE_BLOCK); + } - } else if (below.getType() == Material.CACTUS) { - Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); + } else if (below.getType() == Material.CACTUS) { + Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); - if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { - above.setType(Material.CACTUS); - } - } - } + if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { + above.setType(Material.CACTUS); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java index 473f70f0..a5a13594 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java @@ -12,42 +12,42 @@ import org.bukkit.event.entity.EntityDeathEvent; public class EXPUpgrade implements Listener { - @EventHandler - public void onDeath(EntityDeathEvent e) { - Entity killer = e.getEntity().getKiller(); + @EventHandler + public void onDeath(EntityDeathEvent e) { + Entity killer = e.getEntity().getKiller(); - if (killer == null || !(killer instanceof Player)) - return; + if (killer == null || !(killer instanceof Player)) + return; - FLocation floc = new FLocation(e.getEntity().getLocation()); - Faction faction = Board.getInstance().getFactionAt(floc); + FLocation floc = new FLocation(e.getEntity().getLocation()); + Faction faction = Board.getInstance().getFactionAt(floc); - if (!faction.isWilderness()) { - int level = faction.getUpgrade(Upgrade.EXP); - if (level != 0) { + if (!faction.isWilderness()) { + int level = faction.getUpgrade(Upgrade.EXP); + if (level != 0) { - double multiplier = -1; + double multiplier = -1; - switch (level) { - case 1: - multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-1"); - break; - case 2: - multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-2"); - break; - case 3: - multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-3"); - break; - } + switch (level) { + case 1: + multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-1"); + break; + case 2: + multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-2"); + break; + case 3: + multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-3"); + break; + } - if (multiplier >= 0) - spawnMoreExp(e, multiplier); - } - } - } + if (multiplier >= 0) + spawnMoreExp(e, multiplier); + } + } + } - private void spawnMoreExp(EntityDeathEvent e, double multiplier) { - double newExp = e.getDroppedExp() * multiplier; - e.setDroppedExp((int) newExp); - } + private void spawnMoreExp(EntityDeathEvent e, double multiplier) { + double newExp = e.getDroppedExp() * multiplier; + e.setDroppedExp((int) newExp); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java index 0e14eb6e..b98b8d93 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java @@ -20,278 +20,278 @@ import java.util.List; public class FUpgradesGUI implements Listener { - public void openMainMenu(FPlayer fme) { - Inventory inventory = Bukkit.createInventory(null, 27, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag()))); - List dummySlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.DummyItem.slots"); - Material dummyMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Type")); - int dummyAmount = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Amount"); - short dummyData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Damage") + ""); - ItemStack dummyItem = SavageFactions.plugin.createItem(dummyMaterial, - dummyAmount, - dummyData, - SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Name")), - SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.DummyItem.Lore"))); + public void openMainMenu(FPlayer fme) { + Inventory inventory = Bukkit.createInventory(null, 27, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag()))); + List dummySlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.DummyItem.slots"); + Material dummyMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Type")); + int dummyAmount = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Amount"); + short dummyData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Damage") + ""); + ItemStack dummyItem = SavageFactions.plugin.createItem(dummyMaterial, + dummyAmount, + dummyData, + SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Name")), + SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.DummyItem.Lore"))); - for (int i = 0; i <= dummySlots.size() - 1; i++) { - inventory.setItem(dummySlots.get(i), dummyItem); - } + for (int i = 0; i <= dummySlots.size() - 1; i++) { + inventory.setItem(dummySlots.get(i), dummyItem); + } - ItemStack[] items = buildItems(fme); - List cropSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Crops.CropItem.slots"); - List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); - List expSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.EXP.EXPItem.slots"); - List chestSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Chest.ChestItem.slots"); + ItemStack[] items = buildItems(fme); + List cropSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Crops.CropItem.slots"); + List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); + List expSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.EXP.EXPItem.slots"); + List chestSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Chest.ChestItem.slots"); - for (int i = 0; i < cropSlots.size(); i++) - inventory.setItem(cropSlots.get(i), items[2]); + for (int i = 0; i < cropSlots.size(); i++) + inventory.setItem(cropSlots.get(i), items[2]); - for (int i = 0; i < spawnerSlots.size(); i++) - inventory.setItem(spawnerSlots.get(i), items[1]); + for (int i = 0; i < spawnerSlots.size(); i++) + inventory.setItem(spawnerSlots.get(i), items[1]); - for (int i = 0; i < expSlots.size(); i++) - inventory.setItem(expSlots.get(i), items[0]); + for (int i = 0; i < expSlots.size(); i++) + inventory.setItem(expSlots.get(i), items[0]); - for (int i = 0; i < chestSlots.size(); i++) - inventory.setItem(chestSlots.get(i), items[3]); + for (int i = 0; i < chestSlots.size(); i++) + inventory.setItem(chestSlots.get(i), items[3]); - fme.getPlayer().openInventory(inventory); - } + fme.getPlayer().openInventory(inventory); + } - @EventHandler - public void onClick(InventoryClickEvent e) { - if (e.getClickedInventory() == null || e.getCurrentItem() == null || e.getCurrentItem().getItemMeta() == null || e.getCursor() == null) - return; + @EventHandler + public void onClick(InventoryClickEvent e) { + if (e.getClickedInventory() == null || e.getCurrentItem() == null || e.getCurrentItem().getItemMeta() == null || e.getCursor() == null) + return; - FPlayer fme = FPlayers.getInstance().getByPlayer((Player) e.getWhoClicked()); - if (e.getClickedInventory().getTitle().equalsIgnoreCase(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag())))) { - e.setCancelled(true); - ItemStack[] items = buildItems(fme); - ItemStack cropItem = items[2]; - ItemStack expItem = items[0]; - ItemStack chestitem = items[3]; - ItemStack spawnerItem = items[1]; + FPlayer fme = FPlayers.getInstance().getByPlayer((Player) e.getWhoClicked()); + if (e.getClickedInventory().getTitle().equalsIgnoreCase(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag())))) { + e.setCancelled(true); + ItemStack[] items = buildItems(fme); + ItemStack cropItem = items[2]; + ItemStack expItem = items[0]; + ItemStack chestitem = items[3]; + ItemStack spawnerItem = items[1]; - if (e.getCurrentItem().equals(cropItem)) { - int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); + if (e.getCurrentItem().equals(cropItem)) { + int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); - switch (cropLevel) { - case 3: - return; - case 2: - upgradeItem(fme, Upgrade.CROP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-3")); - break; - case 1: - upgradeItem(fme, Upgrade.CROP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-2")); - break; - case 0: - upgradeItem(fme, Upgrade.CROP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-1")); - break; - } - } else if (e.getCurrentItem().equals(spawnerItem)) { - int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); + switch (cropLevel) { + case 3: + return; + case 2: + upgradeItem(fme, Upgrade.CROP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-3")); + break; + case 1: + upgradeItem(fme, Upgrade.CROP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-2")); + break; + case 0: + upgradeItem(fme, Upgrade.CROP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-1")); + break; + } + } else if (e.getCurrentItem().equals(spawnerItem)) { + int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); - switch (spawnerLevel) { - case 3: - return; - case 2: - upgradeItem(fme, Upgrade.SPAWNER, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-3")); - break; - case 1: - upgradeItem(fme, Upgrade.SPAWNER, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-2")); - break; - case 0: - upgradeItem(fme, Upgrade.SPAWNER, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-1")); - break; - } - } else if (e.getCurrentItem().equals(expItem)) { - int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); + switch (spawnerLevel) { + case 3: + return; + case 2: + upgradeItem(fme, Upgrade.SPAWNER, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-3")); + break; + case 1: + upgradeItem(fme, Upgrade.SPAWNER, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-2")); + break; + case 0: + upgradeItem(fme, Upgrade.SPAWNER, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-1")); + break; + } + } else if (e.getCurrentItem().equals(expItem)) { + int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); - switch (expLevel) { - case 3: - return; - case 2: - upgradeItem(fme, Upgrade.EXP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-3")); - break; - case 1: - upgradeItem(fme, Upgrade.EXP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-2")); - break; - case 0: - upgradeItem(fme, Upgrade.EXP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-1")); - break; - } - } else if (e.getCurrentItem().equals(chestitem)) { - int chestLevel = fme.getFaction().getUpgrade(Upgrade.CHEST); + switch (expLevel) { + case 3: + return; + case 2: + upgradeItem(fme, Upgrade.EXP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-3")); + break; + case 1: + upgradeItem(fme, Upgrade.EXP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-2")); + break; + case 0: + upgradeItem(fme, Upgrade.EXP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-1")); + break; + } + } else if (e.getCurrentItem().equals(chestitem)) { + int chestLevel = fme.getFaction().getUpgrade(Upgrade.CHEST); - switch (chestLevel) { - case 3: - return; - case 2: { - if (upgradeItem(fme, Upgrade.CHEST, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-3"))) - updateChests(fme.getFaction()); - break; - } - case 1: { - if (upgradeItem(fme, Upgrade.CHEST, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-2"))) - updateChests(fme.getFaction()); - break; - } - case 0: { - if (upgradeItem(fme, Upgrade.CHEST, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-1"))) - updateChests(fme.getFaction()); - break; - } - } - } - } - } + switch (chestLevel) { + case 3: + return; + case 2: { + if (upgradeItem(fme, Upgrade.CHEST, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-3"))) + updateChests(fme.getFaction()); + break; + } + case 1: { + if (upgradeItem(fme, Upgrade.CHEST, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-2"))) + updateChests(fme.getFaction()); + break; + } + case 0: { + if (upgradeItem(fme, Upgrade.CHEST, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-1"))) + updateChests(fme.getFaction()); + break; + } + } + } + } + } - private void updateChests(Faction faction) { - String invName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title")); + private void updateChests(Faction faction) { + String invName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title")); - for (Player player : faction.getOnlinePlayers()) { - if (player.getInventory().getTitle() != null && player.getInventory().getTitle().equalsIgnoreCase(invName)) - player.closeInventory(); - } + for (Player player : faction.getOnlinePlayers()) { + if (player.getInventory().getTitle() != null && player.getInventory().getTitle().equalsIgnoreCase(invName)) + player.closeInventory(); + } - int level = faction.getUpgrade(Upgrade.CHEST); - int size = 1; + int level = faction.getUpgrade(Upgrade.CHEST); + int size = 1; - switch (level) { - case 1: - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1"); - break; - case 2: - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2"); - break; - case 3: - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3"); - break; - } - faction.setChestSize(size * 9); - } + switch (level) { + case 1: + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1"); + break; + case 2: + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2"); + break; + case 3: + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3"); + break; + } + faction.setChestSize(size * 9); + } - private ItemStack[] buildItems(FPlayer fme) { - Material expMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Type")); - int expAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Amount"); - short expData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Damage") + ""); - String expName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Name")); - List expLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.EXP.EXPItem.Lore")); - int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); + private ItemStack[] buildItems(FPlayer fme) { + Material expMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Type")); + int expAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Amount"); + short expData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Damage") + ""); + String expName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Name")); + List expLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.EXP.EXPItem.Lore")); + int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); - for (int i = 0; i <= expLore.size() - 1; i++) - expLore.set(i, expLore.get(i).replace("{level}", expLevel + "")); + for (int i = 0; i <= expLore.size() - 1; i++) + expLore.set(i, expLore.get(i).replace("{level}", expLevel + "")); - ItemStack expItem = SavageFactions.plugin.createItem(expMaterial, expAmt, expData, expName, expLore); + ItemStack expItem = SavageFactions.plugin.createItem(expMaterial, expAmt, expData, expName, expLore); - if (expLevel >= 1) { - ItemMeta itemMeta = expItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + if (expLevel >= 1) { + ItemMeta itemMeta = expItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - expItem.setItemMeta(itemMeta); - expItem.setAmount(expLevel); - } + expItem.setItemMeta(itemMeta); + expItem.setAmount(expLevel); + } - Material spawnerMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Type")); - int spawnerAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Amount"); - short spawnerData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Damage") + ""); - String spawnerName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Name")); - List spawnerLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Spawners.SpawnerItem.Lore")); + Material spawnerMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Type")); + int spawnerAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Amount"); + short spawnerData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Damage") + ""); + String spawnerName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Name")); + List spawnerLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Spawners.SpawnerItem.Lore")); - List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); - int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); + List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); + int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); - for (int i = 0; i <= spawnerLore.size() - 1; i++) { - spawnerLore.set(i, spawnerLore.get(i).replace("{level}", spawnerLevel + "")); - } + for (int i = 0; i <= spawnerLore.size() - 1; i++) { + spawnerLore.set(i, spawnerLore.get(i).replace("{level}", spawnerLevel + "")); + } - Material cropMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Type")); - int cropAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Amount"); - short cropData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Damage") + ""); - String cropName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Name")); - List cropLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Crops.CropItem.Lore")); - int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); + Material cropMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Type")); + int cropAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Amount"); + short cropData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Damage") + ""); + String cropName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Name")); + List cropLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Crops.CropItem.Lore")); + int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); - for (int i = 0; i <= cropLore.size() - 1; i++) { - String line = cropLore.get(i); - line = line.replace("{level}", cropLevel + ""); - cropLore.set(i, line); - } + for (int i = 0; i <= cropLore.size() - 1; i++) { + String line = cropLore.get(i); + line = line.replace("{level}", cropLevel + ""); + cropLore.set(i, line); + } - ItemStack cropItem = SavageFactions.plugin.createItem(cropMaterial, cropAmt, cropData, cropName, cropLore); - cropItem.getItemMeta().setLore(cropLore); + ItemStack cropItem = SavageFactions.plugin.createItem(cropMaterial, cropAmt, cropData, cropName, cropLore); + cropItem.getItemMeta().setLore(cropLore); - if (cropLevel >= 1) { - ItemMeta itemMeta = cropItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - cropItem.setItemMeta(itemMeta); + if (cropLevel >= 1) { + ItemMeta itemMeta = cropItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + cropItem.setItemMeta(itemMeta); - cropItem.setAmount(cropLevel); - } + cropItem.setAmount(cropLevel); + } - ItemStack spawnerItem = SavageFactions.plugin.createItem(spawnerMaterial, spawnerAmt, spawnerData, spawnerName, spawnerLore); - spawnerItem.getItemMeta().setLore(spawnerLore); - if (spawnerLevel >= 1) { - ItemMeta itemMeta = spawnerItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + ItemStack spawnerItem = SavageFactions.plugin.createItem(spawnerMaterial, spawnerAmt, spawnerData, spawnerName, spawnerLore); + spawnerItem.getItemMeta().setLore(spawnerLore); + if (spawnerLevel >= 1) { + ItemMeta itemMeta = spawnerItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - spawnerItem.setItemMeta(itemMeta); - spawnerItem.setAmount(spawnerLevel); - } + spawnerItem.setItemMeta(itemMeta); + spawnerItem.setAmount(spawnerLevel); + } - Material chestMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Type")); - int chesttAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Amount"); - short chestData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Damage") + ""); - String chestName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Name", "&e&lUpgrade Chest Size")); - List chestLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Chest.ChestItem.Lore")); - int chestlevel = fme.getFaction().getUpgrade(Upgrade.CHEST); + Material chestMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Type")); + int chesttAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Amount"); + short chestData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Damage") + ""); + String chestName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Name", "&e&lUpgrade Chest Size")); + List chestLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Chest.ChestItem.Lore")); + int chestlevel = fme.getFaction().getUpgrade(Upgrade.CHEST); - for (int i = 0; i <= chestLore.size() - 1; i++) { - String line = chestLore.get(i); - line = line.replace("{level}", chestlevel + ""); - chestLore.set(i, line); - } + for (int i = 0; i <= chestLore.size() - 1; i++) { + String line = chestLore.get(i); + line = line.replace("{level}", chestlevel + ""); + chestLore.set(i, line); + } - ItemStack chestItem = SavageFactions.plugin.createItem(chestMaterial, chesttAmt, chestData, chestName, chestLore); + ItemStack chestItem = SavageFactions.plugin.createItem(chestMaterial, chesttAmt, chestData, chestName, chestLore); - if (chestlevel >= 1) { - ItemMeta itemMeta = chestItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + if (chestlevel >= 1) { + ItemMeta itemMeta = chestItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - chestItem.setItemMeta(itemMeta); - chestItem.setAmount(chestlevel); - } + chestItem.setItemMeta(itemMeta); + chestItem.setAmount(chestlevel); + } - ItemStack[] items = {expItem, spawnerItem, cropItem, chestItem}; - return items; - } + ItemStack[] items = {expItem, spawnerItem, cropItem, chestItem}; + return items; + } - private boolean hasMoney(FPlayer fme, int amt) { - return fme.hasMoney(amt); - } + private boolean hasMoney(FPlayer fme, int amt) { + return fme.hasMoney(amt); + } - private void takeMoney(FPlayer fme, int amt) { - fme.takeMoney(amt); - } + private void takeMoney(FPlayer fme, int amt) { + fme.takeMoney(amt); + } - private boolean upgradeItem(FPlayer fme, Upgrade upgrade, int level, int cost) { - if (hasMoney(fme, cost)) { - takeMoney(fme, cost); - fme.getFaction().setUpgrade(upgrade, level); - fme.getPlayer().closeInventory(); - return true; - } - return false; - } + private boolean upgradeItem(FPlayer fme, Upgrade upgrade, int level, int cost) { + if (hasMoney(fme, cost)) { + takeMoney(fme, cost); + fme.getFaction().setUpgrade(upgrade, level); + fme.getPlayer().closeInventory(); + return true; + } + return false; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java index 209859f5..ad36505f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java @@ -10,32 +10,32 @@ import org.bukkit.event.entity.SpawnerSpawnEvent; public class SpawnerUpgrades implements Listener { - @EventHandler - public void onSpawn(SpawnerSpawnEvent e) { - FLocation floc = new FLocation(e.getLocation()); - Faction factionAtLoc = Board.getInstance().getFactionAt(floc); + @EventHandler + public void onSpawn(SpawnerSpawnEvent e) { + FLocation floc = new FLocation(e.getLocation()); + Faction factionAtLoc = Board.getInstance().getFactionAt(floc); - if (!factionAtLoc.isWilderness()) { - int level = factionAtLoc.getUpgrade(Upgrade.SPAWNER); - if (level != 0) { - switch (level) { - case 1: - lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-1")); - break; - case 2: - lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-2")); - break; - case 3: - lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-3")); - break; - } - } - } - } + if (!factionAtLoc.isWilderness()) { + int level = factionAtLoc.getUpgrade(Upgrade.SPAWNER); + if (level != 0) { + switch (level) { + case 1: + lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-1")); + break; + case 2: + lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-2")); + break; + case 3: + lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-3")); + break; + } + } + } + } - private void lowerSpawnerDelay(SpawnerSpawnEvent e, double multiplier) { - int lowerby = (int) Math.round(e.getSpawner().getDelay() * multiplier); - e.getSpawner().setDelay(e.getSpawner().getDelay() - lowerby); - } + private void lowerSpawnerDelay(SpawnerSpawnEvent e, double multiplier) { + int lowerby = (int) Math.round(e.getSpawner().getDelay() * multiplier); + e.getSpawner().setDelay(e.getSpawner().getDelay() - lowerby); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java index 98e02172..ef7aa8dc 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java @@ -2,17 +2,17 @@ package com.massivecraft.factions.zcore.fupgrades; public enum Upgrade { - CHEST("Chest"), SPAWNER("Spawner"), EXP("Exp"), CROP("Crop"); + CHEST("Chest"), SPAWNER("Spawner"), EXP("Exp"), CROP("Crop"); - private String id; + private String id; - Upgrade(String id) { - this.id = id; - } + Upgrade(String id) { + this.id = id; + } - @Override - public String toString() { - return this.id; - } + @Override + public String toString() { + return this.id; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java index 8cec2e41..70d4a387 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java @@ -7,191 +7,191 @@ import java.util.Set; public class NBTCompound { - private String compundName; - private NBTCompound parent; + private String compundName; + private NBTCompound parent; - protected NBTCompound() { - } + protected NBTCompound() { + } - protected NBTCompound(NBTCompound owner, String name) { - this.compundName = name; - this.parent = owner; - } + protected NBTCompound(NBTCompound owner, String name) { + this.compundName = name; + this.parent = owner; + } - public String getName() { - return compundName; - } + public String getName() { + return compundName; + } - protected Object getCompound() { - return parent.getCompound(); - } + protected Object getCompound() { + return parent.getCompound(); + } - protected void setCompound(Object compound) { - parent.setCompound(compound); - } + protected void setCompound(Object compound) { + parent.setCompound(compound); + } - public NBTCompound getParent() { - return parent; - } + public NBTCompound getParent() { + return parent; + } - public void mergeCompound(NBTCompound comp) { - NBTReflectionUtil.addOtherNBTCompound(this, comp); - } + public void mergeCompound(NBTCompound comp) { + NBTReflectionUtil.addOtherNBTCompound(this, comp); + } - public void setString(String key, String value) { - NBTReflectionUtil.setString(this, key, value); - } + public void setString(String key, String value) { + NBTReflectionUtil.setString(this, key, value); + } - public String getString(String key) { - return NBTReflectionUtil.getString(this, key); - } + public String getString(String key) { + return NBTReflectionUtil.getString(this, key); + } - protected String getContent(String key) { - return NBTReflectionUtil.getContent(this, key); - } + protected String getContent(String key) { + return NBTReflectionUtil.getContent(this, key); + } - public void setInteger(String key, Integer value) { - NBTReflectionUtil.setInt(this, key, value); - } + public void setInteger(String key, Integer value) { + NBTReflectionUtil.setInt(this, key, value); + } - public Integer getInteger(String key) { - return NBTReflectionUtil.getInt(this, key); - } + public Integer getInteger(String key) { + return NBTReflectionUtil.getInt(this, key); + } - public void setDouble(String key, Double value) { - NBTReflectionUtil.setDouble(this, key, value); - } + public void setDouble(String key, Double value) { + NBTReflectionUtil.setDouble(this, key, value); + } - public Double getDouble(String key) { - return NBTReflectionUtil.getDouble(this, key); - } + public Double getDouble(String key) { + return NBTReflectionUtil.getDouble(this, key); + } - public void setByte(String key, Byte value) { - NBTReflectionUtil.setByte(this, key, value); - } + public void setByte(String key, Byte value) { + NBTReflectionUtil.setByte(this, key, value); + } - public Byte getByte(String key) { - return NBTReflectionUtil.getByte(this, key); - } + public Byte getByte(String key) { + return NBTReflectionUtil.getByte(this, key); + } - public void setShort(String key, Short value) { - NBTReflectionUtil.setShort(this, key, value); - } + public void setShort(String key, Short value) { + NBTReflectionUtil.setShort(this, key, value); + } - public Short getShort(String key) { - return NBTReflectionUtil.getShort(this, key); - } + public Short getShort(String key) { + return NBTReflectionUtil.getShort(this, key); + } - public void setLong(String key, Long value) { - NBTReflectionUtil.setLong(this, key, value); - } + public void setLong(String key, Long value) { + NBTReflectionUtil.setLong(this, key, value); + } - public Long getLong(String key) { - return NBTReflectionUtil.getLong(this, key); - } + public Long getLong(String key) { + return NBTReflectionUtil.getLong(this, key); + } - public void setFloat(String key, Float value) { - NBTReflectionUtil.setFloat(this, key, value); - } + public void setFloat(String key, Float value) { + NBTReflectionUtil.setFloat(this, key, value); + } - public Float getFloat(String key) { - return NBTReflectionUtil.getFloat(this, key); - } + public Float getFloat(String key) { + return NBTReflectionUtil.getFloat(this, key); + } - public void setByteArray(String key, byte[] value) { - NBTReflectionUtil.setByteArray(this, key, value); - } + public void setByteArray(String key, byte[] value) { + NBTReflectionUtil.setByteArray(this, key, value); + } - public byte[] getByteArray(String key) { - return NBTReflectionUtil.getByteArray(this, key); - } + public byte[] getByteArray(String key) { + return NBTReflectionUtil.getByteArray(this, key); + } - public void setIntArray(String key, int[] value) { - NBTReflectionUtil.setIntArray(this, key, value); - } + public void setIntArray(String key, int[] value) { + NBTReflectionUtil.setIntArray(this, key, value); + } - public int[] getIntArray(String key) { - return NBTReflectionUtil.getIntArray(this, key); - } + public int[] getIntArray(String key) { + return NBTReflectionUtil.getIntArray(this, key); + } - public void setBoolean(String key, Boolean value) { - NBTReflectionUtil.setBoolean(this, key, value); - } + public void setBoolean(String key, Boolean value) { + NBTReflectionUtil.setBoolean(this, key, value); + } - protected void set(String key, Object val) { - NBTReflectionUtil.set(this, key, val); - } + protected void set(String key, Object val) { + NBTReflectionUtil.set(this, key, val); + } - public Boolean getBoolean(String key) { - return NBTReflectionUtil.getBoolean(this, key); - } + public Boolean getBoolean(String key) { + return NBTReflectionUtil.getBoolean(this, key); + } - public void setObject(String key, Object value) { - NBTReflectionUtil.setObject(this, key, value); - } + public void setObject(String key, Object value) { + NBTReflectionUtil.setObject(this, key, value); + } - public T getObject(String key, Class type) { - return NBTReflectionUtil.getObject(this, key, type); - } + public T getObject(String key, Class type) { + return NBTReflectionUtil.getObject(this, key, type); + } - public Boolean hasKey(String key) { - return NBTReflectionUtil.hasKey(this, key); - } + public Boolean hasKey(String key) { + return NBTReflectionUtil.hasKey(this, key); + } - public void removeKey(String key) { - NBTReflectionUtil.remove(this, key); - } + public void removeKey(String key) { + NBTReflectionUtil.remove(this, key); + } - public Set getKeys() { - return NBTReflectionUtil.getKeys(this); - } + public Set getKeys() { + return NBTReflectionUtil.getKeys(this); + } - public NBTCompound addCompound(String name) { - NBTReflectionUtil.addNBTTagCompound(this, name); - return getCompound(name); - } + public NBTCompound addCompound(String name) { + NBTReflectionUtil.addNBTTagCompound(this, name); + return getCompound(name); + } - public NBTCompound getCompound(String name) { - NBTCompound next = new NBTCompound(this, name); - if (NBTReflectionUtil.valideCompound(next)) return next; - return null; - } + public NBTCompound getCompound(String name) { + NBTCompound next = new NBTCompound(this, name); + if (NBTReflectionUtil.valideCompound(next)) return next; + return null; + } - public NBTList getList(String name, NBTType type) { - return NBTReflectionUtil.getList(this, name, type); - } + public NBTList getList(String name, NBTType type) { + return NBTReflectionUtil.getList(this, name, type); + } - public NBTType getType(String name) { - if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) - return NBTType.NBTTagEnd; - return NBTType.valueOf(NBTReflectionUtil.getType(this, name)); - } + public NBTType getType(String name) { + if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) + return NBTType.NBTTagEnd; + return NBTType.valueOf(NBTReflectionUtil.getType(this, name)); + } - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for (String key : getKeys()) { - result.append(toString(key)); - } - return result.toString(); - } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for (String key : getKeys()) { + result.append(toString(key)); + } + return result.toString(); + } - public String toString(String key) { - StringBuilder result = new StringBuilder(); - NBTCompound compound = this; - while (compound.getParent() != null) { - result.append(" "); - compound = compound.getParent(); - } - if (this.getType(key) == NBTType.NBTTagCompound) { - return this.getCompound(key).toString(); - } else { - return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); - } - } + public String toString(String key) { + StringBuilder result = new StringBuilder(); + NBTCompound compound = this; + while (compound.getParent() != null) { + result.append(" "); + compound = compound.getParent(); + } + if (this.getType(key) == NBTType.NBTTagCompound) { + return this.getCompound(key).toString(); + } else { + return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); + } + } - public String asNBTString() { - return NBTReflectionUtil.gettoCompount(getCompound(), this).toString(); - } + public String asNBTString() { + return NBTReflectionUtil.gettoCompount(getCompound(), this).toString(); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java index 4652dbc4..6d79ad01 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java @@ -2,31 +2,31 @@ package com.massivecraft.factions.zcore.nbtapi; public class NBTContainer extends NBTCompound { - private Object nbt; + private Object nbt; - public NBTContainer() { - this(NBTReflectionUtil.getNewNBTTag()); - } + public NBTContainer() { + this(NBTReflectionUtil.getNewNBTTag()); + } - protected NBTContainer(Object nbt) { - this.nbt = nbt; - } + protected NBTContainer(Object nbt) { + this.nbt = nbt; + } - public NBTContainer(String nbtString) throws IllegalArgumentException { - try { - nbt = NBTReflectionUtil.parseNBT(nbtString); - } catch (Exception ex) { - ex.printStackTrace(); - throw new IllegalArgumentException("Malformed Json: " + ex.getMessage()); - } - } + public NBTContainer(String nbtString) throws IllegalArgumentException { + try { + nbt = NBTReflectionUtil.parseNBT(nbtString); + } catch (Exception ex) { + ex.printStackTrace(); + throw new IllegalArgumentException("Malformed Json: " + ex.getMessage()); + } + } - protected Object getCompound() { - return nbt; - } + protected Object getCompound() { + return nbt; + } - protected void setCompound(Object tag) { - nbt = tag; - } + protected void setCompound(Object tag) { + nbt = tag; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java index 2417393c..4176dfdc 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java @@ -4,18 +4,18 @@ import org.bukkit.entity.Entity; public class NBTEntity extends NBTCompound { - private final Entity ent; + private final Entity ent; - public NBTEntity(Entity entity) { - ent = entity; - } + public NBTEntity(Entity entity) { + ent = entity; + } - protected Object getCompound() { - return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent)); - } + protected Object getCompound() { + return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent)); + } - protected void setCompound(Object compound) { - NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); - } + protected void setCompound(Object compound) { + NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java index 20ecd57f..26da8dc0 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java @@ -7,39 +7,39 @@ import java.io.IOException; public class NBTFile extends NBTCompound { - private final File file; - private Object nbt; + private final File file; + private Object nbt; - public NBTFile(File file) throws IOException { - this.file = file; - if (file.exists()) { - FileInputStream inputsteam = new FileInputStream(file); - nbt = NBTReflectionUtil.readNBTFile(inputsteam); - } else { - nbt = NBTReflectionUtil.getNewNBTTag(); - save(); - } - } + public NBTFile(File file) throws IOException { + this.file = file; + if (file.exists()) { + FileInputStream inputsteam = new FileInputStream(file); + nbt = NBTReflectionUtil.readNBTFile(inputsteam); + } else { + nbt = NBTReflectionUtil.getNewNBTTag(); + save(); + } + } - public void save() throws IOException { - if (!file.exists()) { - file.getParentFile().mkdirs(); - file.createNewFile(); - } - FileOutputStream outStream = new FileOutputStream(file); - NBTReflectionUtil.saveNBTFile(nbt, outStream); - } + public void save() throws IOException { + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + FileOutputStream outStream = new FileOutputStream(file); + NBTReflectionUtil.saveNBTFile(nbt, outStream); + } - public File getFile() { - return file; - } + public File getFile() { + return file; + } - protected Object getCompound() { - return nbt; - } + protected Object getCompound() { + return nbt; + } - protected void setCompound(Object compound) { - nbt = compound; - } + protected void setCompound(Object compound) { + nbt = compound; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java index 1bd3528c..86d49245 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java @@ -4,34 +4,34 @@ import org.bukkit.inventory.ItemStack; public class NBTItem extends NBTCompound { - private ItemStack bukkitItem; + private ItemStack bukkitItem; - public NBTItem(ItemStack item) { - bukkitItem = item.clone(); - } + public NBTItem(ItemStack item) { + bukkitItem = item.clone(); + } - public static NBTContainer convertItemtoNBT(ItemStack item) { - return NBTReflectionUtil.convertNMSItemtoNBTCompound(NBTReflectionUtil.getNMSItemStack(item)); - } + public static NBTContainer convertItemtoNBT(ItemStack item) { + return NBTReflectionUtil.convertNMSItemtoNBTCompound(NBTReflectionUtil.getNMSItemStack(item)); + } - public static ItemStack convertNBTtoItem(NBTCompound comp) { - return NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); - } + public static ItemStack convertNBTtoItem(NBTCompound comp) { + return NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); + } - protected Object getCompound() { - return NBTReflectionUtil.getItemRootNBTTagCompound(NBTReflectionUtil.getNMSItemStack(bukkitItem)); - } + protected Object getCompound() { + return NBTReflectionUtil.getItemRootNBTTagCompound(NBTReflectionUtil.getNMSItemStack(bukkitItem)); + } - protected void setCompound(Object compound) { - bukkitItem = NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.setNBTTag(compound, NBTReflectionUtil.getNMSItemStack(bukkitItem))); - } + protected void setCompound(Object compound) { + bukkitItem = NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.setNBTTag(compound, NBTReflectionUtil.getNMSItemStack(bukkitItem))); + } - public ItemStack getItem() { - return bukkitItem; - } + public ItemStack getItem() { + return bukkitItem; + } - protected void setItem(ItemStack item) { - bukkitItem = item; - } + protected void setItem(ItemStack item) { + bukkitItem = item; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java index a3d5a985..91726778 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java @@ -6,120 +6,120 @@ import java.lang.reflect.Method; public class NBTList { - private String listName; - private NBTCompound parent; - private NBTType type; - private Object listObject; + private String listName; + private NBTCompound parent; + private NBTType type; + private Object listObject; - protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { - parent = owner; - listName = name; - this.type = type; - this.listObject = list; - if (!(type == NBTType.NBTTagString || type == NBTType.NBTTagCompound)) { - System.err.println("List types != String/Compound are currently not implemented!"); - } - } + protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { + parent = owner; + listName = name; + this.type = type; + this.listObject = list; + if (!(type == NBTType.NBTTagString || type == NBTType.NBTTagCompound)) { + System.err.println("List types != String/Compound are currently not implemented!"); + } + } - protected void save() { - parent.set(listName, listObject); - } + protected void save() { + parent.set(listName, listObject); + } - public NBTListCompound addCompound() { - if (type != NBTType.NBTTagCompound) { - new Throwable("Using Compound method on a non Compound list!").printStackTrace(); - return null; - } - try { - Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); - Object compound = NBTReflectionUtil.getNBTTagCompound().newInstance(); - method.invoke(listObject, compound); - return new NBTListCompound(this, compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + public NBTListCompound addCompound() { + if (type != NBTType.NBTTagCompound) { + new Throwable("Using Compound method on a non Compound list!").printStackTrace(); + return null; + } + try { + Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); + Object compound = NBTReflectionUtil.getNBTTagCompound().newInstance(); + method.invoke(listObject, compound); + return new NBTListCompound(this, compound); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } - public NBTListCompound getCompound(int id) { - if (type != NBTType.NBTTagCompound) { - new Throwable("Using Compound method on a non Compound list!").printStackTrace(); - return null; - } - try { - Method method = listObject.getClass().getMethod("get", int.class); - Object compound = method.invoke(listObject, id); - return new NBTListCompound(this, compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + public NBTListCompound getCompound(int id) { + if (type != NBTType.NBTTagCompound) { + new Throwable("Using Compound method on a non Compound list!").printStackTrace(); + return null; + } + try { + Method method = listObject.getClass().getMethod("get", int.class); + Object compound = method.invoke(listObject, id); + return new NBTListCompound(this, compound); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } - public String getString(int i) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return null; - } - try { - Method method = listObject.getClass().getMethod("getString", int.class); - return (String) method.invoke(listObject, i); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + public String getString(int i) { + if (type != NBTType.NBTTagString) { + new Throwable("Using String method on a non String list!").printStackTrace(); + return null; + } + try { + Method method = listObject.getClass().getMethod("getString", int.class); + return (String) method.invoke(listObject, i); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } - public void addString(String s) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return; - } - try { - Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); - method.invoke(listObject, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void addString(String s) { + if (type != NBTType.NBTTagString) { + new Throwable("Using String method on a non String list!").printStackTrace(); + return; + } + try { + Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); + method.invoke(listObject, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); + save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public void setString(int i, String s) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return; - } - try { - Method method = listObject.getClass().getMethod("a", int.class, NBTReflectionUtil.getNBTBase()); - method.invoke(listObject, i, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setString(int i, String s) { + if (type != NBTType.NBTTagString) { + new Throwable("Using String method on a non String list!").printStackTrace(); + return; + } + try { + Method method = listObject.getClass().getMethod("a", int.class, NBTReflectionUtil.getNBTBase()); + method.invoke(listObject, i, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); + save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public void remove(int i) { - try { - Method method = listObject.getClass().getMethod(MethodNames.getRemoveMethodName(), int.class); - method.invoke(listObject, i); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void remove(int i) { + try { + Method method = listObject.getClass().getMethod(MethodNames.getRemoveMethodName(), int.class); + method.invoke(listObject, i); + save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public int size() { - try { - Method method = listObject.getClass().getMethod("size"); - return (int) method.invoke(listObject); - } catch (Exception ex) { - ex.printStackTrace(); - } - return -1; - } + public int size() { + try { + Method method = listObject.getClass().getMethod("size"); + return (int) method.invoke(listObject); + } catch (Exception ex) { + ex.printStackTrace(); + } + return -1; + } - public NBTType getType() { - return type; - } + public NBTType getType() { + return type; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java index e3d92716..59a1ce5f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java @@ -5,98 +5,98 @@ import java.util.Set; public class NBTListCompound { - private NBTList owner; - private Object compound; + private NBTList owner; + private Object compound; - protected NBTListCompound(NBTList parent, Object obj) { - owner = parent; - compound = obj; - } + protected NBTListCompound(NBTList parent, Object obj) { + owner = parent; + compound = obj; + } - public void setString(String key, String value) { - if (value == null) { - remove(key); - return; - } - try { - compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setString(String key, String value) { + if (value == null) { + remove(key); + return; + } + try { + compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value); + owner.save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public void setInteger(String key, int value) { - try { - compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setInteger(String key, int value) { + try { + compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value); + owner.save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public int getInteger(String value) { - try { - return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } + public int getInteger(String value) { + try { + return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value); + } catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } - public void setDouble(String key, double value) { - try { - compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setDouble(String key, double value) { + try { + compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value); + owner.save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public double getDouble(String key) { - try { - return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } + public double getDouble(String key) { + try { + return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } - public String getString(String key) { - try { - return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return ""; - } + public String getString(String key) { + try { + return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return ""; + } - public boolean hasKey(String key) { - try { - return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return false; - } + public boolean hasKey(String key) { + try { + return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return false; + } - @SuppressWarnings("unchecked") - public Set getKeys() { - try { - return (Set) compound.getClass().getMethod("c").invoke(compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return new HashSet<>(); - } + @SuppressWarnings("unchecked") + public Set getKeys() { + try { + return (Set) compound.getClass().getMethod("c").invoke(compound); + } catch (Exception ex) { + ex.printStackTrace(); + } + return new HashSet<>(); + } - public void remove(String key) { - try { - compound.getClass().getMethod("remove", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void remove(String key) { + try { + compound.getClass().getMethod("remove", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java index a35684ef..5df3308e 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java @@ -19,904 +19,904 @@ import java.util.Stack; // TODO: finish codestyle cleanup -sgdc3 public class NBTReflectionUtil { - private static final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - - private static Class getCraftItemStack() { - - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - private static Class getCraftEntity() { - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftEntity"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTBase() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTBase"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTTagString() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTTagString"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNMSItemStack() { - try { - return Class.forName("net.minecraft.server." + version + ".ItemStack"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTTagCompound() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTCompressedStreamTools() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTCompressedStreamTools"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getMojangsonParser() { - try { - return Class.forName("net.minecraft.server." + version + ".MojangsonParser"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getTileEntity() { - try { - return Class.forName("net.minecraft.server." + version + ".TileEntity"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getCraftWorld() { - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - public static Object getNewNBTTag() { - String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - try { - Class c = Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); - return c.newInstance(); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - private static Object getNewBlockPosition(int x, int y, int z) { - String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - try { - Class clazz = Class.forName("net.minecraft.server." + version + ".BlockPosition"); - return clazz.getConstructor(int.class, int.class, int.class).newInstance(x, y, z); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - public static Object setNBTTag(Object NBTTag, Object NMSItem) { - try { - Method method = NMSItem.getClass().getMethod("setTag", NBTTag.getClass()); - method.invoke(NMSItem, NBTTag); - return NMSItem; - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static Object getNMSItemStack(ItemStack item) { - Class clazz = getCraftItemStack(); - - try { - Method method = clazz.getMethod("asNMSCopy", ItemStack.class); - return method.invoke(clazz, item); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object getNMSEntity(Entity entity) { - Class clazz = getCraftEntity(); - - try { - Method method = clazz.getMethod("getHandle"); - return method.invoke(getCraftEntity().cast(entity)); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object parseNBT(String json) { - Class cis = getMojangsonParser(); - - try { - Method method = cis.getMethod("parse", String.class); - return method.invoke(null, json); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object readNBTFile(FileInputStream stream) { - Class clazz = getNBTCompressedStreamTools(); - - try { - Method method = clazz.getMethod("a", InputStream.class); - return method.invoke(clazz, stream); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object saveNBTFile(Object nbt, FileOutputStream stream) { - Class clazz = getNBTCompressedStreamTools(); - - try { - Method method = clazz.getMethod("a", getNBTTagCompound(), OutputStream.class); - return method.invoke(clazz, nbt, stream); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static ItemStack getBukkitItemStack(Object item) { - Class clazz = getCraftItemStack(); - - try { - Method method = clazz.getMethod("asCraftMirror", item.getClass()); - return (ItemStack) method.invoke(clazz, item); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object getItemRootNBTTagCompound(Object nmsitem) { - Class clazz = nmsitem.getClass(); - - try { - Method method = clazz.getMethod("getTag"); - return method.invoke(nmsitem); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { - Class clazz = getNMSItemStack(); - try { - return clazz.getConstructor(getNBTTagCompound()).newInstance(gettoCompount(nbtcompound.getCompound(), nbtcompound)); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) { - Class clazz = nmsitem.getClass(); - - try { - Method method = clazz.getMethod("save", getNBTTagCompound()); - Object answer = method.invoke(nmsitem, getNewNBTTag()); - return new NBTContainer(answer); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object getEntityNBTTagCompound(Object nmsitem) { - Class c = nmsitem.getClass(); - - try { - Method method = c.getMethod(MethodNames.getEntityNbtGetterMethodName(), getNBTTagCompound()); - Object nbt = getNBTTagCompound().newInstance(); - Object answer = method.invoke(nmsitem, nbt); - return answer != null ? answer : nbt; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object setEntityNBTTag(Object NBTTag, Object NMSItem) { - try { - Method method; - method = NMSItem.getClass().getMethod(MethodNames.getEntityNbtSetterMethodName(), getNBTTagCompound()); - method.invoke(NMSItem, NBTTag); - return NMSItem; - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static Object getTileEntityNBTTagCompound(BlockState tile) { - try { - Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); - Object cworld = getCraftWorld().cast(tile.getWorld()); - Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); - Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); - Method method = getTileEntity().getMethod(MethodNames.getTileDataMethodName(), getNBTTagCompound()); - Object tag = getNBTTagCompound().newInstance(); - Object answer = method.invoke(o, tag); - - return answer != null ? answer : tag; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { - try { - Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); - Object cworld = getCraftWorld().cast(tile.getWorld()); - Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); - Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); - Method method = getTileEntity().getMethod("a", getNBTTagCompound()); - method.invoke(o, comp); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static Object getSubNBTTagCompound(Object compound, String name) { - Class c = compound.getClass(); - - try { - Method method = c.getMethod("getCompound", String.class); - return method.invoke(compound, name); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static void addNBTTagCompound(NBTCompound comp, String name) { - if (name == null) { - remove(comp, name); - return; - } - Object nbttag = comp.getCompound(); - if (nbttag == null) { - nbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(nbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); - method.invoke(workingtag, name, getNBTTagCompound().newInstance()); - comp.setCompound(nbttag); - return; - } catch (Exception ex) { - ex.printStackTrace(); - } - return; - } - - public static Boolean valideCompound(NBTCompound comp) { - Object root = comp.getCompound(); - if (root == null) { - root = getNewNBTTag(); - } - return gettoCompount(root, comp) != null; - } - - public static Object gettoCompount(Object nbttag, NBTCompound comp) { - Stack structure = new Stack<>(); - while (comp.getParent() != null) { - structure.add(comp.getName()); - comp = comp.getParent(); - } - while (!structure.isEmpty()) { - nbttag = getSubNBTTagCompound(nbttag, structure.pop()); - if (nbttag == null) { - return null; - } - } - return nbttag; - } - - public static void addOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("a", getNBTTagCompound()); - method.invoke(workingtag, nbtcompound.getCompound()); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static void setString(NBTCompound comp, String key, String text) { - if (text == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setString", String.class, String.class); - method.invoke(workingtag, key, text); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static String getString(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getString", String.class); - return (String) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static String getContent(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("get", String.class); - return method.invoke(workingtag, key).toString(); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setInt(NBTCompound comp, String key, Integer i) { - if (i == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setInt", String.class, int.class); - method.invoke(workingtag, key, i); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Integer getInt(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getInt", String.class); - return (Integer) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setByteArray(NBTCompound comp, String key, byte[] b) { - if (b == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setByteArray", String.class, byte[].class); - method.invoke(workingtag, key, b); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - return; - } - - public static byte[] getByteArray(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getByteArray", String.class); - return (byte[]) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setIntArray(NBTCompound comp, String key, int[] i) { - if (i == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setIntArray", String.class, int[].class); - method.invoke(workingtag, key, i); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static int[] getIntArray(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getIntArray", String.class); - return (int[]) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setFloat(NBTCompound comp, String key, Float f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setFloat", String.class, float.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Float getFloat(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getFloat", String.class); - return (Float) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setLong(NBTCompound comp, String key, Long f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setLong", String.class, long.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Long getLong(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getLong", String.class); - return (Long) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setShort(NBTCompound comp, String key, Short f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setShort", String.class, short.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Short getShort(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getShort", String.class); - return (Short) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setByte(NBTCompound comp, String key, Byte f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setByte", String.class, byte.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Byte getByte(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getByte", String.class); - return (Byte) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setDouble(NBTCompound comp, String key, Double d) { - if (d == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setDouble", String.class, double.class); - method.invoke(workingtag, key, d); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Double getDouble(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getDouble", String.class); - return (Double) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static byte getType(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return 0; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod(MethodNames.getTypeMethodName(), String.class); - return (byte) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } - - public static void setBoolean(NBTCompound comp, String key, Boolean d) { - if (d == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setBoolean", String.class, boolean.class); - method.invoke(workingtag, key, d); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Boolean getBoolean(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getBoolean", String.class); - return (Boolean) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void set(NBTCompound comp, String key, Object val) { - if (val == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) { - new Throwable("InvalideCompound").printStackTrace(); - return; - } - Object workingtag = gettoCompount(rootnbttag, comp); - try { - Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); - method.invoke(workingtag, key, val); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static NBTList getList(NBTCompound comp, String key, NBTType type) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getList", String.class, int.class); - return new NBTList(comp, key, type, method.invoke(workingtag, key, type.getId())); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setObject(NBTCompound comp, String key, Object value) { - if (!MinecraftVersion.hasGsonSupport()) return; - try { - String json = GsonWrapper.getString(value); - setString(comp, key, json); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static T getObject(NBTCompound comp, String key, Class type) { - if (!MinecraftVersion.hasGsonSupport()) return null; - String json = getString(comp, key); - - return json != null ? GsonWrapper.deserializeJson(json, type) : null; - } - - public static void remove(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("remove", String.class); - method.invoke(workingtag, key); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Boolean hasKey(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("hasKey", String.class); - return (Boolean) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - @SuppressWarnings("unchecked") - public static Set getKeys(NBTCompound comp) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - Method method; - try { - method = workingtag.getClass().getMethod("c"); - return (Set) method.invoke(workingtag); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + private static final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + + private static Class getCraftItemStack() { + + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + private static Class getCraftEntity() { + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftEntity"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTBase() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTBase"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTTagString() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTTagString"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNMSItemStack() { + try { + return Class.forName("net.minecraft.server." + version + ".ItemStack"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTTagCompound() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTCompressedStreamTools() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTCompressedStreamTools"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getMojangsonParser() { + try { + return Class.forName("net.minecraft.server." + version + ".MojangsonParser"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getTileEntity() { + try { + return Class.forName("net.minecraft.server." + version + ".TileEntity"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getCraftWorld() { + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + public static Object getNewNBTTag() { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + try { + Class c = Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); + return c.newInstance(); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + private static Object getNewBlockPosition(int x, int y, int z) { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + try { + Class clazz = Class.forName("net.minecraft.server." + version + ".BlockPosition"); + return clazz.getConstructor(int.class, int.class, int.class).newInstance(x, y, z); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + public static Object setNBTTag(Object NBTTag, Object NMSItem) { + try { + Method method = NMSItem.getClass().getMethod("setTag", NBTTag.getClass()); + method.invoke(NMSItem, NBTTag); + return NMSItem; + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static Object getNMSItemStack(ItemStack item) { + Class clazz = getCraftItemStack(); + + try { + Method method = clazz.getMethod("asNMSCopy", ItemStack.class); + return method.invoke(clazz, item); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getNMSEntity(Entity entity) { + Class clazz = getCraftEntity(); + + try { + Method method = clazz.getMethod("getHandle"); + return method.invoke(getCraftEntity().cast(entity)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object parseNBT(String json) { + Class cis = getMojangsonParser(); + + try { + Method method = cis.getMethod("parse", String.class); + return method.invoke(null, json); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object readNBTFile(FileInputStream stream) { + Class clazz = getNBTCompressedStreamTools(); + + try { + Method method = clazz.getMethod("a", InputStream.class); + return method.invoke(clazz, stream); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object saveNBTFile(Object nbt, FileOutputStream stream) { + Class clazz = getNBTCompressedStreamTools(); + + try { + Method method = clazz.getMethod("a", getNBTTagCompound(), OutputStream.class); + return method.invoke(clazz, nbt, stream); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static ItemStack getBukkitItemStack(Object item) { + Class clazz = getCraftItemStack(); + + try { + Method method = clazz.getMethod("asCraftMirror", item.getClass()); + return (ItemStack) method.invoke(clazz, item); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getItemRootNBTTagCompound(Object nmsitem) { + Class clazz = nmsitem.getClass(); + + try { + Method method = clazz.getMethod("getTag"); + return method.invoke(nmsitem); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { + Class clazz = getNMSItemStack(); + try { + return clazz.getConstructor(getNBTTagCompound()).newInstance(gettoCompount(nbtcompound.getCompound(), nbtcompound)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) { + Class clazz = nmsitem.getClass(); + + try { + Method method = clazz.getMethod("save", getNBTTagCompound()); + Object answer = method.invoke(nmsitem, getNewNBTTag()); + return new NBTContainer(answer); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getEntityNBTTagCompound(Object nmsitem) { + Class c = nmsitem.getClass(); + + try { + Method method = c.getMethod(MethodNames.getEntityNbtGetterMethodName(), getNBTTagCompound()); + Object nbt = getNBTTagCompound().newInstance(); + Object answer = method.invoke(nmsitem, nbt); + return answer != null ? answer : nbt; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object setEntityNBTTag(Object NBTTag, Object NMSItem) { + try { + Method method; + method = NMSItem.getClass().getMethod(MethodNames.getEntityNbtSetterMethodName(), getNBTTagCompound()); + method.invoke(NMSItem, NBTTag); + return NMSItem; + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static Object getTileEntityNBTTagCompound(BlockState tile) { + try { + Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); + Object cworld = getCraftWorld().cast(tile.getWorld()); + Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); + Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); + Method method = getTileEntity().getMethod(MethodNames.getTileDataMethodName(), getNBTTagCompound()); + Object tag = getNBTTagCompound().newInstance(); + Object answer = method.invoke(o, tag); + + return answer != null ? answer : tag; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { + try { + Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); + Object cworld = getCraftWorld().cast(tile.getWorld()); + Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); + Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); + Method method = getTileEntity().getMethod("a", getNBTTagCompound()); + method.invoke(o, comp); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static Object getSubNBTTagCompound(Object compound, String name) { + Class c = compound.getClass(); + + try { + Method method = c.getMethod("getCompound", String.class); + return method.invoke(compound, name); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void addNBTTagCompound(NBTCompound comp, String name) { + if (name == null) { + remove(comp, name); + return; + } + Object nbttag = comp.getCompound(); + if (nbttag == null) { + nbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(nbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); + method.invoke(workingtag, name, getNBTTagCompound().newInstance()); + comp.setCompound(nbttag); + return; + } catch (Exception ex) { + ex.printStackTrace(); + } + return; + } + + public static Boolean valideCompound(NBTCompound comp) { + Object root = comp.getCompound(); + if (root == null) { + root = getNewNBTTag(); + } + return gettoCompount(root, comp) != null; + } + + public static Object gettoCompount(Object nbttag, NBTCompound comp) { + Stack structure = new Stack<>(); + while (comp.getParent() != null) { + structure.add(comp.getName()); + comp = comp.getParent(); + } + while (!structure.isEmpty()) { + nbttag = getSubNBTTagCompound(nbttag, structure.pop()); + if (nbttag == null) { + return null; + } + } + return nbttag; + } + + public static void addOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("a", getNBTTagCompound()); + method.invoke(workingtag, nbtcompound.getCompound()); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static void setString(NBTCompound comp, String key, String text) { + if (text == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setString", String.class, String.class); + method.invoke(workingtag, key, text); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static String getString(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getString", String.class); + return (String) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static String getContent(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("get", String.class); + return method.invoke(workingtag, key).toString(); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setInt(NBTCompound comp, String key, Integer i) { + if (i == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setInt", String.class, int.class); + method.invoke(workingtag, key, i); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Integer getInt(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getInt", String.class); + return (Integer) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setByteArray(NBTCompound comp, String key, byte[] b) { + if (b == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setByteArray", String.class, byte[].class); + method.invoke(workingtag, key, b); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + return; + } + + public static byte[] getByteArray(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getByteArray", String.class); + return (byte[]) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setIntArray(NBTCompound comp, String key, int[] i) { + if (i == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setIntArray", String.class, int[].class); + method.invoke(workingtag, key, i); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static int[] getIntArray(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getIntArray", String.class); + return (int[]) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setFloat(NBTCompound comp, String key, Float f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setFloat", String.class, float.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Float getFloat(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getFloat", String.class); + return (Float) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setLong(NBTCompound comp, String key, Long f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setLong", String.class, long.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Long getLong(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getLong", String.class); + return (Long) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setShort(NBTCompound comp, String key, Short f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setShort", String.class, short.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Short getShort(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getShort", String.class); + return (Short) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setByte(NBTCompound comp, String key, Byte f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setByte", String.class, byte.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Byte getByte(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getByte", String.class); + return (Byte) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setDouble(NBTCompound comp, String key, Double d) { + if (d == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setDouble", String.class, double.class); + method.invoke(workingtag, key, d); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Double getDouble(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getDouble", String.class); + return (Double) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static byte getType(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return 0; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod(MethodNames.getTypeMethodName(), String.class); + return (byte) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } + + public static void setBoolean(NBTCompound comp, String key, Boolean d) { + if (d == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setBoolean", String.class, boolean.class); + method.invoke(workingtag, key, d); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Boolean getBoolean(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getBoolean", String.class); + return (Boolean) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void set(NBTCompound comp, String key, Object val) { + if (val == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) { + new Throwable("InvalideCompound").printStackTrace(); + return; + } + Object workingtag = gettoCompount(rootnbttag, comp); + try { + Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); + method.invoke(workingtag, key, val); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static NBTList getList(NBTCompound comp, String key, NBTType type) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getList", String.class, int.class); + return new NBTList(comp, key, type, method.invoke(workingtag, key, type.getId())); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setObject(NBTCompound comp, String key, Object value) { + if (!MinecraftVersion.hasGsonSupport()) return; + try { + String json = GsonWrapper.getString(value); + setString(comp, key, json); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static T getObject(NBTCompound comp, String key, Class type) { + if (!MinecraftVersion.hasGsonSupport()) return null; + String json = getString(comp, key); + + return json != null ? GsonWrapper.deserializeJson(json, type) : null; + } + + public static void remove(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("remove", String.class); + method.invoke(workingtag, key); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Boolean hasKey(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("hasKey", String.class); + return (Boolean) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + @SuppressWarnings("unchecked") + public static Set getKeys(NBTCompound comp) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + Method method; + try { + method = workingtag.getClass().getMethod("c"); + return (Set) method.invoke(workingtag); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java index dc78290e..cfc56e06 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java @@ -4,18 +4,18 @@ import org.bukkit.block.BlockState; public class NBTTileEntity extends NBTCompound { - private final BlockState tile; + private final BlockState tile; - public NBTTileEntity(BlockState tile) { - this.tile = tile; - } + public NBTTileEntity(BlockState tile) { + this.tile = tile; + } - protected Object getCompound() { - return NBTReflectionUtil.getTileEntityNBTTagCompound(tile); - } + protected Object getCompound() { + return NBTReflectionUtil.getTileEntityNBTTagCompound(tile); + } - protected void setCompound(Object compound) { - NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); - } + protected void setCompound(Object compound) { + NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java index afa9d60a..37d87ec6 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java @@ -1,34 +1,34 @@ package com.massivecraft.factions.zcore.nbtapi; public enum NBTType { - NBTTagEnd(0), - NBTTagByte(1), - NBTTagShort(2), - NBTTagInt(3), - NBTTagLong(4), - NBTTagFloat(5), - NBTTagDouble(6), - NBTTagByteArray(7), - NBTTagIntArray(11), - NBTTagString(8), - NBTTagList(9), - NBTTagCompound(10); + NBTTagEnd(0), + NBTTagByte(1), + NBTTagShort(2), + NBTTagInt(3), + NBTTagLong(4), + NBTTagFloat(5), + NBTTagDouble(6), + NBTTagByteArray(7), + NBTTagIntArray(11), + NBTTagString(8), + NBTTagList(9), + NBTTagCompound(10); - private final int id; + private final int id; - NBTType(int i) { - id = i; - } + NBTType(int i) { + id = i; + } - public static NBTType valueOf(int id) { - for (NBTType t : values()) - if (t.getId() == id) - return t; - return NBTType.NBTTagEnd; - } + public static NBTType valueOf(int id) { + for (NBTType t : values()) + if (t.getId() == id) + return t; + return NBTType.NBTTagEnd; + } - public int getId() { - return id; - } + public int getId() { + return id; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java index 77492633..4a8eaf55 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java @@ -4,24 +4,24 @@ import com.google.gson.Gson; public class GsonWrapper { - private static final Gson gson = new Gson(); + private static final Gson gson = new Gson(); - public static String getString(Object obj) { - return gson.toJson(obj); - } + public static String getString(Object obj) { + return gson.toJson(obj); + } - public static T deserializeJson(String json, Class type) { - try { - if (json == null) { - return null; - } + public static T deserializeJson(String json, Class type) { + try { + if (json == null) { + return null; + } - T obj = gson.fromJson(json, type); - return type.cast(obj); - } catch (Exception ex) { - ex.printStackTrace(); - return null; - } - } + T obj = gson.fromJson(json, type); + return type.cast(obj); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java index 126ad031..f45ba7f6 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java @@ -2,25 +2,25 @@ package com.massivecraft.factions.zcore.nbtapi.utils; public class MethodNames { - private final static MinecraftVersion MINECRAFT_VERSION = MinecraftVersion.getVersion(); + private final static MinecraftVersion MINECRAFT_VERSION = MinecraftVersion.getVersion(); - public static String getTileDataMethodName() { - return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "save"; - } + public static String getTileDataMethodName() { + return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "save"; + } - public static String getTypeMethodName() { - return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "d"; - } + public static String getTypeMethodName() { + return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "d"; + } - public static String getEntityNbtGetterMethodName() { - return "b"; - } + public static String getEntityNbtGetterMethodName() { + return "b"; + } - public static String getEntityNbtSetterMethodName() { - return "a"; - } + public static String getEntityNbtSetterMethodName() { + return "a"; + } - public static String getRemoveMethodName() { - return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "a" : "remove"; - } + public static String getRemoveMethodName() { + return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "a" : "remove"; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java index 372610c1..3b3ea260 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java @@ -3,58 +3,58 @@ package com.massivecraft.factions.zcore.nbtapi.utils; import org.bukkit.Bukkit; public enum MinecraftVersion { - Unknown(0), - MC1_7_R4(174), - MC1_8_R3(183), - MC1_9_R1(191), - MC1_9_R2(192), - MC1_10_R1(1101), - MC1_11_R1(1111), - MC1_12_R1(1121); + Unknown(0), + MC1_7_R4(174), + MC1_8_R3(183), + MC1_9_R1(191), + MC1_9_R2(192), + MC1_10_R1(1101), + MC1_11_R1(1111), + MC1_12_R1(1121); - private static MinecraftVersion version; - private static Boolean hasGsonSupport; + private static MinecraftVersion version; + private static Boolean hasGsonSupport; - private final int versionId; + private final int versionId; - MinecraftVersion(int versionId) { - this.versionId = versionId; - } + MinecraftVersion(int versionId) { + this.versionId = versionId; + } - public static MinecraftVersion getVersion() { - if (version == null) { - final String ver = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - System.out.println("[NBTAPI] Found Spigot: " + ver + "!Trying to find NMS support"); + public static MinecraftVersion getVersion() { + if (version == null) { + final String ver = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + System.out.println("[NBTAPI] Found Spigot: " + ver + "!Trying to find NMS support"); - try { - version = MinecraftVersion.valueOf(ver.replace("v", "MC")); - } catch (IllegalArgumentException ex) { - version = MinecraftVersion.Unknown; - } + try { + version = MinecraftVersion.valueOf(ver.replace("v", "MC")); + } catch (IllegalArgumentException ex) { + version = MinecraftVersion.Unknown; + } - if (version != Unknown) { - System.out.println("[NBTAPI] NMS support '" + version.name() + "' loaded!"); - } else { - System.out.println("[NBTAPI] Wasn't able to find NMS Support!Some functions will not work!"); - } - } - return version; - } + if (version != Unknown) { + System.out.println("[NBTAPI] NMS support '" + version.name() + "' loaded!"); + } else { + System.out.println("[NBTAPI] Wasn't able to find NMS Support!Some functions will not work!"); + } + } + return version; + } - public static boolean hasGsonSupport() { - if (hasGsonSupport == null) { - try { - System.out.println("Found Gson: " + Class.forName("com.google.gson.Gson")); - hasGsonSupport = true; - } catch (Exception ex) { - hasGsonSupport = false; - } - } - return hasGsonSupport; - } + public static boolean hasGsonSupport() { + if (hasGsonSupport == null) { + try { + System.out.println("Found Gson: " + Class.forName("com.google.gson.Gson")); + hasGsonSupport = true; + } catch (Exception ex) { + hasGsonSupport = false; + } + } + return hasGsonSupport; + } - public int getVersionId() { - return versionId; - } + public int getVersionId() { + return versionId; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java index 8dd916e6..c01d007d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java @@ -20,372 +20,372 @@ import java.util.Map.Entry; public abstract class MemoryBoard extends Board { - public MemoryBoardMap flocationIds = new MemoryBoardMap(); + public MemoryBoardMap flocationIds = new MemoryBoardMap(); - //----------------------------------------------// - // Get and Set - //----------------------------------------------// - public String getIdAt(FLocation flocation) { - if (!flocationIds.containsKey(flocation)) { - return "0"; - } + //----------------------------------------------// + // Get and Set + //----------------------------------------------// + public String getIdAt(FLocation flocation) { + if (!flocationIds.containsKey(flocation)) { + return "0"; + } - return flocationIds.get(flocation); - } + return flocationIds.get(flocation); + } - public Faction getFactionAt(FLocation flocation) { - return Factions.getInstance().getFactionById(getIdAt(flocation)); - } + public Faction getFactionAt(FLocation flocation) { + return Factions.getInstance().getFactionById(getIdAt(flocation)); + } - public void setIdAt(String id, FLocation flocation) { - clearOwnershipAt(flocation); + public void setIdAt(String id, FLocation flocation) { + clearOwnershipAt(flocation); - if (id.equals("0")) { - removeAt(flocation); - } + if (id.equals("0")) { + removeAt(flocation); + } - flocationIds.put(flocation, id); - } + flocationIds.put(flocation, id); + } - public void setFactionAt(Faction faction, FLocation flocation) { - setIdAt(faction.getId(), flocation); - } + public void setFactionAt(Faction faction, FLocation flocation) { + setIdAt(faction.getId(), flocation); + } - public void removeAt(FLocation flocation) { - Faction faction = getFactionAt(flocation); - Iterator it = faction.getWarps().values().iterator(); - while (it.hasNext()) { - if (flocation.isInChunk(it.next().getLocation())) { - it.remove(); - } - } - clearOwnershipAt(flocation); - flocationIds.remove(flocation); - } + public void removeAt(FLocation flocation) { + Faction faction = getFactionAt(flocation); + Iterator it = faction.getWarps().values().iterator(); + while (it.hasNext()) { + if (flocation.isInChunk(it.next().getLocation())) { + it.remove(); + } + } + clearOwnershipAt(flocation); + flocationIds.remove(flocation); + } - public Set getAllClaims(String factionId) { - Set locs = new HashSet<>(); - for (Entry entry : flocationIds.entrySet()) { - if (entry.getValue().equals(factionId)) { - locs.add(entry.getKey()); - } - } - return locs; - } + public Set getAllClaims(String factionId) { + Set locs = new HashSet<>(); + for (Entry entry : flocationIds.entrySet()) { + if (entry.getValue().equals(factionId)) { + locs.add(entry.getKey()); + } + } + return locs; + } - public Set getAllClaims(Faction faction) { - return getAllClaims(faction.getId()); - } + public Set getAllClaims(Faction faction) { + return getAllClaims(faction.getId()); + } - // not to be confused with claims, ownership referring to further member-specific ownership of a claim - public void clearOwnershipAt(FLocation flocation) { - Faction faction = getFactionAt(flocation); - if (faction != null && faction.isNormal()) { - faction.clearClaimOwnership(flocation); - } - } + // not to be confused with claims, ownership referring to further member-specific ownership of a claim + public void clearOwnershipAt(FLocation flocation) { + Faction faction = getFactionAt(flocation); + if (faction != null && faction.isNormal()) { + faction.clearClaimOwnership(flocation); + } + } - public void unclaimAll(String factionId) { - Faction faction = Factions.getInstance().getFactionById(factionId); - if (faction != null && faction.isNormal()) { - faction.clearAllClaimOwnership(); - faction.clearWarps(); - } - clean(factionId); - } + public void unclaimAll(String factionId) { + Faction faction = Factions.getInstance().getFactionById(factionId); + if (faction != null && faction.isNormal()) { + faction.clearAllClaimOwnership(); + faction.clearWarps(); + } + clean(factionId); + } - public void unclaimAllInWorld(String factionId, World world) { - for (FLocation loc : getAllClaims(factionId)) { - if (loc.getWorldName().equals(world.getName())) { - removeAt(loc); - } - } - } + public void unclaimAllInWorld(String factionId, World world) { + for (FLocation loc : getAllClaims(factionId)) { + if (loc.getWorldName().equals(world.getName())) { + removeAt(loc); + } + } + } - public void clean(String factionId) { - flocationIds.removeFaction(factionId); - } + public void clean(String factionId) { + flocationIds.removeFaction(factionId); + } - // Is this coord NOT completely surrounded by coords claimed by the same faction? - // Simpler: Is there any nearby coord with a faction other than the faction here? - public boolean isBorderLocation(FLocation flocation) { - Faction faction = getFactionAt(flocation); - FLocation a = flocation.getRelative(1, 0); - FLocation b = flocation.getRelative(-1, 0); - FLocation c = flocation.getRelative(0, 1); - FLocation d = flocation.getRelative(0, -1); - return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d); - } + // Is this coord NOT completely surrounded by coords claimed by the same faction? + // Simpler: Is there any nearby coord with a faction other than the faction here? + public boolean isBorderLocation(FLocation flocation) { + Faction faction = getFactionAt(flocation); + FLocation a = flocation.getRelative(1, 0); + FLocation b = flocation.getRelative(-1, 0); + FLocation c = flocation.getRelative(0, 1); + FLocation d = flocation.getRelative(0, -1); + return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d); + } - // Is this coord connected to any coord claimed by the specified faction? - public boolean isConnectedLocation(FLocation flocation, Faction faction) { - FLocation a = flocation.getRelative(1, 0); - FLocation b = flocation.getRelative(-1, 0); - FLocation c = flocation.getRelative(0, 1); - FLocation d = flocation.getRelative(0, -1); - return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d); - } + // Is this coord connected to any coord claimed by the specified faction? + public boolean isConnectedLocation(FLocation flocation, Faction faction) { + FLocation a = flocation.getRelative(1, 0); + FLocation b = flocation.getRelative(-1, 0); + FLocation c = flocation.getRelative(0, 1); + FLocation d = flocation.getRelative(0, -1); + return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d); + } - /** - * Checks if there is another faction within a given radius other than Wilderness. Used for HCF feature that - * requires a 'buffer' between factions. - * - * @param flocation - center location. - * @param faction - faction checking for. - * @param radius - chunk radius to check. - * @return true if another Faction is within the radius, otherwise false. - */ - public boolean hasFactionWithin(FLocation flocation, Faction faction, int radius) { - for (int x = -radius; x <= radius; x++) { - for (int z = -radius; z <= radius; z++) { - if (x == 0 && z == 0) { - continue; - } + /** + * Checks if there is another faction within a given radius other than Wilderness. Used for HCF feature that + * requires a 'buffer' between factions. + * + * @param flocation - center location. + * @param faction - faction checking for. + * @param radius - chunk radius to check. + * @return true if another Faction is within the radius, otherwise false. + */ + public boolean hasFactionWithin(FLocation flocation, Faction faction, int radius) { + for (int x = -radius; x <= radius; x++) { + for (int z = -radius; z <= radius; z++) { + if (x == 0 && z == 0) { + continue; + } - FLocation relative = flocation.getRelative(x, z); - Faction other = getFactionAt(relative); + FLocation relative = flocation.getRelative(x, z); + Faction other = getFactionAt(relative); - if (other.isNormal() && other != faction) { - return true; - } - } - } - return false; - } + if (other.isNormal() && other != faction) { + return true; + } + } + } + return false; + } - public void clean() { - Iterator> iter = flocationIds.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - if (!Factions.getInstance().isValidFactionId(entry.getValue())) { - SavageFactions.plugin.log("Board cleaner removed " + entry.getValue() + " from " + entry.getKey()); - iter.remove(); - } - } - } + public void clean() { + Iterator> iter = flocationIds.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (!Factions.getInstance().isValidFactionId(entry.getValue())) { + SavageFactions.plugin.log("Board cleaner removed " + entry.getValue() + " from " + entry.getKey()); + iter.remove(); + } + } + } - //----------------------------------------------// - // Cleaner. Remove orphaned foreign keys - //----------------------------------------------// + //----------------------------------------------// + // Cleaner. Remove orphaned foreign keys + //----------------------------------------------// - public int getFactionCoordCount(String factionId) { - return flocationIds.getOwnedLandCount(factionId); - } + public int getFactionCoordCount(String factionId) { + return flocationIds.getOwnedLandCount(factionId); + } - //----------------------------------------------// - // Coord count - //----------------------------------------------// + //----------------------------------------------// + // Coord count + //----------------------------------------------// - public int getFactionCoordCount(Faction faction) { - return getFactionCoordCount(faction.getId()); - } + public int getFactionCoordCount(Faction faction) { + return getFactionCoordCount(faction.getId()); + } - public int getFactionCoordCountInWorld(Faction faction, String worldName) { - String factionId = faction.getId(); - int ret = 0; - for (Entry entry : flocationIds.entrySet()) { - if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { - ret += 1; - } - } - return ret; - } + public int getFactionCoordCountInWorld(Faction faction, String worldName) { + String factionId = faction.getId(); + int ret = 0; + for (Entry entry : flocationIds.entrySet()) { + if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { + ret += 1; + } + } + return ret; + } - /** - * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction - * of decreasing z - */ - public ArrayList getMap(FPlayer fplayer, FLocation flocation, double inDegrees) { - Faction faction = fplayer.getFaction(); - ArrayList ret = new ArrayList<>(); - Faction factionLoc = getFactionAt(flocation); - ret.add(new FancyMessage(ChatColor.DARK_GRAY + SavageFactions.plugin.txt.titleize("(" + flocation.getCoordString() + ") " + factionLoc.getTag(fplayer)))); - int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); + /** + * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction + * of decreasing z + */ + public ArrayList getMap(FPlayer fplayer, FLocation flocation, double inDegrees) { + Faction faction = fplayer.getFaction(); + ArrayList ret = new ArrayList<>(); + Faction factionLoc = getFactionAt(flocation); + ret.add(new FancyMessage(ChatColor.DARK_GRAY + SavageFactions.plugin.txt.titleize("(" + flocation.getCoordString() + ") " + factionLoc.getTag(fplayer)))); + int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); - // Get the compass - ArrayList asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.DARK_GREEN, SavageFactions.plugin.txt.parse("")); + // Get the compass + ArrayList asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.DARK_GREEN, SavageFactions.plugin.txt.parse("")); - int halfWidth = Conf.mapWidth / 2; - // Use player's value for height - int halfHeight = fplayer.getMapHeight() / 2; - FLocation topLeft = flocation.getRelative(-halfWidth, -halfHeight); - int width = halfWidth * 2 + 1; - int height = halfHeight * 2 + 1; + int halfWidth = Conf.mapWidth / 2; + // Use player's value for height + int halfHeight = fplayer.getMapHeight() / 2; + FLocation topLeft = flocation.getRelative(-halfWidth, -halfHeight); + int width = halfWidth * 2 + 1; + int height = halfHeight * 2 + 1; - if (Conf.showMapFactionKey) { - height--; - } + if (Conf.showMapFactionKey) { + height--; + } - Map fList = new HashMap<>(); - int chrIdx = 0; + Map fList = new HashMap<>(); + int chrIdx = 0; - // For each row - for (int dz = 0; dz < height; dz++) { - // Draw and add that row - FancyMessage row = new FancyMessage(""); + // For each row + for (int dz = 0; dz < height; dz++) { + // Draw and add that row + FancyMessage row = new FancyMessage(""); - if (dz < 3) { - row.then(asciiCompass.get(dz)); - } - for (int dx = (dz < 3 ? 6 : 3); dx < width; dx++) { - if (dx == halfWidth && dz == halfHeight) { - row.then("+").color(ChatColor.AQUA).tooltip(TL.CLAIM_YOUAREHERE.toString()); - } else { - FLocation flocationHere = topLeft.getRelative(dx, dz); - Faction factionHere = getFactionAt(flocationHere); - Relation relation = fplayer.getRelationTo(factionHere); - if (flocationHere.isOutsideWorldBorder(buffer)) { - row.then("-").color(ChatColor.BLACK).tooltip(TL.CLAIM_MAP_OUTSIDEBORDER.toString()); - } else if (factionHere.isWilderness()) { - row.then("-").color(Conf.colorWilderness); - // Lol someone didnt add the x and z making it claim the wrong position Can i copyright this xD - if (fplayer.getPlayer().hasPermission(Permission.CLAIMAT.node)) { - row.tooltip(TL.CLAIM_CLICK_TO_CLAIM.format(dx + topLeft.getX(), dz + topLeft.getZ())) - .command(String.format("/f claimat %s %d %d", flocation.getWorldName(), dx + topLeft.getX(), dz + topLeft.getZ())); - } - } else if (factionHere.isSafeZone()) { - row.then("+").color(Conf.colorSafezone).tooltip(oneLineToolTip(factionHere, fplayer)); - } else if (factionHere.isWarZone()) { - row.then("+").color(Conf.colorWar).tooltip(oneLineToolTip(factionHere, fplayer)); - } else if (factionHere == faction || factionHere == factionLoc || relation.isAtLeast(Relation.ALLY) || - (Conf.showNeutralFactionsOnMap && relation.equals(Relation.NEUTRAL)) || - (Conf.showEnemyFactionsOnMap && relation.equals(Relation.ENEMY)) || - (Conf.showTrucesFactionsOnMap && relation.equals(Relation.TRUCE))) { - if (!fList.containsKey(factionHere.getTag())) { - fList.put(factionHere.getTag(), Conf.mapKeyChrs[Math.min(chrIdx++, Conf.mapKeyChrs.length - 1)]); - } - char tag = fList.get(factionHere.getTag()); + if (dz < 3) { + row.then(asciiCompass.get(dz)); + } + for (int dx = (dz < 3 ? 6 : 3); dx < width; dx++) { + if (dx == halfWidth && dz == halfHeight) { + row.then("+").color(ChatColor.AQUA).tooltip(TL.CLAIM_YOUAREHERE.toString()); + } else { + FLocation flocationHere = topLeft.getRelative(dx, dz); + Faction factionHere = getFactionAt(flocationHere); + Relation relation = fplayer.getRelationTo(factionHere); + if (flocationHere.isOutsideWorldBorder(buffer)) { + row.then("-").color(ChatColor.BLACK).tooltip(TL.CLAIM_MAP_OUTSIDEBORDER.toString()); + } else if (factionHere.isWilderness()) { + row.then("-").color(Conf.colorWilderness); + // Lol someone didnt add the x and z making it claim the wrong position Can i copyright this xD + if (fplayer.getPlayer().hasPermission(Permission.CLAIMAT.node)) { + row.tooltip(TL.CLAIM_CLICK_TO_CLAIM.format(dx + topLeft.getX(), dz + topLeft.getZ())) + .command(String.format("/f claimat %s %d %d", flocation.getWorldName(), dx + topLeft.getX(), dz + topLeft.getZ())); + } + } else if (factionHere.isSafeZone()) { + row.then("+").color(Conf.colorSafezone).tooltip(oneLineToolTip(factionHere, fplayer)); + } else if (factionHere.isWarZone()) { + row.then("+").color(Conf.colorWar).tooltip(oneLineToolTip(factionHere, fplayer)); + } else if (factionHere == faction || factionHere == factionLoc || relation.isAtLeast(Relation.ALLY) || + (Conf.showNeutralFactionsOnMap && relation.equals(Relation.NEUTRAL)) || + (Conf.showEnemyFactionsOnMap && relation.equals(Relation.ENEMY)) || + (Conf.showTrucesFactionsOnMap && relation.equals(Relation.TRUCE))) { + if (!fList.containsKey(factionHere.getTag())) { + fList.put(factionHere.getTag(), Conf.mapKeyChrs[Math.min(chrIdx++, Conf.mapKeyChrs.length - 1)]); + } + char tag = fList.get(factionHere.getTag()); - //row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(getToolTip(factionHere, fplayer)); - //changed out with a performance friendly one line tooltip :D - row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(oneLineToolTip(factionHere, fplayer)); - } else { - row.then("-").color(ChatColor.GRAY); - } - } - } - ret.add(row); - } + //row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(getToolTip(factionHere, fplayer)); + //changed out with a performance friendly one line tooltip :D + row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(oneLineToolTip(factionHere, fplayer)); + } else { + row.then("-").color(ChatColor.GRAY); + } + } + } + ret.add(row); + } - // Add the faction key - if (Conf.showMapFactionKey) { - FancyMessage fRow = new FancyMessage(""); - for (String key : fList.keySet()) { - fRow.then(String.format("%s: %s ", fList.get(key), key)).color(ChatColor.GRAY); - } - ret.add(fRow); - } + // Add the faction key + if (Conf.showMapFactionKey) { + FancyMessage fRow = new FancyMessage(""); + for (String key : fList.keySet()) { + fRow.then(String.format("%s: %s ", fList.get(key), key)).color(ChatColor.GRAY); + } + ret.add(fRow); + } - return ret; - } + return ret; + } - //----------------------------------------------// - // Map generation - //----------------------------------------------// + //----------------------------------------------// + // Map generation + //----------------------------------------------// - private List oneLineToolTip(Faction faction, FPlayer to) { - return Arrays.asList(faction.describeTo(to)); - } + private List oneLineToolTip(Faction faction, FPlayer to) { + return Arrays.asList(faction.describeTo(to)); + } - @SuppressWarnings("unused") - private List getToolTip(Faction faction, FPlayer to) { - List ret = new ArrayList<>(); - List show = SavageFactions.plugin.getConfig().getStringList("map"); + @SuppressWarnings("unused") + private List getToolTip(Faction faction, FPlayer to) { + List ret = new ArrayList<>(); + List show = SavageFactions.plugin.getConfig().getStringList("map"); - if (!faction.isNormal()) { - String tag = faction.getTag(to); - // send header and that's all - String header = show.get(0); - if (TagReplacer.HEADER.contains(header)) { - ret.add(SavageFactions.plugin.txt.titleize(tag)); - } else { - ret.add(SavageFactions.plugin.txt.parse(TagReplacer.FACTION.replace(header, tag))); - } - return ret; // we only show header for non-normal factions - } + if (!faction.isNormal()) { + String tag = faction.getTag(to); + // send header and that's all + String header = show.get(0); + if (TagReplacer.HEADER.contains(header)) { + ret.add(SavageFactions.plugin.txt.titleize(tag)); + } else { + ret.add(SavageFactions.plugin.txt.parse(TagReplacer.FACTION.replace(header, tag))); + } + return ret; // we only show header for non-normal factions + } - for (String raw : show) { - // Hack to get rid of the extra underscores in title normally used to center tag - if (raw.contains("{header}")) { - raw = raw.replace("{header}", faction.getTag(to)); - } + for (String raw : show) { + // Hack to get rid of the extra underscores in title normally used to center tag + if (raw.contains("{header}")) { + raw = raw.replace("{header}", faction.getTag(to)); + } - String parsed = TagUtil.parsePlain(faction, to, raw); // use relations - if (parsed == null) { - continue; // Due to minimal f show. - } + String parsed = TagUtil.parsePlain(faction, to, raw); // use relations + if (parsed == null) { + continue; // Due to minimal f show. + } - if (TagUtil.hasFancy(parsed)) { - List fancy = TagUtil.parseFancy(faction, to, parsed); - if (fancy != null) { - for (FancyMessage msg : fancy) { - ret.add((SavageFactions.plugin.txt.parse(msg.toOldMessageFormat()))); - } - } - continue; - } + if (TagUtil.hasFancy(parsed)) { + List fancy = TagUtil.parseFancy(faction, to, parsed); + if (fancy != null) { + for (FancyMessage msg : fancy) { + ret.add((SavageFactions.plugin.txt.parse(msg.toOldMessageFormat()))); + } + } + continue; + } - if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { - if (parsed.contains("{ig}")) { - // replaces all variables with no home TL - parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); - } - if (parsed.contains("%")) { - parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. - } - ret.add(SavageFactions.plugin.txt.parse(parsed)); - } - } + if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { + if (parsed.contains("{ig}")) { + // replaces all variables with no home TL + parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); + } + if (parsed.contains("%")) { + parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. + } + ret.add(SavageFactions.plugin.txt.parse(parsed)); + } + } - return ret; - } + return ret; + } - public abstract void convertFrom(MemoryBoard old); + public abstract void convertFrom(MemoryBoard old); - public class MemoryBoardMap extends HashMap { - private static final long serialVersionUID = -6689617828610585368L; + public class MemoryBoardMap extends HashMap { + private static final long serialVersionUID = -6689617828610585368L; - Multimap factionToLandMap = HashMultimap.create(); + Multimap factionToLandMap = HashMultimap.create(); - @Override - public String put(FLocation floc, String factionId) { - String previousValue = super.put(floc, factionId); - if (previousValue != null) { - factionToLandMap.remove(previousValue, floc); - } + @Override + public String put(FLocation floc, String factionId) { + String previousValue = super.put(floc, factionId); + if (previousValue != null) { + factionToLandMap.remove(previousValue, floc); + } - factionToLandMap.put(factionId, floc); - return previousValue; - } + factionToLandMap.put(factionId, floc); + return previousValue; + } - @Override - public String remove(Object key) { - String result = super.remove(key); - if (result != null) { - FLocation floc = (FLocation) key; - factionToLandMap.remove(result, floc); - } + @Override + public String remove(Object key) { + String result = super.remove(key); + if (result != null) { + FLocation floc = (FLocation) key; + factionToLandMap.remove(result, floc); + } - return result; - } + return result; + } - @Override - public void clear() { - super.clear(); - factionToLandMap.clear(); - } + @Override + public void clear() { + super.clear(); + factionToLandMap.clear(); + } - public int getOwnedLandCount(String factionId) { - return factionToLandMap.get(factionId).size(); - } + public int getOwnedLandCount(String factionId) { + return factionToLandMap.get(factionId).size(); + } - public void removeFaction(String factionId) { - Collection flocations = factionToLandMap.removeAll(factionId); - for (FLocation floc : flocations) { - super.remove(floc); - } - } - } + public void removeFaction(String factionId) { + Collection flocations = factionToLandMap.removeAll(factionId); + for (FLocation floc : flocations) { + super.remove(floc); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java index 380cd548..647f4395 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java @@ -44,1187 +44,1187 @@ import java.util.UUID; public abstract class MemoryFPlayer implements FPlayer { - public boolean inVault = false; - protected String factionId; - protected Role role; - protected String title; - protected double power; - protected double powerBoost; - protected long lastPowerUpdateTime; - protected long lastLoginTime; - protected ChatMode chatMode; - protected boolean ignoreAllianceChat = false; - protected String id; - protected String name; - protected boolean monitorJoins; - protected boolean spyingChat = false; - protected boolean showScoreboard = true; - protected WarmUpUtil.Warmup warmup; - protected int warmupTask; - protected boolean isAdminBypassing = false; - protected int kills, deaths; - protected boolean willAutoLeave = true; - protected int mapHeight = 8; // default to old value - protected boolean isFlying = false; - protected boolean enteringPassword = false; - protected String enteringPasswordWarp = ""; - protected transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked? - protected transient boolean mapAutoUpdating; - protected transient Faction autoClaimFor; - protected transient boolean autoSafeZoneEnabled; - protected transient boolean autoWarZoneEnabled; - protected transient boolean loginPvpDisabled; - protected transient long lastFrostwalkerMessage; - protected transient boolean shouldTakeFallDamage = true; - protected boolean isStealthEnabled = false; - boolean playerAlerts = false; - boolean inspectMode = false; - - public MemoryFPlayer() { - } - - public MemoryFPlayer(String id) { - this.id = id; - this.resetFactionData(false); - this.power = Conf.powerPlayerStarting; - this.lastPowerUpdateTime = System.currentTimeMillis(); - this.lastLoginTime = System.currentTimeMillis(); - this.mapAutoUpdating = false; - this.autoClaimFor = null; - this.autoSafeZoneEnabled = false; - this.autoWarZoneEnabled = false; - this.loginPvpDisabled = Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0; - this.powerBoost = 0.0; - this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false); - this.kills = 0; - this.deaths = 0; - this.mapHeight = Conf.mapHeight; - - if (!Conf.newPlayerStartingFactionID.equals("0") && Factions.getInstance().isValidFactionId(Conf.newPlayerStartingFactionID)) { - this.factionId = Conf.newPlayerStartingFactionID; - } - } - - public MemoryFPlayer(MemoryFPlayer other) { - this.factionId = other.factionId; - this.id = other.id; - this.power = other.power; - this.lastLoginTime = other.lastLoginTime; - this.mapAutoUpdating = other.mapAutoUpdating; - this.autoClaimFor = other.autoClaimFor; - this.autoSafeZoneEnabled = other.autoSafeZoneEnabled; - this.autoWarZoneEnabled = other.autoWarZoneEnabled; - this.loginPvpDisabled = other.loginPvpDisabled; - this.powerBoost = other.powerBoost; - this.role = other.role; - this.title = other.title; - this.chatMode = other.chatMode; - this.spyingChat = other.spyingChat; - this.lastStoodAt = other.lastStoodAt; - this.isAdminBypassing = other.isAdminBypassing; - this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", true); - this.kills = other.kills; - this.deaths = other.deaths; - this.mapHeight = Conf.mapHeight; - } - - public boolean isStealthEnabled() { - return this.isStealthEnabled; - } - - public void setStealth(boolean stealth) { - this.isStealthEnabled = stealth; - } - - public void login() { - this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); - this.deaths = getPlayer().getStatistic(Statistic.DEATHS); - } - - public void logout() { - this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); - this.deaths = getPlayer().getStatistic(Statistic.DEATHS); - } - - public Faction getFaction() { - if (this.factionId == null) { - this.factionId = "0"; - } - return Factions.getInstance().getFactionById(this.factionId); - } - - public void setFaction(Faction faction) { - Faction oldFaction = this.getFaction(); - if (oldFaction != null) { - oldFaction.removeFPlayer(this); - } - faction.addFPlayer(this); - this.factionId = faction.getId(); - } - - public String getFactionId() { - return this.factionId; - } - - public boolean hasFaction() { - return !factionId.equals("0"); - } - - public void setMonitorJoins(boolean monitor) { - this.monitorJoins = monitor; - } - - public boolean isMonitoringJoins() { - return this.monitorJoins; - } - - public Role getRole() { - // Hack to fix null roles.. - if (role == null) { - this.role = Role.NORMAL; - } - - return this.role; - } - - public void setRole(Role role) { - this.role = role; - } - - public double getPowerBoost() { - return this.powerBoost; - } - - public void setPowerBoost(double powerBoost) { - this.powerBoost = powerBoost; - } - - public boolean willAutoLeave() { - return this.willAutoLeave; - } - - public void setAutoLeave(boolean willLeave) { - this.willAutoLeave = willLeave; - SavageFactions.plugin.debug(name + " set autoLeave to " + willLeave); - } - - public long getLastFrostwalkerMessage() { - return this.lastFrostwalkerMessage; - } - - public void setLastFrostwalkerMessage() { - this.lastFrostwalkerMessage = System.currentTimeMillis(); - } - - public Faction getAutoClaimFor() { - return autoClaimFor; - } - - public void setAutoClaimFor(Faction faction) { - this.autoClaimFor = faction; - if (this.autoClaimFor != null) { - // TODO: merge these into same autoclaim - this.autoSafeZoneEnabled = false; - this.autoWarZoneEnabled = false; - } - } - - public boolean isAutoSafeClaimEnabled() { - return autoSafeZoneEnabled; - } - - public void setIsAutoSafeClaimEnabled(boolean enabled) { - this.autoSafeZoneEnabled = enabled; - if (enabled) { - this.autoClaimFor = null; - this.autoWarZoneEnabled = false; - } - } - - public boolean isAutoWarClaimEnabled() { - return autoWarZoneEnabled; - } - - public void setIsAutoWarClaimEnabled(boolean enabled) { - this.autoWarZoneEnabled = enabled; - if (enabled) { - this.autoClaimFor = null; - this.autoSafeZoneEnabled = false; - } - } - - public boolean isAdminBypassing() { - return this.isAdminBypassing; - } - - public boolean isVanished() { - return Essentials.isVanished(getPlayer()); - } - - public void setIsAdminBypassing(boolean val) { - this.isAdminBypassing = val; - } - - public ChatMode getChatMode() { - if (this.factionId.equals("0") || !Conf.factionOnlyChat) { - this.chatMode = ChatMode.PUBLIC; - } - return chatMode; - } - - public void setChatMode(ChatMode chatMode) { - this.chatMode = chatMode; - } - - public boolean isIgnoreAllianceChat() { - return ignoreAllianceChat; - } - - public void setIgnoreAllianceChat(boolean ignore) { - this.ignoreAllianceChat = ignore; - } - - public boolean isSpyingChat() { - return spyingChat; - } - - public void setSpyingChat(boolean chatSpying) { - this.spyingChat = chatSpying; - } - - // -------------------------------------------- // - // Getters And Setters - // -------------------------------------------- // - - // FIELD: account - public String getAccountId() { - return this.getId(); - } - - public void resetFactionData(boolean doSpoutUpdate) { - // clean up any territory ownership in old faction, if there is one - if (factionId != null && Factions.getInstance().isValidFactionId(this.getFactionId())) { - Faction currentFaction = this.getFaction(); - currentFaction.removeFPlayer(this); - if (currentFaction.isNormal()) { - currentFaction.clearClaimOwnership(this); - } - } - - this.factionId = "0"; // The default neutral faction - this.chatMode = ChatMode.PUBLIC; - this.role = Role.NORMAL; - this.title = ""; - this.autoClaimFor = null; - } - - public void resetFactionData() { - this.resetFactionData(true); - } - - public long getLastLoginTime() { - return lastLoginTime; - } - - public void setLastLoginTime(long lastLoginTime) { - losePowerFromBeingOffline(); - this.lastLoginTime = lastLoginTime; - this.lastPowerUpdateTime = lastLoginTime; - if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { - this.loginPvpDisabled = true; - } - } - - public boolean isMapAutoUpdating() { - return mapAutoUpdating; - } - - public void setMapAutoUpdating(boolean mapAutoUpdating) { - this.mapAutoUpdating = mapAutoUpdating; - } - - //----------------------------------------------// - // Title, Name, Faction Tag and Chat - //----------------------------------------------// - - // Base: - - public boolean hasLoginPvpDisabled() { - if (!loginPvpDisabled) { - return false; - } - if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) { - this.loginPvpDisabled = false; - return false; - } - return true; - } - - public FLocation getLastStoodAt() { - return this.lastStoodAt; - } - - public void setLastStoodAt(FLocation flocation) { - this.lastStoodAt = flocation; - } - - public String getTitle() { - return this.hasFaction() ? title : TL.NOFACTION_PREFIX.toString(); - } - - public void setTitle(CommandSender sender, String title) { - // Check if the setter has it. - if (sender.hasPermission(Permission.TITLE_COLOR.node)) { - title = ChatColor.translateAlternateColorCodes('&', title); - } - - this.title = title; - } - - // Base concatenations: - - public String getName() { - if (this.name == null) { - // Older versions of FactionsUUID don't save the name, - // so `name` will be null the first time it's retrieved - // after updating - OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(getId())); - this.name = offline.getName() != null ? offline.getName() : getId(); - } - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getTag() { - return this.hasFaction() ? this.getFaction().getTag() : ""; - } - - // Colored concatenations: - // These are used in information messages - - public String getNameAndSomething(String something) { - String ret = this.role.getPrefix(); - if (something.length() > 0) { - ret += something + " "; - } - ret += this.getName(); - return ret; - } - - public String getNameAndTitle() { - return this.getNameAndSomething(this.getTitle()); - } - - // Chat Tag: - // These are injected into the format of global chat messages. - - public String getNameAndTag() { - return this.getNameAndSomething(this.getTag()); - } - - public String getNameAndTitle(Faction faction) { - return this.getColorTo(faction) + this.getNameAndTitle(); - } - - public String getNameAndTitle(MemoryFPlayer fplayer) { - return this.getColorTo(fplayer) + this.getNameAndTitle(); - } - - public String getChatTag() { - return this.hasFaction() ? String.format(Conf.chatTagFormat, this.getRole().getPrefix() + this.getTag()) : TL.NOFACTION_PREFIX.toString(); - } - - // Colored Chat Tag - public String getChatTag(Faction faction) { - return this.hasFaction() ? this.getRelationTo(faction).getColor() + getChatTag() : ""; - } - - // ------------------------------- - // Relation and relation colors - // ------------------------------- - - public String getChatTag(MemoryFPlayer fplayer) { - return this.hasFaction() ? this.getColorTo(fplayer) + getChatTag() : ""; - } - - public int getKills() { - return isOnline() ? getPlayer().getStatistic(Statistic.PLAYER_KILLS) : this.kills; - } - - public int getDeaths() { - return isOnline() ? getPlayer().getStatistic(Statistic.DEATHS) : this.deaths; - - } - - @Override - public String describeTo(RelationParticipator that, boolean ucfirst) { - return RelationUtil.describeThatToMe(this, that, ucfirst); - } - - @Override - public String describeTo(RelationParticipator that) { - return RelationUtil.describeThatToMe(this, that); - } - - @Override - public Relation getRelationTo(RelationParticipator rp) { - return RelationUtil.getRelationTo(this, rp); - } - - @Override - public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { - return RelationUtil.getRelationTo(this, rp, ignorePeaceful); - } - - public Relation getRelationToLocation() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this); - } - - @Override - public ChatColor getColorTo(RelationParticipator rp) { - return RelationUtil.getColorOfThatToMe(this, rp); - } - - //----------------------------------------------// - // Health - //----------------------------------------------// - public void heal(int amnt) { - Player player = this.getPlayer(); - if (player == null) { - return; - } - player.setHealth(player.getHealth() + amnt); - } - - //----------------------------------------------// - // Power - //----------------------------------------------// - public double getPower() { - this.updatePower(); - return this.power; - } - - public void alterPower(double delta) { - this.power += delta; - if (this.power > this.getPowerMax()) { - this.power = this.getPowerMax(); - } else if (this.power < this.getPowerMin()) { - this.power = this.getPowerMin(); - } - } - - public double getPowerMax() { - return Conf.powerPlayerMax + this.powerBoost; - } - - public double getPowerMin() { - return Conf.powerPlayerMin + this.powerBoost; - } - - public int getPowerRounded() { - return (int) Math.round(this.getPower()); - } - - public int getPowerMaxRounded() { - return (int) Math.round(this.getPowerMax()); - } - - public int getPowerMinRounded() { - return (int) Math.round(this.getPowerMin()); - } - - public void updatePower() { - if (this.isOffline()) { - losePowerFromBeingOffline(); - if (!Conf.powerRegenOffline) { - return; - } - } else if (hasFaction() && getFaction().isPowerFrozen()) { - return; // Don't let power regen if faction power is frozen. - } - - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - Player thisPlayer = this.getPlayer(); - if (thisPlayer != null && thisPlayer.isDead()) { - return; // don't let dead players regain power until they respawn - } - - PowerRegenEvent powerRegenEvent = new PowerRegenEvent(getFaction(), this); - Bukkit.getServer().getPluginManager().callEvent(powerRegenEvent); - - if (!powerRegenEvent.isCancelled()) - this.alterPower(millisPassed * Conf.powerPerMinute / 60000); // millisPerMinute : 60 * 1000 - } - - public void losePowerFromBeingOffline() { - if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - double loss = millisPassed * Conf.powerOfflineLossPerDay / (24 * 60 * 60 * 1000); - if (this.power - loss < Conf.powerOfflineLossLimit) { - loss = this.power; - } - this.alterPower(-loss); - } - } - - public void onDeath() { - this.updatePower(); - this.alterPower(-Conf.powerPerDeath); - if (hasFaction()) { - getFaction().setLastDeath(System.currentTimeMillis()); - } - } - - //----------------------------------------------// - // Territory - //----------------------------------------------// - public boolean isInOwnTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)) == this.getFaction(); - } - - public boolean isInOthersTerritory() { - Faction factionHere = Board.getInstance().getFactionAt(new FLocation(this)); - return factionHere != null && factionHere.isNormal() && factionHere != this.getFaction(); - } - - public boolean isInAllyTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isAlly(); - } - - public boolean isInNeutralTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isNeutral(); - } - - public boolean isInEnemyTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isEnemy(); - } - - public void sendFactionHereMessage(Faction from) { - Faction toShow = Board.getInstance().getFactionAt(getLastStoodAt()); - boolean showChat = true; - if (showInfoBoard(toShow)) { - FScoreboard.get(this).setTemporarySidebar(new FInfoSidebar(toShow)); - showChat = SavageFactions.plugin.getConfig().getBoolean("scoreboard.also-send-chat", true); - } - if (showChat) { - this.sendMessage(SavageFactions.plugin.txt.parse(TL.FACTION_LEAVE.format(from.getTag(this), toShow.getTag(this)))); - } - } - - // ------------------------------- - // Actions - // ------------------------------- - - /** - * Check if the scoreboard should be shown. Simple method to be used by above method. - * - * @param toShow Faction to be shown. - * @return true if should show, otherwise false. - */ - public boolean showInfoBoard(Faction toShow) { - return showScoreboard && !toShow.isWarZone() && !toShow.isWilderness() && !toShow.isSafeZone() && SavageFactions.plugin.getConfig().contains("scoreboard.finfo") && SavageFactions.plugin.getConfig().getBoolean("scoreboard.finfo-enabled", false) && FScoreboard.get(this) != null; - } - - @Override - public boolean showScoreboard() { - return this.showScoreboard; - } - - @Override - public void setShowScoreboard(boolean show) { - this.showScoreboard = show; - } - - public void leave(boolean makePay) { - Faction myFaction = this.getFaction(); - makePay = makePay && Econ.shouldBeUsed() && !this.isAdminBypassing(); - - if (myFaction == null) { - resetFactionData(); - return; - } - - boolean perm = myFaction.isPermanent(); - - if (!perm && this.getRole() == Role.LEADER && myFaction.getFPlayers().size() > 1) { - msg(TL.LEAVE_PASSADMIN); - return; - } - - if (!Conf.canLeaveWithNegativePower && this.getPower() < 0) { - msg(TL.LEAVE_NEGATIVEPOWER); - return; - } - - // if economy is enabled and they're not on the bypass list, make sure they can pay - if (makePay && !Econ.hasAtLeast(this, Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString())) { - return; - } - - FPlayerLeaveEvent leaveEvent = new FPlayerLeaveEvent(this, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.LEAVE); - Bukkit.getServer().getPluginManager().callEvent(leaveEvent); - if (leaveEvent.isCancelled()) { - return; - } - - // then make 'em pay (if applicable) - if (makePay && !Econ.modifyMoney(this, -Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString(), TL.LEAVE_FORLEAVE.toString())) { - return; - } - - // Am I the last one in the faction? - if (myFaction.getFPlayers().size() == 1) { - // Transfer all money - if (Econ.shouldBeUsed()) { - Econ.transferMoney(this, myFaction, this, Econ.getBalance(myFaction.getAccountId())); - } - } - - if (myFaction.isNormal()) { - for (FPlayer fplayer : myFaction.getFPlayersWhereOnline(true)) { - fplayer.msg(TL.LEAVE_LEFT, this.describeTo(fplayer, true), myFaction.describeTo(fplayer)); - } - - if (Conf.logFactionLeave) { - SavageFactions.plugin.log(TL.LEAVE_LEFT.format(this.getName(), myFaction.getTag())); - } - } - - myFaction.removeAnnouncements(this); - this.resetFactionData(); - - if (myFaction.isNormal() && !perm && myFaction.getFPlayers().isEmpty()) { - // Remove this faction - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg(TL.LEAVE_DISBANDED, myFaction.describeTo(fplayer, true)); - } - - FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), PlayerDisbandReason.LEAVE); - Bukkit.getPluginManager().callEvent(disbandEvent); - - Factions.getInstance().removeFaction(myFaction.getId()); - if (Conf.logFactionDisband) { - SavageFactions.plugin.log(TL.LEAVE_DISBANDEDLOG.format(myFaction.getTag(), myFaction.getId(), this.getName())); - } - } - } - - public boolean canClaimForFaction(Faction forFaction) { - return this.isAdminBypassing() || !forFaction.isWilderness() && (forFaction == this.getFaction() && this.getRole().isAtLeast(Role.MODERATOR)) || (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) || (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())); - } - - public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure) { - return canClaimForFactionAtLocation(forFaction, new FLocation(location), notifyFailure); - } - - public boolean canClaimForFactionAtLocation(Faction forFaction, FLocation flocation, boolean notifyFailure) { - String error = null; - Faction myFaction = getFaction(); - Faction currentFaction = Board.getInstance().getFactionAt(flocation); - int ownedLand = forFaction.getLandRounded(); - int factionBuffer = SavageFactions.plugin.getConfig().getInt("hcf.buffer-zone", 0); - int worldBuffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); - - if (Conf.worldGuardChecking && Worldguard.checkForRegionsInChunk(flocation)) { - // Checks for WorldGuard regions in the chunk attempting to be claimed - error = SavageFactions.plugin.txt.parse(TL.CLAIM_PROTECTED.toString()); - } else if (flocation.isOutsideWorldBorder(SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0))) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); - } else if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_DISABLED.toString()); - } else if (this.isAdminBypassing()) { - return true; - } else if (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) { - return true; - } else if (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())) { - return true; - } else if (currentFaction.getAccess(this, PermissableAction.TERRITORY) == Access.ALLOW) { - return true; - } else if (myFaction != forFaction) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_CANTCLAIM.toString(), forFaction.describeTo(this)); - } else if (forFaction == currentFaction) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALREADYOWN.toString(), forFaction.describeTo(this, true)); - } else if (this.getRole().value < Role.MODERATOR.value) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_MUSTBE.toString(), Role.MODERATOR.getTranslation()); - } else if (forFaction.getFPlayers().size() < Conf.claimsRequireMinFactionMembers) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_MEMBERS.toString(), Conf.claimsRequireMinFactionMembers); - } else if (currentFaction.isSafeZone()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_SAFEZONE.toString()); - } else if (currentFaction.isWarZone()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_WARZONE.toString()); - } else if (SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true) && ownedLand >= forFaction.getPowerRounded()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_POWER.toString()); - } else if (Conf.claimedLandsMax != 0 && ownedLand >= Conf.claimedLandsMax && forFaction.isNormal()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_LIMIT.toString()); - } else if (currentFaction.getRelationTo(forFaction) == Relation.ALLY) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALLY.toString()); - } else if (Conf.claimsMustBeConnected && !this.isAdminBypassing() && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, myFaction) && (!Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction || !currentFaction.isNormal())) { - if (Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_CONTIGIOUS.toString()); - } else { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_FACTIONCONTIGUOUS.toString()); - } - } else if (factionBuffer > 0 && Board.getInstance().hasFactionWithin(flocation, myFaction, factionBuffer)) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_TOOCLOSETOOTHERFACTION.format(factionBuffer)); - } else if (flocation.isOutsideWorldBorder(worldBuffer)) { - if (worldBuffer > 0) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEBORDERBUFFER.format(worldBuffer)); - } else { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); - } - } else if (currentFaction.isNormal()) { - if (myFaction.isPeaceful()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFUL.toString(), currentFaction.getTag(this)); - } else if (currentFaction.isPeaceful()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFULTARGET.toString(), currentFaction.getTag(this)); - } else if (!currentFaction.hasLandInflation()) { - // TODO more messages WARN current faction most importantly - error = SavageFactions.plugin.txt.parse(TL.CLAIM_THISISSPARTA.toString(), currentFaction.getTag(this)); - } else if (currentFaction.hasLandInflation() && !SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true)) { - // deny over claim when it normally would be allowed. - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OVERCLAIM_DISABLED.toString()); - } else if (!Board.getInstance().isBorderLocation(flocation)) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_BORDER.toString()); - } - } - // TODO: Add more else if statements. - - if (notifyFailure && error != null) { - msg(error); - } - return error == null; - } - - public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure) { - return attemptClaim(forFaction, new FLocation(location), notifyFailure); - } - - public boolean shouldBeSaved() { - return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); - } - - public void msg(String str, Object... args) { - this.sendMessage(SavageFactions.plugin.txt.parse(str, args)); - } - - public void msg(TL translation, Object... args) { - this.msg(translation.toString(), args); - } - - public Player getPlayer() { - return Bukkit.getPlayer(UUID.fromString(this.getId())); - } - - public boolean isOnline() { - return this.getPlayer() != null; - } - - // make sure target player should be able to detect that this player is online - public boolean isOnlineAndVisibleTo(Player player) { - Player target = this.getPlayer(); - return target != null && player.canSee(target); - } - - public boolean isOffline() { - return !isOnline(); - } - - public boolean isFlying() { - return isFlying; - } - - public void setFlying(boolean fly) { - setFFlying(fly, false); - } - - public void setFFlying(boolean fly, boolean damage) { - Player player = getPlayer(); - if (player != null) { - player.setAllowFlight(fly); - player.setFlying(fly); - } - - if (!damage) { - msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); - if (!fly) { - sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3) + "")); - } - - } else { - msg(TL.COMMAND_FLY_DAMAGE); - } - - // If leaving fly mode, don't let them take fall damage for x seconds. - if (!fly) { - int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); - CmdFly.flyMap.remove(player.getName()); - - // If the value is 0 or lower, make them take fall damage. - // Otherwise, start a timer and have this cancel after a few seconds. - // Short task so we're just doing it in method. Not clean but eh. - if (cooldown > 0) { - setTakeFallDamage(false); - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - setTakeFallDamage(true); - } - }, 20L * cooldown); - } - } - - isFlying = fly; - } - - public boolean isInVault() { - return inVault; - } - - public void setInVault(boolean status) { - inVault = status; - } - - public boolean canFlyAtLocation() { - return canFlyAtLocation(lastStoodAt); - } - - public boolean canFlyAtLocation(FLocation location) { - Faction faction = Board.getInstance().getFactionAt(location); - if ((faction == getFaction() && getRole() == Role.LEADER) || isAdminBypassing) { - return true; - } - - Access access = faction.getAccess(this, PermissableAction.FLY); - return access == null || access == Access.UNDEFINED || access == Access.ALLOW; - } - - public boolean shouldTakeFallDamage() { - return this.shouldTakeFallDamage; - } - - public void setTakeFallDamage(boolean fallDamage) { - this.shouldTakeFallDamage = fallDamage; - } - - public boolean isEnteringPassword() { - return enteringPassword; - } - - public void setEnteringPassword(boolean toggle, String warp) { - enteringPassword = toggle; - enteringPasswordWarp = warp; - } - - // -------------------------------------------- // - // Message Sending Helpers - // -------------------------------------------- // - - public String getEnteringWarp() { - return enteringPasswordWarp; - } - - public void sendMessage(String msg) { - if (msg.contains("{null}")) { - return; // user wants this message to not send - } - if (msg.contains("/n/")) { - for (String s : msg.split("/n/")) { - sendMessage(s); - } - return; - } - Player player = this.getPlayer(); - if (player == null) { - return; - } - player.sendMessage(msg); - } - - public void sendMessage(List msgs) { - for (String msg : msgs) { - this.sendMessage(msg); - } - } - - public void sendFancyMessage(FancyMessage message) { - Player player = getPlayer(); - if (player == null || !player.isOnGround()) { - return; - } - - message.send(player); - } - - public void sendFancyMessage(List messages) { - Player player = getPlayer(); - if (player == null) { - return; - } - - for (FancyMessage msg : messages) { - msg.send(player); - } - } - - public int getMapHeight() { - if (this.mapHeight < 1) { - this.mapHeight = Conf.mapHeight; - } - - return this.mapHeight; - } - - public void setMapHeight(int height) { - this.mapHeight = height > (Conf.mapHeight * 2) ? (Conf.mapHeight * 2) : height; - } - - public String getNameAndTitle(FPlayer fplayer) { - return this.getColorTo(fplayer) + this.getNameAndTitle(); - } - - @Override - public String getChatTag(FPlayer fplayer) { - return this.hasFaction() ? this.getRelationTo(fplayer).getColor() + getChatTag() : ""; - } - - @Override - public String getId() { - return id; - } - - @Override - public void setId(String id) { - this.id = id; - } - - public abstract void remove(); - - @Override - public void clearWarmup() { - if (warmup != null) { - Bukkit.getScheduler().cancelTask(warmupTask); - this.stopWarmup(); - } - } - - @Override - public void stopWarmup() { - warmup = null; - } - - @Override - public boolean isWarmingUp() { - return warmup != null; - } - - @Override - public WarmUpUtil.Warmup getWarmupType() { - return warmup; - } - - @Override - public void addWarmup(WarmUpUtil.Warmup warmup, int taskId) { - if (this.warmup != null) { - this.clearWarmup(); - } - this.warmup = warmup; - this.warmupTask = taskId; - } - - @Override - public boolean checkIfNearbyEnemies() { - Player me = this.getPlayer(); - int radius = Conf.stealthFlyCheckRadius; - for (Entity e : me.getNearbyEntities(radius, 255, radius)) { - if (e == null) { - continue; - } - if (e instanceof Player) { - Player eplayer = (((Player) e).getPlayer()); - if (eplayer == null) { - continue; - } - FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); - if (efplayer == null) { - continue; - } - if (efplayer != null && this.getRelationTo(efplayer).equals(Relation.ENEMY) && !efplayer.isStealthEnabled()) { - setFlying(false); - msg(TL.COMMAND_FLY_ENEMY_NEAR); - Bukkit.getServer().getPluginManager().callEvent(new FPlayerStoppedFlying(this)); - return true; - } - } - } - return false; - } - - @Override - public Boolean canflyinWilderness() { - return getPlayer().hasPermission("factions.fly.wilderness"); - } - - @Override - public Boolean canflyinWarzone() { - return getPlayer().hasPermission("factions.fly.warzone"); - - } - - @Override - public Boolean canflyinSafezone() { - return getPlayer().hasPermission("factions.fly.safezone"); - - } - - @Override - public Boolean canflyinEnemy() { - return getPlayer().hasPermission("factions.fly.enemy"); - - } - - @Override - public Boolean canflyinAlly() { - return getPlayer().hasPermission("factions.fly.ally"); - - } - - @Override - public Boolean canflyinTruce() { - return getPlayer().hasPermission("factions.fly.truce"); - - } - - @Override - public Boolean canflyinNeutral() { - return getPlayer().hasPermission("factions.fly.neutral"); - - } - - @Override - public boolean isInspectMode() { - return inspectMode; - } - - @Override - public void setInspectMode(boolean status) { - inspectMode = status; - } - - public boolean attemptClaim(Faction forFaction, FLocation flocation, boolean notifyFailure) { - // notifyFailure is false if called by auto-claim; no need to notify on every failure for it - // return value is false on failure, true on success - - Faction currentFaction = Board.getInstance().getFactionAt(flocation); - int ownedLand = forFaction.getLandRounded(); - - if (!this.canClaimForFactionAtLocation(forFaction, flocation, notifyFailure)) { - return false; - } - - // if economy is enabled and they're not on the bypass list, make sure they can pay - boolean mustPay = Econ.shouldBeUsed() && !this.isAdminBypassing() && !forFaction.isSafeZone() && !forFaction.isWarZone(); - double cost = 0.0; - EconomyParticipator payee = null; - if (mustPay) { - cost = Econ.calculateClaimCost(ownedLand, currentFaction.isNormal()); - - - if (Conf.econClaimUnconnectedFee != 0.0 && forFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, forFaction)) { - cost += Conf.econClaimUnconnectedFee; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts && this.hasFaction()) { - payee = this.getFaction(); - } else { - payee = this; - } - - if (!Econ.hasAtLeast(payee, cost, TL.CLAIM_TOCLAIM.toString())) { - return false; - } - } - - LandClaimEvent claimEvent = new LandClaimEvent(flocation, forFaction, this); - Bukkit.getPluginManager().callEvent(claimEvent); - if (claimEvent.isCancelled()) { - return false; - } - - // then make 'em pay (if applicable) - if (mustPay && !Econ.modifyMoney(payee, -cost, TL.CLAIM_TOCLAIM.toString(), TL.CLAIM_FORCLAIM.toString())) { - return false; - } - - // Was an over claim - if (currentFaction.isNormal() && currentFaction.hasLandInflation()) { - // Give them money for over claiming. - Econ.modifyMoney(payee, Conf.econOverclaimRewardMultiplier, TL.CLAIM_TOOVERCLAIM.toString(), TL.CLAIM_FOROVERCLAIM.toString()); - } - - // announce success - Set informTheseFPlayers = new HashSet<>(); - informTheseFPlayers.add(this); - informTheseFPlayers.addAll(forFaction.getFPlayersWhereOnline(true)); - for (FPlayer fp : informTheseFPlayers) { - fp.msg(TL.CLAIM_CLAIMED, this.describeTo(fp, true), forFaction.describeTo(fp), currentFaction.describeTo(fp)); - } - - Board.getInstance().setFactionAt(forFaction, flocation); - - if (Conf.logLandClaims) { - SavageFactions.plugin.log(TL.CLAIM_CLAIMEDLOG.toString(), this.getName(), flocation.getCoordString(), forFaction.getTag()); - } - - return true; - } - - - @Override - public String getRolePrefix() { - - switch (getRole()) { - case RECRUIT: - return Conf.prefixRecruit; - case NORMAL: - return Conf.prefixNormal; - case MODERATOR: - return Conf.prefixMod; - case COLEADER: - return Conf.prefixCoLeader; - case LEADER: - return Conf.prefixLeader; - } - - return null; - } - - @Override - public boolean hasMoney(int amt) { - Economy econ = SavageFactions.plugin.getEcon(); - if (econ.getBalance(getPlayer()) >= amt) { - return true; - } else { - getPlayer().closeInventory(); - msg(TL.GENERIC_NOTENOUGHMONEY); - return false; - } - } - - @Override - public void takeMoney(int amt) { - if (hasMoney(amt)) { - Economy econ = SavageFactions.plugin.getEcon(); - econ.withdrawPlayer(getPlayer(), amt); - sendMessage(TL.GENERIC_MONEYTAKE.toString().replace("{amount}", amt + "")); - } - } + public boolean inVault = false; + protected String factionId; + protected Role role; + protected String title; + protected double power; + protected double powerBoost; + protected long lastPowerUpdateTime; + protected long lastLoginTime; + protected ChatMode chatMode; + protected boolean ignoreAllianceChat = false; + protected String id; + protected String name; + protected boolean monitorJoins; + protected boolean spyingChat = false; + protected boolean showScoreboard = true; + protected WarmUpUtil.Warmup warmup; + protected int warmupTask; + protected boolean isAdminBypassing = false; + protected int kills, deaths; + protected boolean willAutoLeave = true; + protected int mapHeight = 8; // default to old value + protected boolean isFlying = false; + protected boolean enteringPassword = false; + protected String enteringPasswordWarp = ""; + protected transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked? + protected transient boolean mapAutoUpdating; + protected transient Faction autoClaimFor; + protected transient boolean autoSafeZoneEnabled; + protected transient boolean autoWarZoneEnabled; + protected transient boolean loginPvpDisabled; + protected transient long lastFrostwalkerMessage; + protected transient boolean shouldTakeFallDamage = true; + protected boolean isStealthEnabled = false; + boolean playerAlerts = false; + boolean inspectMode = false; + + public MemoryFPlayer() { + } + + public MemoryFPlayer(String id) { + this.id = id; + this.resetFactionData(false); + this.power = Conf.powerPlayerStarting; + this.lastPowerUpdateTime = System.currentTimeMillis(); + this.lastLoginTime = System.currentTimeMillis(); + this.mapAutoUpdating = false; + this.autoClaimFor = null; + this.autoSafeZoneEnabled = false; + this.autoWarZoneEnabled = false; + this.loginPvpDisabled = Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0; + this.powerBoost = 0.0; + this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false); + this.kills = 0; + this.deaths = 0; + this.mapHeight = Conf.mapHeight; + + if (!Conf.newPlayerStartingFactionID.equals("0") && Factions.getInstance().isValidFactionId(Conf.newPlayerStartingFactionID)) { + this.factionId = Conf.newPlayerStartingFactionID; + } + } + + public MemoryFPlayer(MemoryFPlayer other) { + this.factionId = other.factionId; + this.id = other.id; + this.power = other.power; + this.lastLoginTime = other.lastLoginTime; + this.mapAutoUpdating = other.mapAutoUpdating; + this.autoClaimFor = other.autoClaimFor; + this.autoSafeZoneEnabled = other.autoSafeZoneEnabled; + this.autoWarZoneEnabled = other.autoWarZoneEnabled; + this.loginPvpDisabled = other.loginPvpDisabled; + this.powerBoost = other.powerBoost; + this.role = other.role; + this.title = other.title; + this.chatMode = other.chatMode; + this.spyingChat = other.spyingChat; + this.lastStoodAt = other.lastStoodAt; + this.isAdminBypassing = other.isAdminBypassing; + this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", true); + this.kills = other.kills; + this.deaths = other.deaths; + this.mapHeight = Conf.mapHeight; + } + + public boolean isStealthEnabled() { + return this.isStealthEnabled; + } + + public void setStealth(boolean stealth) { + this.isStealthEnabled = stealth; + } + + public void login() { + this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); + this.deaths = getPlayer().getStatistic(Statistic.DEATHS); + } + + public void logout() { + this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); + this.deaths = getPlayer().getStatistic(Statistic.DEATHS); + } + + public Faction getFaction() { + if (this.factionId == null) { + this.factionId = "0"; + } + return Factions.getInstance().getFactionById(this.factionId); + } + + public void setFaction(Faction faction) { + Faction oldFaction = this.getFaction(); + if (oldFaction != null) { + oldFaction.removeFPlayer(this); + } + faction.addFPlayer(this); + this.factionId = faction.getId(); + } + + public String getFactionId() { + return this.factionId; + } + + public boolean hasFaction() { + return !factionId.equals("0"); + } + + public void setMonitorJoins(boolean monitor) { + this.monitorJoins = monitor; + } + + public boolean isMonitoringJoins() { + return this.monitorJoins; + } + + public Role getRole() { + // Hack to fix null roles.. + if (role == null) { + this.role = Role.NORMAL; + } + + return this.role; + } + + public void setRole(Role role) { + this.role = role; + } + + public double getPowerBoost() { + return this.powerBoost; + } + + public void setPowerBoost(double powerBoost) { + this.powerBoost = powerBoost; + } + + public boolean willAutoLeave() { + return this.willAutoLeave; + } + + public void setAutoLeave(boolean willLeave) { + this.willAutoLeave = willLeave; + SavageFactions.plugin.debug(name + " set autoLeave to " + willLeave); + } + + public long getLastFrostwalkerMessage() { + return this.lastFrostwalkerMessage; + } + + public void setLastFrostwalkerMessage() { + this.lastFrostwalkerMessage = System.currentTimeMillis(); + } + + public Faction getAutoClaimFor() { + return autoClaimFor; + } + + public void setAutoClaimFor(Faction faction) { + this.autoClaimFor = faction; + if (this.autoClaimFor != null) { + // TODO: merge these into same autoclaim + this.autoSafeZoneEnabled = false; + this.autoWarZoneEnabled = false; + } + } + + public boolean isAutoSafeClaimEnabled() { + return autoSafeZoneEnabled; + } + + public void setIsAutoSafeClaimEnabled(boolean enabled) { + this.autoSafeZoneEnabled = enabled; + if (enabled) { + this.autoClaimFor = null; + this.autoWarZoneEnabled = false; + } + } + + public boolean isAutoWarClaimEnabled() { + return autoWarZoneEnabled; + } + + public void setIsAutoWarClaimEnabled(boolean enabled) { + this.autoWarZoneEnabled = enabled; + if (enabled) { + this.autoClaimFor = null; + this.autoSafeZoneEnabled = false; + } + } + + public boolean isAdminBypassing() { + return this.isAdminBypassing; + } + + public boolean isVanished() { + return Essentials.isVanished(getPlayer()); + } + + public void setIsAdminBypassing(boolean val) { + this.isAdminBypassing = val; + } + + public ChatMode getChatMode() { + if (this.factionId.equals("0") || !Conf.factionOnlyChat) { + this.chatMode = ChatMode.PUBLIC; + } + return chatMode; + } + + public void setChatMode(ChatMode chatMode) { + this.chatMode = chatMode; + } + + public boolean isIgnoreAllianceChat() { + return ignoreAllianceChat; + } + + public void setIgnoreAllianceChat(boolean ignore) { + this.ignoreAllianceChat = ignore; + } + + public boolean isSpyingChat() { + return spyingChat; + } + + public void setSpyingChat(boolean chatSpying) { + this.spyingChat = chatSpying; + } + + // -------------------------------------------- // + // Getters And Setters + // -------------------------------------------- // + + // FIELD: account + public String getAccountId() { + return this.getId(); + } + + public void resetFactionData(boolean doSpoutUpdate) { + // clean up any territory ownership in old faction, if there is one + if (factionId != null && Factions.getInstance().isValidFactionId(this.getFactionId())) { + Faction currentFaction = this.getFaction(); + currentFaction.removeFPlayer(this); + if (currentFaction.isNormal()) { + currentFaction.clearClaimOwnership(this); + } + } + + this.factionId = "0"; // The default neutral faction + this.chatMode = ChatMode.PUBLIC; + this.role = Role.NORMAL; + this.title = ""; + this.autoClaimFor = null; + } + + public void resetFactionData() { + this.resetFactionData(true); + } + + public long getLastLoginTime() { + return lastLoginTime; + } + + public void setLastLoginTime(long lastLoginTime) { + losePowerFromBeingOffline(); + this.lastLoginTime = lastLoginTime; + this.lastPowerUpdateTime = lastLoginTime; + if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { + this.loginPvpDisabled = true; + } + } + + public boolean isMapAutoUpdating() { + return mapAutoUpdating; + } + + public void setMapAutoUpdating(boolean mapAutoUpdating) { + this.mapAutoUpdating = mapAutoUpdating; + } + + //----------------------------------------------// + // Title, Name, Faction Tag and Chat + //----------------------------------------------// + + // Base: + + public boolean hasLoginPvpDisabled() { + if (!loginPvpDisabled) { + return false; + } + if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) { + this.loginPvpDisabled = false; + return false; + } + return true; + } + + public FLocation getLastStoodAt() { + return this.lastStoodAt; + } + + public void setLastStoodAt(FLocation flocation) { + this.lastStoodAt = flocation; + } + + public String getTitle() { + return this.hasFaction() ? title : TL.NOFACTION_PREFIX.toString(); + } + + public void setTitle(CommandSender sender, String title) { + // Check if the setter has it. + if (sender.hasPermission(Permission.TITLE_COLOR.node)) { + title = ChatColor.translateAlternateColorCodes('&', title); + } + + this.title = title; + } + + // Base concatenations: + + public String getName() { + if (this.name == null) { + // Older versions of FactionsUUID don't save the name, + // so `name` will be null the first time it's retrieved + // after updating + OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(getId())); + this.name = offline.getName() != null ? offline.getName() : getId(); + } + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTag() { + return this.hasFaction() ? this.getFaction().getTag() : ""; + } + + // Colored concatenations: + // These are used in information messages + + public String getNameAndSomething(String something) { + String ret = this.role.getPrefix(); + if (something.length() > 0) { + ret += something + " "; + } + ret += this.getName(); + return ret; + } + + public String getNameAndTitle() { + return this.getNameAndSomething(this.getTitle()); + } + + // Chat Tag: + // These are injected into the format of global chat messages. + + public String getNameAndTag() { + return this.getNameAndSomething(this.getTag()); + } + + public String getNameAndTitle(Faction faction) { + return this.getColorTo(faction) + this.getNameAndTitle(); + } + + public String getNameAndTitle(MemoryFPlayer fplayer) { + return this.getColorTo(fplayer) + this.getNameAndTitle(); + } + + public String getChatTag() { + return this.hasFaction() ? String.format(Conf.chatTagFormat, this.getRole().getPrefix() + this.getTag()) : TL.NOFACTION_PREFIX.toString(); + } + + // Colored Chat Tag + public String getChatTag(Faction faction) { + return this.hasFaction() ? this.getRelationTo(faction).getColor() + getChatTag() : ""; + } + + // ------------------------------- + // Relation and relation colors + // ------------------------------- + + public String getChatTag(MemoryFPlayer fplayer) { + return this.hasFaction() ? this.getColorTo(fplayer) + getChatTag() : ""; + } + + public int getKills() { + return isOnline() ? getPlayer().getStatistic(Statistic.PLAYER_KILLS) : this.kills; + } + + public int getDeaths() { + return isOnline() ? getPlayer().getStatistic(Statistic.DEATHS) : this.deaths; + + } + + @Override + public String describeTo(RelationParticipator that, boolean ucfirst) { + return RelationUtil.describeThatToMe(this, that, ucfirst); + } + + @Override + public String describeTo(RelationParticipator that) { + return RelationUtil.describeThatToMe(this, that); + } + + @Override + public Relation getRelationTo(RelationParticipator rp) { + return RelationUtil.getRelationTo(this, rp); + } + + @Override + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { + return RelationUtil.getRelationTo(this, rp, ignorePeaceful); + } + + public Relation getRelationToLocation() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this); + } + + @Override + public ChatColor getColorTo(RelationParticipator rp) { + return RelationUtil.getColorOfThatToMe(this, rp); + } + + //----------------------------------------------// + // Health + //----------------------------------------------// + public void heal(int amnt) { + Player player = this.getPlayer(); + if (player == null) { + return; + } + player.setHealth(player.getHealth() + amnt); + } + + //----------------------------------------------// + // Power + //----------------------------------------------// + public double getPower() { + this.updatePower(); + return this.power; + } + + public void alterPower(double delta) { + this.power += delta; + if (this.power > this.getPowerMax()) { + this.power = this.getPowerMax(); + } else if (this.power < this.getPowerMin()) { + this.power = this.getPowerMin(); + } + } + + public double getPowerMax() { + return Conf.powerPlayerMax + this.powerBoost; + } + + public double getPowerMin() { + return Conf.powerPlayerMin + this.powerBoost; + } + + public int getPowerRounded() { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() { + return (int) Math.round(this.getPowerMax()); + } + + public int getPowerMinRounded() { + return (int) Math.round(this.getPowerMin()); + } + + public void updatePower() { + if (this.isOffline()) { + losePowerFromBeingOffline(); + if (!Conf.powerRegenOffline) { + return; + } + } else if (hasFaction() && getFaction().isPowerFrozen()) { + return; // Don't let power regen if faction power is frozen. + } + + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + Player thisPlayer = this.getPlayer(); + if (thisPlayer != null && thisPlayer.isDead()) { + return; // don't let dead players regain power until they respawn + } + + PowerRegenEvent powerRegenEvent = new PowerRegenEvent(getFaction(), this); + Bukkit.getServer().getPluginManager().callEvent(powerRegenEvent); + + if (!powerRegenEvent.isCancelled()) + this.alterPower(millisPassed * Conf.powerPerMinute / 60000); // millisPerMinute : 60 * 1000 + } + + public void losePowerFromBeingOffline() { + if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + double loss = millisPassed * Conf.powerOfflineLossPerDay / (24 * 60 * 60 * 1000); + if (this.power - loss < Conf.powerOfflineLossLimit) { + loss = this.power; + } + this.alterPower(-loss); + } + } + + public void onDeath() { + this.updatePower(); + this.alterPower(-Conf.powerPerDeath); + if (hasFaction()) { + getFaction().setLastDeath(System.currentTimeMillis()); + } + } + + //----------------------------------------------// + // Territory + //----------------------------------------------// + public boolean isInOwnTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)) == this.getFaction(); + } + + public boolean isInOthersTerritory() { + Faction factionHere = Board.getInstance().getFactionAt(new FLocation(this)); + return factionHere != null && factionHere.isNormal() && factionHere != this.getFaction(); + } + + public boolean isInAllyTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isAlly(); + } + + public boolean isInNeutralTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isNeutral(); + } + + public boolean isInEnemyTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isEnemy(); + } + + public void sendFactionHereMessage(Faction from) { + Faction toShow = Board.getInstance().getFactionAt(getLastStoodAt()); + boolean showChat = true; + if (showInfoBoard(toShow)) { + FScoreboard.get(this).setTemporarySidebar(new FInfoSidebar(toShow)); + showChat = SavageFactions.plugin.getConfig().getBoolean("scoreboard.also-send-chat", true); + } + if (showChat) { + this.sendMessage(SavageFactions.plugin.txt.parse(TL.FACTION_LEAVE.format(from.getTag(this), toShow.getTag(this)))); + } + } + + // ------------------------------- + // Actions + // ------------------------------- + + /** + * Check if the scoreboard should be shown. Simple method to be used by above method. + * + * @param toShow Faction to be shown. + * @return true if should show, otherwise false. + */ + public boolean showInfoBoard(Faction toShow) { + return showScoreboard && !toShow.isWarZone() && !toShow.isWilderness() && !toShow.isSafeZone() && SavageFactions.plugin.getConfig().contains("scoreboard.finfo") && SavageFactions.plugin.getConfig().getBoolean("scoreboard.finfo-enabled", false) && FScoreboard.get(this) != null; + } + + @Override + public boolean showScoreboard() { + return this.showScoreboard; + } + + @Override + public void setShowScoreboard(boolean show) { + this.showScoreboard = show; + } + + public void leave(boolean makePay) { + Faction myFaction = this.getFaction(); + makePay = makePay && Econ.shouldBeUsed() && !this.isAdminBypassing(); + + if (myFaction == null) { + resetFactionData(); + return; + } + + boolean perm = myFaction.isPermanent(); + + if (!perm && this.getRole() == Role.LEADER && myFaction.getFPlayers().size() > 1) { + msg(TL.LEAVE_PASSADMIN); + return; + } + + if (!Conf.canLeaveWithNegativePower && this.getPower() < 0) { + msg(TL.LEAVE_NEGATIVEPOWER); + return; + } + + // if economy is enabled and they're not on the bypass list, make sure they can pay + if (makePay && !Econ.hasAtLeast(this, Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString())) { + return; + } + + FPlayerLeaveEvent leaveEvent = new FPlayerLeaveEvent(this, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.LEAVE); + Bukkit.getServer().getPluginManager().callEvent(leaveEvent); + if (leaveEvent.isCancelled()) { + return; + } + + // then make 'em pay (if applicable) + if (makePay && !Econ.modifyMoney(this, -Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString(), TL.LEAVE_FORLEAVE.toString())) { + return; + } + + // Am I the last one in the faction? + if (myFaction.getFPlayers().size() == 1) { + // Transfer all money + if (Econ.shouldBeUsed()) { + Econ.transferMoney(this, myFaction, this, Econ.getBalance(myFaction.getAccountId())); + } + } + + if (myFaction.isNormal()) { + for (FPlayer fplayer : myFaction.getFPlayersWhereOnline(true)) { + fplayer.msg(TL.LEAVE_LEFT, this.describeTo(fplayer, true), myFaction.describeTo(fplayer)); + } + + if (Conf.logFactionLeave) { + SavageFactions.plugin.log(TL.LEAVE_LEFT.format(this.getName(), myFaction.getTag())); + } + } + + myFaction.removeAnnouncements(this); + this.resetFactionData(); + + if (myFaction.isNormal() && !perm && myFaction.getFPlayers().isEmpty()) { + // Remove this faction + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg(TL.LEAVE_DISBANDED, myFaction.describeTo(fplayer, true)); + } + + FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), PlayerDisbandReason.LEAVE); + Bukkit.getPluginManager().callEvent(disbandEvent); + + Factions.getInstance().removeFaction(myFaction.getId()); + if (Conf.logFactionDisband) { + SavageFactions.plugin.log(TL.LEAVE_DISBANDEDLOG.format(myFaction.getTag(), myFaction.getId(), this.getName())); + } + } + } + + public boolean canClaimForFaction(Faction forFaction) { + return this.isAdminBypassing() || !forFaction.isWilderness() && (forFaction == this.getFaction() && this.getRole().isAtLeast(Role.MODERATOR)) || (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) || (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())); + } + + public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure) { + return canClaimForFactionAtLocation(forFaction, new FLocation(location), notifyFailure); + } + + public boolean canClaimForFactionAtLocation(Faction forFaction, FLocation flocation, boolean notifyFailure) { + String error = null; + Faction myFaction = getFaction(); + Faction currentFaction = Board.getInstance().getFactionAt(flocation); + int ownedLand = forFaction.getLandRounded(); + int factionBuffer = SavageFactions.plugin.getConfig().getInt("hcf.buffer-zone", 0); + int worldBuffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); + + if (Conf.worldGuardChecking && Worldguard.checkForRegionsInChunk(flocation)) { + // Checks for WorldGuard regions in the chunk attempting to be claimed + error = SavageFactions.plugin.txt.parse(TL.CLAIM_PROTECTED.toString()); + } else if (flocation.isOutsideWorldBorder(SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0))) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); + } else if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_DISABLED.toString()); + } else if (this.isAdminBypassing()) { + return true; + } else if (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) { + return true; + } else if (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())) { + return true; + } else if (currentFaction.getAccess(this, PermissableAction.TERRITORY) == Access.ALLOW) { + return true; + } else if (myFaction != forFaction) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_CANTCLAIM.toString(), forFaction.describeTo(this)); + } else if (forFaction == currentFaction) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALREADYOWN.toString(), forFaction.describeTo(this, true)); + } else if (this.getRole().value < Role.MODERATOR.value) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_MUSTBE.toString(), Role.MODERATOR.getTranslation()); + } else if (forFaction.getFPlayers().size() < Conf.claimsRequireMinFactionMembers) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_MEMBERS.toString(), Conf.claimsRequireMinFactionMembers); + } else if (currentFaction.isSafeZone()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_SAFEZONE.toString()); + } else if (currentFaction.isWarZone()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_WARZONE.toString()); + } else if (SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true) && ownedLand >= forFaction.getPowerRounded()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_POWER.toString()); + } else if (Conf.claimedLandsMax != 0 && ownedLand >= Conf.claimedLandsMax && forFaction.isNormal()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_LIMIT.toString()); + } else if (currentFaction.getRelationTo(forFaction) == Relation.ALLY) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALLY.toString()); + } else if (Conf.claimsMustBeConnected && !this.isAdminBypassing() && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, myFaction) && (!Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction || !currentFaction.isNormal())) { + if (Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_CONTIGIOUS.toString()); + } else { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_FACTIONCONTIGUOUS.toString()); + } + } else if (factionBuffer > 0 && Board.getInstance().hasFactionWithin(flocation, myFaction, factionBuffer)) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_TOOCLOSETOOTHERFACTION.format(factionBuffer)); + } else if (flocation.isOutsideWorldBorder(worldBuffer)) { + if (worldBuffer > 0) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEBORDERBUFFER.format(worldBuffer)); + } else { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); + } + } else if (currentFaction.isNormal()) { + if (myFaction.isPeaceful()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFUL.toString(), currentFaction.getTag(this)); + } else if (currentFaction.isPeaceful()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFULTARGET.toString(), currentFaction.getTag(this)); + } else if (!currentFaction.hasLandInflation()) { + // TODO more messages WARN current faction most importantly + error = SavageFactions.plugin.txt.parse(TL.CLAIM_THISISSPARTA.toString(), currentFaction.getTag(this)); + } else if (currentFaction.hasLandInflation() && !SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true)) { + // deny over claim when it normally would be allowed. + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OVERCLAIM_DISABLED.toString()); + } else if (!Board.getInstance().isBorderLocation(flocation)) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_BORDER.toString()); + } + } + // TODO: Add more else if statements. + + if (notifyFailure && error != null) { + msg(error); + } + return error == null; + } + + public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure) { + return attemptClaim(forFaction, new FLocation(location), notifyFailure); + } + + public boolean shouldBeSaved() { + return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); + } + + public void msg(String str, Object... args) { + this.sendMessage(SavageFactions.plugin.txt.parse(str, args)); + } + + public void msg(TL translation, Object... args) { + this.msg(translation.toString(), args); + } + + public Player getPlayer() { + return Bukkit.getPlayer(UUID.fromString(this.getId())); + } + + public boolean isOnline() { + return this.getPlayer() != null; + } + + // make sure target player should be able to detect that this player is online + public boolean isOnlineAndVisibleTo(Player player) { + Player target = this.getPlayer(); + return target != null && player.canSee(target); + } + + public boolean isOffline() { + return !isOnline(); + } + + public boolean isFlying() { + return isFlying; + } + + public void setFlying(boolean fly) { + setFFlying(fly, false); + } + + public void setFFlying(boolean fly, boolean damage) { + Player player = getPlayer(); + if (player != null) { + player.setAllowFlight(fly); + player.setFlying(fly); + } + + if (!damage) { + msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); + if (!fly) { + sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3) + "")); + } + + } else { + msg(TL.COMMAND_FLY_DAMAGE); + } + + // If leaving fly mode, don't let them take fall damage for x seconds. + if (!fly) { + int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); + CmdFly.flyMap.remove(player.getName()); + + // If the value is 0 or lower, make them take fall damage. + // Otherwise, start a timer and have this cancel after a few seconds. + // Short task so we're just doing it in method. Not clean but eh. + if (cooldown > 0) { + setTakeFallDamage(false); + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + setTakeFallDamage(true); + } + }, 20L * cooldown); + } + } + + isFlying = fly; + } + + public boolean isInVault() { + return inVault; + } + + public void setInVault(boolean status) { + inVault = status; + } + + public boolean canFlyAtLocation() { + return canFlyAtLocation(lastStoodAt); + } + + public boolean canFlyAtLocation(FLocation location) { + Faction faction = Board.getInstance().getFactionAt(location); + if ((faction == getFaction() && getRole() == Role.LEADER) || isAdminBypassing) { + return true; + } + + Access access = faction.getAccess(this, PermissableAction.FLY); + return access == null || access == Access.UNDEFINED || access == Access.ALLOW; + } + + public boolean shouldTakeFallDamage() { + return this.shouldTakeFallDamage; + } + + public void setTakeFallDamage(boolean fallDamage) { + this.shouldTakeFallDamage = fallDamage; + } + + public boolean isEnteringPassword() { + return enteringPassword; + } + + public void setEnteringPassword(boolean toggle, String warp) { + enteringPassword = toggle; + enteringPasswordWarp = warp; + } + + // -------------------------------------------- // + // Message Sending Helpers + // -------------------------------------------- // + + public String getEnteringWarp() { + return enteringPasswordWarp; + } + + public void sendMessage(String msg) { + if (msg.contains("{null}")) { + return; // user wants this message to not send + } + if (msg.contains("/n/")) { + for (String s : msg.split("/n/")) { + sendMessage(s); + } + return; + } + Player player = this.getPlayer(); + if (player == null) { + return; + } + player.sendMessage(msg); + } + + public void sendMessage(List msgs) { + for (String msg : msgs) { + this.sendMessage(msg); + } + } + + public void sendFancyMessage(FancyMessage message) { + Player player = getPlayer(); + if (player == null || !player.isOnGround()) { + return; + } + + message.send(player); + } + + public void sendFancyMessage(List messages) { + Player player = getPlayer(); + if (player == null) { + return; + } + + for (FancyMessage msg : messages) { + msg.send(player); + } + } + + public int getMapHeight() { + if (this.mapHeight < 1) { + this.mapHeight = Conf.mapHeight; + } + + return this.mapHeight; + } + + public void setMapHeight(int height) { + this.mapHeight = height > (Conf.mapHeight * 2) ? (Conf.mapHeight * 2) : height; + } + + public String getNameAndTitle(FPlayer fplayer) { + return this.getColorTo(fplayer) + this.getNameAndTitle(); + } + + @Override + public String getChatTag(FPlayer fplayer) { + return this.hasFaction() ? this.getRelationTo(fplayer).getColor() + getChatTag() : ""; + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public abstract void remove(); + + @Override + public void clearWarmup() { + if (warmup != null) { + Bukkit.getScheduler().cancelTask(warmupTask); + this.stopWarmup(); + } + } + + @Override + public void stopWarmup() { + warmup = null; + } + + @Override + public boolean isWarmingUp() { + return warmup != null; + } + + @Override + public WarmUpUtil.Warmup getWarmupType() { + return warmup; + } + + @Override + public void addWarmup(WarmUpUtil.Warmup warmup, int taskId) { + if (this.warmup != null) { + this.clearWarmup(); + } + this.warmup = warmup; + this.warmupTask = taskId; + } + + @Override + public boolean checkIfNearbyEnemies() { + Player me = this.getPlayer(); + int radius = Conf.stealthFlyCheckRadius; + for (Entity e : me.getNearbyEntities(radius, 255, radius)) { + if (e == null) { + continue; + } + if (e instanceof Player) { + Player eplayer = (((Player) e).getPlayer()); + if (eplayer == null) { + continue; + } + FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); + if (efplayer == null) { + continue; + } + if (efplayer != null && this.getRelationTo(efplayer).equals(Relation.ENEMY) && !efplayer.isStealthEnabled()) { + setFlying(false); + msg(TL.COMMAND_FLY_ENEMY_NEAR); + Bukkit.getServer().getPluginManager().callEvent(new FPlayerStoppedFlying(this)); + return true; + } + } + } + return false; + } + + @Override + public Boolean canflyinWilderness() { + return getPlayer().hasPermission("factions.fly.wilderness"); + } + + @Override + public Boolean canflyinWarzone() { + return getPlayer().hasPermission("factions.fly.warzone"); + + } + + @Override + public Boolean canflyinSafezone() { + return getPlayer().hasPermission("factions.fly.safezone"); + + } + + @Override + public Boolean canflyinEnemy() { + return getPlayer().hasPermission("factions.fly.enemy"); + + } + + @Override + public Boolean canflyinAlly() { + return getPlayer().hasPermission("factions.fly.ally"); + + } + + @Override + public Boolean canflyinTruce() { + return getPlayer().hasPermission("factions.fly.truce"); + + } + + @Override + public Boolean canflyinNeutral() { + return getPlayer().hasPermission("factions.fly.neutral"); + + } + + @Override + public boolean isInspectMode() { + return inspectMode; + } + + @Override + public void setInspectMode(boolean status) { + inspectMode = status; + } + + public boolean attemptClaim(Faction forFaction, FLocation flocation, boolean notifyFailure) { + // notifyFailure is false if called by auto-claim; no need to notify on every failure for it + // return value is false on failure, true on success + + Faction currentFaction = Board.getInstance().getFactionAt(flocation); + int ownedLand = forFaction.getLandRounded(); + + if (!this.canClaimForFactionAtLocation(forFaction, flocation, notifyFailure)) { + return false; + } + + // if economy is enabled and they're not on the bypass list, make sure they can pay + boolean mustPay = Econ.shouldBeUsed() && !this.isAdminBypassing() && !forFaction.isSafeZone() && !forFaction.isWarZone(); + double cost = 0.0; + EconomyParticipator payee = null; + if (mustPay) { + cost = Econ.calculateClaimCost(ownedLand, currentFaction.isNormal()); + + + if (Conf.econClaimUnconnectedFee != 0.0 && forFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, forFaction)) { + cost += Conf.econClaimUnconnectedFee; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts && this.hasFaction()) { + payee = this.getFaction(); + } else { + payee = this; + } + + if (!Econ.hasAtLeast(payee, cost, TL.CLAIM_TOCLAIM.toString())) { + return false; + } + } + + LandClaimEvent claimEvent = new LandClaimEvent(flocation, forFaction, this); + Bukkit.getPluginManager().callEvent(claimEvent); + if (claimEvent.isCancelled()) { + return false; + } + + // then make 'em pay (if applicable) + if (mustPay && !Econ.modifyMoney(payee, -cost, TL.CLAIM_TOCLAIM.toString(), TL.CLAIM_FORCLAIM.toString())) { + return false; + } + + // Was an over claim + if (currentFaction.isNormal() && currentFaction.hasLandInflation()) { + // Give them money for over claiming. + Econ.modifyMoney(payee, Conf.econOverclaimRewardMultiplier, TL.CLAIM_TOOVERCLAIM.toString(), TL.CLAIM_FOROVERCLAIM.toString()); + } + + // announce success + Set informTheseFPlayers = new HashSet<>(); + informTheseFPlayers.add(this); + informTheseFPlayers.addAll(forFaction.getFPlayersWhereOnline(true)); + for (FPlayer fp : informTheseFPlayers) { + fp.msg(TL.CLAIM_CLAIMED, this.describeTo(fp, true), forFaction.describeTo(fp), currentFaction.describeTo(fp)); + } + + Board.getInstance().setFactionAt(forFaction, flocation); + + if (Conf.logLandClaims) { + SavageFactions.plugin.log(TL.CLAIM_CLAIMEDLOG.toString(), this.getName(), flocation.getCoordString(), forFaction.getTag()); + } + + return true; + } + + + @Override + public String getRolePrefix() { + + switch (getRole()) { + case RECRUIT: + return Conf.prefixRecruit; + case NORMAL: + return Conf.prefixNormal; + case MODERATOR: + return Conf.prefixMod; + case COLEADER: + return Conf.prefixCoLeader; + case LEADER: + return Conf.prefixLeader; + } + + return null; + } + + @Override + public boolean hasMoney(int amt) { + Economy econ = SavageFactions.plugin.getEcon(); + if (econ.getBalance(getPlayer()) >= amt) { + return true; + } else { + getPlayer().closeInventory(); + msg(TL.GENERIC_NOTENOUGHMONEY); + return false; + } + } + + @Override + public void takeMoney(int amt) { + if (hasMoney(amt)) { + Economy econ = SavageFactions.plugin.getEcon(); + econ.withdrawPlayer(getPlayer(), amt); + sendMessage(TL.GENERIC_MONEYTAKE.toString().replace("{amount}", amt + "")); + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java index b120e028..02138532 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java @@ -12,55 +12,55 @@ import java.util.*; import java.util.concurrent.ConcurrentSkipListMap; public abstract class MemoryFPlayers extends FPlayers { - public Map fPlayers = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER); + public Map fPlayers = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER); - public void clean() { - for (FPlayer fplayer : this.fPlayers.values()) { - if (!Factions.getInstance().isValidFactionId(fplayer.getFactionId())) { - SavageFactions.plugin.log("Reset faction data (invalid faction:" + fplayer.getFactionId() + ") for player " + fplayer.getName()); - fplayer.resetFactionData(false); - } - } - } + public void clean() { + for (FPlayer fplayer : this.fPlayers.values()) { + if (!Factions.getInstance().isValidFactionId(fplayer.getFactionId())) { + SavageFactions.plugin.log("Reset faction data (invalid faction:" + fplayer.getFactionId() + ") for player " + fplayer.getName()); + fplayer.resetFactionData(false); + } + } + } - public Collection getOnlinePlayers() { - Set entities = new HashSet<>(); - for (Player player : Bukkit.getServer().getOnlinePlayers()) { - entities.add(this.getByPlayer(player)); - } - return entities; - } + public Collection getOnlinePlayers() { + Set entities = new HashSet<>(); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + entities.add(this.getByPlayer(player)); + } + return entities; + } - @Override - public FPlayer getByPlayer(Player player) { - return getById(player.getUniqueId().toString()); - } + @Override + public FPlayer getByPlayer(Player player) { + return getById(player.getUniqueId().toString()); + } - @Override - public List getAllFPlayers() { - return new ArrayList<>(fPlayers.values()); - } + @Override + public List getAllFPlayers() { + return new ArrayList<>(fPlayers.values()); + } - @Override - public abstract void forceSave(); + @Override + public abstract void forceSave(); - public abstract void load(); + public abstract void load(); - @Override - public FPlayer getByOfflinePlayer(OfflinePlayer player) { - return getById(player.getUniqueId().toString()); - } + @Override + public FPlayer getByOfflinePlayer(OfflinePlayer player) { + return getById(player.getUniqueId().toString()); + } - @Override - public FPlayer getById(String id) { - FPlayer player = fPlayers.get(id); - if (player == null) { - player = generateFPlayer(id); - } - return player; - } + @Override + public FPlayer getById(String id) { + FPlayer player = fPlayers.get(id); + if (player == null) { + player = generateFPlayer(id); + } + return player; + } - public abstract FPlayer generateFPlayer(String id); + public abstract FPlayer generateFPlayer(String id); - public abstract void convertFrom(MemoryFPlayers old); + public abstract void convertFrom(MemoryFPlayers old); } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java index 306826d4..c66bce5f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java @@ -34,1211 +34,1211 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; public abstract class MemoryFaction implements Faction, EconomyParticipator { - public HashMap rules = new HashMap(); - public int tnt; - public Location checkpoint; - public LazyLocation vault; - public HashMap upgrades = new HashMap<>(); - protected String id = null; - protected boolean peacefulExplosionsEnabled; - protected boolean permanent; - protected String tag; - protected String description; - protected boolean open; - protected boolean peaceful; - protected Integer permanentPower; - protected LazyLocation home; - protected long foundedDate; - protected transient long lastPlayerLoggedOffTime; - protected double money; - protected double powerBoost; - protected String paypal; - protected Map relationWish = new HashMap<>(); - protected Map> claimOwnership = new ConcurrentHashMap<>(); - protected transient Set fplayers = new HashSet<>(); - protected Set invites = new HashSet<>(); - protected HashMap> announcements = new HashMap<>(); - protected ConcurrentHashMap warps = new ConcurrentHashMap<>(); - protected ConcurrentHashMap warpPasswords = new ConcurrentHashMap<>(); - protected int maxVaults; - protected Role defaultRole; - protected Map> permissions = new HashMap<>(); - protected Set bans = new HashSet<>(); - protected String player; - Inventory chest; - Map bannerSerialized; - private long lastDeath; - - // -------------------------------------------- // - // Construct - // -------------------------------------------- // - public MemoryFaction() { - } - - public MemoryFaction(String id) { - this.id = id; - this.open = Conf.newFactionsDefaultOpen; - this.tag = "???"; - this.description = TL.GENERIC_DEFAULTDESCRIPTION.toString(); - this.lastPlayerLoggedOffTime = 0; - this.peaceful = false; - this.peacefulExplosionsEnabled = false; - this.permanent = false; - this.money = 0.0; - this.powerBoost = 0.0; - this.foundedDate = System.currentTimeMillis(); - this.maxVaults = Conf.defaultMaxVaults; - this.defaultRole = Role.RECRUIT; - - resetPerms(); // Reset on new Faction so it has default values. - } - - public MemoryFaction(MemoryFaction old) { - id = old.id; - peacefulExplosionsEnabled = old.peacefulExplosionsEnabled; - permanent = old.permanent; - tag = old.tag; - description = old.description; - open = old.open; - foundedDate = old.foundedDate; - peaceful = old.peaceful; - permanentPower = old.permanentPower; - home = old.home; - lastPlayerLoggedOffTime = old.lastPlayerLoggedOffTime; - money = old.money; - powerBoost = old.powerBoost; - relationWish = old.relationWish; - claimOwnership = old.claimOwnership; - fplayers = new HashSet<>(); - invites = old.invites; - announcements = old.announcements; - this.defaultRole = Role.NORMAL; - - resetPerms(); // Reset on new Faction so it has default values. - } - - public HashMap> getAnnouncements() { - return this.announcements; - } - - public void addAnnouncement(FPlayer fPlayer, String msg) { - List list = announcements.containsKey(fPlayer.getId()) ? announcements.get(fPlayer.getId()) : new ArrayList(); - list.add(msg); - announcements.put(fPlayer.getId(), list); - } - - public void sendUnreadAnnouncements(FPlayer fPlayer) { - if (!announcements.containsKey(fPlayer.getId())) { - return; - } - fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_TOP); - for (String s : announcements.get(fPlayer.getPlayer().getUniqueId().toString())) { - fPlayer.sendMessage(s); - } - fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_BOTTOM); - announcements.remove(fPlayer.getId()); - } - - public void removeAnnouncements(FPlayer fPlayer) { - announcements.remove(fPlayer.getId()); - } - - public ConcurrentHashMap getWarps() { - return this.warps; - } - - public LazyLocation getWarp(String name) { - return this.warps.get(name); - } - - public void setWarp(String name, LazyLocation loc) { - this.warps.put(name, loc); - } - - public boolean isWarp(String name) { - return this.warps.containsKey(name); - } - - public boolean removeWarp(String name) { - warpPasswords.remove(name); // remove password no matter what. - return warps.remove(name) != null; - } - - public boolean isWarpPassword(String warp, String password) { - return hasWarpPassword(warp) && warpPasswords.get(warp.toLowerCase()).equals(password); - } - - public String getPaypal() { - return this.paypal; - } - - public void paypalSet(String paypal) { - this.paypal = paypal; - } - - public boolean hasWarpPassword(String warp) { - return warpPasswords.containsKey(warp.toLowerCase()); - } - - public void setWarpPassword(String warp, String password) { - warpPasswords.put(warp.toLowerCase(), password); - } - - public void clearWarps() { - warps.clear(); - } - - public int getMaxVaults() { - return this.maxVaults; - } - - public void setMaxVaults(int value) { - this.maxVaults = value; - } - - public String getFocused() { - return this.player; - } - - public void setFocused(String fp) { - this.player = fp; - } - - public Set getInvites() { - return invites; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public void invite(FPlayer fplayer) { - this.invites.add(fplayer.getId()); - } - - public void deinvite(FPlayer fplayer) { - this.invites.remove(fplayer.getId()); - } - - public boolean isInvited(FPlayer fplayer) { - return this.invites.contains(fplayer.getId()); - } - - public void ban(FPlayer target, FPlayer banner) { - BanInfo info = new BanInfo(banner.getId(), target.getId(), System.currentTimeMillis()); - this.bans.add(info); - } - - public void unban(FPlayer player) { - Iterator iter = bans.iterator(); - while (iter.hasNext()) { - if (iter.next().getBanned().equalsIgnoreCase(player.getId())) { - iter.remove(); - } - } - } - - @Override - public void disband(Player disbander) { - disband(disbander, PlayerDisbandReason.PLUGIN); - } - - @Override - public void disband(Player disbander, PlayerDisbandReason reason) { - - boolean disbanderIsConsole = disbander == null; - FPlayer fdisbander = FPlayers.getInstance().getByOfflinePlayer(disbander); - - FactionDisbandEvent disbandEvent = new FactionDisbandEvent(disbander, this.getId(), reason); - Bukkit.getServer().getPluginManager().callEvent(disbandEvent); - if (disbandEvent.isCancelled()) { - return; - } - - // Send FPlayerLeaveEvent for each player in the faction - for (FPlayer fplayer : this.getFPlayers()) { - Bukkit.getServer().getPluginManager().callEvent(new FPlayerLeaveEvent(fplayer, this, FPlayerLeaveEvent.PlayerLeaveReason.DISBAND)); - } - - if (Conf.logFactionDisband) { - //TODO: Format this correctly and translate. - SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") was disbanded by " + (disbanderIsConsole ? "console command" : fdisbander.getName()) + "."); - } - - if (Econ.shouldBeUsed() && !disbanderIsConsole) { - //Give all the faction's money to the disbander - double amount = Econ.getBalance(this.getAccountId()); - Econ.transferMoney(fdisbander, this, fdisbander, amount, false); - - if (amount > 0.0) { - String amountString = Econ.moneyString(amount); - msg(TL.COMMAND_DISBAND_HOLDINGS, amountString); - //TODO: Format this correctly and translate - SavageFactions.plugin.log(fdisbander.getName() + " has been given bank holdings of " + amountString + " from disbanding " + this.getTag() + "."); - } - } - - Factions.getInstance().removeFaction(this.getId()); - FTeamWrapper.applyUpdates(this); - } - - public boolean isBanned(FPlayer player) { - for (BanInfo info : bans) { - if (info.getBanned().equalsIgnoreCase(player.getId())) { - return true; - } - } - - return false; - } - - public Set getBannedPlayers() { - return this.bans; - } - - public String getRule(int index) { - if (rules.size() == 0) return null; - return rules.get(index); - } - - public HashMap getRulesMap() { - return rules; - } - - public void setRule(int index, String rule) { - rules.put(index, rule); - } - - public void removeRule(int index) { - HashMap newRule = rules; - newRule.remove(index); - rules = newRule; - } - - public void addTnt(int amt) { - tnt += amt; - } - - public void takeTnt(int amt) { - tnt -= amt; - } - - public int getTnt() { - return tnt; - } - - - public Location getVault() { - if (vault == null) { - return null; - } - return vault.getLocation(); - } - - public void setVault(Location vaultLocation) { - if (vaultLocation == null) { - vault = null; - return; - } - LazyLocation newlocation = new LazyLocation(vaultLocation); - vault = newlocation; - } - - public int getUpgrade(Upgrade upgrade) { - if (upgrades.keySet().contains(upgrade.toString())) { - return upgrades.get(upgrade.toString()); - } - return 0; - } - - @Override - public Inventory getChestInventory() { - if (chest != null) { - return chest; - } else { - int level = getUpgrade(Upgrade.CHEST); - int size = 9; - if (level == 1) { - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1") * 9; - } else if (level == 2) { - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2") * 9; - } else if (level == 3) { - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3") * 9; - } - - chest = Bukkit.createInventory(null, size, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); - return chest; - - } - - } - - @Override - public void setChestSize(int chestSize) { - ItemStack[] contents = this.getChestInventory().getContents(); - chest = Bukkit.createInventory(null, chestSize, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); - chest.setContents(contents); - } - - - @Override - public void setBannerPattern(ItemStack banner) { - bannerSerialized = banner.serialize(); - } - - @Override - public ItemStack getBanner() { - if (bannerSerialized == null) { - return null; - } - return ItemStack.deserialize(bannerSerialized); - } - - public void setUpgrade(Upgrade upgrade, int level) { - upgrades.put(upgrade.toString(), level); - } - - public Location getCheckpoint() { - return checkpoint; - } - - public void setCheckpoint(Location location) { - checkpoint = location; - } - - public void clearRules() { - rules.clear(); - } - - public void addRule(String rule) { - rules.put(rules.size(), rule); - } - - public boolean getOpen() { - return open; - } - - public void setOpen(boolean isOpen) { - open = isOpen; - } - - public boolean isPeaceful() { - return this.peaceful; - } - - public void setPeaceful(boolean isPeaceful) { - this.peaceful = isPeaceful; - } - - public boolean getPeacefulExplosionsEnabled() { - return this.peacefulExplosionsEnabled; - } - - public void setPeacefulExplosionsEnabled(boolean val) { - peacefulExplosionsEnabled = val; - } - - public boolean noExplosionsInTerritory() { - return this.peaceful && !peacefulExplosionsEnabled; - } - - public boolean isPermanent() { - return permanent || !this.isNormal(); - } - - public void setPermanent(boolean isPermanent) { - permanent = isPermanent; - } - - public String getTag() { - return this.tag; - } - - public void setTag(String str) { - if (Conf.factionTagForceUpperCase) { - str = str.toUpperCase(); - } - this.tag = str; - } - - public String getTag(String prefix) { - return prefix + this.tag; - } - - public String getTag(Faction otherFaction) { - if (otherFaction == null) { - return getTag(); - } - return this.getTag(this.getColorTo(otherFaction).toString()); - } - - public String getTag(FPlayer otherFplayer) { - if (otherFplayer == null) { - return getTag(); - } - return this.getTag(this.getColorTo(otherFplayer).toString()); - } - - public String getComparisonTag() { - return MiscUtil.getComparisonString(this.tag); - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String value) { - this.description = value; - } - - public boolean hasHome() { - return this.getHome() != null; - } - - public Location getHome() { - confirmValidHome(); - return (this.home != null) ? this.home.getLocation() : null; - } - - public void setHome(Location home) { - this.home = new LazyLocation(home); - } - - public long getFoundedDate() { - if (this.foundedDate == 0) { - setFoundedDate(System.currentTimeMillis()); - } - return this.foundedDate; - } - - public void setFoundedDate(long newDate) { - this.foundedDate = newDate; - } - - public void confirmValidHome() { - if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getInstance().getFactionAt(new FLocation(this.home.getLocation())) == this)) { - return; - } - - msg("Your faction home has been un-set since it is no longer in your territory."); - this.home = null; - } - - public String getAccountId() { - String aid = "faction-" + this.getId(); - - // We need to override the default money given to players. - if (!Econ.hasAccount(aid)) { - Econ.setBalance(aid, 0); - } - - return aid; - } - - public Integer getPermanentPower() { - return this.permanentPower; - } - - public void setPermanentPower(Integer permanentPower) { - this.permanentPower = permanentPower; - } - - public boolean hasPermanentPower() { - return this.permanentPower != null; - } - - public double getPowerBoost() { - return this.powerBoost; - } - - public void setPowerBoost(double powerBoost) { - this.powerBoost = powerBoost; - } - - public boolean isPowerFrozen() { - int freezeSeconds = SavageFactions.plugin.getConfig().getInt("hcf.powerfreeze", 0); - return freezeSeconds != 0 && System.currentTimeMillis() - lastDeath < freezeSeconds * 1000; - - } - - public long getLastDeath() { - return this.lastDeath; - } - - // -------------------------------------------- // - // F Permissions stuff - // -------------------------------------------- // - - public void setLastDeath(long time) { - this.lastDeath = time; - } - - public int getKills() { - int kills = 0; - for (FPlayer fp : getFPlayers()) { - kills += fp.getKills(); - } - - return kills; - } - - public int getDeaths() { - int deaths = 0; - for (FPlayer fp : getFPlayers()) { - deaths += fp.getDeaths(); - } - - return deaths; - } - - public Access getAccess(Permissable permissable, PermissableAction permissableAction) { - if (permissable == null || permissableAction == null) { - return Access.UNDEFINED; - } - - Map accessMap = permissions.get(permissable); - if (accessMap != null && accessMap.containsKey(permissableAction)) { - return accessMap.get(permissableAction); - } - - return Access.UNDEFINED; - } - - /** - * Get the Access of a player. Will use player's Role if they are a faction member. Otherwise, uses their Relation. - * - * @param player - * @param permissableAction - * @return - */ - public Access getAccess(FPlayer player, PermissableAction permissableAction) { - if (player == null || permissableAction == null) { - return Access.UNDEFINED; - } - - Permissable perm; - - if (player.getFaction() == this) { - perm = player.getRole(); - } else { - perm = player.getFaction().getRelationTo(this); - } - - Map accessMap = permissions.get(perm); - if (accessMap != null && accessMap.containsKey(permissableAction)) { - return accessMap.get(permissableAction); - } - - return Access.UNDEFINED; - } - - public void setPermission(Permissable permissable, PermissableAction permissableAction, Access access) { - Map accessMap = permissions.get(permissable); - if (accessMap == null) { - accessMap = new HashMap<>(); - } - - accessMap.put(permissableAction, access); - } - - public void resetPerms() { - SavageFactions.plugin.log(Level.WARNING, "Resetting permissions for Faction: " + tag); - - permissions.clear(); - - // First populate a map with undefined as the permission for each action. - Map freshMap = new HashMap<>(); - for (PermissableAction permissableAction : PermissableAction.values()) { - freshMap.put(permissableAction, Access.UNDEFINED); - } - - // Put the map in there for each relation. - for (Relation relation : Relation.values()) { - if (relation != Relation.MEMBER) { - permissions.put(relation, new HashMap<>(freshMap)); - } - } - - // And each role. - for (Role role : Role.values()) { - if (role != Role.LEADER) { - permissions.put(role, new HashMap<>(freshMap)); - } - } - } - - public void setDefaultPerms() { - if (!Conf.useCustomDefaultPermissions) return; - Map defaultMap = new HashMap<>(); - for (PermissableAction permissableAction : PermissableAction.values()) { - defaultMap.put(permissableAction, Access.UNDEFINED); - } - // Put the map in there for each relation. - for (Relation relation : Relation.values()) { - if (relation != Relation.MEMBER) { - if (!Conf.defaultFactionPermissions.containsKey(relation.nicename)) - permissions.put(relation, new HashMap<>(defaultMap)); - else - permissions.put(relation, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(relation.nicename))); - } - } - - // And each role. - for (Role role : Role.values()) { - if (role != Role.LEADER) { - if (!Conf.defaultFactionPermissions.containsKey(role.nicename)) - permissions.put(role, new HashMap<>(defaultMap)); - else - permissions.put(role, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(role.nicename))); - } - } - } - - /** - * Read only map of Permissions. - * - * @return - */ - public Map> getPermissions() { - return Collections.unmodifiableMap(permissions); - } - - public Role getDefaultRole() { - return this.defaultRole; - } - - public void setDefaultRole(Role role) { - this.defaultRole = role; - } - - // -------------------------------------------- // - // Extra Getters And Setters - // -------------------------------------------- // - public boolean noPvPInTerritory() { - return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); - } - - public boolean noMonstersInTerritory() { - return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); - } - - // ------------------------------- - // Understand the types - // ------------------------------- - - public boolean isNormal() { - return !(this.isWilderness() || this.isSafeZone() || this.isWarZone()); - } - - public boolean isNone() { - return this.getId().equals("0"); - } - - public boolean isWilderness() { - return this.getId().equals("0"); - } - - public boolean isSafeZone() { - return this.getId().equals("-1"); - } - - public boolean isWarZone() { - return this.getId().equals("-2"); - } - - public boolean isPlayerFreeType() { - return this.isSafeZone() || this.isWarZone(); - } - - // ------------------------------- - // Relation and relation colors - // ------------------------------- - - @Override - public String describeTo(RelationParticipator that, boolean ucfirst) { - return RelationUtil.describeThatToMe(this, that, ucfirst); - } - - @Override - public String describeTo(RelationParticipator that) { - return RelationUtil.describeThatToMe(this, that); - } - - @Override - public Relation getRelationTo(RelationParticipator rp) { - return RelationUtil.getRelationTo(this, rp); - } - - @Override - public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { - return RelationUtil.getRelationTo(this, rp, ignorePeaceful); - } - - @Override - public ChatColor getColorTo(RelationParticipator rp) { - return RelationUtil.getColorOfThatToMe(this, rp); - } - - public Relation getRelationWish(Faction otherFaction) { - if (this.relationWish.containsKey(otherFaction.getId())) { - return this.relationWish.get(otherFaction.getId()); - } - return Relation.fromString(SavageFactions.plugin.getConfig().getString("default-relation", "neutral")); // Always default to old behavior. - } - - public void setRelationWish(Faction otherFaction, Relation relation) { - if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)) { - this.relationWish.remove(otherFaction.getId()); - } else { - this.relationWish.put(otherFaction.getId(), relation); - } - } - - public int getRelationCount(Relation relation) { - int count = 0; - for (Faction faction : Factions.getInstance().getAllFactions()) { - if (faction.getRelationTo(this) == relation) { - count++; - } - } - return count; - } - - // ----------------------------------------------// - // Power - // ----------------------------------------------// - public double getPower() { - if (this.hasPermanentPower()) { - return this.getPermanentPower(); - } - - double ret = 0; - for (FPlayer fplayer : fplayers) { - ret += fplayer.getPower(); - } - if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { - ret = Conf.powerFactionMax; - } - return ret + this.powerBoost; - } - - public double getPowerMax() { - if (this.hasPermanentPower()) { - return this.getPermanentPower(); - } - - double ret = 0; - for (FPlayer fplayer : fplayers) { - ret += fplayer.getPowerMax(); - } - if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { - ret = Conf.powerFactionMax; - } - return ret + this.powerBoost; - } - - public int getPowerRounded() { - return (int) Math.round(this.getPower()); - } - - public int getPowerMaxRounded() { - return (int) Math.round(this.getPowerMax()); - } - - public int getLandRounded() { - return Board.getInstance().getFactionCoordCount(this); - } - - public int getLandRoundedInWorld(String worldName) { - return Board.getInstance().getFactionCoordCountInWorld(this, worldName); - } - - public boolean hasLandInflation() { - return this.getLandRounded() > this.getPowerRounded(); - } - - // ------------------------------- - // FPlayers - // ------------------------------- - - // maintain the reference list of FPlayers in this faction - public void refreshFPlayers() { - fplayers.clear(); - if (this.isPlayerFreeType()) { - return; - } - - for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { - if (fplayer.getFactionId().equalsIgnoreCase(id)) { - fplayers.add(fplayer); - } - } - } - - public boolean addFPlayer(FPlayer fplayer) { - return !this.isPlayerFreeType() && fplayers.add(fplayer); - } - - public boolean removeFPlayer(FPlayer fplayer) { - return !this.isPlayerFreeType() && fplayers.remove(fplayer); - } - - public int getSize() { - return fplayers.size(); - } - - public Set getFPlayers() { - // return a shallow copy of the FPlayer list, to prevent tampering and - // concurrency issues - return new HashSet<>(fplayers); - } - - public Set getFPlayersWhereOnline(boolean online) { - Set ret = new HashSet<>(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.isOnline() == online) { - ret.add(fplayer); - } - } - - return ret; - } - - public Set getFPlayersWhereOnline(boolean online, FPlayer viewer) { - Set ret = new HashSet<>(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer viewed : fplayers) { - // Add if their online status is what we want - if (viewed.isOnline() == online) { - // If we want online, check to see if we are able to see this player - // This checks if they are in vanish. - if (online - && viewed.getPlayer() != null - && viewer.getPlayer() != null - && viewer.getPlayer().canSee(viewed.getPlayer())) { - ret.add(viewed); - // If we want offline, just add them. - // Prob a better way to do this but idk. - } else if (!online) { - ret.add(viewed); - } - } - } - - return ret; - } - - - public FPlayer getFPlayerAdmin() { - if (!this.isNormal()) { - return null; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.getRole() == Role.LEADER) { - return fplayer; - } - } - return null; - } - - public FPlayer getFPlayerLeader() { - return getFPlayerAdmin(); - } - - public ArrayList getFPlayersWhereRole(Role role) { - ArrayList ret = new ArrayList<>(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.getRole() == role) { - ret.add(fplayer); - } - } - - return ret; - } - - public ArrayList getOnlinePlayers() { - ArrayList ret = new ArrayList<>(); - if (this.isPlayerFreeType()) { - return ret; - } - - for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fplayer.getFaction() == this) { - ret.add(player); - } - } - - return ret; - } - - // slightly faster check than getOnlinePlayers() if you just want to see if - // there are any players online - public boolean hasPlayersOnline() { - // only real factions can have players online, not safe zone / war zone - if (this.isPlayerFreeType()) { - return false; - } - - for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fplayer != null && fplayer.getFaction() == this) { - return true; - } - } - - // even if all players are technically logged off, maybe someone was on - // recently enough to not consider them officially offline yet - return Conf.considerFactionsReallyOfflineAfterXMinutes > 0 && System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000); - } - - public void memberLoggedOff() { - if (this.isNormal()) { - lastPlayerLoggedOffTime = System.currentTimeMillis(); - } - } - - // used when current leader is about to be removed from the faction; - // promotes new leader, or disbands faction if no other members left - @Override - public void promoteNewLeader() { - promoteNewLeader(false); - } - - @Override - public void promoteNewLeader(boolean autoLeave) { - if (!this.isNormal()) { - return; - } - if (this.isPermanent() && Conf.permanentFactionsDisableLeaderPromotion) { - return; - } - - FPlayer oldLeader = this.getFPlayerAdmin(); - - // get list of moderators, or list of normal members if there are no moderators - ArrayList replacements = this.getFPlayersWhereRole(Role.MODERATOR); - if (replacements == null || replacements.isEmpty()) { - replacements = this.getFPlayersWhereRole(Role.NORMAL); - } - - if (replacements == null || replacements.isEmpty()) { // faction admin is the only member; one-man faction - if (this.isPermanent()) { - if (oldLeader != null) { - oldLeader.setRole(Role.NORMAL); - } - return; - } - - // no members left and faction isn't permanent, so disband it - if (Conf.logFactionDisband) { - SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") has been disbanded since it has no members left" + (autoLeave ? " and by inactivity" : "") + "."); - } - - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg("The faction %s was disbanded.", this.getTag(fplayer)); - } - - FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), autoLeave ? PlayerDisbandReason.INACTIVITY : PlayerDisbandReason.LEAVE); - Bukkit.getPluginManager().callEvent(disbandEvent); - - Factions.getInstance().removeFaction(getId()); - } else { // promote new faction admin - if (oldLeader != null) { - oldLeader.setRole(Role.NORMAL); - } - replacements.get(0).setRole(Role.LEADER); - //TODO:TL - this.msg("Faction admin %s has been removed. %s has been promoted as the new faction admin.", oldLeader == null ? "" : oldLeader.getName(), replacements.get(0).getName()); - SavageFactions.plugin.log("Faction " + this.getTag() + " (" + this.getId() + ") admin was removed. Replacement admin: " + replacements.get(0).getName()); - } - } - - // ----------------------------------------------// - // Messages - // ----------------------------------------------// - public void msg(String message, Object... args) { - message = SavageFactions.plugin.txt.parse(message, args); - - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(message); - } - } - - public void msg(TL translation, Object... args) { - msg(translation.toString(), args); - } - - public void sendMessage(String message) { - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(message); - } - } - - public void sendMessage(List messages) { - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(messages); - } - } - - // ----------------------------------------------// - // Ownership of specific claims - // ----------------------------------------------// - - public Map> getClaimOwnership() { - return claimOwnership; - } - - public void clearAllClaimOwnership() { - claimOwnership.clear(); - } - - public void clearClaimOwnership(FLocation loc) { - claimOwnership.remove(loc); - } - - public void clearClaimOwnership(FPlayer player) { - if (id == null || id.isEmpty()) { - return; - } - - Set ownerData; - - for (Entry> entry : claimOwnership.entrySet()) { - ownerData = entry.getValue(); - - if (ownerData == null) { - continue; - } - - Iterator iter = ownerData.iterator(); - while (iter.hasNext()) { - if (iter.next().equals(player.getId())) { - iter.remove(); - } - } - - if (ownerData.isEmpty()) { - claimOwnership.remove(entry.getKey()); - } - } - } - - public int getCountOfClaimsWithOwners() { - return claimOwnership.isEmpty() ? 0 : claimOwnership.size(); - } - - public boolean doesLocationHaveOwnersSet(FLocation loc) { - if (claimOwnership.isEmpty() || !claimOwnership.containsKey(loc)) { - return false; - } - - Set ownerData = claimOwnership.get(loc); - return ownerData != null && !ownerData.isEmpty(); - } - - public boolean isPlayerInOwnerList(FPlayer player, FLocation loc) { - if (claimOwnership.isEmpty()) { - return false; - } - Set ownerData = claimOwnership.get(loc); - return ownerData != null && ownerData.contains(player.getId()); - } - - public void setPlayerAsOwner(FPlayer player, FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - ownerData = new HashSet<>(); - } - ownerData.add(player.getId()); - claimOwnership.put(loc, ownerData); - } - - public void removePlayerAsOwner(FPlayer player, FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - return; - } - ownerData.remove(player.getId()); - claimOwnership.put(loc, ownerData); - } - - public Set getOwnerList(FLocation loc) { - return claimOwnership.get(loc); - } - - public String getOwnerListString(FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null || ownerData.isEmpty()) { - return ""; - } - - StringBuilder ownerList = new StringBuilder(); - - for (String anOwnerData : ownerData) { - if (ownerList.length() > 0) { - ownerList.append(", "); - } - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(anOwnerData)); - //TODO:TL - ownerList.append(offlinePlayer != null ? offlinePlayer.getName() : "null player"); - } - return ownerList.toString(); - } - - public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { - // in own faction, with sufficient role or permission to bypass - // ownership? - if (fplayer.getFaction() == this && (fplayer.getRole().isAtLeast(Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.LEADER) || Permission.OWNERSHIP_BYPASS.has(fplayer.getPlayer()))) { - return true; - } - - // make sure claimOwnership is initialized - if (claimOwnership.isEmpty()) { - return true; - } - - // need to check the ownership list, then - Set ownerData = claimOwnership.get(loc); - - // if no owner list, owner list is empty, or player is in owner list, - // they're allowed - return ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getId()); - } - - // ----------------------------------------------// - // Persistance and entity management - // ----------------------------------------------// - public void remove() { - if (Econ.shouldBeUsed()) { - Econ.setBalance(getAccountId(), 0); - } - - // Clean the board - ((MemoryBoard) Board.getInstance()).clean(id); - - for (FPlayer fPlayer : fplayers) { - fPlayer.resetFactionData(false); - } - } - - public Set getAllClaims() { - return Board.getInstance().getAllClaims(this); - } + public HashMap rules = new HashMap(); + public int tnt; + public Location checkpoint; + public LazyLocation vault; + public HashMap upgrades = new HashMap<>(); + protected String id = null; + protected boolean peacefulExplosionsEnabled; + protected boolean permanent; + protected String tag; + protected String description; + protected boolean open; + protected boolean peaceful; + protected Integer permanentPower; + protected LazyLocation home; + protected long foundedDate; + protected transient long lastPlayerLoggedOffTime; + protected double money; + protected double powerBoost; + protected String paypal; + protected Map relationWish = new HashMap<>(); + protected Map> claimOwnership = new ConcurrentHashMap<>(); + protected transient Set fplayers = new HashSet<>(); + protected Set invites = new HashSet<>(); + protected HashMap> announcements = new HashMap<>(); + protected ConcurrentHashMap warps = new ConcurrentHashMap<>(); + protected ConcurrentHashMap warpPasswords = new ConcurrentHashMap<>(); + protected int maxVaults; + protected Role defaultRole; + protected Map> permissions = new HashMap<>(); + protected Set bans = new HashSet<>(); + protected String player; + Inventory chest; + Map bannerSerialized; + private long lastDeath; + + // -------------------------------------------- // + // Construct + // -------------------------------------------- // + public MemoryFaction() { + } + + public MemoryFaction(String id) { + this.id = id; + this.open = Conf.newFactionsDefaultOpen; + this.tag = "???"; + this.description = TL.GENERIC_DEFAULTDESCRIPTION.toString(); + this.lastPlayerLoggedOffTime = 0; + this.peaceful = false; + this.peacefulExplosionsEnabled = false; + this.permanent = false; + this.money = 0.0; + this.powerBoost = 0.0; + this.foundedDate = System.currentTimeMillis(); + this.maxVaults = Conf.defaultMaxVaults; + this.defaultRole = Role.RECRUIT; + + resetPerms(); // Reset on new Faction so it has default values. + } + + public MemoryFaction(MemoryFaction old) { + id = old.id; + peacefulExplosionsEnabled = old.peacefulExplosionsEnabled; + permanent = old.permanent; + tag = old.tag; + description = old.description; + open = old.open; + foundedDate = old.foundedDate; + peaceful = old.peaceful; + permanentPower = old.permanentPower; + home = old.home; + lastPlayerLoggedOffTime = old.lastPlayerLoggedOffTime; + money = old.money; + powerBoost = old.powerBoost; + relationWish = old.relationWish; + claimOwnership = old.claimOwnership; + fplayers = new HashSet<>(); + invites = old.invites; + announcements = old.announcements; + this.defaultRole = Role.NORMAL; + + resetPerms(); // Reset on new Faction so it has default values. + } + + public HashMap> getAnnouncements() { + return this.announcements; + } + + public void addAnnouncement(FPlayer fPlayer, String msg) { + List list = announcements.containsKey(fPlayer.getId()) ? announcements.get(fPlayer.getId()) : new ArrayList(); + list.add(msg); + announcements.put(fPlayer.getId(), list); + } + + public void sendUnreadAnnouncements(FPlayer fPlayer) { + if (!announcements.containsKey(fPlayer.getId())) { + return; + } + fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_TOP); + for (String s : announcements.get(fPlayer.getPlayer().getUniqueId().toString())) { + fPlayer.sendMessage(s); + } + fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_BOTTOM); + announcements.remove(fPlayer.getId()); + } + + public void removeAnnouncements(FPlayer fPlayer) { + announcements.remove(fPlayer.getId()); + } + + public ConcurrentHashMap getWarps() { + return this.warps; + } + + public LazyLocation getWarp(String name) { + return this.warps.get(name); + } + + public void setWarp(String name, LazyLocation loc) { + this.warps.put(name, loc); + } + + public boolean isWarp(String name) { + return this.warps.containsKey(name); + } + + public boolean removeWarp(String name) { + warpPasswords.remove(name); // remove password no matter what. + return warps.remove(name) != null; + } + + public boolean isWarpPassword(String warp, String password) { + return hasWarpPassword(warp) && warpPasswords.get(warp.toLowerCase()).equals(password); + } + + public String getPaypal() { + return this.paypal; + } + + public void paypalSet(String paypal) { + this.paypal = paypal; + } + + public boolean hasWarpPassword(String warp) { + return warpPasswords.containsKey(warp.toLowerCase()); + } + + public void setWarpPassword(String warp, String password) { + warpPasswords.put(warp.toLowerCase(), password); + } + + public void clearWarps() { + warps.clear(); + } + + public int getMaxVaults() { + return this.maxVaults; + } + + public void setMaxVaults(int value) { + this.maxVaults = value; + } + + public String getFocused() { + return this.player; + } + + public void setFocused(String fp) { + this.player = fp; + } + + public Set getInvites() { + return invites; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void invite(FPlayer fplayer) { + this.invites.add(fplayer.getId()); + } + + public void deinvite(FPlayer fplayer) { + this.invites.remove(fplayer.getId()); + } + + public boolean isInvited(FPlayer fplayer) { + return this.invites.contains(fplayer.getId()); + } + + public void ban(FPlayer target, FPlayer banner) { + BanInfo info = new BanInfo(banner.getId(), target.getId(), System.currentTimeMillis()); + this.bans.add(info); + } + + public void unban(FPlayer player) { + Iterator iter = bans.iterator(); + while (iter.hasNext()) { + if (iter.next().getBanned().equalsIgnoreCase(player.getId())) { + iter.remove(); + } + } + } + + @Override + public void disband(Player disbander) { + disband(disbander, PlayerDisbandReason.PLUGIN); + } + + @Override + public void disband(Player disbander, PlayerDisbandReason reason) { + + boolean disbanderIsConsole = disbander == null; + FPlayer fdisbander = FPlayers.getInstance().getByOfflinePlayer(disbander); + + FactionDisbandEvent disbandEvent = new FactionDisbandEvent(disbander, this.getId(), reason); + Bukkit.getServer().getPluginManager().callEvent(disbandEvent); + if (disbandEvent.isCancelled()) { + return; + } + + // Send FPlayerLeaveEvent for each player in the faction + for (FPlayer fplayer : this.getFPlayers()) { + Bukkit.getServer().getPluginManager().callEvent(new FPlayerLeaveEvent(fplayer, this, FPlayerLeaveEvent.PlayerLeaveReason.DISBAND)); + } + + if (Conf.logFactionDisband) { + //TODO: Format this correctly and translate. + SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") was disbanded by " + (disbanderIsConsole ? "console command" : fdisbander.getName()) + "."); + } + + if (Econ.shouldBeUsed() && !disbanderIsConsole) { + //Give all the faction's money to the disbander + double amount = Econ.getBalance(this.getAccountId()); + Econ.transferMoney(fdisbander, this, fdisbander, amount, false); + + if (amount > 0.0) { + String amountString = Econ.moneyString(amount); + msg(TL.COMMAND_DISBAND_HOLDINGS, amountString); + //TODO: Format this correctly and translate + SavageFactions.plugin.log(fdisbander.getName() + " has been given bank holdings of " + amountString + " from disbanding " + this.getTag() + "."); + } + } + + Factions.getInstance().removeFaction(this.getId()); + FTeamWrapper.applyUpdates(this); + } + + public boolean isBanned(FPlayer player) { + for (BanInfo info : bans) { + if (info.getBanned().equalsIgnoreCase(player.getId())) { + return true; + } + } + + return false; + } + + public Set getBannedPlayers() { + return this.bans; + } + + public String getRule(int index) { + if (rules.size() == 0) return null; + return rules.get(index); + } + + public HashMap getRulesMap() { + return rules; + } + + public void setRule(int index, String rule) { + rules.put(index, rule); + } + + public void removeRule(int index) { + HashMap newRule = rules; + newRule.remove(index); + rules = newRule; + } + + public void addTnt(int amt) { + tnt += amt; + } + + public void takeTnt(int amt) { + tnt -= amt; + } + + public int getTnt() { + return tnt; + } + + + public Location getVault() { + if (vault == null) { + return null; + } + return vault.getLocation(); + } + + public void setVault(Location vaultLocation) { + if (vaultLocation == null) { + vault = null; + return; + } + LazyLocation newlocation = new LazyLocation(vaultLocation); + vault = newlocation; + } + + public int getUpgrade(Upgrade upgrade) { + if (upgrades.keySet().contains(upgrade.toString())) { + return upgrades.get(upgrade.toString()); + } + return 0; + } + + @Override + public Inventory getChestInventory() { + if (chest != null) { + return chest; + } else { + int level = getUpgrade(Upgrade.CHEST); + int size = 9; + if (level == 1) { + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1") * 9; + } else if (level == 2) { + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2") * 9; + } else if (level == 3) { + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3") * 9; + } + + chest = Bukkit.createInventory(null, size, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); + return chest; + + } + + } + + @Override + public void setChestSize(int chestSize) { + ItemStack[] contents = this.getChestInventory().getContents(); + chest = Bukkit.createInventory(null, chestSize, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); + chest.setContents(contents); + } + + + @Override + public void setBannerPattern(ItemStack banner) { + bannerSerialized = banner.serialize(); + } + + @Override + public ItemStack getBanner() { + if (bannerSerialized == null) { + return null; + } + return ItemStack.deserialize(bannerSerialized); + } + + public void setUpgrade(Upgrade upgrade, int level) { + upgrades.put(upgrade.toString(), level); + } + + public Location getCheckpoint() { + return checkpoint; + } + + public void setCheckpoint(Location location) { + checkpoint = location; + } + + public void clearRules() { + rules.clear(); + } + + public void addRule(String rule) { + rules.put(rules.size(), rule); + } + + public boolean getOpen() { + return open; + } + + public void setOpen(boolean isOpen) { + open = isOpen; + } + + public boolean isPeaceful() { + return this.peaceful; + } + + public void setPeaceful(boolean isPeaceful) { + this.peaceful = isPeaceful; + } + + public boolean getPeacefulExplosionsEnabled() { + return this.peacefulExplosionsEnabled; + } + + public void setPeacefulExplosionsEnabled(boolean val) { + peacefulExplosionsEnabled = val; + } + + public boolean noExplosionsInTerritory() { + return this.peaceful && !peacefulExplosionsEnabled; + } + + public boolean isPermanent() { + return permanent || !this.isNormal(); + } + + public void setPermanent(boolean isPermanent) { + permanent = isPermanent; + } + + public String getTag() { + return this.tag; + } + + public void setTag(String str) { + if (Conf.factionTagForceUpperCase) { + str = str.toUpperCase(); + } + this.tag = str; + } + + public String getTag(String prefix) { + return prefix + this.tag; + } + + public String getTag(Faction otherFaction) { + if (otherFaction == null) { + return getTag(); + } + return this.getTag(this.getColorTo(otherFaction).toString()); + } + + public String getTag(FPlayer otherFplayer) { + if (otherFplayer == null) { + return getTag(); + } + return this.getTag(this.getColorTo(otherFplayer).toString()); + } + + public String getComparisonTag() { + return MiscUtil.getComparisonString(this.tag); + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String value) { + this.description = value; + } + + public boolean hasHome() { + return this.getHome() != null; + } + + public Location getHome() { + confirmValidHome(); + return (this.home != null) ? this.home.getLocation() : null; + } + + public void setHome(Location home) { + this.home = new LazyLocation(home); + } + + public long getFoundedDate() { + if (this.foundedDate == 0) { + setFoundedDate(System.currentTimeMillis()); + } + return this.foundedDate; + } + + public void setFoundedDate(long newDate) { + this.foundedDate = newDate; + } + + public void confirmValidHome() { + if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getInstance().getFactionAt(new FLocation(this.home.getLocation())) == this)) { + return; + } + + msg("Your faction home has been un-set since it is no longer in your territory."); + this.home = null; + } + + public String getAccountId() { + String aid = "faction-" + this.getId(); + + // We need to override the default money given to players. + if (!Econ.hasAccount(aid)) { + Econ.setBalance(aid, 0); + } + + return aid; + } + + public Integer getPermanentPower() { + return this.permanentPower; + } + + public void setPermanentPower(Integer permanentPower) { + this.permanentPower = permanentPower; + } + + public boolean hasPermanentPower() { + return this.permanentPower != null; + } + + public double getPowerBoost() { + return this.powerBoost; + } + + public void setPowerBoost(double powerBoost) { + this.powerBoost = powerBoost; + } + + public boolean isPowerFrozen() { + int freezeSeconds = SavageFactions.plugin.getConfig().getInt("hcf.powerfreeze", 0); + return freezeSeconds != 0 && System.currentTimeMillis() - lastDeath < freezeSeconds * 1000; + + } + + public long getLastDeath() { + return this.lastDeath; + } + + // -------------------------------------------- // + // F Permissions stuff + // -------------------------------------------- // + + public void setLastDeath(long time) { + this.lastDeath = time; + } + + public int getKills() { + int kills = 0; + for (FPlayer fp : getFPlayers()) { + kills += fp.getKills(); + } + + return kills; + } + + public int getDeaths() { + int deaths = 0; + for (FPlayer fp : getFPlayers()) { + deaths += fp.getDeaths(); + } + + return deaths; + } + + public Access getAccess(Permissable permissable, PermissableAction permissableAction) { + if (permissable == null || permissableAction == null) { + return Access.UNDEFINED; + } + + Map accessMap = permissions.get(permissable); + if (accessMap != null && accessMap.containsKey(permissableAction)) { + return accessMap.get(permissableAction); + } + + return Access.UNDEFINED; + } + + /** + * Get the Access of a player. Will use player's Role if they are a faction member. Otherwise, uses their Relation. + * + * @param player + * @param permissableAction + * @return + */ + public Access getAccess(FPlayer player, PermissableAction permissableAction) { + if (player == null || permissableAction == null) { + return Access.UNDEFINED; + } + + Permissable perm; + + if (player.getFaction() == this) { + perm = player.getRole(); + } else { + perm = player.getFaction().getRelationTo(this); + } + + Map accessMap = permissions.get(perm); + if (accessMap != null && accessMap.containsKey(permissableAction)) { + return accessMap.get(permissableAction); + } + + return Access.UNDEFINED; + } + + public void setPermission(Permissable permissable, PermissableAction permissableAction, Access access) { + Map accessMap = permissions.get(permissable); + if (accessMap == null) { + accessMap = new HashMap<>(); + } + + accessMap.put(permissableAction, access); + } + + public void resetPerms() { + SavageFactions.plugin.log(Level.WARNING, "Resetting permissions for Faction: " + tag); + + permissions.clear(); + + // First populate a map with undefined as the permission for each action. + Map freshMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + freshMap.put(permissableAction, Access.UNDEFINED); + } + + // Put the map in there for each relation. + for (Relation relation : Relation.values()) { + if (relation != Relation.MEMBER) { + permissions.put(relation, new HashMap<>(freshMap)); + } + } + + // And each role. + for (Role role : Role.values()) { + if (role != Role.LEADER) { + permissions.put(role, new HashMap<>(freshMap)); + } + } + } + + public void setDefaultPerms() { + if (!Conf.useCustomDefaultPermissions) return; + Map defaultMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + defaultMap.put(permissableAction, Access.UNDEFINED); + } + // Put the map in there for each relation. + for (Relation relation : Relation.values()) { + if (relation != Relation.MEMBER) { + if (!Conf.defaultFactionPermissions.containsKey(relation.nicename)) + permissions.put(relation, new HashMap<>(defaultMap)); + else + permissions.put(relation, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(relation.nicename))); + } + } + + // And each role. + for (Role role : Role.values()) { + if (role != Role.LEADER) { + if (!Conf.defaultFactionPermissions.containsKey(role.nicename)) + permissions.put(role, new HashMap<>(defaultMap)); + else + permissions.put(role, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(role.nicename))); + } + } + } + + /** + * Read only map of Permissions. + * + * @return + */ + public Map> getPermissions() { + return Collections.unmodifiableMap(permissions); + } + + public Role getDefaultRole() { + return this.defaultRole; + } + + public void setDefaultRole(Role role) { + this.defaultRole = role; + } + + // -------------------------------------------- // + // Extra Getters And Setters + // -------------------------------------------- // + public boolean noPvPInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); + } + + public boolean noMonstersInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); + } + + // ------------------------------- + // Understand the types + // ------------------------------- + + public boolean isNormal() { + return !(this.isWilderness() || this.isSafeZone() || this.isWarZone()); + } + + public boolean isNone() { + return this.getId().equals("0"); + } + + public boolean isWilderness() { + return this.getId().equals("0"); + } + + public boolean isSafeZone() { + return this.getId().equals("-1"); + } + + public boolean isWarZone() { + return this.getId().equals("-2"); + } + + public boolean isPlayerFreeType() { + return this.isSafeZone() || this.isWarZone(); + } + + // ------------------------------- + // Relation and relation colors + // ------------------------------- + + @Override + public String describeTo(RelationParticipator that, boolean ucfirst) { + return RelationUtil.describeThatToMe(this, that, ucfirst); + } + + @Override + public String describeTo(RelationParticipator that) { + return RelationUtil.describeThatToMe(this, that); + } + + @Override + public Relation getRelationTo(RelationParticipator rp) { + return RelationUtil.getRelationTo(this, rp); + } + + @Override + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { + return RelationUtil.getRelationTo(this, rp, ignorePeaceful); + } + + @Override + public ChatColor getColorTo(RelationParticipator rp) { + return RelationUtil.getColorOfThatToMe(this, rp); + } + + public Relation getRelationWish(Faction otherFaction) { + if (this.relationWish.containsKey(otherFaction.getId())) { + return this.relationWish.get(otherFaction.getId()); + } + return Relation.fromString(SavageFactions.plugin.getConfig().getString("default-relation", "neutral")); // Always default to old behavior. + } + + public void setRelationWish(Faction otherFaction, Relation relation) { + if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)) { + this.relationWish.remove(otherFaction.getId()); + } else { + this.relationWish.put(otherFaction.getId(), relation); + } + } + + public int getRelationCount(Relation relation) { + int count = 0; + for (Faction faction : Factions.getInstance().getAllFactions()) { + if (faction.getRelationTo(this) == relation) { + count++; + } + } + return count; + } + + // ----------------------------------------------// + // Power + // ----------------------------------------------// + public double getPower() { + if (this.hasPermanentPower()) { + return this.getPermanentPower(); + } + + double ret = 0; + for (FPlayer fplayer : fplayers) { + ret += fplayer.getPower(); + } + if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { + ret = Conf.powerFactionMax; + } + return ret + this.powerBoost; + } + + public double getPowerMax() { + if (this.hasPermanentPower()) { + return this.getPermanentPower(); + } + + double ret = 0; + for (FPlayer fplayer : fplayers) { + ret += fplayer.getPowerMax(); + } + if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { + ret = Conf.powerFactionMax; + } + return ret + this.powerBoost; + } + + public int getPowerRounded() { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() { + return (int) Math.round(this.getPowerMax()); + } + + public int getLandRounded() { + return Board.getInstance().getFactionCoordCount(this); + } + + public int getLandRoundedInWorld(String worldName) { + return Board.getInstance().getFactionCoordCountInWorld(this, worldName); + } + + public boolean hasLandInflation() { + return this.getLandRounded() > this.getPowerRounded(); + } + + // ------------------------------- + // FPlayers + // ------------------------------- + + // maintain the reference list of FPlayers in this faction + public void refreshFPlayers() { + fplayers.clear(); + if (this.isPlayerFreeType()) { + return; + } + + for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { + if (fplayer.getFactionId().equalsIgnoreCase(id)) { + fplayers.add(fplayer); + } + } + } + + public boolean addFPlayer(FPlayer fplayer) { + return !this.isPlayerFreeType() && fplayers.add(fplayer); + } + + public boolean removeFPlayer(FPlayer fplayer) { + return !this.isPlayerFreeType() && fplayers.remove(fplayer); + } + + public int getSize() { + return fplayers.size(); + } + + public Set getFPlayers() { + // return a shallow copy of the FPlayer list, to prevent tampering and + // concurrency issues + return new HashSet<>(fplayers); + } + + public Set getFPlayersWhereOnline(boolean online) { + Set ret = new HashSet<>(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.isOnline() == online) { + ret.add(fplayer); + } + } + + return ret; + } + + public Set getFPlayersWhereOnline(boolean online, FPlayer viewer) { + Set ret = new HashSet<>(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer viewed : fplayers) { + // Add if their online status is what we want + if (viewed.isOnline() == online) { + // If we want online, check to see if we are able to see this player + // This checks if they are in vanish. + if (online + && viewed.getPlayer() != null + && viewer.getPlayer() != null + && viewer.getPlayer().canSee(viewed.getPlayer())) { + ret.add(viewed); + // If we want offline, just add them. + // Prob a better way to do this but idk. + } else if (!online) { + ret.add(viewed); + } + } + } + + return ret; + } + + + public FPlayer getFPlayerAdmin() { + if (!this.isNormal()) { + return null; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.getRole() == Role.LEADER) { + return fplayer; + } + } + return null; + } + + public FPlayer getFPlayerLeader() { + return getFPlayerAdmin(); + } + + public ArrayList getFPlayersWhereRole(Role role) { + ArrayList ret = new ArrayList<>(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.getRole() == role) { + ret.add(fplayer); + } + } + + return ret; + } + + public ArrayList getOnlinePlayers() { + ArrayList ret = new ArrayList<>(); + if (this.isPlayerFreeType()) { + return ret; + } + + for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer.getFaction() == this) { + ret.add(player); + } + } + + return ret; + } + + // slightly faster check than getOnlinePlayers() if you just want to see if + // there are any players online + public boolean hasPlayersOnline() { + // only real factions can have players online, not safe zone / war zone + if (this.isPlayerFreeType()) { + return false; + } + + for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer != null && fplayer.getFaction() == this) { + return true; + } + } + + // even if all players are technically logged off, maybe someone was on + // recently enough to not consider them officially offline yet + return Conf.considerFactionsReallyOfflineAfterXMinutes > 0 && System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000); + } + + public void memberLoggedOff() { + if (this.isNormal()) { + lastPlayerLoggedOffTime = System.currentTimeMillis(); + } + } + + // used when current leader is about to be removed from the faction; + // promotes new leader, or disbands faction if no other members left + @Override + public void promoteNewLeader() { + promoteNewLeader(false); + } + + @Override + public void promoteNewLeader(boolean autoLeave) { + if (!this.isNormal()) { + return; + } + if (this.isPermanent() && Conf.permanentFactionsDisableLeaderPromotion) { + return; + } + + FPlayer oldLeader = this.getFPlayerAdmin(); + + // get list of moderators, or list of normal members if there are no moderators + ArrayList replacements = this.getFPlayersWhereRole(Role.MODERATOR); + if (replacements == null || replacements.isEmpty()) { + replacements = this.getFPlayersWhereRole(Role.NORMAL); + } + + if (replacements == null || replacements.isEmpty()) { // faction admin is the only member; one-man faction + if (this.isPermanent()) { + if (oldLeader != null) { + oldLeader.setRole(Role.NORMAL); + } + return; + } + + // no members left and faction isn't permanent, so disband it + if (Conf.logFactionDisband) { + SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") has been disbanded since it has no members left" + (autoLeave ? " and by inactivity" : "") + "."); + } + + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg("The faction %s was disbanded.", this.getTag(fplayer)); + } + + FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), autoLeave ? PlayerDisbandReason.INACTIVITY : PlayerDisbandReason.LEAVE); + Bukkit.getPluginManager().callEvent(disbandEvent); + + Factions.getInstance().removeFaction(getId()); + } else { // promote new faction admin + if (oldLeader != null) { + oldLeader.setRole(Role.NORMAL); + } + replacements.get(0).setRole(Role.LEADER); + //TODO:TL + this.msg("Faction admin %s has been removed. %s has been promoted as the new faction admin.", oldLeader == null ? "" : oldLeader.getName(), replacements.get(0).getName()); + SavageFactions.plugin.log("Faction " + this.getTag() + " (" + this.getId() + ") admin was removed. Replacement admin: " + replacements.get(0).getName()); + } + } + + // ----------------------------------------------// + // Messages + // ----------------------------------------------// + public void msg(String message, Object... args) { + message = SavageFactions.plugin.txt.parse(message, args); + + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(message); + } + } + + public void msg(TL translation, Object... args) { + msg(translation.toString(), args); + } + + public void sendMessage(String message) { + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(message); + } + } + + public void sendMessage(List messages) { + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(messages); + } + } + + // ----------------------------------------------// + // Ownership of specific claims + // ----------------------------------------------// + + public Map> getClaimOwnership() { + return claimOwnership; + } + + public void clearAllClaimOwnership() { + claimOwnership.clear(); + } + + public void clearClaimOwnership(FLocation loc) { + claimOwnership.remove(loc); + } + + public void clearClaimOwnership(FPlayer player) { + if (id == null || id.isEmpty()) { + return; + } + + Set ownerData; + + for (Entry> entry : claimOwnership.entrySet()) { + ownerData = entry.getValue(); + + if (ownerData == null) { + continue; + } + + Iterator iter = ownerData.iterator(); + while (iter.hasNext()) { + if (iter.next().equals(player.getId())) { + iter.remove(); + } + } + + if (ownerData.isEmpty()) { + claimOwnership.remove(entry.getKey()); + } + } + } + + public int getCountOfClaimsWithOwners() { + return claimOwnership.isEmpty() ? 0 : claimOwnership.size(); + } + + public boolean doesLocationHaveOwnersSet(FLocation loc) { + if (claimOwnership.isEmpty() || !claimOwnership.containsKey(loc)) { + return false; + } + + Set ownerData = claimOwnership.get(loc); + return ownerData != null && !ownerData.isEmpty(); + } + + public boolean isPlayerInOwnerList(FPlayer player, FLocation loc) { + if (claimOwnership.isEmpty()) { + return false; + } + Set ownerData = claimOwnership.get(loc); + return ownerData != null && ownerData.contains(player.getId()); + } + + public void setPlayerAsOwner(FPlayer player, FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + ownerData = new HashSet<>(); + } + ownerData.add(player.getId()); + claimOwnership.put(loc, ownerData); + } + + public void removePlayerAsOwner(FPlayer player, FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + return; + } + ownerData.remove(player.getId()); + claimOwnership.put(loc, ownerData); + } + + public Set getOwnerList(FLocation loc) { + return claimOwnership.get(loc); + } + + public String getOwnerListString(FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null || ownerData.isEmpty()) { + return ""; + } + + StringBuilder ownerList = new StringBuilder(); + + for (String anOwnerData : ownerData) { + if (ownerList.length() > 0) { + ownerList.append(", "); + } + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(anOwnerData)); + //TODO:TL + ownerList.append(offlinePlayer != null ? offlinePlayer.getName() : "null player"); + } + return ownerList.toString(); + } + + public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { + // in own faction, with sufficient role or permission to bypass + // ownership? + if (fplayer.getFaction() == this && (fplayer.getRole().isAtLeast(Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.LEADER) || Permission.OWNERSHIP_BYPASS.has(fplayer.getPlayer()))) { + return true; + } + + // make sure claimOwnership is initialized + if (claimOwnership.isEmpty()) { + return true; + } + + // need to check the ownership list, then + Set ownerData = claimOwnership.get(loc); + + // if no owner list, owner list is empty, or player is in owner list, + // they're allowed + return ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getId()); + } + + // ----------------------------------------------// + // Persistance and entity management + // ----------------------------------------------// + public void remove() { + if (Econ.shouldBeUsed()) { + Econ.setBalance(getAccountId(), 0); + } + + // Clean the board + ((MemoryBoard) Board.getInstance()).clean(id); + + for (FPlayer fPlayer : fplayers) { + fPlayer.resetFactionData(false); + } + } + + public Set getAllClaims() { + return Board.getInstance().getAllClaims(this); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java index 76d1caee..292f083f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java @@ -13,164 +13,164 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public abstract class MemoryFactions extends Factions { - public final Map factions = new ConcurrentHashMap<>(); - public int nextId = 1; + public final Map factions = new ConcurrentHashMap<>(); + public int nextId = 1; - public void load() { - // Make sure the default neutral faction exists - if (!factions.containsKey("0")) { - Faction faction = generateFactionObject("0"); - factions.put("0", faction); - faction.setTag(TL.WILDERNESS.toString()); - faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); - } else { - Faction faction = factions.get("0"); - if (!faction.getTag().equalsIgnoreCase(TL.WILDERNESS.toString())) { - faction.setTag(TL.WILDERNESS.toString()); - } - if (!faction.getDescription().equalsIgnoreCase(TL.WILDERNESS_DESCRIPTION.toString())) { - faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); - } - } + public void load() { + // Make sure the default neutral faction exists + if (!factions.containsKey("0")) { + Faction faction = generateFactionObject("0"); + factions.put("0", faction); + faction.setTag(TL.WILDERNESS.toString()); + faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("0"); + if (!faction.getTag().equalsIgnoreCase(TL.WILDERNESS.toString())) { + faction.setTag(TL.WILDERNESS.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.WILDERNESS_DESCRIPTION.toString())) { + faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); + } + } - // Make sure the safe zone faction exists - if (!factions.containsKey("-1")) { - Faction faction = generateFactionObject("-1"); - factions.put("-1", faction); - faction.setTag(TL.SAFEZONE.toString()); - faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); - } else { - Faction faction = factions.get("-1"); - if (!faction.getTag().equalsIgnoreCase(TL.SAFEZONE.toString())) { - faction.setTag(TL.SAFEZONE.toString()); - } - if (!faction.getDescription().equalsIgnoreCase(TL.SAFEZONE_DESCRIPTION.toString())) { - faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); - } - // if SafeZone has old pre-1.6.0 name, rename it to remove troublesome " " - if (faction.getTag().contains(" ")) { - faction.setTag(TL.SAFEZONE.toString()); - } - } + // Make sure the safe zone faction exists + if (!factions.containsKey("-1")) { + Faction faction = generateFactionObject("-1"); + factions.put("-1", faction); + faction.setTag(TL.SAFEZONE.toString()); + faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("-1"); + if (!faction.getTag().equalsIgnoreCase(TL.SAFEZONE.toString())) { + faction.setTag(TL.SAFEZONE.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.SAFEZONE_DESCRIPTION.toString())) { + faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); + } + // if SafeZone has old pre-1.6.0 name, rename it to remove troublesome " " + if (faction.getTag().contains(" ")) { + faction.setTag(TL.SAFEZONE.toString()); + } + } - // Make sure the war zone faction exists - if (!factions.containsKey("-2")) { - Faction faction = generateFactionObject("-2"); - factions.put("-2", faction); - faction.setTag(TL.WARZONE.toString()); - faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); - } else { - Faction faction = factions.get("-2"); - if (!faction.getTag().equalsIgnoreCase(TL.WARZONE.toString())) { - faction.setTag(TL.WARZONE.toString()); - } - if (!faction.getDescription().equalsIgnoreCase(TL.WARZONE_DESCRIPTION.toString())) { - faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); - } - // if WarZone has old pre-1.6.0 name, rename it to remove troublesome " " - if (faction.getTag().contains(" ")) { - faction.setTag(TL.WARZONE.toString()); - } - } - } + // Make sure the war zone faction exists + if (!factions.containsKey("-2")) { + Faction faction = generateFactionObject("-2"); + factions.put("-2", faction); + faction.setTag(TL.WARZONE.toString()); + faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("-2"); + if (!faction.getTag().equalsIgnoreCase(TL.WARZONE.toString())) { + faction.setTag(TL.WARZONE.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.WARZONE_DESCRIPTION.toString())) { + faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); + } + // if WarZone has old pre-1.6.0 name, rename it to remove troublesome " " + if (faction.getTag().contains(" ")) { + faction.setTag(TL.WARZONE.toString()); + } + } + } - public Faction getFactionById(String id) { - return factions.get(id); - } + public Faction getFactionById(String id) { + return factions.get(id); + } - public abstract Faction generateFactionObject(String string); + public abstract Faction generateFactionObject(String string); - public Faction getByTag(String str) { - String compStr = MiscUtil.getComparisonString(str); - for (Faction faction : factions.values()) { - if (faction.getComparisonTag().equals(compStr)) { - return faction; - } - } - return null; - } + public Faction getByTag(String str) { + String compStr = MiscUtil.getComparisonString(str); + for (Faction faction : factions.values()) { + if (faction.getComparisonTag().equals(compStr)) { + return faction; + } + } + return null; + } - public Faction getBestTagMatch(String start) { - int best = 0; - start = start.toLowerCase(); - int minlength = start.length(); - Faction bestMatch = null; - for (Faction faction : factions.values()) { - String candidate = faction.getTag(); - candidate = ChatColor.stripColor(candidate); - if (candidate.length() < minlength) { - continue; - } - if (!candidate.toLowerCase().startsWith(start)) { - continue; - } + public Faction getBestTagMatch(String start) { + int best = 0; + start = start.toLowerCase(); + int minlength = start.length(); + Faction bestMatch = null; + for (Faction faction : factions.values()) { + String candidate = faction.getTag(); + candidate = ChatColor.stripColor(candidate); + if (candidate.length() < minlength) { + continue; + } + if (!candidate.toLowerCase().startsWith(start)) { + continue; + } - // The closer to zero the better - int lendiff = candidate.length() - minlength; - if (lendiff == 0) { - return faction; - } - if (lendiff < best || best == 0) { - best = lendiff; - bestMatch = faction; - } - } + // The closer to zero the better + int lendiff = candidate.length() - minlength; + if (lendiff == 0) { + return faction; + } + if (lendiff < best || best == 0) { + best = lendiff; + bestMatch = faction; + } + } - return bestMatch; - } + return bestMatch; + } - public boolean isTagTaken(String str) { - return this.getByTag(str) != null; - } + public boolean isTagTaken(String str) { + return this.getByTag(str) != null; + } - public boolean isValidFactionId(String id) { - return factions.containsKey(id); - } + public boolean isValidFactionId(String id) { + return factions.containsKey(id); + } - public Faction createFaction() { - Faction faction = generateFactionObject(); - factions.put(faction.getId(), faction); - return faction; - } + public Faction createFaction() { + Faction faction = generateFactionObject(); + factions.put(faction.getId(), faction); + return faction; + } - public Set getFactionTags() { - Set tags = new HashSet<>(); - for (Faction faction : factions.values()) { - tags.add(faction.getTag()); - } - return tags; - } + public Set getFactionTags() { + Set tags = new HashSet<>(); + for (Faction faction : factions.values()) { + tags.add(faction.getTag()); + } + return tags; + } - public abstract Faction generateFactionObject(); + public abstract Faction generateFactionObject(); - public void removeFaction(String id) { - factions.remove(id).remove(); - } + public void removeFaction(String id) { + factions.remove(id).remove(); + } - @Override - public ArrayList getAllFactions() { - return new ArrayList<>(factions.values()); - } + @Override + public ArrayList getAllFactions() { + return new ArrayList<>(factions.values()); + } - @Override - public Faction getNone() { - return factions.get("0"); - } + @Override + public Faction getNone() { + return factions.get("0"); + } - @Override - public Faction getWilderness() { - return factions.get("0"); - } + @Override + public Faction getWilderness() { + return factions.get("0"); + } - @Override - public Faction getSafeZone() { - return factions.get("-1"); - } + @Override + public Faction getSafeZone() { + return factions.get("-1"); + } - @Override - public Faction getWarZone() { - return factions.get("-2"); - } + @Override + public Faction getWarZone() { + return factions.get("-2"); + } - public abstract void convertFrom(MemoryFactions old); + public abstract void convertFrom(MemoryFactions old); } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java b/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java index 232c9d21..892b0853 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java @@ -7,24 +7,24 @@ import com.massivecraft.factions.zcore.MPlugin; public class SaveTask implements Runnable { - private static boolean running = false; + private static boolean running = false; - MPlugin p; + MPlugin p; - public SaveTask(MPlugin p) { - this.p = p; - } + public SaveTask(MPlugin p) { + this.p = p; + } - public void run() { - if (!p.getAutoSave() || running) { - return; - } - running = true; - p.preAutoSave(); - Factions.getInstance().forceSave(false); - FPlayers.getInstance().forceSave(false); - Board.getInstance().forceSave(false); - p.postAutoSave(); - running = false; - } + public void run() { + if (!p.getAutoSave() || running) { + return; + } + running = true; + p.preAutoSave(); + Factions.getInstance().forceSave(false); + FPlayers.getInstance().forceSave(false); + Board.getInstance().forceSave(false); + p.postAutoSave(); + running = false; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java index 2ee4d2da..f72c2aac 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java @@ -10,36 +10,36 @@ import java.util.logging.Logger; public class FactionsJSON { - public static void convertTo() { - if (!(Factions.getInstance() instanceof MemoryFactions)) { - return; - } - if (!(FPlayers.getInstance() instanceof MemoryFPlayers)) { - return; - } - if (!(Board.getInstance() instanceof MemoryBoard)) { - return; - } - new BukkitRunnable() { - @Override - public void run() { - Logger logger = SavageFactions.plugin.getLogger(); - logger.info("Beginning Board conversion to JSON"); - new JSONBoard().convertFrom((MemoryBoard) Board.getInstance()); - logger.info("Board Converted"); - logger.info("Beginning FPlayers conversion to JSON"); - new JSONFPlayers().convertFrom((MemoryFPlayers) FPlayers.getInstance()); - logger.info("FPlayers Converted"); - logger.info("Beginning Factions conversion to JSON"); - new JSONFactions().convertFrom((MemoryFactions) Factions.getInstance()); - logger.info("Factions Converted"); - logger.info("Refreshing object caches"); - for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { - Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); - faction.addFPlayer(fPlayer); - } - logger.info("Conversion Complete"); - } - }.runTaskAsynchronously(SavageFactions.plugin); - } + public static void convertTo() { + if (!(Factions.getInstance() instanceof MemoryFactions)) { + return; + } + if (!(FPlayers.getInstance() instanceof MemoryFPlayers)) { + return; + } + if (!(Board.getInstance() instanceof MemoryBoard)) { + return; + } + new BukkitRunnable() { + @Override + public void run() { + Logger logger = SavageFactions.plugin.getLogger(); + logger.info("Beginning Board conversion to JSON"); + new JSONBoard().convertFrom((MemoryBoard) Board.getInstance()); + logger.info("Board Converted"); + logger.info("Beginning FPlayers conversion to JSON"); + new JSONFPlayers().convertFrom((MemoryFPlayers) FPlayers.getInstance()); + logger.info("FPlayers Converted"); + logger.info("Beginning Factions conversion to JSON"); + new JSONFactions().convertFrom((MemoryFactions) Factions.getInstance()); + logger.info("Factions Converted"); + logger.info("Refreshing object caches"); + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); + faction.addFPlayer(fPlayer); + } + logger.info("Conversion Complete"); + } + }.runTaskAsynchronously(SavageFactions.plugin); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java index d2b447ac..618d39d8 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java @@ -16,88 +16,88 @@ import java.util.TreeMap; public class JSONBoard extends MemoryBoard { - private static transient File file = new File(SavageFactions.plugin.getDataFolder(), "board.json"); + private static transient File file = new File(SavageFactions.plugin.getDataFolder(), "board.json"); - // -------------------------------------------- // - // Persistance - // -------------------------------------------- // + // -------------------------------------------- // + // Persistance + // -------------------------------------------- // - public Map> dumpAsSaveFormat() { - Map> worldCoordIds = new HashMap<>(); + public Map> dumpAsSaveFormat() { + Map> worldCoordIds = new HashMap<>(); - String worldName, coords; - String id; + String worldName, coords; + String id; - for (Entry entry : flocationIds.entrySet()) { - worldName = entry.getKey().getWorldName(); - coords = entry.getKey().getCoordString(); - id = entry.getValue(); - if (!worldCoordIds.containsKey(worldName)) { - worldCoordIds.put(worldName, new TreeMap()); - } + for (Entry entry : flocationIds.entrySet()) { + worldName = entry.getKey().getWorldName(); + coords = entry.getKey().getCoordString(); + id = entry.getValue(); + if (!worldCoordIds.containsKey(worldName)) { + worldCoordIds.put(worldName, new TreeMap()); + } - worldCoordIds.get(worldName).put(coords, id); - } + worldCoordIds.get(worldName).put(coords, id); + } - return worldCoordIds; - } + return worldCoordIds; + } - public void loadFromSaveFormat(Map> worldCoordIds) { - flocationIds.clear(); + public void loadFromSaveFormat(Map> worldCoordIds) { + flocationIds.clear(); - String worldName; - String[] coords; - int x, z; - String factionId; + String worldName; + String[] coords; + int x, z; + String factionId; - for (Entry> entry : worldCoordIds.entrySet()) { - worldName = entry.getKey(); - for (Entry entry2 : entry.getValue().entrySet()) { - coords = entry2.getKey().trim().split("[,\\s]+"); - x = Integer.parseInt(coords[0]); - z = Integer.parseInt(coords[1]); - factionId = entry2.getValue(); - flocationIds.put(new FLocation(worldName, x, z), factionId); - } - } - } + for (Entry> entry : worldCoordIds.entrySet()) { + worldName = entry.getKey(); + for (Entry entry2 : entry.getValue().entrySet()) { + coords = entry2.getKey().trim().split("[,\\s]+"); + x = Integer.parseInt(coords[0]); + z = Integer.parseInt(coords[1]); + factionId = entry2.getValue(); + flocationIds.put(new FLocation(worldName, x, z), factionId); + } + } + } - public void forceSave() { - forceSave(true); - } + public void forceSave() { + forceSave(true); + } - public void forceSave(boolean sync) { - DiscUtil.writeCatch(file, SavageFactions.plugin.gson.toJson(dumpAsSaveFormat()), sync); - } + public void forceSave(boolean sync) { + DiscUtil.writeCatch(file, SavageFactions.plugin.gson.toJson(dumpAsSaveFormat()), sync); + } - public boolean load() { - SavageFactions.plugin.log("Loading board from disk"); + public boolean load() { + SavageFactions.plugin.log("Loading board from disk"); - if (!file.exists()) { - SavageFactions.plugin.log("No board to load from disk. Creating new file."); - forceSave(); - return true; - } + if (!file.exists()) { + SavageFactions.plugin.log("No board to load from disk. Creating new file."); + forceSave(); + return true; + } - try { - Type type = new TypeToken>>() { - }.getType(); - Map> worldCoordIds = SavageFactions.plugin.gson.fromJson(DiscUtil.read(file), type); - loadFromSaveFormat(worldCoordIds); - SavageFactions.plugin.log("Loaded " + flocationIds.size() + " board locations"); - } catch (Exception e) { - e.printStackTrace(); - SavageFactions.plugin.log("Failed to load the board from disk."); - return false; - } + try { + Type type = new TypeToken>>() { + }.getType(); + Map> worldCoordIds = SavageFactions.plugin.gson.fromJson(DiscUtil.read(file), type); + loadFromSaveFormat(worldCoordIds); + SavageFactions.plugin.log("Loaded " + flocationIds.size() + " board locations"); + } catch (Exception e) { + e.printStackTrace(); + SavageFactions.plugin.log("Failed to load the board from disk."); + return false; + } - return true; - } + return true; + } - @Override - public void convertFrom(MemoryBoard old) { - this.flocationIds = old.flocationIds; - forceSave(); - Board.instance = this; - } + @Override + public void convertFrom(MemoryBoard old) { + this.flocationIds = old.flocationIds; + forceSave(); + Board.instance = this; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java index ade236a0..d2e0618c 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java @@ -6,20 +6,20 @@ import com.massivecraft.factions.zcore.persist.MemoryFPlayer; public class JSONFPlayer extends MemoryFPlayer { - public JSONFPlayer(MemoryFPlayer arg0) { - super(arg0); - } + public JSONFPlayer(MemoryFPlayer arg0) { + super(arg0); + } - public JSONFPlayer(String id) { - super(id); - } + public JSONFPlayer(String id) { + super(id); + } - @Override - public void remove() { - ((JSONFPlayers) FPlayers.getInstance()).fPlayers.remove(getId()); - } + @Override + public void remove() { + ((JSONFPlayers) FPlayers.getInstance()).fPlayers.remove(getId()); + } - public boolean shouldBeSaved() { - return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); - } + public boolean shouldBeSaved() { + return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java index c6c843ad..9851824a 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java @@ -21,170 +21,170 @@ import java.util.Map.Entry; import java.util.logging.Level; public class JSONFPlayers extends MemoryFPlayers { - // Info on how to persist - private Gson gson; - private File file; + // Info on how to persist + private Gson gson; + private File file; - public JSONFPlayers() { - file = new File(SavageFactions.plugin.getDataFolder(), "players.json"); - gson = SavageFactions.plugin.gson; - } + public JSONFPlayers() { + file = new File(SavageFactions.plugin.getDataFolder(), "players.json"); + gson = SavageFactions.plugin.gson; + } - public Gson getGson() { - return gson; - } + public Gson getGson() { + return gson; + } - public void setGson(Gson gson) { - this.gson = gson; - } + public void setGson(Gson gson) { + this.gson = gson; + } - public void convertFrom(MemoryFPlayers old) { - this.fPlayers.putAll(Maps.transformValues(old.fPlayers, new Function() { - @Override - public JSONFPlayer apply(FPlayer arg0) { - return new JSONFPlayer((MemoryFPlayer) arg0); - } - })); - forceSave(); - FPlayers.instance = this; - } + public void convertFrom(MemoryFPlayers old) { + this.fPlayers.putAll(Maps.transformValues(old.fPlayers, new Function() { + @Override + public JSONFPlayer apply(FPlayer arg0) { + return new JSONFPlayer((MemoryFPlayer) arg0); + } + })); + forceSave(); + FPlayers.instance = this; + } - public void forceSave() { - forceSave(true); - } + public void forceSave() { + forceSave(true); + } - public void forceSave(boolean sync) { - final Map entitiesThatShouldBeSaved = new HashMap<>(); - for (FPlayer entity : this.fPlayers.values()) { - if (((MemoryFPlayer) entity).shouldBeSaved()) { - entitiesThatShouldBeSaved.put(entity.getId(), (JSONFPlayer) entity); - } - } + public void forceSave(boolean sync) { + final Map entitiesThatShouldBeSaved = new HashMap<>(); + for (FPlayer entity : this.fPlayers.values()) { + if (((MemoryFPlayer) entity).shouldBeSaved()) { + entitiesThatShouldBeSaved.put(entity.getId(), (JSONFPlayer) entity); + } + } - saveCore(file, entitiesThatShouldBeSaved, sync); - } + saveCore(file, entitiesThatShouldBeSaved, sync); + } - private boolean saveCore(File target, Map data, boolean sync) { - return DiscUtil.writeCatch(target, this.gson.toJson(data), sync); - } + private boolean saveCore(File target, Map data, boolean sync) { + return DiscUtil.writeCatch(target, this.gson.toJson(data), sync); + } - public void load() { - Map fplayers = this.loadCore(); - if (fplayers == null) { - return; - } - this.fPlayers.clear(); - this.fPlayers.putAll(fplayers); - SavageFactions.plugin.log("Loaded " + fPlayers.size() + " players"); - } + public void load() { + Map fplayers = this.loadCore(); + if (fplayers == null) { + return; + } + this.fPlayers.clear(); + this.fPlayers.putAll(fplayers); + SavageFactions.plugin.log("Loaded " + fPlayers.size() + " players"); + } - private Map loadCore() { - if (!this.file.exists()) { - return new HashMap<>(); - } + private Map loadCore() { + if (!this.file.exists()) { + return new HashMap<>(); + } - String content = DiscUtil.readCatch(this.file); - if (content == null) { - return null; - } + String content = DiscUtil.readCatch(this.file); + if (content == null) { + return null; + } - Map data = this.gson.fromJson(content, new TypeToken>() { - }.getType()); - Set list = new HashSet<>(); - Set invalidList = new HashSet<>(); - for (Entry entry : data.entrySet()) { - String key = entry.getKey(); - entry.getValue().setId(key); - if (doesKeyNeedMigration(key)) { - if (!isKeyInvalid(key)) { - list.add(key); - } else { - invalidList.add(key); - } - } - } + Map data = this.gson.fromJson(content, new TypeToken>() { + }.getType()); + Set list = new HashSet<>(); + Set invalidList = new HashSet<>(); + for (Entry entry : data.entrySet()) { + String key = entry.getKey(); + entry.getValue().setId(key); + if (doesKeyNeedMigration(key)) { + if (!isKeyInvalid(key)) { + list.add(key); + } else { + invalidList.add(key); + } + } + } - if (list.size() > 0) { - // We've got some converting to do! - Bukkit.getLogger().log(Level.INFO, "Factions is now updating players.json"); + if (list.size() > 0) { + // We've got some converting to do! + Bukkit.getLogger().log(Level.INFO, "Factions is now updating players.json"); - // First we'll make a backup, because god forbid anybody heed a - // warning - File file = new File(this.file.getParentFile(), "players.json.old"); - try { - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - saveCore(file, data, true); - Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); + // First we'll make a backup, because god forbid anybody heed a + // warning + File file = new File(this.file.getParentFile(), "players.json.old"); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + saveCore(file, data, true); + Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); - // Start fetching those UUIDs - Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + list.size() + " old player names to UUID. This may take a while."); - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); - try { - Map response = fetcher.call(); - for (String s : list) { - // Are we missing any responses? - if (!response.containsKey(s)) { - // They don't have a UUID so they should just be removed - invalidList.add(s); - } - } - for (String value : response.keySet()) { - // For all the valid responses, let's replace their old - // named entry with a UUID key - String id = response.get(value).toString(); + // Start fetching those UUIDs + Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + list.size() + " old player names to UUID. This may take a while."); + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); + try { + Map response = fetcher.call(); + for (String s : list) { + // Are we missing any responses? + if (!response.containsKey(s)) { + // They don't have a UUID so they should just be removed + invalidList.add(s); + } + } + for (String value : response.keySet()) { + // For all the valid responses, let's replace their old + // named entry with a UUID key + String id = response.get(value).toString(); - JSONFPlayer player = data.get(value); + JSONFPlayer player = data.get(value); - if (player == null) { - // The player never existed here, and shouldn't persist - invalidList.add(value); - continue; - } + if (player == null) { + // The player never existed here, and shouldn't persist + invalidList.add(value); + continue; + } - player.setId(id); // Update the object so it knows + player.setId(id); // Update the object so it knows - data.remove(value); // Out with the old... - data.put(id, player); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - if (invalidList.size() > 0) { - for (String name : invalidList) { - // Remove all the invalid names we collected - data.remove(name); - } - Bukkit.getLogger().log(Level.INFO, "While converting we found names that either don't have a UUID or aren't players and removed them from storage."); - Bukkit.getLogger().log(Level.INFO, "The following names were detected as being invalid: " + StringUtils.join(invalidList, ", ")); - } - saveCore(this.file, data, true); // Update the - // flatfile - Bukkit.getLogger().log(Level.INFO, "Done converting players.json to UUID."); - } - return data; - } + data.remove(value); // Out with the old... + data.put(id, player); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + if (invalidList.size() > 0) { + for (String name : invalidList) { + // Remove all the invalid names we collected + data.remove(name); + } + Bukkit.getLogger().log(Level.INFO, "While converting we found names that either don't have a UUID or aren't players and removed them from storage."); + Bukkit.getLogger().log(Level.INFO, "The following names were detected as being invalid: " + StringUtils.join(invalidList, ", ")); + } + saveCore(this.file, data, true); // Update the + // flatfile + Bukkit.getLogger().log(Level.INFO, "Done converting players.json to UUID."); + } + return data; + } - private boolean doesKeyNeedMigration(String key) { - if (!key.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { - // Not a valid UUID.. - // Valid playername, we'll mark this as one for conversion - // to UUID - return key.matches("[a-zA-Z0-9_]{2,16}"); - } - return false; - } + private boolean doesKeyNeedMigration(String key) { + if (!key.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { + // Not a valid UUID.. + // Valid playername, we'll mark this as one for conversion + // to UUID + return key.matches("[a-zA-Z0-9_]{2,16}"); + } + return false; + } - private boolean isKeyInvalid(String key) { - return !key.matches("[a-zA-Z0-9_]{2,16}"); - } + private boolean isKeyInvalid(String key) { + return !key.matches("[a-zA-Z0-9_]{2,16}"); + } - @Override - public FPlayer generateFPlayer(String id) { - FPlayer player = new JSONFPlayer(id); - this.fPlayers.put(player.getId(), player); - return player; - } + @Override + public FPlayer generateFPlayer(String id) { + FPlayer player = new JSONFPlayer(id); + this.fPlayers.put(player.getId(), player); + return player; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java index af1b4e81..c96e85c9 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java @@ -4,14 +4,14 @@ import com.massivecraft.factions.zcore.persist.MemoryFaction; public class JSONFaction extends MemoryFaction { - public JSONFaction(MemoryFaction arg0) { - super(arg0); - } + public JSONFaction(MemoryFaction arg0) { + super(arg0); + } - public JSONFaction() { - } + public JSONFaction() { + } - public JSONFaction(String id) { - super(id); - } + public JSONFaction(String id) { + super(id); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java index 89ecac94..9d79dfb8 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java @@ -1,253 +1,253 @@ -package com.massivecraft.factions.zcore.persist.json; - -import com.google.common.base.Function; -import com.google.common.collect.Maps; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.massivecraft.factions.FLocation; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.Factions; -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.zcore.persist.MemoryFaction; -import com.massivecraft.factions.zcore.persist.MemoryFactions; -import com.massivecraft.factions.zcore.util.DiscUtil; -import com.massivecraft.factions.zcore.util.UUIDFetcher; -import org.bukkit.Bukkit; - -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.Map.Entry; -import java.util.logging.Level; - -public class JSONFactions extends MemoryFactions { - // Info on how to persist - private final Gson gson; - private final File file; - - public JSONFactions() { - this.file = new File(SavageFactions.plugin.getDataFolder(), "factions.json"); - this.gson = SavageFactions.plugin.gson; - this.nextId = 1; - } - - public Gson getGson() { - return gson; - } - - // -------------------------------------------- // - // CONSTRUCTORS - // -------------------------------------------- // - - public File getFile() { - return file; - } - - public void forceSave() { - forceSave(true); - } - - public void forceSave(boolean sync) { - final Map entitiesThatShouldBeSaved = new HashMap<>(); - for (Faction entity : this.factions.values()) { - entitiesThatShouldBeSaved.put(entity.getId(), (JSONFaction) entity); - } - - saveCore(file, entitiesThatShouldBeSaved, sync); - } - - private boolean saveCore(File target, Map entities, boolean sync) { - return DiscUtil.writeCatch(target, this.gson.toJson(entities), sync); - } - - public void load() { - Map factions = this.loadCore(); - if (factions == null) { - return; - } - this.factions.putAll(factions); - - super.load(); - SavageFactions.plugin.log("Loaded " + factions.size() + " Factions"); - } - - private Map loadCore() { - if (!this.file.exists()) { - return new HashMap<>(); - } - - String content = DiscUtil.readCatch(this.file); - if (content == null) { - return null; - } - - Map data = this.gson.fromJson(content, new TypeToken>() { - }.getType()); - - this.nextId = 1; - // Do we have any names that need updating in claims or invites? - - int needsUpdate = 0; - for (Entry entry : data.entrySet()) { - String id = entry.getKey(); - Faction f = entry.getValue(); - f.setId(id); - this.updateNextIdForId(id); - needsUpdate += whichKeysNeedMigration(f.getInvites()).size(); - for (Set keys : f.getClaimOwnership().values()) { - needsUpdate += whichKeysNeedMigration(keys).size(); - } - } - - if (needsUpdate > 0) { - // We've got some converting to do! - Bukkit.getLogger().log(Level.INFO, "Factions is now updating factions.json"); - - // First we'll make a backup, because god forbid anybody heed a - // warning - File file = new File(this.file.getParentFile(), "factions.json.old"); - try { - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - saveCore(file, data, true); - Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); - - Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + needsUpdate + " old player names to UUID. This may take a while."); - - // Update claim ownership - - for (String string : data.keySet()) { - Faction f = data.get(string); - Map> claims = f.getClaimOwnership(); - for (FLocation key : claims.keySet()) { - Set set = claims.get(key); - - Set list = whichKeysNeedMigration(set); - - if (list.size() > 0) { - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); - try { - Map response = fetcher.call(); - for (String value : response.keySet()) { - // Let's replace their old named entry with a - // UUID key - String id = response.get(value).toString(); - set.remove(value.toLowerCase()); // Out with the - // old... - set.add(id); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - claims.put(key, set); // Update - } - } - } - - // Update invites - - for (String string : data.keySet()) { - Faction f = data.get(string); - Set invites = f.getInvites(); - Set list = whichKeysNeedMigration(invites); - - if (list.size() > 0) { - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); - try { - Map response = fetcher.call(); - for (String value : response.keySet()) { - // Let's replace their old named entry with a UUID - // key - String id = response.get(value).toString(); - invites.remove(value.toLowerCase()); // Out with the - // old... - invites.add(id); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - saveCore(this.file, data, true); // Update the flatfile - Bukkit.getLogger().log(Level.INFO, "Done converting factions.json to UUID."); - } - return data; - } - - private Set whichKeysNeedMigration(Set keys) { - HashSet list = new HashSet<>(); - for (String value : keys) { - if (!value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { - // Not a valid UUID.. - if (value.matches("[a-zA-Z0-9_]{2,16}")) { - // Valid playername, we'll mark this as one for conversion - // to UUID - list.add(value); - } - } - } - return list; - } - - // -------------------------------------------- // - // ID MANAGEMENT - // -------------------------------------------- // - - public String getNextId() { - while (!isIdFree(this.nextId)) { - this.nextId += 1; - } - return Integer.toString(this.nextId); - } - - public boolean isIdFree(String id) { - return !this.factions.containsKey(id); - } - - public boolean isIdFree(int id) { - return this.isIdFree(Integer.toString(id)); - } - - protected synchronized void updateNextIdForId(int id) { - if (this.nextId < id) { - this.nextId = id + 1; - } - } - - protected void updateNextIdForId(String id) { - try { - int idAsInt = Integer.parseInt(id); - this.updateNextIdForId(idAsInt); - } catch (Exception ignored) { - } - } - - @Override - public Faction generateFactionObject() { - String id = getNextId(); - Faction faction = new JSONFaction(id); - updateNextIdForId(id); - return faction; - } - - @Override - public Faction generateFactionObject(String id) { - return new JSONFaction(id); - } - - @Override - public void convertFrom(MemoryFactions old) { - this.factions.putAll(Maps.transformValues(old.factions, new Function() { - @Override - public JSONFaction apply(Faction arg0) { - return new JSONFaction((MemoryFaction) arg0); - } - })); - this.nextId = old.nextId; - forceSave(); - Factions.instance = this; - } -} +package com.massivecraft.factions.zcore.persist.json; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.zcore.persist.MemoryFaction; +import com.massivecraft.factions.zcore.persist.MemoryFactions; +import com.massivecraft.factions.zcore.util.DiscUtil; +import com.massivecraft.factions.zcore.util.UUIDFetcher; +import org.bukkit.Bukkit; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; +import java.util.logging.Level; + +public class JSONFactions extends MemoryFactions { + // Info on how to persist + private final Gson gson; + private final File file; + + public JSONFactions() { + this.file = new File(SavageFactions.plugin.getDataFolder(), "factions.json"); + this.gson = SavageFactions.plugin.gson; + this.nextId = 1; + } + + public Gson getGson() { + return gson; + } + + // -------------------------------------------- // + // CONSTRUCTORS + // -------------------------------------------- // + + public File getFile() { + return file; + } + + public void forceSave() { + forceSave(true); + } + + public void forceSave(boolean sync) { + final Map entitiesThatShouldBeSaved = new HashMap<>(); + for (Faction entity : this.factions.values()) { + entitiesThatShouldBeSaved.put(entity.getId(), (JSONFaction) entity); + } + + saveCore(file, entitiesThatShouldBeSaved, sync); + } + + private boolean saveCore(File target, Map entities, boolean sync) { + return DiscUtil.writeCatch(target, this.gson.toJson(entities), sync); + } + + public void load() { + Map factions = this.loadCore(); + if (factions == null) { + return; + } + this.factions.putAll(factions); + + super.load(); + SavageFactions.plugin.log("Loaded " + factions.size() + " Factions"); + } + + private Map loadCore() { + if (!this.file.exists()) { + return new HashMap<>(); + } + + String content = DiscUtil.readCatch(this.file); + if (content == null) { + return null; + } + + Map data = this.gson.fromJson(content, new TypeToken>() { + }.getType()); + + this.nextId = 1; + // Do we have any names that need updating in claims or invites? + + int needsUpdate = 0; + for (Entry entry : data.entrySet()) { + String id = entry.getKey(); + Faction f = entry.getValue(); + f.setId(id); + this.updateNextIdForId(id); + needsUpdate += whichKeysNeedMigration(f.getInvites()).size(); + for (Set keys : f.getClaimOwnership().values()) { + needsUpdate += whichKeysNeedMigration(keys).size(); + } + } + + if (needsUpdate > 0) { + // We've got some converting to do! + Bukkit.getLogger().log(Level.INFO, "Factions is now updating factions.json"); + + // First we'll make a backup, because god forbid anybody heed a + // warning + File file = new File(this.file.getParentFile(), "factions.json.old"); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + saveCore(file, data, true); + Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); + + Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + needsUpdate + " old player names to UUID. This may take a while."); + + // Update claim ownership + + for (String string : data.keySet()) { + Faction f = data.get(string); + Map> claims = f.getClaimOwnership(); + for (FLocation key : claims.keySet()) { + Set set = claims.get(key); + + Set list = whichKeysNeedMigration(set); + + if (list.size() > 0) { + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); + try { + Map response = fetcher.call(); + for (String value : response.keySet()) { + // Let's replace their old named entry with a + // UUID key + String id = response.get(value).toString(); + set.remove(value.toLowerCase()); // Out with the + // old... + set.add(id); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + claims.put(key, set); // Update + } + } + } + + // Update invites + + for (String string : data.keySet()) { + Faction f = data.get(string); + Set invites = f.getInvites(); + Set list = whichKeysNeedMigration(invites); + + if (list.size() > 0) { + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); + try { + Map response = fetcher.call(); + for (String value : response.keySet()) { + // Let's replace their old named entry with a UUID + // key + String id = response.get(value).toString(); + invites.remove(value.toLowerCase()); // Out with the + // old... + invites.add(id); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + saveCore(this.file, data, true); // Update the flatfile + Bukkit.getLogger().log(Level.INFO, "Done converting factions.json to UUID."); + } + return data; + } + + private Set whichKeysNeedMigration(Set keys) { + HashSet list = new HashSet<>(); + for (String value : keys) { + if (!value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { + // Not a valid UUID.. + if (value.matches("[a-zA-Z0-9_]{2,16}")) { + // Valid playername, we'll mark this as one for conversion + // to UUID + list.add(value); + } + } + } + return list; + } + + // -------------------------------------------- // + // ID MANAGEMENT + // -------------------------------------------- // + + public String getNextId() { + while (!isIdFree(this.nextId)) { + this.nextId += 1; + } + return Integer.toString(this.nextId); + } + + public boolean isIdFree(String id) { + return !this.factions.containsKey(id); + } + + public boolean isIdFree(int id) { + return this.isIdFree(Integer.toString(id)); + } + + protected synchronized void updateNextIdForId(int id) { + if (this.nextId < id) { + this.nextId = id + 1; + } + } + + protected void updateNextIdForId(String id) { + try { + int idAsInt = Integer.parseInt(id); + this.updateNextIdForId(idAsInt); + } catch (Exception ignored) { + } + } + + @Override + public Faction generateFactionObject() { + String id = getNextId(); + Faction faction = new JSONFaction(id); + updateNextIdForId(id); + return faction; + } + + @Override + public Faction generateFactionObject(String id) { + return new JSONFaction(id); + } + + @Override + public void convertFrom(MemoryFactions old) { + this.factions.putAll(Maps.transformValues(old.factions, new Function() { + @Override + public JSONFaction apply(Faction arg0) { + return new JSONFaction((MemoryFaction) arg0); + } + })); + this.nextId = old.nextId; + forceSave(); + Factions.instance = this; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java index eaf37257..fcf2e7ca 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java @@ -1,121 +1,121 @@ -package com.massivecraft.factions.zcore.util; - -import com.massivecraft.factions.SavageFactions; -import org.bukkit.Bukkit; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -public class DiscUtil { - - // -------------------------------------------- // - // CONSTANTS - // -------------------------------------------- // - - private final static String UTF8 = "UTF-8"; - - // -------------------------------------------- // - // BYTE - // -------------------------------------------- // - private static HashMap locks = new HashMap<>(); - - public static byte[] readBytes(File file) throws IOException { - int length = (int) file.length(); - byte[] output = new byte[length]; - InputStream in = new FileInputStream(file); - int offset = 0; - while (offset < length) { - offset += in.read(output, offset, (length - offset)); - } - in.close(); - return output; - } - - // -------------------------------------------- // - // STRING - // -------------------------------------------- // - - public static void writeBytes(File file, byte[] bytes) throws IOException { - FileOutputStream out = new FileOutputStream(file); - out.write(bytes); - out.close(); - } - - public static void write(File file, String content) throws IOException { - writeBytes(file, utf8(content)); - } - - // -------------------------------------------- // - // CATCH - // -------------------------------------------- // - - public static String read(File file) throws IOException { - return utf8(readBytes(file)); - } - - public static boolean writeCatch(final File file, final String content, boolean sync) { - String name = file.getName(); - final Lock lock; - - // Create lock for each file if there isn't already one. - if (locks.containsKey(name)) { - lock = locks.get(name); - } else { - ReadWriteLock rwl = new ReentrantReadWriteLock(); - lock = rwl.writeLock(); - locks.put(name, lock); - } - - if (sync) { - lock.lock(); - try { - write(file, content); - } catch (IOException e) { - e.printStackTrace(); - } finally { - lock.unlock(); - } - } else { - Bukkit.getScheduler().runTaskAsynchronously(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - lock.lock(); - try { - write(file, content); - } catch (IOException e) { - e.printStackTrace(); - } finally { - lock.unlock(); - } - } - }); - } - - return true; // don't really care but for some reason this is a boolean. - } - - public static String readCatch(File file) { - try { - return read(file); - } catch (IOException e) { - return null; - } - } - - // -------------------------------------------- // - // UTF8 ENCODE AND DECODE - // -------------------------------------------- // - - public static byte[] utf8(String string) { - return string.getBytes(StandardCharsets.UTF_8); - } - - public static String utf8(byte[] bytes) { - return new String(bytes, StandardCharsets.UTF_8); - } - +package com.massivecraft.factions.zcore.util; + +import com.massivecraft.factions.SavageFactions; +import org.bukkit.Bukkit; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class DiscUtil { + + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private final static String UTF8 = "UTF-8"; + + // -------------------------------------------- // + // BYTE + // -------------------------------------------- // + private static HashMap locks = new HashMap<>(); + + public static byte[] readBytes(File file) throws IOException { + int length = (int) file.length(); + byte[] output = new byte[length]; + InputStream in = new FileInputStream(file); + int offset = 0; + while (offset < length) { + offset += in.read(output, offset, (length - offset)); + } + in.close(); + return output; + } + + // -------------------------------------------- // + // STRING + // -------------------------------------------- // + + public static void writeBytes(File file, byte[] bytes) throws IOException { + FileOutputStream out = new FileOutputStream(file); + out.write(bytes); + out.close(); + } + + public static void write(File file, String content) throws IOException { + writeBytes(file, utf8(content)); + } + + // -------------------------------------------- // + // CATCH + // -------------------------------------------- // + + public static String read(File file) throws IOException { + return utf8(readBytes(file)); + } + + public static boolean writeCatch(final File file, final String content, boolean sync) { + String name = file.getName(); + final Lock lock; + + // Create lock for each file if there isn't already one. + if (locks.containsKey(name)) { + lock = locks.get(name); + } else { + ReadWriteLock rwl = new ReentrantReadWriteLock(); + lock = rwl.writeLock(); + locks.put(name, lock); + } + + if (sync) { + lock.lock(); + try { + write(file, content); + } catch (IOException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } else { + Bukkit.getScheduler().runTaskAsynchronously(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + lock.lock(); + try { + write(file, content); + } catch (IOException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } + }); + } + + return true; // don't really care but for some reason this is a boolean. + } + + public static String readCatch(File file) { + try { + return read(file); + } catch (IOException e) { + return null; + } + } + + // -------------------------------------------- // + // UTF8 ENCODE AND DECODE + // -------------------------------------------- // + + public static byte[] utf8(String string) { + return string.getBytes(StandardCharsets.UTF_8); + } + + public static String utf8(byte[] bytes) { + return new String(bytes, StandardCharsets.UTF_8); + } + } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java index 3d8a8933..5d457631 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java @@ -10,65 +10,65 @@ import java.util.Map.Entry; public class PermUtil { - public Map permissionDescriptions = new HashMap<>(); + public Map permissionDescriptions = new HashMap<>(); - protected MPlugin p; + protected MPlugin p; - public PermUtil(MPlugin p) { - this.p = p; - this.setup(); - } + public PermUtil(MPlugin p) { + this.p = p; + this.setup(); + } - public String getForbiddenMessage(String perm) { - return p.txt.parse(TL.GENERIC_NOPERMISSION.toString(), getPermissionDescription(perm)); - } + public String getForbiddenMessage(String perm) { + return p.txt.parse(TL.GENERIC_NOPERMISSION.toString(), getPermissionDescription(perm)); + } - /** - * This method hooks into all permission plugins we are supporting - */ - public final void setup() { - for (Permission permission : p.getDescription().getPermissions()) { - //plugin.log("\""+permission.getName()+"\" = \""+permission.getDescription()+"\""); - this.permissionDescriptions.put(permission.getName(), permission.getDescription()); - } - } + /** + * This method hooks into all permission plugins we are supporting + */ + public final void setup() { + for (Permission permission : p.getDescription().getPermissions()) { + //plugin.log("\""+permission.getName()+"\" = \""+permission.getDescription()+"\""); + this.permissionDescriptions.put(permission.getName(), permission.getDescription()); + } + } - public String getPermissionDescription(String perm) { - String desc = permissionDescriptions.get(perm); + public String getPermissionDescription(String perm) { + String desc = permissionDescriptions.get(perm); - return desc != null ? desc : TL.GENERIC_DOTHAT.toString(); - } + return desc != null ? desc : TL.GENERIC_DOTHAT.toString(); + } - /** - * This method tests if me has a certain permission and returns true if me has. Otherwise false - */ - public boolean has(CommandSender me, String perm) { - return me != null && me.hasPermission(perm); - } + /** + * This method tests if me has a certain permission and returns true if me has. Otherwise false + */ + public boolean has(CommandSender me, String perm) { + return me != null && me.hasPermission(perm); + } - public boolean has(CommandSender me, String perm, boolean informSenderIfNot) { - if (has(me, perm)) { - return true; - } else if (informSenderIfNot && me != null) { - me.sendMessage(this.getForbiddenMessage(perm)); - } - return false; - } + public boolean has(CommandSender me, String perm, boolean informSenderIfNot) { + if (has(me, perm)) { + return true; + } else if (informSenderIfNot && me != null) { + me.sendMessage(this.getForbiddenMessage(perm)); + } + return false; + } - public T pickFirstVal(CommandSender me, Map perm2val) { - if (perm2val == null) { - return null; - } - T ret = null; + public T pickFirstVal(CommandSender me, Map perm2val) { + if (perm2val == null) { + return null; + } + T ret = null; - for (Entry entry : perm2val.entrySet()) { - ret = entry.getValue(); - if (has(me, entry.getKey())) { - break; - } - } + for (Entry entry : perm2val.entrySet()) { + ret = entry.getValue(); + if (has(me, entry.getKey())) { + break; + } + } - return ret; - } + return ret; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/Persist.java b/src/main/java/com/massivecraft/factions/zcore/util/Persist.java index 65042cb2..21d3027a 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/Persist.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/Persist.java @@ -10,144 +10,144 @@ import java.util.logging.Level; public class Persist { - private MPlugin p; + private MPlugin p; - public Persist(MPlugin p) { - this.p = p; - } + public Persist(MPlugin p) { + this.p = p; + } - // ------------------------------------------------------------ // - // GET NAME - What should we call this type of object? - // ------------------------------------------------------------ // + // ------------------------------------------------------------ // + // GET NAME - What should we call this type of object? + // ------------------------------------------------------------ // - public static String getName(Class clazz) { - return clazz.getSimpleName().toLowerCase(); - } + public static String getName(Class clazz) { + return clazz.getSimpleName().toLowerCase(); + } - public static String getName(Object o) { - return getName(o.getClass()); - } + public static String getName(Object o) { + return getName(o.getClass()); + } - public static String getName(Type type) { - return getName(type.getClass()); - } + public static String getName(Type type) { + return getName(type.getClass()); + } - // ------------------------------------------------------------ // - // GET FILE - In which file would we like to store this object? - // ------------------------------------------------------------ // + // ------------------------------------------------------------ // + // GET FILE - In which file would we like to store this object? + // ------------------------------------------------------------ // - public File getFile(String name) { - return new File(p.getDataFolder(), name + ".json"); - } + public File getFile(String name) { + return new File(p.getDataFolder(), name + ".json"); + } - public File getFile(Class clazz) { - return getFile(getName(clazz)); - } + public File getFile(Class clazz) { + return getFile(getName(clazz)); + } - public File getFile(Object obj) { - return getFile(getName(obj)); - } + public File getFile(Object obj) { + return getFile(getName(obj)); + } - public File getFile(Type type) { - return getFile(getName(type)); - } + public File getFile(Type type) { + return getFile(getName(type)); + } - // NICE WRAPPERS + // NICE WRAPPERS - public T loadOrSaveDefault(T def, Class clazz) { - return loadOrSaveDefault(def, clazz, getFile(clazz)); - } + public T loadOrSaveDefault(T def, Class clazz) { + return loadOrSaveDefault(def, clazz, getFile(clazz)); + } - public T loadOrSaveDefault(T def, Class clazz, String name) { - return loadOrSaveDefault(def, clazz, getFile(name)); - } + public T loadOrSaveDefault(T def, Class clazz, String name) { + return loadOrSaveDefault(def, clazz, getFile(name)); + } - public T loadOrSaveDefault(T def, Class clazz, File file) { - if (!file.exists()) { - p.log("Creating default: " + file); - this.save(def, file); - return def; - } + public T loadOrSaveDefault(T def, Class clazz, File file) { + if (!file.exists()) { + p.log("Creating default: " + file); + this.save(def, file); + return def; + } - T loaded = this.load(clazz, file); + T loaded = this.load(clazz, file); - if (loaded == null) { - p.log(Level.WARNING, "Using default as I failed to load: " + file); + if (loaded == null) { + p.log(Level.WARNING, "Using default as I failed to load: " + file); - // backup bad file, so user can attempt to recover their changes from it - File backup = new File(file.getPath() + "_bad"); - if (backup.exists()) { - backup.delete(); - } - p.log(Level.WARNING, "Backing up copy of bad file to: " + backup); - file.renameTo(backup); + // backup bad file, so user can attempt to recover their changes from it + File backup = new File(file.getPath() + "_bad"); + if (backup.exists()) { + backup.delete(); + } + p.log(Level.WARNING, "Backing up copy of bad file to: " + backup); + file.renameTo(backup); - return def; - } + return def; + } - return loaded; - } + return loaded; + } - // SAVE + // SAVE - public boolean save(Object instance) { - return save(instance, getFile(instance)); - } + public boolean save(Object instance) { + return save(instance, getFile(instance)); + } - public boolean save(Object instance, String name) { - return save(instance, getFile(name)); - } + public boolean save(Object instance, String name) { + return save(instance, getFile(name)); + } - public boolean save(Object instance, File file) { - return DiscUtil.writeCatch(file, p.gson.toJson(instance), true); - } + public boolean save(Object instance, File file) { + return DiscUtil.writeCatch(file, p.gson.toJson(instance), true); + } - // LOAD BY CLASS + // LOAD BY CLASS - public T load(Class clazz) { - return load(clazz, getFile(clazz)); - } + public T load(Class clazz) { + return load(clazz, getFile(clazz)); + } - public T load(Class clazz, String name) { - return load(clazz, getFile(name)); - } + public T load(Class clazz, String name) { + return load(clazz, getFile(name)); + } - public T load(Class clazz, File file) { - String content = DiscUtil.readCatch(file); - if (content == null) { - return null; - } + public T load(Class clazz, File file) { + String content = DiscUtil.readCatch(file); + if (content == null) { + return null; + } - try { - return p.gson.fromJson(content, clazz); - } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely - p.log(Level.WARNING, ex.getMessage()); - } + try { + return p.gson.fromJson(content, clazz); + } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely + p.log(Level.WARNING, ex.getMessage()); + } - return null; - } + return null; + } - // LOAD BY TYPE - @SuppressWarnings("unchecked") - public T load(Type typeOfT, String name) { - return (T) load(typeOfT, getFile(name)); - } + // LOAD BY TYPE + @SuppressWarnings("unchecked") + public T load(Type typeOfT, String name) { + return (T) load(typeOfT, getFile(name)); + } - @SuppressWarnings("unchecked") - public T load(Type typeOfT, File file) { - String content = DiscUtil.readCatch(file); - if (content == null) { - return null; - } + @SuppressWarnings("unchecked") + public T load(Type typeOfT, File file) { + String content = DiscUtil.readCatch(file); + if (content == null) { + return null; + } - try { - return (T) p.gson.fromJson(content, typeOfT); - } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely - p.log(Level.WARNING, ex.getMessage()); - } + try { + return (T) p.gson.fromJson(content, typeOfT); + } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely + p.log(Level.WARNING, ex.getMessage()); + } - return null; - } + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java index 1f9ffe84..cacba74b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java @@ -1,82 +1,82 @@ -package com.massivecraft.factions.zcore.util; - -import org.bukkit.Effect; -import org.bukkit.Location; - -import java.util.Collection; -import java.util.Random; - -// http://mc.kev009.com/Protocol -// ----------------------------- -// Smoke Directions -// ----------------------------- -// Direction ID Direction -// 0 South - East -// 1 South -// 2 South - West -// 3 East -// 4 (Up or middle ?) -// 5 West -// 6 North - East -// 7 North -// 8 North - West -//----------------------------- - -public class SmokeUtil { - - public static Random random = new Random(); - - // -------------------------------------------- // - // Spawn once - // -------------------------------------------- // - - // Single ======== - public static void spawnSingle(Location location, int direction) { - if (location == null) { - return; - } - location.getWorld().playEffect(location.clone(), Effect.SMOKE, direction); - } - - public static void spawnSingle(Location location) { - spawnSingle(location, 4); - } - - public static void spawnSingleRandom(Location location) { - spawnSingle(location, random.nextInt(9)); - } - - // Simple Cloud ======== - public static void spawnCloudSimple(Location location) { - for (int i = 0; i <= 8; i++) { - spawnSingle(location, i); - } - } - - public static void spawnCloudSimple(Collection locations) { - for (Location location : locations) { - spawnCloudSimple(location); - } - } - - // Random Cloud ======== - public static void spawnCloudRandom(Location location, float thickness) { - int singles = (int) Math.floor(thickness * 9); - for (int i = 0; i < singles; i++) { - spawnSingleRandom(location.clone()); - } - } - - public static void spawnCloudRandom(Collection locations, float thickness) { - for (Location location : locations) { - spawnCloudRandom(location, thickness); - } - } - - // -------------------------------------------- // - // Attach continuous effects to or locations - // -------------------------------------------- // - - // TODO - -} +package com.massivecraft.factions.zcore.util; + +import org.bukkit.Effect; +import org.bukkit.Location; + +import java.util.Collection; +import java.util.Random; + +// http://mc.kev009.com/Protocol +// ----------------------------- +// Smoke Directions +// ----------------------------- +// Direction ID Direction +// 0 South - East +// 1 South +// 2 South - West +// 3 East +// 4 (Up or middle ?) +// 5 West +// 6 North - East +// 7 North +// 8 North - West +//----------------------------- + +public class SmokeUtil { + + public static Random random = new Random(); + + // -------------------------------------------- // + // Spawn once + // -------------------------------------------- // + + // Single ======== + public static void spawnSingle(Location location, int direction) { + if (location == null) { + return; + } + location.getWorld().playEffect(location.clone(), Effect.SMOKE, direction); + } + + public static void spawnSingle(Location location) { + spawnSingle(location, 4); + } + + public static void spawnSingleRandom(Location location) { + spawnSingle(location, random.nextInt(9)); + } + + // Simple Cloud ======== + public static void spawnCloudSimple(Location location) { + for (int i = 0; i <= 8; i++) { + spawnSingle(location, i); + } + } + + public static void spawnCloudSimple(Collection locations) { + for (Location location : locations) { + spawnCloudSimple(location); + } + } + + // Random Cloud ======== + public static void spawnCloudRandom(Location location, float thickness) { + int singles = (int) Math.floor(thickness * 9); + for (int i = 0; i < singles; i++) { + spawnSingleRandom(location.clone()); + } + } + + public static void spawnCloudRandom(Collection locations, float thickness) { + for (Location location : locations) { + spawnCloudRandom(location, thickness); + } + } + + // -------------------------------------------- // + // Attach continuous effects to or locations + // -------------------------------------------- // + + // TODO + +} diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TL.java b/src/main/java/com/massivecraft/factions/zcore/util/TL.java index 8edff483..202c3e83 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TL.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TL.java @@ -26,1018 +26,1018 @@ import java.text.SimpleDateFormat; * changes. */ public enum TL { - /** - * Translation meta - */ - _AUTHOR("misc"), - _RESPONSIBLE("misc"), - _LANGUAGE("English"), - _ENCODING("UTF-8"), - _LOCALE("en_US"), - _REQUIRESUNICODE("false"), - _DEFAULT("true"), - _STATE("complete"), //incomplete, limited, partial, majority, complete - - /** - * Localised translation meta - */ - _LOCAL_AUTHOR("misc"), - _LOCAL_RESPONSIBLE("misc"), - _LOCAL_LANGUAGE("English"), - _LOCAL_REGION("US"), - _LOCAL_STATE("complete"), //And this is the English version. It's not ever going to be not complete. - - /** - * Command translations - */ - - /** - * Messsges for /f help - */ - COMMAND_HELP_NEXTCREATE("Learn how to create a faction on the next page."), - COMMAND_HELP_INVITATIONS("command.help.invitations", "You might want to close it and use invitations:"), - COMMAND_HELP_HOME("And don't forget to set your home:"), - COMMAND_HELP_404("&c&l» &7This page does &cnot &7exist"), - COMMAND_HELP_BANK_1("Your faction has a bank which is used to pay for certain"), //Move to last /f help page - COMMAND_HELP_BANK_2("things, so it will need to have money deposited into it."), //Move to last /f help page - COMMAND_HELP_BANK_3("To learn more, use the money command."), //Move to last /f help page - COMMAND_HELP_PLAYERTITLES("Player titles are just for fun. No rules connected to them."), //Move to last /f help page - COMMAND_HELP_OWNERSHIP_1("Claimed land with ownership set is further protected so"), //Move to last /f help page - COMMAND_HELP_OWNERSHIP_2("that only the owner(s), faction admin, and possibly the"), //Move to last /f help page - COMMAND_HELP_OWNERSHIP_3("faction moderators have full access."), //Move to last /f help page - COMMAND_HELP_RELATIONS_1("Set the relation you WISH to have with another faction."), //Move to last /f help page - COMMAND_HELP_RELATIONS_2("Your default relation with other factions will be neutral."), //Move to last /f help page - COMMAND_HELP_RELATIONS_3("If BOTH factions choose \"ally\" you will be allies."), //Move to last /f help page - COMMAND_HELP_RELATIONS_4("If ONE faction chooses \"enemy\" you will be enemies."), //Move to last /f help page - COMMAND_HELP_RELATIONS_5("You can never hurt members or allies."), //Move to last /f help page - COMMAND_HELP_RELATIONS_6("You can not hurt neutrals in their own territory."), //Move to last /f help page - COMMAND_HELP_RELATIONS_7("You can always hurt enemies and players without faction."), //Move to last /f help page - COMMAND_HELP_RELATIONS_8(""), - COMMAND_HELP_RELATIONS_9("Damage from enemies is reduced in your own territory."), //Move to last /f help page - COMMAND_HELP_RELATIONS_10("When you die you lose power. It is restored over time."), //Move to last /f help page - COMMAND_HELP_RELATIONS_11("The power of a faction is the sum of all member power."), //Move to last /f help page - COMMAND_HELP_RELATIONS_12("The power of a faction determines how much land it can hold."), //Move to last /f help page - COMMAND_HELP_RELATIONS_13("You can claim land from factions with too little power."), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_1("Only faction members can build and destroy in their own"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_2("territory. Usage of the following items is also restricted:"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_3("Door, Chest, Furnace, Dispenser, Diode."), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_4(""), - COMMAND_HELP_PERMISSIONS_5("Make sure to put pressure plates in front of doors for your"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_6("guest visitors. Otherwise they can't get through. You can"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_7("also use this to create member only areas."), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_8("As dispensers are protected, you can create traps without"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_9("worrying about those arrows getting stolen."), //Move to last /f help page - COMMAND_HELP_ADMIN_1("&a&l» &a/f claim safezone \n &7claim land for the Safe Zone"), - COMMAND_HELP_ADMIN_2("&a&l» &a/f claim warzone \n &7claim land for the War Zone"), - COMMAND_HELP_ADMIN_3("&a&l» &a/f autoclaim [safezone|warzone] \n &7take a guess"), - COMMAND_HELP_MOAR_1("Finally some commands for the server admins:"), - COMMAND_HELP_MOAR_2("More commands for server admins:"), - COMMAND_HELP_MOAR_3("Even more commands for server admins:"), - COMMAND_HELP_DESCRIPTION("\n &a&l» &7Display a &ahelp &7page"), - - COMMAND_NEAR_DESCRIPTION("Get nearby faction players in a radius."), - COMMAND_NEAR_DISABLED_MSG("&cThis command is disabled!"), - COMMAND_NEAR_FORMAT("{playername} &c({distance}m)"), - COMMAND_NEAR_USE_MSG("&cFaction members nearby"), - - /** - * Messsges for Faction Admins/Mods - */ - - COMMAND_UPGRADES_DESCRIPTION("&cOpen the Upgrades Menu"), - - COMMAND_ADMIN_NOTMEMBER("&c&l[!] &7%1$s &cis not a member in your faction."), - COMMAND_ADMIN_NOTADMIN("&c&l[!] &cYou are not the faction admin."), - COMMAND_ADMIN_TARGETSELF("'&c&l[!] &cThe target player musn''t be yourself."), - COMMAND_ADMIN_DEMOTES("&c&l[!] &cYou have demoted &7%1$s &cfrom the position of faction admin."), - COMMAND_ADMIN_DEMOTED("&c&l[!] &cYou have been demoted from the position of faction admin by &7%1$s&c"), - COMMAND_ADMIN_PROMOTES("&e&l[!] &eYou have promoted &6%1$s &eto the position of faction admin."), - COMMAND_ADMIN_PROMOTED("&e&l[!] &6%1$s &egave &6%2$s ðe leadership of &6%3$s&e."), - COMMAND_ADMIN_DESCRIPTION("Hand over your admin rights"), - COMMAND_ADMIN_NOMEMBERS("&e&l[!] &cNo one else to promote, please disband faction."), - - COMMAND_AHOME_DESCRIPTION("Send a player to their f home no matter what."), - COMMAND_AHOME_NOHOME("%1$s doesn't have an f home."), - COMMAND_AHOME_SUCCESS("$1%s was sent to their f home."), - COMMAND_AHOME_OFFLINE("%1$s is offline."), - COMMAND_AHOME_TARGET("You were sent to your f home."), - - COMMAND_ANNOUNCE_DESCRIPTION("Announce a message to players in faction."), - - COMMAND_FREECAM_ENEMYINRADIUS("Freecam disabled, An enemy is closeby!"), - COMMAND_FREECAM_OUTSIDEFLIGHT("Please dont leave the flight radius!"), - COMMAND_FREECAM_ENABLED("Freecam is now enabled!"), - COMMAND_FREECAM_DISABLED("Freecam is now disabled"), - COMMAND_FREECAM_DESCRIPTION("Go into spectator mode"), - - - COMMAND_AUTOCLAIM_ENABLED("&c&l[!] &7Now &cauto-claiming&7 land for %1$s."), - COMMAND_AUTOCLAIM_DISABLED("&c&l[!] Auto-claiming&7 of land is now &cdisabled."), - COMMAND_AUTOCLAIM_REQUIREDRANK("&c&l[!] &7You must be &c%1$s&7 to claim land."), - COMMAND_AUTOCLAIM_OTHERFACTION("&c&l[!]&7 You &ccan't &7claim land for &c%1$s&7."), - COMMAND_AUTOCLAIM_DESCRIPTION("Auto-claim land as you walk around"), - - COMMAND_AUTOHELP_HELPFOR("Help for command \""), - - COMMAND_BAN_DESCRIPTION("Ban players from joining your Faction."), - COMMAND_BAN_TARGET("&c&l[!] &7You were &cbanned &7from &c%1$s"), // banned player perspective - COMMAND_BAN_BANNED("&c&l[!] &7%1$s &cbanned &7%2$s"), - COMMAND_BAN_SELF("&c&l[!] &7You may &cnot &7ban &cyourself&7."), - COMMAND_BAN_INSUFFICIENTRANK("&c&l[!] &7Your &crank &7is too low to&c ban &7%1$s"), - COMMAND_BAN_ALREADYBANNED("&c&l[!] &7This player is &calready banned&7!"), - - COMMAND_BANLIST_DESCRIPTION("View a Faction's ban list"), - COMMAND_BANLIST_HEADER("&c&l[!] &7There are &c%d&7 bans for &c%s"), - COMMAND_BANLIST_ENTRY("&7%d. &c%s &r&7// &c%s &r&7// &c%s"), - COMMAND_BANLIST_NOFACTION("&c&l[!] &7You are &cnot &7in a Faction."), - COMMAND_BANLIST_INVALID("&c&l[!] &7The faction &c%s &7does not exist"), - - COMMAND_BOOM_PEACEFULONLY("&c&l[!] &7This command is &conly &7usable by factions which are &cspecifically &7designated as &cpeaceful&7."), - COMMAND_BOOM_TOTOGGLE("to toggle explosions"), - COMMAND_BOOM_FORTOGGLE("for toggling explosions"), - COMMAND_BOOM_ENABLED("&c&l[!] &c%1$s&7 has&c %2$s&7 explosions in your faction's territory."), - COMMAND_BOOM_DESCRIPTION("Toggle explosions (peaceful factions only)"), - - - COMMAND_BYPASS_ENABLE("&e&l[!] &eYou have enabled admin bypass mode. You will be able to build or destroy anywhere."), - COMMAND_BYPASS_ENABLELOG(" has ENABLED admin bypass mode."), - COMMAND_BYPASS_DISABLE("&c&l[!] &cYou have disabled admin bypass mode."), - COMMAND_BYPASS_DISABLELOG(" has DISABLED admin bypass mode."), - COMMAND_BYPASS_DESCRIPTION("Enable admin bypass mode"), - - COMMAND_BANNER_DESCRIPTION("Turn a held banner into a war banner"), - COMMAND_BANNER_NOTENOUGHMONEY("&c&l[!] &7You do&c not&7 have enough money"), - COMMAND_BANNER_MONEYTAKE("&c&l[!] $&c{amount} &7has been taken from your account."), - COMMAND_BANNER_SUCCESS("&c&l[!] &7You have created a &c&lWarBanner!"), - COMMAND_BANNER_DISABLED("&c&l[!] &7Buying&c warbanners&7 is &cdisabled!"), - - COMMAND_TPBANNER_NOTSET("&c&l[!] &7Your faction &cdoes not &7have a &c&lWarBanner &7placed!"), - COMMAND_TPBANNER_SUCCESS("&c&l[!] &cTeleporting &7to your factions's &c&lWarBanner"), - COMMAND_TPBANNER_DESCRIPTION("Teleport to your faction banner"), - - - COMMAND_CHAT_DISABLED("&c&l[!] &7The built in chat channels are &cdisabled &7on this server."), - COMMAND_CHAT_INVALIDMODE("&c&l[!] &cUnrecognised &7chat mode. Please enter either '&da&7','&af&7','&6m&7' or '&fp&7'"), - COMMAND_CHAT_DESCRIPTION("Change chat mode"), - - COMMAND_CHAT_MODE_PUBLIC("&c&l[!] &fPublic &7chat mode."), - COMMAND_CHAT_MODE_ALLIANCE("&c&l[!] &dAlliance &7only chat mode."), - COMMAND_CHAT_MODE_TRUCE("&c&l[!] &5Truce &7only chat mode."), - COMMAND_CHAT_MODE_FACTION("&c&l[!] &aFaction&7 only chat mode."), - COMMAND_CHAT_MODE_MOD("&c&l[!] &dMod &7only chat mode."), - COMMAND_CHAT_MOD_ONLY("&c&l[!] &7Only Mods can talk through this chat mode."), - - COMMAND_CHATSPY_ENABLE("&c&l[!] &7You have &cenabled &7chat spying mode."), - COMMAND_CHATSPY_ENABLELOG(" has ENABLED chat spying mode."), - COMMAND_CHATSPY_DISABLE("&c&l[!] &7You have &cdisabled &7chat spying mode."), - COMMAND_CHATSPY_DISABLELOG(" has DISABLED chat spying mode."), - COMMAND_CHATSPY_DESCRIPTION("Enable admin chat spy mode"), - - COMMAND_CLAIM_INVALIDRADIUS("&c&l[!]&7 If you specify a &cradius&7, it must be at least &c1&7."), - COMMAND_CLAIM_DENIED("&c&l[!]&7 You &cdo not &7have &cpermission&7 to &cclaim&7 in a radius."), - COMMAND_CLAIM_DESCRIPTION("Claim land from where you are standing"), - - COMMAND_CLAIMLINE_INVALIDRADIUS("&c&l[!]&7 If you &cspecify&7 a distance, it must be at least &c1&7."), - COMMAND_CLAIMLINE_DENIED("&c&l[!]&7 You &cdo not &7have&c permission&7 to claim in a line."), - COMMAND_CLAIMLINE_DESCRIPTION("Claim land in a straight line."), - COMMAND_CLAIMLINE_ABOVEMAX("&c&l[!]&7 The &cmaximum&7 limit for claim line is &c%s&7."), - COMMAND_CLAIMLINE_NOTVALID("&c&l[!]&7 &c%s&7 is not a &ccardinal &7direction. You may use &cnorth&7, &ceast&7, &csouth &7or &cwest&7."), - - COMMAND_CONFIG_NOEXIST("&c&l[!]&7 No configuration setting \"&c%1$s&7\" exists."), - COMMAND_CONFIG_SET_TRUE("\" option set to true (enabled)."), - COMMAND_CONFIG_SET_FALSE("\" option set to false (disabled)."), - COMMAND_CONFIG_OPTIONSET("\" option set to "), - COMMAND_CONFIG_COLOURSET("\" color option set to \""), - COMMAND_CONFIG_INTREQUIRED("Cannot set \"%1$s\": An integer (whole number) value required."), - COMMAND_CONFIG_LONGREQUIRED("Cannot set \"%1$s\": A long integer (whole number) value required."), - COMMAND_CONFIG_DOUBLEREQUIRED("Cannot set \"%1$s\": A double (numeric) value required."), - COMMAND_CONFIG_FLOATREQUIRED("Cannot set \"%1$s\": A float (numeric) value required."), - COMMAND_CONFIG_INVALID_COLOUR("Cannot set \"%1$s\": \"%2$s\" is not a valid color."), - COMMAND_CONFIG_INVALID_COLLECTION("\"%1$s\" is not a data collection type which can be modified with this command."), - COMMAND_CONFIG_INVALID_MATERIAL("Cannot change \"%1$s\" set: \"%2$s\" is not a valid material."), - COMMAND_CONFIG_INVALID_TYPESET("\"%1$s\" is not a data type set which can be modified with this command."), - COMMAND_CONFIG_MATERIAL_ADDED("\"%1$s\" set: Material \"%2$s\" added."), - COMMAND_CONFIG_MATERIAL_REMOVED("\"%1$s\" set: Material \"%2$s\" removed."), - COMMAND_CONFIG_SET_ADDED("\"%1$s\" set: \"%2$s\" added."), - COMMAND_CONFIG_SET_REMOVED("\"%1$s\" set: \"%2$s\" removed."), - COMMAND_CONFIG_LOG(" (Command was run by %1$s.)"), - COMMAND_CONFIG_ERROR_SETTING("Error setting configuration setting \"%1$s\" to \"%2$s\"."), - COMMAND_CONFIG_ERROR_MATCHING("Configuration setting \"%1$s\" couldn't be matched, though it should be... please report this error."), - COMMAND_CONFIG_ERROR_TYPE("'%1$s' is of type '%2$s', which cannot be modified with this command."), - COMMAND_CONFIG_DESCRIPTION("Change a conf.json setting"), - - COMMAND_CONVERT_BACKEND_RUNNING("&c&l[!]&7 Already running that backend."), - COMMAND_CONVERT_BACKEND_INVALID("&c&l[!]&7 Invalid backend"), - COMMAND_CONVERT_DESCRIPTION("Convert the plugin backend"), - - COMMAND_COORDS_MESSAGE("&c&l[!] &7{player}&7's coords are &c{x}&7,&c{y}&7,&c{z}&7 in &c{world}"), - COMMAND_COORDS_DESCRIPTION("broadcast your coords to your faction"), - - COMMAND_CHECKPOINT_DISABLED("&c&l[!]&7 You &ccannot&7 use checkpoint while its&c disabled&7!"), - COMMAND_CHECKPOINT_SET("&c&l[!]&7 You have &cset&7 the &cfaction checkpoint&7 at your &cLocation&7."), - COMMAND_CHECKPOINT_GO("&c&l[!]&7 &cTeleporting&7 to &cfaction checkpoint"), - COMMAND_CHECKPOINT_INVALIDLOCATION("&c&l[!]&7 &cInvalid Location!&7 You can &cset&7 checkpoints in &cyour claims&7 or &2wilderness&7."), - COMMAND_CHECKPOINT_NOT_SET("&c&l[!]&7 You have to &cset &7the &cfaction checkpoint&7 first."), - COMMAND_CHECKPOINT_CLAIMED("&c&l[!]&7 Your current &cfaction checkpoint&7 is claimed, set a &cnew &7one!"), - COMMAND_CHECKPOINT_DESCRIPTION("Set or go to your faction checkpoint!"), - - COMMAND_CREATE_MUSTLEAVE("&c&l[!]&7 You must &cleave &7your &ccurrent faction &7first."), - COMMAND_CREATE_INUSE("&c&l[!]&7 That tag is &calready &7in use."), - COMMAND_CREATE_TOCREATE("to create a new faction"), - COMMAND_CREATE_FORCREATE("for creating a new faction"), - COMMAND_CREATE_ERROR("&c&l[!]&7 There was an &cinternal error&7 while trying to create your faction. &cPlease try again&7."), - COMMAND_CREATE_CREATED("&c&l[!]&7 &c%1$s &7created a new faction &c&l%2$s"), - COMMAND_CREATE_YOUSHOULD("&c&l[!]&7 You should now: &c%1$s"), - COMMAND_CREATE_CREATEDLOG(" created a new faction: "), - COMMAND_CREATE_DESCRIPTION("Create a new faction"), - - COMMAND_DEINVITE_CANDEINVITE("&c&l[!]&7 Players you can &cdeinvite: "), - COMMAND_DEINVITE_CLICKTODEINVITE("&c&l[!]&7 Click to &crevoke&7 invite for &c%1$s"), - COMMAND_DEINVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of &c%2$s"), - COMMAND_DEINVITE_MIGHTWANT("&c&l[!]&7 You might want to: &c%1$s"), - COMMAND_DEINVITE_REVOKED("&c&l[!]&7 &7%1$s &crevoked&7 your invitation to &c%2$s&7."), - COMMAND_DEINVITE_REVOKES("&c&l[!]&7 %1$s&c revoked &7%2$s's&c invitation."), - COMMAND_DEINVITE_DESCRIPTION("Remove a pending invitation"), - - COMMAND_DELFWARP_DELETED("&c&l[!]&7 Deleted warp &c%1$s"), - COMMAND_DELFWARP_INVALID("&c&l[!]&7 Couldn't &cfind&7 warp &c%1$s"), - COMMAND_DELFWARP_TODELETE("to delete warp"), - COMMAND_DELFWARP_FORDELETE("for deleting warp"), - COMMAND_DELFWARP_DESCRIPTION("Delete a faction warp"), - - COMMAND_DESCRIPTION_CHANGES("&c&l[!]&7 You have &cchanged&7 the &cdescription&7 for &c%1$s&7 to:"), - COMMAND_DESCRIPTION_CHANGED("&c&l[!]&7 The faction&c %1$s&7 changed their &cdescription &7to:"), - COMMAND_DESCRIPTION_TOCHANGE("to change faction description"), - COMMAND_DESCRIPTION_FORCHANGE("for changing faction description"), - COMMAND_DESCRIPTION_DESCRIPTION("Change the faction description"), - - COMMAND_DISBAND_IMMUTABLE("&c&l[!]&7 &7You &ccannot&7 disband &2Wilderness&7,&e SafeZone&7, or &4WarZone."), - COMMAND_DISBAND_MARKEDPERMANENT("&c&l[!]&7 This faction is designated as&c permanent&7, so you cannot disband it."), - COMMAND_DISBAND_BROADCAST_YOURS("&c&l[!]&7 &c%1$s&7 disbanded your &cfaction."), - COMMAND_DISBAND_BROADCAST_NOTYOURS("&c&l[!]&7 &c%1$s &7disbanded the faction &c%2$s."), - COMMAND_DISBAND_HOLDINGS("&c&l[!]&7 &7You have been given the disbanded &cfaction's bank&7, totaling &c%1$s."), - COMMAND_DISBAND_PLAYER("&c&l[!] &7You have disbanded your &cfaction"), - COMMAND_DISBAND_CONFIRM("&c&l[!]&7 Your Faction has&c {tnt} &7tnt left in the bank, it will be &clost&7 if the faction is &cdisbanded&7. Type&c /f disband &7again within &c10&7 seconds to&c disband&7."), - COMMAND_DISBAND_DESCRIPTION("Disband a faction"), - - COMMAND_FLY_DISABLED("&c&l[!]&7 Sorry, Faction flight is &cdisabled &7on this server"), - COMMAND_FLY_DESCRIPTION("Enter or leave Faction flight mode"), - COMMAND_FLY_CHANGE("&c&l[!]&7 Faction flight &c%1$s"), - COMMAND_FLY_COOLDOWN("&c&l[!]&7 You will &cnot&7 take fall damage for &c{amount}&7 seconds"), - COMMAND_FLY_DAMAGE("&c&l[!]&7 Faction flight &cdisabled&7 due to entering combat"), - COMMAND_FLY_NO_ACCESS("&c&l[!]&7 &cCannot fly &7in territory of %1$s"), - COMMAND_FLY_ENEMY_NEAR("&c&l[!]&7 Flight has been&c disabled&7 an enemy is nearby"), - COMMAND_FLY_CHECK_ENEMY("&c&l[!]&7 Cannot fly here, an enemy is &cnearby"), - COMMAND_FLY_NO_EPEARL("&c&l[!] &7You &ccannot&7 throw enderpearls while flying!"), - - COMMAND_FOCUS_SAMEFACTION("&c[!] You may not focus players in your faction!"), - COMMAND_FOCUS_FOCUSING("&c&l[!] &7Your faction is now focusing &c%s"), - COMMAND_FOCUS_NO_LONGER("&c&l[!] &7Your faction is no longer focusing &c%s"), - COMMAND_FOCUS_DESCRIPTION("Focus a Specific Player"), - - - COMMAND_FWARP_CLICKTOWARP("&c&l[!]&7 Click to &cwarp!"), - COMMAND_FWARP_COMMANDFORMAT("&c&l[!]&7 /f warp &c[password]"), - COMMAND_FWARP_WARPED("&c&l[!]&7 Warped to &c%1$s"), - COMMAND_FWARP_INVALID_WARP("&c&l[!]&7 Couldn't find warp &c%1$s"), - COMMAND_FWARP_TOWARP("to warp"), - COMMAND_FWARP_FORWARPING("for warping"), - COMMAND_FWARP_WARPS("Warps: "), - COMMAND_FWARP_DESCRIPTION("Teleport to a faction warp"), - COMMAND_FWARP_INVALID_PASSWORD("&c&l[!]&7 &cInvalid password!"), - COMMAND_FWARP_PASSWORD_REQUIRED("&c&l[!]&c Warp Password:"), - COMMAND_FWARP_PASSWORD_TIMEOUT("&c&l[!]&7 Warp password &ccanceled"), - - COMMAND_HINT_PERMISSION("&aYou can manage your factions permissions using &7/f perms"), - - COMMAND_HOME_DISABLED("&c&l[!]&7 Sorry, Faction homes are &cdisabled on this server."), - COMMAND_HOME_TELEPORTDISABLED("&c&l[!]&7 Sorry, the ability to &cteleport &7to Faction homes is &cdisabled &7on this server."), - COMMAND_HOME_NOHOME("&c&l[!]&7 Your faction does &cnot &7have a home. "), - COMMAND_HOME_INENEMY("&c&l[!]&7 You &ccannot teleport &7to your &cfaction home&7 while in the territory of an &cenemy faction&7."), - COMMAND_HOME_WRONGWORLD("&c&l[!]&7 You &ccannot &7teleport to your &cfaction home&7 while in a different world."), - COMMAND_HOME_ENEMYNEAR("&c&l[!]&7 You &ccannot teleport&7 to your faction home while an enemy is within &c%s&7 blocks of you."), - COMMAND_HOME_TOTELEPORT("to teleport to your faction home"), - COMMAND_HOME_FORTELEPORT("for teleporting to your faction home"), - COMMAND_HOME_DESCRIPTION("Teleport to the faction home"), - COMMAND_HOME_BLOCKED("&c&l[!] You may not teleport to a home that is claimed by &b%1$s"), - - COMMAND_INSPECT_DISABLED_MSG("&c&l[!]&7 Inspect mode is now &cdisabled."), - COMMAND_INSPECT_DISABLED_NOFAC("&c&l[!]&7 Inspect mode is now &cdisabled,&7 because you &cdo not have a faction!"), - COMMAND_INSPECT_ENABLED("&c&l[!]&7 Inspect mode is now &aEnabled."), - COMMAND_INSPECT_HEADER("&c&m---&7Inspect Data&c&m---&c//&7x:{x},y:{y},z:{z}"), - COMMAND_INSPECT_ROW("&c{time} &7// &c{action} &7// &c{player} &7// &c{block-type}"), - COMMAND_INSPECT_NODATA("&c&l[!]&7 &7No Data was found!"), - COMMAND_INSPECT_NOTINCLAIM("&c&l[!]&7 &7You can &conly&7 inspect in &cyour &7claims!"), - COMMAND_INSPECT_BYPASS("&c&l[!]&7 Inspecting in &cbypass&7 mode"), - COMMAND_INSPECT_DESCRIPTION("Inspect blocks!"), - - COMMAND_INVITE_TOINVITE("to invite someone"), - COMMAND_INVITE_FORINVITE("for inviting someone"), - COMMAND_INVITE_CLICKTOJOIN("Click to join!"), - COMMAND_INVITE_INVITEDYOU(" &chas invited you to join "), - COMMAND_INVITE_INVITED("&c&l[!]&7 &c%1$s&7 invited &c%2$s&7 to your faction."), - COMMAND_INVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of&c %2$s"), - COMMAND_INVITE_ALREADYINVITED("&c&l[!]&7 &c%1$s&7 has already been invited"), - COMMAND_INVITE_DESCRIPTION("Invite a player to your faction"), - COMMAND_INVITE_BANNED("&c&l[!]&7 &7%1$s &cis banned &7from your Faction. &cNot &7sending an invite."), - - COMMAND_JOIN_CANNOTFORCE("&c&l[!]&7 You&c do not&7 have permission to &cmove other players&7 into a faction."), - COMMAND_JOIN_SYSTEMFACTION("&c&l[!]&7 Players may only join &cnormal factions&7. This is a &c&lsystem faction&7."), - COMMAND_JOIN_ALREADYMEMBER("&c&l[!]&7 &c%1$s %2$s already a member of&c %3$s"), - COMMAND_JOIN_ATLIMIT(" &c&l[!]&7 The faction &c%1$s &7is at the limit of&c %2$d&7 members, so&c %3$s&7 cannot currently join."), - COMMAND_JOIN_INOTHERFACTION("&c&l[!]&7 &c%1$s &7must leave&c %2$s &7current faction first."), - COMMAND_JOIN_NEGATIVEPOWER("&c&l[!]&7 &c%1$s &7cannot join a faction with a &cnegative power&7 level."), - COMMAND_JOIN_REQUIRESINVITATION("&c&l[!]&7 This faction &crequires&7 an invitation."), - COMMAND_JOIN_ATTEMPTEDJOIN("&c&l[!]&7 &c%1$s&7 tried to join your faction."), - COMMAND_JOIN_TOJOIN("to join a faction"), - COMMAND_JOIN_FORJOIN("for joining a faction"), - COMMAND_JOIN_SUCCESS("&c&l[!]&7 &c%1$s &7successfully joined &c%2$s."), - COMMAND_JOIN_MOVED("&c&l[!]&7 &c%1$s &7moved you into the faction&c %2$s."), - COMMAND_JOIN_JOINED("&c&l[!]&7 &c%1$s &7joined your faction."), - COMMAND_JOIN_JOINEDLOG("&c&l[!]&7 &c%1$s&7 joined the faction&c %2$s."), - COMMAND_JOIN_MOVEDLOG("&c&l[!]&7 &c%1$s &7moved the player&c %2$s &7into the faction&c %3$s&7."), - COMMAND_JOIN_DESCRIPTION("&a&l» &7Join a faction"), - COMMAND_JOIN_BANNED("&c&l[!]&7 You are &cbanned &7from &c%1$s."), - - COMMAND_KICK_CANDIDATES("&c&l[!]&7 Players you can kick: "), - COMMAND_KICK_CLICKTOKICK("Click to kick "), - COMMAND_KICK_SELF("&c&l[!]&7 You &ccannot &7kick&c yourself&7."), - COMMAND_KICK_NONE("&c&l[!]&7 That player&c is not&7 in a faction."), - COMMAND_KICK_NOTMEMBER("&c&l[!]&7 &c%1$s is not a member of %2$s"), - COMMAND_KICK_INSUFFICIENTRANK("&c&l[!]&7 Your rank is &ctoo low &7to kick this player."), - COMMAND_KICK_NEGATIVEPOWER("&c&l[!]&7 You &ccannot &7kick that member until their power is &apositive&7."), - COMMAND_KICK_TOKICK("to kick someone from the faction"), - COMMAND_KICK_FORKICK("for kicking someone from the faction"), - COMMAND_KICK_FACTION("&c&l[!]&7 %1$s&7 kicked %2$s&c from the faction!"), //message given to faction members - COMMAND_KICK_KICKS("&c&l[!]&7 You kicked &c%1$s&7 from the faction&c %2$s&7!"), //kicker perspective - COMMAND_KICK_KICKED("&c&l[!]&7 &c%1$s &7kicked you from&c %2$s&7!"), //kicked player perspective - COMMAND_KICK_DESCRIPTION("Kick a player from the faction"), - - COMMAND_LIST_FACTIONLIST("&c&l[!]&7 Faction List "), - COMMAND_LIST_TOLIST("to list the factions"), - COMMAND_LIST_FORLIST("for listing the factions"), - COMMAND_LIST_ONLINEFACTIONLESS("Online factionless: "), - COMMAND_LIST_DESCRIPTION("&a&l» &7See a list of the factions"), - - COMMAND_LOCK_LOCKED("&c&l[!]&7 Factions is now&c locked"), - COMMAND_LOCK_UNLOCKED("&c&l[!]&7 Factions in now&a unlocked"), - COMMAND_LOCK_DESCRIPTION("Lock all write stuff. Apparently."), - - COMMAND_LOGINS_TOGGLE("&c&l[!]&7 Set login / logout notifications for Faction members to: &c%s"), - COMMAND_LOGINS_DESCRIPTION("Toggle(?) login / logout notifications for Faction members"), - - COMMAND_LOWPOWER_HEADER("&8&m--------&8&8&m---------"), - COMMAND_LOWPOWER_FORMAT("&c{player} &8(&c{player_power}&8/&c{maxpower}&8)"), - COMMAND_LOWPOWER_DESCRIPTION("Shows a list of players in your faction with lower power levels"), - - COMMAND_MAP_TOSHOW("to show the map"), - COMMAND_MAP_FORSHOW("for showing the map"), - COMMAND_MAP_UPDATE_ENABLED("&c&l[!]&7 Map auto update &aENABLED."), - COMMAND_MAP_UPDATE_DISABLED("&c&l[!]&7 Map auto update &cDISABLED."), - COMMAND_MAP_DESCRIPTION("Show the territory map, and set optional auto update"), - - COMMAND_MAPHEIGHT_DESCRIPTION("&eUpdate the lines that /f map sends"), - COMMAND_MAPHEIGHT_SET("&c&l[!]&7 Set /f map lines to &c&a%1$d"), - COMMAND_MAPHEIGHT_CURRENT("&c&l[!]&7 Current &cmapheight: &a%1$d"), - - COMMAND_MOD_CANDIDATES("&c&l[!]&7 Players you can promote: "), - COMMAND_MOD_CLICKTOPROMOTE("Click to promote "), - COMMAND_MOD_NOTMEMBER("&c&l[!]&7 &c%1$s7 is not a member in your faction."), - COMMAND_MOD_NOTADMIN("&c&l[!]&7 You &care not&7 the faction admin."), - COMMAND_MOD_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), - COMMAND_MOD_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin.&7 Demote them first."), - COMMAND_MOD_REVOKES("&c&l[!]&7 &7You have &cremoved&7 moderator status from &c%1$s."), - COMMAND_MOD_REVOKED("&c&l[!]&7 &c%1$s&7 is &cno longer&7 moderator in your faction."), - COMMAND_MOD_PROMOTES("&c&l[!]&7 &c%1$s&7 was &cpromoted&7 to moderator in your faction."), - COMMAND_MOD_PROMOTED("&c&l[!]&7 You have promoted&c %1$s&7 to moderator."), - COMMAND_MOD_DESCRIPTION("Give or revoke moderator rights"), - - COMMAND_COLEADER_CANDIDATES("&c&l[!]&7 Players you can promote: "), - COMMAND_COLEADER_CLICKTOPROMOTE("Click to promote "), - COMMAND_COLEADER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member&7 in your faction."), - COMMAND_COLEADER_NOTADMIN("&c&l[!]&7 You are&c not&7 the faction admin."), - COMMAND_COLEADER_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), - COMMAND_COLEADER_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin&7. Demote them first."), - COMMAND_COLEADER_REVOKES("&c&l[!]&7 You have removed &ccoleader &7status from&c %1$s&7."), - COMMAND_COLEADER_REVOKED("&c&l[!]&7 &c%1$s&7 is no longer&c coleader &7in your faction."), - COMMAND_COLEADER_PROMOTES("&c&l[!]&7 &c%1$s&7 was promoted to &ccoleader &7in your faction."), - COMMAND_COLEADER_PROMOTED("&c&l[!]&7 You have &cpromoted &7%1$s to &ccoleader."), - COMMAND_COLEADER_DESCRIPTION("Give or revoke coleader rights"), - - COMMAND_MODIFYPOWER_ADDED("&c&l[!]&7 Added &c%1$f &7power to &c%2$s. &7New total rounded power: &c%3$d"), - COMMAND_MODIFYPOWER_DESCRIPTION("Modify the power of a faction/player"), - - COMMAND_MONEY_LONG("&c&l[!]&7 The faction money commands."), - COMMAND_MONEY_DESCRIPTION("Faction money commands"), - - COMMAND_MONEYBALANCE_SHORT("show faction balance"), - COMMAND_MONEYBALANCE_DESCRIPTION("Show your factions current money balance"), - - COMMAND_MONEYDEPOSIT_DESCRIPTION("Deposit money"), - COMMAND_MONEYDEPOSIT_DEPOSITED("&c&l[!]&7 &c%1$s &7deposited&c %2$s&7 in the faction bank:&c %3$s"), - - COMMAND_MONEYTRANSFERFF_DESCRIPTION("Transfer f -> f"), - COMMAND_MONEYTRANSFERFF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred&c %2$s &7from the faction &c\"%3$s\"&7 to the faction&c \"%4$s\"&7"), - - COMMAND_MONEYTRANSFERFP_DESCRIPTION("Transfer f -> plugin"), - COMMAND_MONEYTRANSFERFP_TRANSFER("&c&l[!]&7 &c%1$s &7transferred&c %2$s &7from the faction&c \"%3$s\" &7to the player &c\"%4$s\""), - - COMMAND_MONEYTRANSFERPF_DESCRIPTION("Transfer plugin -> f"), - COMMAND_MONEYTRANSFERPF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred &c%2$s&7 from the player &c\"%3$s\" &7to the faction&c \"%4$s\""), - - COMMAND_MONEYWITHDRAW_DESCRIPTION("Withdraw money"), - COMMAND_MONEYWITHDRAW_WITHDRAW("&c&l[!]&7 &c%1$s&7 withdrew&c %2$s &7from the faction bank:&c %3$s"), - - COMMAND_OPEN_TOOPEN("to open or close the faction"), - COMMAND_OPEN_FOROPEN("for opening or closing the faction"), - COMMAND_OPEN_OPEN("open"), - COMMAND_OPEN_CLOSED("closed"), - COMMAND_OPEN_CHANGES("&c&l[!]&7 &c%1$s&7 changed the faction to &c%2$s&7."), - COMMAND_OPEN_CHANGED("&c&l[!]&7 The faction &c%1$s&7 is now &c%2$s"), - COMMAND_OPEN_DESCRIPTION("Switch if invitation is required to join"), - - COMMAND_OWNER_DISABLED("&c&l[!]&7 Sorry, but &cowned areas &7are &cdisabled &7on this server."), - COMMAND_OWNER_LIMIT("&c&l[!]&7 Sorry, but you have reached the server's &climit&7 of &c%1$d&7 owned areas per faction."), - COMMAND_OWNER_WRONGFACTION("&c&l[!]&7 &7This land is &cnot claimed &7by your faction, so you &ccan't set&7 ownership of it."), - COMMAND_OWNER_NOTCLAIMED("&c&l[!]&7 This land&c is not &7claimed by a faction. Ownership &cis not &7possible."), - COMMAND_OWNER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member &7of this faction."), - COMMAND_OWNER_CLEARED("&c&l[!]&7 You have &ccleared &7ownership for this claimed area."), - COMMAND_OWNER_REMOVED("&c&l[!]&7 You have&c removed ownership &7of this &cclaimed land&7 from &c%1$s&7."), - COMMAND_OWNER_TOSET("to set ownership of claimed land"), - COMMAND_OWNER_FORSET("for setting ownership of claimed land"), - COMMAND_OWNER_ADDED("&c&l[!]&7 You have added &c%1$s&7 to the &cowner list&7 for this claimed land."), - COMMAND_OWNER_DESCRIPTION("Set ownership of claimed land"), - - COMMAND_KILLHOLOGRAMS_DESCRIPTION("Kill holograms in a radius, admin command"), - - COMMAND_OWNERLIST_DISABLED("&c&l[!]&7 &cSorry, &7but owned areas are &cdisabled&7 on this server."),//dup-> - COMMAND_OWNERLIST_WRONGFACTION("&c&l[!]&7 This land &cis not&7 claimed by your faction."),//eq - COMMAND_OWNERLIST_NOTCLAIMED("&c&l[!]&7 This land is not claimed by any faction, thus no owners."),//eq - COMMAND_OWNERLIST_NONE("&c&l[!]&7 No owners are set here; everyone in the faction has access."), - COMMAND_OWNERLIST_OWNERS("&c&l[!]&7 Current owner(s) of this land: %1$s"), - COMMAND_OWNERLIST_DESCRIPTION("List owner(s) of this claimed land"), - - COMMAND_PAYPALSET_DESCRIPTION("&c&l[!] &7Set the email of your faction to claim rewards."), - COMMAND_PAYPALSEE_DESCRIPTION("&c&l[!] &7View a specific factions paypal email with &b/f &b."), - COMMAND_PAYPALSET_CREATED("&c&l[!] &7Make sure to type &b/f &7!"), - COMMAND_PAYPALSET_SUCCESSFUL("&c&l[!] &7Successfully set your factions email - &b%1$s&7."), - COMMAND_PAYPALSEE_FACTION_PAYPAL("&c&l[!] &b%1$s's &7faction has their paypal set to &b%2$s&7."), - COMMAND_PAYPALSEE_FACTION_NOTSET("&c&l[!] &b%1$s's &7paypal has not yet been set!"), - COMMAND_PAYPALSEE_FACTION_NOFACTION("&c&l[!] &b%1$s &7does not have a faction!"), - - COMMAND_PEACEFUL_DESCRIPTION("&c&l[!]&7Set a faction to peaceful"), - COMMAND_PEACEFUL_YOURS("&c&l[!]&7%1$s has %2$s your faction"), - COMMAND_PEACEFUL_OTHER("&c&l[!]&7%s has %s the faction '%s'."), - COMMAND_PEACEFUL_GRANT("&c&l[!]&7 granted peaceful status to"), - COMMAND_PEACEFUL_REVOKE("removed peaceful status from"), - - COMMAND_PERM_DESCRIPTION("&c&l[!]&7&6Edit or list your Faction's permissions."), - COMMAND_PERM_INVALID_RELATION("&c&l[!]&7Invalid relation defined. Try something like&c 'ally'"), - COMMAND_PERM_INVALID_ACCESS("&c&l[!]&7 Invalid access defined. Try something like &c'allow'"), - COMMAND_PERM_INVALID_ACTION("&c&l[!]&7 Invalid action defined. Try something like &c'build'"), - COMMAND_PERM_SET("&c&l[!]&7 Set permission&c %1$s &7to &c%2$s &7for relation&c %3$s"), - COMMAND_PERM_TOP("RCT MEM OFF ALLY TRUCE NEUT ENEMY"), - - COMMAND_PERMANENT_DESCRIPTION("Toggles a permanent faction option"), - COMMAND_PERMANENT_GRANT("&c&l[!]&7 added permanent status to"), - COMMAND_PERMANENT_REVOKE("&c&l[!]&7 removed permanent status from"), - COMMAND_PERMANENT_YOURS("&c&l[!]&7 &c%1$s&7 has &c%2$s&7 your faction"), - COMMAND_PERMANENT_OTHER("&c&l[!]&7 &c%s &7has &c%s &7the faction &c'%s'."), - COMMAND_PROMOTE_TARGET("&c&l[!]&7 You've been &c%1$s&7 to &c%2$s"), - COMMAND_PROMOTE_SUCCESS("&c&l[!]&7 You successfully&c %1$s %2$s &cto&7 %3$s"), - COMMAND_PROMOTE_PROMOTED("promoted"), - COMMAND_PROMOTE_DEMOTED("demoted"), - COMMAND_PROMOTE_COLEADER_ADMIN("&c&l[!]&7 &cColeaders cant promote players to Admin!"), - - COMMAND_PERMANENTPOWER_DESCRIPTION("Toggle permanent faction power option"), - COMMAND_PERMANENTPOWER_GRANT("added permanentpower status to"), - COMMAND_PERMANENTPOWER_REVOKE("removed permanentpower status from"), - COMMAND_PERMANENTPOWER_SUCCESS("&c&l[!]&7 You&c %s &7%s."), - COMMAND_PERMANENTPOWER_FACTION("&c&l[!]&7 &c%s %s &7your faction"), - - COMMAND_PROMOTE_DESCRIPTION("/f promote "), - COMMAND_PROMOTE_WRONGFACTION("&c&l[!]&7 &c%1$s&7 is &cnot&7 part of your faction."), - COMMAND_NOACCESS("&c&l[!]&7 You don't have access to that."), - COMMAND_PROMOTE_NOTTHATPLAYER("&c&l[!]&7 That player &ccannot&7 be promoted."), - COMMAND_PROMOTE_NOT_ALLOWED("&c&l[!]&7 You cannot promote to the same rank as yourself!"), - COMMAND_PROMOTE_NOTSELF("&c&l[!]&7 You cannot manage your own rank."), - COMMAND_PROMOTE_NOT_SAME("&c&l[!]&7 You cannot promote to the same rank as yourself!"), - - - COMMAND_POWER_TOSHOW("to show player power info"), - COMMAND_POWER_FORSHOW("for showing player power info"), - COMMAND_POWER_POWER("&c&l[!]&7 &c%1$s » &cPower &7/ &cMaxpower&a » &c%2$d &7/&c%3$d %4$s"), - COMMAND_POWER_BONUS(" (bonus: "), - COMMAND_POWER_PENALTY(" (penalty: "), - COMMAND_POWER_DESCRIPTION("&a&l» &7Show player &apower &7info"), - - COMMAND_POWERBOOST_HELP_1("&c&l[!]&7 You must specify \"plugin\" or \"player\" to target a player or \"f\" or \"faction\" to target a faction."), - COMMAND_POWERBOOST_HELP_2("&c&l[!]&7 ex. /f powerboost plugin SomePlayer 0.5 -or- /f powerboost f SomeFaction -5"), - COMMAND_POWERBOOST_INVALIDNUM("You must specify a valid numeric value for the power bonus/penalty amount."), - COMMAND_POWERBOOST_PLAYER("Player \"%1$s\""), - COMMAND_POWERBOOST_FACTION("Faction \"%1$s\""), - COMMAND_POWERBOOST_BOOST("%1$s now has a power bonus/penalty of %2$d to min and max power levels."), - COMMAND_POWERBOOST_BOOSTLOG("%1$s has set the power bonus/penalty for %2$s to %3$d."), - COMMAND_POWERBOOST_DESCRIPTION("Apply permanent power bonus/penalty to specified player or faction"), - - COMMAND_RELATIONS_ALLTHENOPE("&c&l[!]&7 &cNope!You can't."), - COMMAND_RELATIONS_MORENOPE("&c&l[!]&7 &cNope!&7You can't declare a relation to &cyourself"), - COMMAND_RELATIONS_ALREADYINRELATIONSHIP("&c&l[!]&7 You &calready&7 have that relation wish set with&c %1$s."), - COMMAND_RELATIONS_TOMARRY("to change a relation wish"), - COMMAND_RELATIONS_FORMARRY("for changing a relation wish"), - COMMAND_RELATIONS_MUTUAL("&c&l[!]&7 Your faction is now %1$s to %2$s"), - COMMAND_RELATIONS_PEACEFUL("&c&l[!]&7 This will have no effect while your faction is peaceful."), - COMMAND_RELATIONS_PEACEFULOTHER("&c&l[!]&7 This will have &cno effect&7 while their faction is peaceful."), - COMMAND_RELATIONS_DESCRIPTION("Set relation wish to another faction"), - COMMAND_RELATIONS_EXCEEDS_ME("&c&l[!]&7 Failed to set relation wish. You can only have %1$s %2$s."), - COMMAND_RELATIONS_EXCEEDS_THEY("&c&l[!]&7 Failed to set relation wish. They can only have %1$s %2$s."), - - COMMAND_RELATIONS_PROPOSAL_1("&c&l[!]&7&c %1$s &7wishes to be your&c %2$s"), - COMMAND_RELATIONS_PROPOSAL_2("&c&l[!]&7 Type &c/%1$s %2$s %3$s&7 to accept."), - COMMAND_RELATIONS_PROPOSAL_SENT("&c&l[!]&7 &c%1$s&7 were informed that you wish to be &c%2$s"), - - COMMAND_RELOAD_TIME("&c&l[!]&7 Reloaded &call &7configuration files from disk, took &c%1$d ms."), - COMMAND_RELOAD_DESCRIPTION("Reload data file(s) from disk"), - - COMMAND_SAFEUNCLAIMALL_DESCRIPTION("Unclaim all safezone land"), - COMMAND_SAFEUNCLAIMALL_UNCLAIMED("&c&l[!]&7 You unclaimed&c ALL&7 safe zone land."), - COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG("&c&l[!]&7 &c%1$s&7 unclaimed all safe zones."), - - COMMAND_SAVEALL_SUCCESS("&c&l[!]&7 &cFactions saved to disk!"), - COMMAND_SAVEALL_DESCRIPTION("Save all data to disk"), - - COMMAND_SCOREBOARD_DESCRIPTION("Scoreboardy things"), - - COMMAND_SETBANNER_SUCCESS("&c&l[!] &7Banner Pattern Set!"), - COMMAND_SETBANNER_NOTBANNER("&c&l[!] &7The item is &cnot&7 a banner!"), - COMMAND_SETBANNER_DESCRIPTION("set banner pattern for your faction"), - - - COMMAND_SETDEFAULTROLE_DESCRIPTION("/f defaultrole - set your Faction's default role."), - COMMAND_SETDEFAULTROLE_NOTTHATROLE("&c&l[!]&7 You cannot set the default to admin."), - COMMAND_SETDEFAULTROLE_SUCCESS("Set default role of your faction to %1$s"), - COMMAND_SETDEFAULTROLE_INVALIDROLE("Couldn't find matching role for %1$s"), - - COMMAND_SETFWARP_NOTCLAIMED("&c&l[!]&7 You can &conly&7 set warps in your faction territory."), - COMMAND_SETFWARP_LIMIT("&c&l[!]&7 Your Faction already has the &cmax amount&7 of warps set &c(%1$d)."), - COMMAND_SETFWARP_SET("&c&l[!]&7 Set warp &c%1$s&7 and password &c'%2$s' &7to your location."), - COMMAND_SETFWARP_TOSET("to set warp"), - COMMAND_SETFWARP_FORSET("for setting warp"), - COMMAND_SETFWARP_DESCRIPTION("Set a faction warp"), - - COMMAND_SETHOME_DISABLED("&c&l[!]&7 &cSorry&7, Faction homes are disabled on this server."), - COMMAND_SETHOME_NOTCLAIMED("&c&l[!]&c Sorry&7, your faction home can only be set inside your &cown &7claimed territory."), - COMMAND_SETHOME_TOSET("to set the faction home"), - COMMAND_SETHOME_FORSET("for setting the faction home"), - COMMAND_SETHOME_SET("&c&l[!]&c %1$s&7 set the home for your faction. You can now use:"), - COMMAND_SETHOME_SETOTHER("&c&l[!]&7 You have set the home for the &c%1$s&7 faction."), - COMMAND_SETHOME_DESCRIPTION("Set the faction home"), - - COMMAND_SETMAXVAULTS_DESCRIPTION("Set max vaults for a Faction."), - COMMAND_SETMAXVAULTS_SUCCESS("&aSet max vaults for &e%s &ato &b%d"), - - COMMAND_VAULT_DESCRIPTION("Open your placed faction vault!"), - COMMAND_VAULT_INVALID("&c&l[!]&7 Your vault was either&c claimed&7, &cbroken&7, or has&c not been&7 placed yet."), - COMMAND_VAULT_OPENING("&c&l[!]&7 Opening faction vault."), - COMMAND_VAULT_NO_HOPPER("&c&l[!] &7You cannot place a hopper near a vault!"), - - COMMAND_GETVAULT_ALREADYSET("&c&l[!]&7 Vault has already been set!"), - COMMAND_GETVAULT_ALREADYHAVE("&c&l[!]&7 You already have a vault in your inventory!"), - COMMAND_GETVAULT_CHESTNEAR("&c&l[!]&7 &7There is a chest or hopper &cnearby"), - COMMAND_GETVAULT_SUCCESS("&cSucessfully set vault."), - COMMAND_GETVAULT_INVALIDLOCATION("&cVault can only be placed in faction land!"), - COMMAND_GETVAULT_DESCRIPTION("Get the faction vault item!"), - COMMAND_GETVAULT_RECEIVE("&cYou have recieved a faction vault!"), - COMMAND_GETVAULT_NOMONEY("&cYou do not have enough money"), - COMMAND_GETVAULT_MONEYTAKE("&c{amount} has been taken from your account"), - - COMMAND_SHOW_NOFACTION_SELF("You are not in a faction"), - COMMAND_SHOW_NOFACTION_OTHER("That's not a faction"), - COMMAND_SHOW_TOSHOW("to show faction information"), - COMMAND_SHOW_FORSHOW("for showing faction information"), - COMMAND_SHOW_DESCRIPTION("Description: %1$s"), - COMMAND_SHOW_PEACEFUL("This faction is Peaceful"), - COMMAND_SHOW_PERMANENT("This faction is permanent, remaining even with no members."), - COMMAND_SHOW_JOINING("Joining: %1$s "), - COMMAND_SHOW_INVITATION("invitation is required"), - COMMAND_SHOW_UNINVITED("no invitation is needed"), - COMMAND_SHOW_NOHOME("n/a"), - COMMAND_SHOW_POWER("Land / Power / Maxpower: %1$d/%2$d/%3$d %4$s."), - COMMAND_SHOW_BONUS(" (bonus: "), - COMMAND_SHOW_PENALTY(" (penalty: "), - COMMAND_SHOW_DEPRECIATED("(%1$s depreciated)"), //This is spelled correctly. - COMMAND_SHOW_LANDVALUE("Total land value: %1$s %2$s"), - COMMAND_SHOW_BANKCONTAINS("Bank contains: %1$s"), - COMMAND_SHOW_ALLIES("Allies: "), - COMMAND_SHOW_ENEMIES("Enemies: "), - COMMAND_SHOW_MEMBERSONLINE("Members online: "), - COMMAND_SHOW_MEMBERSOFFLINE("Members offline: "), - COMMAND_SHOW_COMMANDDESCRIPTION("Show faction information"), - COMMAND_SHOW_DEATHS_TIL_RAIDABLE("DTR: %1$d"), - COMMAND_SHOW_EXEMPT("This faction is exempt and cannot be seen."), - COMMAND_SHOW_NEEDFACTION("&cYou need to join a faction to view your own!"), - - COMMAND_SHOWCLAIMS_HEADER("&8&m-------------&8<{faction}'s claims&8>&8&m-------------"), - COMMAND_SHOWCLAIMS_FORMAT("&8[{world}]:"), - COMMAND_SHOWCLAIMS_CHUNKSFORMAT("&8(&c{x}&8,&c{z}&8)"), - COMMAND_SHOWCLAIMS_DESCRIPTION("show your factions claims!"), - - COMMAND_SHOWINVITES_PENDING("Players with pending invites: "), - COMMAND_SHOWINVITES_CLICKTOREVOKE("Click to revoke invite for %1$s"), - COMMAND_SHOWINVITES_DESCRIPTION("Show pending faction invites"), - - COMMAND_STATUS_FORMAT("%1$s Power: %2$s Last Seen: %3$s"), - COMMAND_STATUS_ONLINE("Online"), - COMMAND_STATUS_AGOSUFFIX(" ago."), - COMMAND_STATUS_DESCRIPTION("Show the status of a player"), - - COMMAND_STEALTH_DESCRIPTION("Enable and Disable Stealth Mode"), - COMMAND_STEALTH_ENABLE("&cStealth &7» &7You will no longer disable nearby players in /f fly."), - COMMAND_STEALTH_DISABLE("&cStealth &8» &7You will now disable other nearby players in /f fly."), - COMMAND_STEALTH_MUSTBEMEMBER("&cStealth &8» &4You must be in a faction to use this command"), - - COMMAND_STUCK_TIMEFORMAT("m 'minutes', s 'seconds.'"), - COMMAND_STUCK_CANCELLED("Teleport cancelled because you were damaged"), - COMMAND_STUCK_OUTSIDE("Teleport cancelled because you left %1$d block radius"), - COMMAND_STUCK_EXISTS("You are already teleporting, you must wait %1$s"), - COMMAND_STUCK_START("Teleport will commence in %s. Don't take or deal damage. "), - COMMAND_STUCK_TELEPORT("Teleported safely to %1$d, %2$d, %3$d."), - COMMAND_STUCK_TOSTUCK("to safely teleport %1$s out"), - COMMAND_STUCK_FORSTUCK("for %1$s initiating a safe teleport out"), - COMMAND_STUCK_DESCRIPTION("Safely teleports you out of enemy faction"), - - COMMAND_SEECHUNK_ENABLED("&cSeechunk enabled!"), - COMMAND_SEECHUNK_DISABLED("&cSeechunk disabled!"), - - - COMMAND_TAG_TAKEN("That tag is already taken"), - COMMAND_TAG_TOCHANGE("to change the faction tag"), - COMMAND_TAG_FORCHANGE("for changing the faction tag"), - COMMAND_TAG_FACTION("%1$s changed your faction tag to %2$s"), - COMMAND_TAG_CHANGED("The faction %1$s changed their name to %2$s."), - COMMAND_TAG_DESCRIPTION("Change the faction tag"), - - COMMAND_TITLE_TOCHANGE("to change a players title"), - COMMAND_TITLE_FORCHANGE("for changing a players title"), - COMMAND_TITLE_CHANGED("%1$s changed a title: %2$s"), - COMMAND_TITLE_DESCRIPTION("Set or remove a players title"), - - COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION("Toggles whether or not you will see alliance chat"), - COMMAND_TOGGLEALLIANCECHAT_IGNORE("Alliance chat is now ignored"), - COMMAND_TOGGLEALLIANCECHAT_UNIGNORE("Alliance chat is no longer ignored"), - - COMMAND_TOGGLESB_DISABLED("You can't toggle scoreboards while they are disabled."), - - COMMAND_TOP_DESCRIPTION("Sort Factions to see the top of some criteria."), - COMMAND_TOP_TOP("Top Factions by %s. Page %d/%d"), - COMMAND_TOP_LINE("%d. &6%s: &c%s"), // Rank. Faction: Value - COMMAND_TOP_INVALID("Could not sort by %s. Try balance, online, members, power or land."), - - COMMAND_TNT_DISABLED_MSG("&cThis command is disabled!"), - COMMAND_TNT_INVALID_NUM("The amount needs to be a number!"), - COMMAND_TNT_DEPOSIT_SUCCESS("&cSuccessfully deposited tnt."), - COMMAND_TNT_EXCEEDLIMIT("&cThis exceeds the bank limit!"), - COMMAND_TNT_WIDTHDRAW_SUCCESS("&cSuccessfully withdrew tnt."), - COMMAND_TNT_WIDTHDRAW_NOTENOUGH("&cNot enough tnt in bank."), - COMMAND_TNT_DEPOSIT_NOTENOUGH("&cNot enough tnt in tnt inventory."), - COMMAND_TNT_AMOUNT("&cYour faction has {amount} tnt in the tnt bank."), - COMMAND_TNT_POSITIVE("&cPlease use positive numbers!"), - COMMAND_TNT_DESCRIPTION("add/widthraw from faction's tnt bank"), - COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE("&cNot enough space in your inventory."), - COMMAND_TNT_ADD_DESCRIPTION("&b/f tnt add&3 "), - COMMAND_TNT_TAKE_DESCRIPTION("&b/f tnt take&3 "), - - COMMAND_TNTFILL_HEADER("&c&l[!] &7Filling tnt in dispensers..."), - COMMAND_TNTFILL_SUCCESS("&c&l[!] &7Filled &c{amount}&7 Tnt in &c{dispensers} &7dispensers"), - COMMAND_TNTFILL_NOTENOUGH("&c&l[!] &7Not enough tnt in inventory."), - COMMAND_TNTFILL_RADIUSMAX("&c&l[!] &7The max radius is {max}"), - COMMAND_TNTFILL_AMOUNTMAX("&c&l[!] &7The max amount is {max}"), - COMMAND_TNTFILL_MOD("&c&l[!] &7Tnt will be used from the faction bank because you dont have the specified amount in your inventory and you are a {role}"), - COMMAND_TNTFILL_DESCRIPTION("Fill tnt into dispensers around you"), - - COMMAND_UNBAN_DESCRIPTION("Unban someone from your Faction"), - COMMAND_UNBAN_NOTBANNED("&7%s &cisn't banned. Not doing anything."), - COMMAND_UNBAN_UNBANNED("&e%1$s &cunbanned &7%2$s"), - COMMAND_UNBAN_TARGET("&aYou were unbanned from &r%s"), - - COMMAND_UNCLAIM_SAFEZONE_SUCCESS("Safe zone was unclaimed."), - COMMAND_UNCLAIM_SAFEZONE_NOPERM("This is a safe zone. You lack permissions to unclaim."), - COMMAND_UNCLAIM_WARZONE_SUCCESS("War zone was unclaimed."), - COMMAND_UNCLAIM_WARZONE_NOPERM("This is a war zone. You lack permissions to unclaim."), - COMMAND_UNCLAIM_UNCLAIMED("%1$s unclaimed some of your land."), - COMMAND_UNCLAIM_UNCLAIMS("You unclaimed this land."), - COMMAND_UNCLAIM_LOG("%1$s unclaimed land at (%2$s) from the faction: %3$s"), - COMMAND_UNCLAIM_WRONGFACTION("You don't own this land."), - COMMAND_UNCLAIM_TOUNCLAIM("to unclaim this land"), - COMMAND_UNCLAIM_FORUNCLAIM("for unclaiming this land"), - COMMAND_UNCLAIM_FACTIONUNCLAIMED("%1$s unclaimed some land."), - COMMAND_UNCLAIM_DESCRIPTION("Unclaim the land where you are standing"), - - COMMAND_UNCLAIMALL_TOUNCLAIM("to unclaim all faction land"), - COMMAND_UNCLAIMALL_FORUNCLAIM("for unclaiming all faction land"), - COMMAND_UNCLAIMALL_UNCLAIMED("%1$s unclaimed ALL of your faction's land."), - COMMAND_UNCLAIMALL_LOG("%1$s unclaimed everything for the faction: %2$s"), - COMMAND_UNCLAIMALL_DESCRIPTION("Unclaim all of your factions land"), - COMMAND_UNCLAIM_CLICKTOUNCLAIM("Click to unclaim &2(%1$d, %2$d)"), - - COMMAND_VERSION_NAME("&c&l[!]&7 &c&k||| &r&4SavageFactions&7 &c&k|||&r &c» &7By ProSavage"), - COMMAND_VERSION_VERSION("&7Version &c» &7%1$s"), - COMMAND_VERSION_DESCRIPTION("Show plugin and translation version information"), - - COMMAND_WARUNCLAIMALL_DESCRIPTION("Unclaim all warzone land"), - COMMAND_WARUNCLAIMALL_SUCCESS("You unclaimed ALL war zone land."), - COMMAND_WARUNCLAIMALL_LOG("%1$s unclaimed all war zones."), - - COMMAND_RULES_DISABLED_MSG("&cThis command is disabled!"), - COMMAND_RULES_DESCRIPTION("set/remove/add rules!"), - COMMAND_RULES_ADD_INVALIDARGS("Please include a rule!"), - COMMAND_RULES_SET_INVALIDARGS("Please include a line number & rule!"), - COMMAND_RULES_REMOVE_INVALIDARGS("Please include a line number!"), - COMMAND_RULES_ADD_SUCCESS("&cRule added successfully!"), - COMMAND_RULES_REMOVE_SUCCESS("&cRule removed successfully!"), - COMMAND_RULES_SET_SUCCESS("&cRule set successfully!"), - COMMAND_RULES_CLEAR_SUCCESS("&cRule cleared successfully!"), - - /** - * Leaving - This is accessed through a command, and so it MAY need a COMMAND_* slug :s - */ - LEAVE_PASSADMIN("You must give the admin role to someone else first."), - LEAVE_NEGATIVEPOWER("You cannot leave until your power is positive."), - LEAVE_TOLEAVE("to leave your faction."), - LEAVE_FORLEAVE("for leaving your faction."), - LEAVE_LEFT("%s left faction %s."), - LEAVE_DISBANDED("%s was disbanded."), - LEAVE_DISBANDEDLOG("The faction %s (%s) was disbanded due to the last player (%s) leaving."), - LEAVE_DESCRIPTION("\\n &a&l» &7Leave your faction"), - - /** - * Claiming - Same as above basically. No COMMAND_* because it's not in a command class, but... - */ - CLAIM_PROTECTED("This land is protected"), - CLAIM_DISABLED("Sorry, this world has land claiming disabled."), - CLAIM_CANTCLAIM("You can't claim land for %s."), - CLAIM_ALREADYOWN("%s already own this land."), - CLAIM_MUSTBE("You must be %s to claim land."), - CLAIM_MEMBERS("Factions must have at least %s members to claim land."), - CLAIM_SAFEZONE("You can not claim a Safe Zone."), - CLAIM_WARZONE("You can not claim a War Zone."), - CLAIM_POWER("You can't claim more land!You need more power!"), - CLAIM_LIMIT("Limit reached. You can't claim more land!"), - CLAIM_ALLY("You can't claim the land of your allies."), - CLAIM_CONTIGIOUS("You can only claim additional land which is connected to your first claim or controlled by another faction!"), - CLAIM_FACTIONCONTIGUOUS("You can only claim additional land which is connected to your first claim!"), - CLAIM_PEACEFUL("%s owns this land. Your faction is peaceful, so you cannot claim land from other factions."), - CLAIM_PEACEFULTARGET("%s owns this land, and is a peaceful faction. You cannot claim land from them."), - CLAIM_THISISSPARTA("%s owns this land and is strong enough to keep it."), - CLAIM_BORDER("You must start claiming land at the border of the territory."), - CLAIM_TOCLAIM("to claim this land"), - CLAIM_FORCLAIM("for claiming this land"), - CLAIM_TOOVERCLAIM("to overclaim this land"), - CLAIM_FOROVERCLAIM("for over claiming this land"), - CLAIM_CLAIMED("%s claimed land for %s from %s."), - CLAIM_CLAIMEDLOG("%s claimed land at (%s) for the faction: %s"), - CLAIM_OVERCLAIM_DISABLED("Over claiming is disabled on this server."), - CLAIM_TOOCLOSETOOTHERFACTION("Your claim is too close to another Faction. Buffer required is %d"), - CLAIM_OUTSIDEWORLDBORDER("Your claim is outside the border."), - CLAIM_OUTSIDEBORDERBUFFER("Your claim is outside the border. %d chunks away world edge required."), - CLAIM_CLICK_TO_CLAIM("Click to try to claim &2(%1$d, %2$d)"), - CLAIM_MAP_OUTSIDEBORDER("&cThis claim is outside the worldborder!"), - CLAIM_YOUAREHERE("You are here"), - CLAIM_NO_TERRITORY_PERM("You do not have permission from your faction leader to do this!"), - - /** - * More generic, or less easily categorisable translations, which may apply to more than one class - */ - GENERIC_YOU("you"), - GENERIC_YOURFACTION("your faction"), - GENERIC_NOPERMISSION("You don't have permission to %1$s."), - GENERIC_FPERM_NOPERMISSION("&7The faction leader does not allow you to &c%1$s."), - GENERIC_DOTHAT("do that"), //Ugh nuke this from high orbit - GENERIC_NOPLAYERMATCH("No player match found for \"%1$s\"."), - GENERIC_NOPLAYERFOUND("No player \"%1$s\" could not be found."), - GENERIC_ARGS_TOOFEW("Too few arguments. Use like this:"), - GENERIC_ARGS_TOOMANY("Strange argument \"%1$s\". Use the command like this:"), - GENERIC_DEFAULTDESCRIPTION("Default faction description :("), - GENERIC_OWNERS("Owner(s): %1$s"), - GENERIC_PUBLICLAND("Public faction land."), - GENERIC_FACTIONLESS("factionless"), - GENERIC_SERVERADMIN("A server admin"), - GENERIC_DISABLED("disabled"), - GENERIC_ENABLED("enabled"), - GENERIC_INFINITY("∞"), - GENERIC_CONSOLEONLY("This command cannot be run as a player."), - GENERIC_PLAYERONLY("This command can only be used by ingame players."), - GENERIC_ASKYOURLEADER(" Ask your leader to:"), - GENERIC_YOUSHOULD("You should:"), - GENERIC_YOUMAYWANT("You may want to: "), - GENERIC_TRANSLATION_VERSION("Translation: %1$s(%2$s,%3$s) State: %4$s"), - GENERIC_TRANSLATION_CONTRIBUTORS("Translation contributors: %1$s"), - GENERIC_TRANSLATION_RESPONSIBLE("Responsible for translation: %1$s"), - GENERIC_FACTIONTAG_TOOSHORT("The faction tag can't be shorter than %1$s chars."), - GENERIC_FACTIONTAG_TOOLONG("The faction tag can't be longer than %s chars."), - GENERIC_FACTIONTAG_ALPHANUMERIC("Faction tag must be alphanumeric. \"%s\" is not allowed."), - GENERIC_PLACEHOLDER(""), - GENERIC_NOTENOUGHMONEY("&cYou dont have enough money!"), - GENERIC_MONEYTAKE("&c{amount} has been taken from your account."), - - - WARBANNER_NOFACTION("&cYou need a faction to use a warbanner!"), - WARBANNER_COOLDOWN("&cThe warbanner is on cooldown for your faction!"), - WARBANNER_INVALIDLOC("&cYou can only use warbanners in enemy land or the warzone"), - - /** - * ASCII compass (for chat map) - */ - COMPASS_SHORT_NORTH("N"), - COMPASS_SHORT_EAST("E"), - COMPASS_SHORT_SOUTH("S"), - COMPASS_SHORT_WEST("W"), - - /** - * Chat modes - */ - CHAT_MOD("mod chat"), - CHAT_FACTION("faction chat"), - CHAT_ALLIANCE("alliance chat"), - CHAT_TRUCE("truce chat"), - CHAT_PUBLIC("public chat"), - - /** - * Economy stuff - */ - - ECON_OFF("no %s"), // no balance, no value, no refund, etc - ECON_FORMAT("###,###.###"), - - /** - * Relations - */ - RELATION_MEMBER_SINGULAR("member"), - RELATION_MEMBER_PLURAL("members"), - RELATION_ALLY_SINGULAR("ally"), - RELATION_ALLY_PLURAL("allies"), - RELATION_TRUCE_SINGULAR("truce"), - RELATION_TRUCE_PLURAL("truces"), - RELATION_NEUTRAL_SINGULAR("neutral"), - RELATION_NEUTRAL_PLURAL("neutrals"), - RELATION_ENEMY_SINGULAR("enemy"), - RELATION_ENEMY_PLURAL("enemies"), - - /** - * Roles - */ - ROLE_LEADER("leader"), - ROLE_COLEADER("coleader"), - ROLE_MODERATOR("moderator"), - ROLE_NORMAL("normal member"), - ROLE_RECRUIT("recruit"), - - /** - * Region types. - */ - REGION_SAFEZONE("safezone"), - REGION_WARZONE("warzone"), - REGION_WILDERNESS("wilderness"), - - REGION_PEACEFUL("peaceful territory"), - /** - * In the player and entity listeners - */ - PLAYER_CANTHURT("You may not harm other players in %s"), - PLAYER_SAFEAUTO("This land is now a safe zone."), - PLAYER_WARAUTO("This land is now a war zone."), - PLAYER_OUCH("Ouch, that is starting to hurt. You should give it a rest."), - PLAYER_USE_WILDERNESS("You can't use %s in the wilderness."), - PLAYER_USE_SAFEZONE("You can't use %s in a safe zone."), - PLAYER_USE_WARZONE("You can't use %s in a war zone."), - PLAYER_USE_TERRITORY("You can't %s in the territory of %s."), - PLAYER_USE_OWNED("You can't use %s in this territory, it is owned by: %s."), - PLAYER_COMMAND_WARZONE("You can't use the command '%s' in warzone."), - PLAYER_COMMAND_NEUTRAL("You can't use the command '%s' in neutral territory."), - PLAYER_COMMAND_ENEMY("You can't use the command '%s' in enemy territory."), - PLAYER_COMMAND_PERMANENT("You can't use the command '%s' because you are in a permanent faction."), - PLAYER_COMMAND_ALLY("You can't use the command '%s' in ally territory."), - PLAYER_COMMAND_WILDERNESS("You can't use the command '%s' in the wilderness."), - - PLAYER_POWER_NOLOSS_PEACEFUL("You didn't lose any power since you are in a peaceful faction."), - PLAYER_POWER_NOLOSS_WORLD("You didn't lose any power due to the world you died in."), - PLAYER_POWER_NOLOSS_WILDERNESS("You didn't lose any power since you were in the wilderness."), - PLAYER_POWER_NOLOSS_WARZONE("You didn't lose any power since you were in a war zone."), - PLAYER_POWER_LOSS_WARZONE("The world you are in has power loss normally disabled, but you still lost power since you were in a war zone.\nYour power is now %d / %d"), - PLAYER_POWER_NOW("Your power is now %d / %d"), - - PLAYER_PVP_LOGIN("You can't hurt other players for %d seconds after logging in."), - PLAYER_PVP_REQUIREFACTION("You can't hurt other players until you join a faction."), - PLAYER_PVP_FACTIONLESS("You can't hurt players who are not currently in a faction."), - PLAYER_PVP_PEACEFUL("Peaceful players cannot participate in combat."), - PLAYER_PVP_NEUTRAL("You can't hurt neutral factions. Declare them as an enemy."), - PLAYER_PVP_CANTHURT("You can't hurt %s."), - - PLAYER_PVP_NEUTRALFAIL("You can't hurt %s in their own territory unless you declare them as an enemy."), - PLAYER_PVP_TRIED("%s tried to hurt you."), - - /** - * Strings lying around in other bits of the plugins - */ - NOPAGES("Sorry. No Pages available."), - INVALIDPAGE("Invalid page. Must be between 1 and %1$d"), - - /** - * The ones here before I started messing around with this - */ - TITLE("title", "&bFactions &0|&r"), - WILDERNESS("wilderness", "&2Wilderness"), - WILDERNESS_DESCRIPTION("wilderness-description", ""), - WARZONE("warzone", "&4Warzone"), - WARZONE_DESCRIPTION("warzone-description", "Not the safest place to be."), - SAFEZONE("safezone", "&6Safezone"), - SAFEZONE_DESCRIPTION("safezone-description", "Free from pvp and monsters."), - TOGGLE_SB("toggle-sb", "You now have scoreboards set to {value}"), - FACTION_LEAVE("faction-leave", "Leaving %1$s, Entering %2$s"), - FACTIONS_ANNOUNCEMENT_TOP("faction-announcement-top", "&d--Unread Faction Announcements--"), - FACTIONS_ANNOUNCEMENT_BOTTOM("faction-announcement-bottom", "&d--Unread Faction Announcements--"), - DEFAULT_PREFIX("default-prefix", "{relationcolor}[{faction}]"), - FACTION_LOGIN("faction-login", "&e%1$s &9logged in."), - FACTION_LOGOUT("faction-logout", "&e%1$s &9logged out.."), - NOFACTION_PREFIX("nofactions-prefix", "&6[&a4-&6]&r"), - DATE_FORMAT("date-format", "MM/d/yy h:ma"), // 3/31/15 07:49AM - - /** - * Raidable is used in multiple places. Allow more than just true/false. - */ - RAIDABLE_TRUE("raidable-true", "true"), - RAIDABLE_FALSE("raidable-false", "false"), - /** - * Warmups - */ - WARMUPS_NOTIFY_FLIGHT("&eFlight will enable in &d%2$d &eseconds."), - WARMUPS_NOTIFY_TELEPORT("&eYou will teleport to &d%1$s &ein &d%2$d &eseconds."), - WARMUPS_ALREADY("&cYou are already warming up."), - WARMUPS_CANCELLED("&cYou have cancelled your warmup."); - - public static SimpleDateFormat sdf; - private static YamlConfiguration LANG; - private String path; - private String def; - - /** - * Lang enum constructor. - * - * @param path The string path. - * @param start The default string. - */ - TL(String path, String start) { - this.path = path; - this.def = start; - } - - /** - * Lang enum constructor. Use this when your desired path simply exchanges '_' for '.' - * - * @param start The default string. - */ - TL(String start) { - this.path = this.name().replace('_', '.'); - if (this.path.startsWith(".")) { - path = "root" + path; - } - this.def = start; - } - - /** - * Set the {@code YamlConfiguration} to use. - * - * @param config The config to set. - */ - public static void setFile(YamlConfiguration config) { - LANG = config; - sdf = new SimpleDateFormat(DATE_FORMAT.toString()); - } - - @Override - public String toString() { - return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def)) + (this == TITLE ? " " : ""); - } - - public String format(Object... args) { - return String.format(toString(), args); - } - - /** - * Get the default value of the path. - * - * @return The default value of the path. - */ - public String getDefault() { - return this.def; - } - - /** - * Get the path to the string. - * - * @return The path to the string. - */ - public String getPath() { - return this.path; - } + /** + * Translation meta + */ + _AUTHOR("misc"), + _RESPONSIBLE("misc"), + _LANGUAGE("English"), + _ENCODING("UTF-8"), + _LOCALE("en_US"), + _REQUIRESUNICODE("false"), + _DEFAULT("true"), + _STATE("complete"), //incomplete, limited, partial, majority, complete + + /** + * Localised translation meta + */ + _LOCAL_AUTHOR("misc"), + _LOCAL_RESPONSIBLE("misc"), + _LOCAL_LANGUAGE("English"), + _LOCAL_REGION("US"), + _LOCAL_STATE("complete"), //And this is the English version. It's not ever going to be not complete. + + /** + * Command translations + */ + + /** + * Messsges for /f help + */ + COMMAND_HELP_NEXTCREATE("Learn how to create a faction on the next page."), + COMMAND_HELP_INVITATIONS("command.help.invitations", "You might want to close it and use invitations:"), + COMMAND_HELP_HOME("And don't forget to set your home:"), + COMMAND_HELP_404("&c&l» &7This page does &cnot &7exist"), + COMMAND_HELP_BANK_1("Your faction has a bank which is used to pay for certain"), //Move to last /f help page + COMMAND_HELP_BANK_2("things, so it will need to have money deposited into it."), //Move to last /f help page + COMMAND_HELP_BANK_3("To learn more, use the money command."), //Move to last /f help page + COMMAND_HELP_PLAYERTITLES("Player titles are just for fun. No rules connected to them."), //Move to last /f help page + COMMAND_HELP_OWNERSHIP_1("Claimed land with ownership set is further protected so"), //Move to last /f help page + COMMAND_HELP_OWNERSHIP_2("that only the owner(s), faction admin, and possibly the"), //Move to last /f help page + COMMAND_HELP_OWNERSHIP_3("faction moderators have full access."), //Move to last /f help page + COMMAND_HELP_RELATIONS_1("Set the relation you WISH to have with another faction."), //Move to last /f help page + COMMAND_HELP_RELATIONS_2("Your default relation with other factions will be neutral."), //Move to last /f help page + COMMAND_HELP_RELATIONS_3("If BOTH factions choose \"ally\" you will be allies."), //Move to last /f help page + COMMAND_HELP_RELATIONS_4("If ONE faction chooses \"enemy\" you will be enemies."), //Move to last /f help page + COMMAND_HELP_RELATIONS_5("You can never hurt members or allies."), //Move to last /f help page + COMMAND_HELP_RELATIONS_6("You can not hurt neutrals in their own territory."), //Move to last /f help page + COMMAND_HELP_RELATIONS_7("You can always hurt enemies and players without faction."), //Move to last /f help page + COMMAND_HELP_RELATIONS_8(""), + COMMAND_HELP_RELATIONS_9("Damage from enemies is reduced in your own territory."), //Move to last /f help page + COMMAND_HELP_RELATIONS_10("When you die you lose power. It is restored over time."), //Move to last /f help page + COMMAND_HELP_RELATIONS_11("The power of a faction is the sum of all member power."), //Move to last /f help page + COMMAND_HELP_RELATIONS_12("The power of a faction determines how much land it can hold."), //Move to last /f help page + COMMAND_HELP_RELATIONS_13("You can claim land from factions with too little power."), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_1("Only faction members can build and destroy in their own"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_2("territory. Usage of the following items is also restricted:"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_3("Door, Chest, Furnace, Dispenser, Diode."), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_4(""), + COMMAND_HELP_PERMISSIONS_5("Make sure to put pressure plates in front of doors for your"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_6("guest visitors. Otherwise they can't get through. You can"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_7("also use this to create member only areas."), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_8("As dispensers are protected, you can create traps without"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_9("worrying about those arrows getting stolen."), //Move to last /f help page + COMMAND_HELP_ADMIN_1("&a&l» &a/f claim safezone \n &7claim land for the Safe Zone"), + COMMAND_HELP_ADMIN_2("&a&l» &a/f claim warzone \n &7claim land for the War Zone"), + COMMAND_HELP_ADMIN_3("&a&l» &a/f autoclaim [safezone|warzone] \n &7take a guess"), + COMMAND_HELP_MOAR_1("Finally some commands for the server admins:"), + COMMAND_HELP_MOAR_2("More commands for server admins:"), + COMMAND_HELP_MOAR_3("Even more commands for server admins:"), + COMMAND_HELP_DESCRIPTION("\n &a&l» &7Display a &ahelp &7page"), + + COMMAND_NEAR_DESCRIPTION("Get nearby faction players in a radius."), + COMMAND_NEAR_DISABLED_MSG("&cThis command is disabled!"), + COMMAND_NEAR_FORMAT("{playername} &c({distance}m)"), + COMMAND_NEAR_USE_MSG("&cFaction members nearby"), + + /** + * Messsges for Faction Admins/Mods + */ + + COMMAND_UPGRADES_DESCRIPTION("&cOpen the Upgrades Menu"), + + COMMAND_ADMIN_NOTMEMBER("&c&l[!] &7%1$s &cis not a member in your faction."), + COMMAND_ADMIN_NOTADMIN("&c&l[!] &cYou are not the faction admin."), + COMMAND_ADMIN_TARGETSELF("'&c&l[!] &cThe target player musn''t be yourself."), + COMMAND_ADMIN_DEMOTES("&c&l[!] &cYou have demoted &7%1$s &cfrom the position of faction admin."), + COMMAND_ADMIN_DEMOTED("&c&l[!] &cYou have been demoted from the position of faction admin by &7%1$s&c"), + COMMAND_ADMIN_PROMOTES("&e&l[!] &eYou have promoted &6%1$s &eto the position of faction admin."), + COMMAND_ADMIN_PROMOTED("&e&l[!] &6%1$s &egave &6%2$s ðe leadership of &6%3$s&e."), + COMMAND_ADMIN_DESCRIPTION("Hand over your admin rights"), + COMMAND_ADMIN_NOMEMBERS("&e&l[!] &cNo one else to promote, please disband faction."), + + COMMAND_AHOME_DESCRIPTION("Send a player to their f home no matter what."), + COMMAND_AHOME_NOHOME("%1$s doesn't have an f home."), + COMMAND_AHOME_SUCCESS("$1%s was sent to their f home."), + COMMAND_AHOME_OFFLINE("%1$s is offline."), + COMMAND_AHOME_TARGET("You were sent to your f home."), + + COMMAND_ANNOUNCE_DESCRIPTION("Announce a message to players in faction."), + + COMMAND_FREECAM_ENEMYINRADIUS("Freecam disabled, An enemy is closeby!"), + COMMAND_FREECAM_OUTSIDEFLIGHT("Please dont leave the flight radius!"), + COMMAND_FREECAM_ENABLED("Freecam is now enabled!"), + COMMAND_FREECAM_DISABLED("Freecam is now disabled"), + COMMAND_FREECAM_DESCRIPTION("Go into spectator mode"), + + + COMMAND_AUTOCLAIM_ENABLED("&c&l[!] &7Now &cauto-claiming&7 land for %1$s."), + COMMAND_AUTOCLAIM_DISABLED("&c&l[!] Auto-claiming&7 of land is now &cdisabled."), + COMMAND_AUTOCLAIM_REQUIREDRANK("&c&l[!] &7You must be &c%1$s&7 to claim land."), + COMMAND_AUTOCLAIM_OTHERFACTION("&c&l[!]&7 You &ccan't &7claim land for &c%1$s&7."), + COMMAND_AUTOCLAIM_DESCRIPTION("Auto-claim land as you walk around"), + + COMMAND_AUTOHELP_HELPFOR("Help for command \""), + + COMMAND_BAN_DESCRIPTION("Ban players from joining your Faction."), + COMMAND_BAN_TARGET("&c&l[!] &7You were &cbanned &7from &c%1$s"), // banned player perspective + COMMAND_BAN_BANNED("&c&l[!] &7%1$s &cbanned &7%2$s"), + COMMAND_BAN_SELF("&c&l[!] &7You may &cnot &7ban &cyourself&7."), + COMMAND_BAN_INSUFFICIENTRANK("&c&l[!] &7Your &crank &7is too low to&c ban &7%1$s"), + COMMAND_BAN_ALREADYBANNED("&c&l[!] &7This player is &calready banned&7!"), + + COMMAND_BANLIST_DESCRIPTION("View a Faction's ban list"), + COMMAND_BANLIST_HEADER("&c&l[!] &7There are &c%d&7 bans for &c%s"), + COMMAND_BANLIST_ENTRY("&7%d. &c%s &r&7// &c%s &r&7// &c%s"), + COMMAND_BANLIST_NOFACTION("&c&l[!] &7You are &cnot &7in a Faction."), + COMMAND_BANLIST_INVALID("&c&l[!] &7The faction &c%s &7does not exist"), + + COMMAND_BOOM_PEACEFULONLY("&c&l[!] &7This command is &conly &7usable by factions which are &cspecifically &7designated as &cpeaceful&7."), + COMMAND_BOOM_TOTOGGLE("to toggle explosions"), + COMMAND_BOOM_FORTOGGLE("for toggling explosions"), + COMMAND_BOOM_ENABLED("&c&l[!] &c%1$s&7 has&c %2$s&7 explosions in your faction's territory."), + COMMAND_BOOM_DESCRIPTION("Toggle explosions (peaceful factions only)"), + + + COMMAND_BYPASS_ENABLE("&e&l[!] &eYou have enabled admin bypass mode. You will be able to build or destroy anywhere."), + COMMAND_BYPASS_ENABLELOG(" has ENABLED admin bypass mode."), + COMMAND_BYPASS_DISABLE("&c&l[!] &cYou have disabled admin bypass mode."), + COMMAND_BYPASS_DISABLELOG(" has DISABLED admin bypass mode."), + COMMAND_BYPASS_DESCRIPTION("Enable admin bypass mode"), + + COMMAND_BANNER_DESCRIPTION("Turn a held banner into a war banner"), + COMMAND_BANNER_NOTENOUGHMONEY("&c&l[!] &7You do&c not&7 have enough money"), + COMMAND_BANNER_MONEYTAKE("&c&l[!] $&c{amount} &7has been taken from your account."), + COMMAND_BANNER_SUCCESS("&c&l[!] &7You have created a &c&lWarBanner!"), + COMMAND_BANNER_DISABLED("&c&l[!] &7Buying&c warbanners&7 is &cdisabled!"), + + COMMAND_TPBANNER_NOTSET("&c&l[!] &7Your faction &cdoes not &7have a &c&lWarBanner &7placed!"), + COMMAND_TPBANNER_SUCCESS("&c&l[!] &cTeleporting &7to your factions's &c&lWarBanner"), + COMMAND_TPBANNER_DESCRIPTION("Teleport to your faction banner"), + + + COMMAND_CHAT_DISABLED("&c&l[!] &7The built in chat channels are &cdisabled &7on this server."), + COMMAND_CHAT_INVALIDMODE("&c&l[!] &cUnrecognised &7chat mode. Please enter either '&da&7','&af&7','&6m&7' or '&fp&7'"), + COMMAND_CHAT_DESCRIPTION("Change chat mode"), + + COMMAND_CHAT_MODE_PUBLIC("&c&l[!] &fPublic &7chat mode."), + COMMAND_CHAT_MODE_ALLIANCE("&c&l[!] &dAlliance &7only chat mode."), + COMMAND_CHAT_MODE_TRUCE("&c&l[!] &5Truce &7only chat mode."), + COMMAND_CHAT_MODE_FACTION("&c&l[!] &aFaction&7 only chat mode."), + COMMAND_CHAT_MODE_MOD("&c&l[!] &dMod &7only chat mode."), + COMMAND_CHAT_MOD_ONLY("&c&l[!] &7Only Mods can talk through this chat mode."), + + COMMAND_CHATSPY_ENABLE("&c&l[!] &7You have &cenabled &7chat spying mode."), + COMMAND_CHATSPY_ENABLELOG(" has ENABLED chat spying mode."), + COMMAND_CHATSPY_DISABLE("&c&l[!] &7You have &cdisabled &7chat spying mode."), + COMMAND_CHATSPY_DISABLELOG(" has DISABLED chat spying mode."), + COMMAND_CHATSPY_DESCRIPTION("Enable admin chat spy mode"), + + COMMAND_CLAIM_INVALIDRADIUS("&c&l[!]&7 If you specify a &cradius&7, it must be at least &c1&7."), + COMMAND_CLAIM_DENIED("&c&l[!]&7 You &cdo not &7have &cpermission&7 to &cclaim&7 in a radius."), + COMMAND_CLAIM_DESCRIPTION("Claim land from where you are standing"), + + COMMAND_CLAIMLINE_INVALIDRADIUS("&c&l[!]&7 If you &cspecify&7 a distance, it must be at least &c1&7."), + COMMAND_CLAIMLINE_DENIED("&c&l[!]&7 You &cdo not &7have&c permission&7 to claim in a line."), + COMMAND_CLAIMLINE_DESCRIPTION("Claim land in a straight line."), + COMMAND_CLAIMLINE_ABOVEMAX("&c&l[!]&7 The &cmaximum&7 limit for claim line is &c%s&7."), + COMMAND_CLAIMLINE_NOTVALID("&c&l[!]&7 &c%s&7 is not a &ccardinal &7direction. You may use &cnorth&7, &ceast&7, &csouth &7or &cwest&7."), + + COMMAND_CONFIG_NOEXIST("&c&l[!]&7 No configuration setting \"&c%1$s&7\" exists."), + COMMAND_CONFIG_SET_TRUE("\" option set to true (enabled)."), + COMMAND_CONFIG_SET_FALSE("\" option set to false (disabled)."), + COMMAND_CONFIG_OPTIONSET("\" option set to "), + COMMAND_CONFIG_COLOURSET("\" color option set to \""), + COMMAND_CONFIG_INTREQUIRED("Cannot set \"%1$s\": An integer (whole number) value required."), + COMMAND_CONFIG_LONGREQUIRED("Cannot set \"%1$s\": A long integer (whole number) value required."), + COMMAND_CONFIG_DOUBLEREQUIRED("Cannot set \"%1$s\": A double (numeric) value required."), + COMMAND_CONFIG_FLOATREQUIRED("Cannot set \"%1$s\": A float (numeric) value required."), + COMMAND_CONFIG_INVALID_COLOUR("Cannot set \"%1$s\": \"%2$s\" is not a valid color."), + COMMAND_CONFIG_INVALID_COLLECTION("\"%1$s\" is not a data collection type which can be modified with this command."), + COMMAND_CONFIG_INVALID_MATERIAL("Cannot change \"%1$s\" set: \"%2$s\" is not a valid material."), + COMMAND_CONFIG_INVALID_TYPESET("\"%1$s\" is not a data type set which can be modified with this command."), + COMMAND_CONFIG_MATERIAL_ADDED("\"%1$s\" set: Material \"%2$s\" added."), + COMMAND_CONFIG_MATERIAL_REMOVED("\"%1$s\" set: Material \"%2$s\" removed."), + COMMAND_CONFIG_SET_ADDED("\"%1$s\" set: \"%2$s\" added."), + COMMAND_CONFIG_SET_REMOVED("\"%1$s\" set: \"%2$s\" removed."), + COMMAND_CONFIG_LOG(" (Command was run by %1$s.)"), + COMMAND_CONFIG_ERROR_SETTING("Error setting configuration setting \"%1$s\" to \"%2$s\"."), + COMMAND_CONFIG_ERROR_MATCHING("Configuration setting \"%1$s\" couldn't be matched, though it should be... please report this error."), + COMMAND_CONFIG_ERROR_TYPE("'%1$s' is of type '%2$s', which cannot be modified with this command."), + COMMAND_CONFIG_DESCRIPTION("Change a conf.json setting"), + + COMMAND_CONVERT_BACKEND_RUNNING("&c&l[!]&7 Already running that backend."), + COMMAND_CONVERT_BACKEND_INVALID("&c&l[!]&7 Invalid backend"), + COMMAND_CONVERT_DESCRIPTION("Convert the plugin backend"), + + COMMAND_COORDS_MESSAGE("&c&l[!] &7{player}&7's coords are &c{x}&7,&c{y}&7,&c{z}&7 in &c{world}"), + COMMAND_COORDS_DESCRIPTION("broadcast your coords to your faction"), + + COMMAND_CHECKPOINT_DISABLED("&c&l[!]&7 You &ccannot&7 use checkpoint while its&c disabled&7!"), + COMMAND_CHECKPOINT_SET("&c&l[!]&7 You have &cset&7 the &cfaction checkpoint&7 at your &cLocation&7."), + COMMAND_CHECKPOINT_GO("&c&l[!]&7 &cTeleporting&7 to &cfaction checkpoint"), + COMMAND_CHECKPOINT_INVALIDLOCATION("&c&l[!]&7 &cInvalid Location!&7 You can &cset&7 checkpoints in &cyour claims&7 or &2wilderness&7."), + COMMAND_CHECKPOINT_NOT_SET("&c&l[!]&7 You have to &cset &7the &cfaction checkpoint&7 first."), + COMMAND_CHECKPOINT_CLAIMED("&c&l[!]&7 Your current &cfaction checkpoint&7 is claimed, set a &cnew &7one!"), + COMMAND_CHECKPOINT_DESCRIPTION("Set or go to your faction checkpoint!"), + + COMMAND_CREATE_MUSTLEAVE("&c&l[!]&7 You must &cleave &7your &ccurrent faction &7first."), + COMMAND_CREATE_INUSE("&c&l[!]&7 That tag is &calready &7in use."), + COMMAND_CREATE_TOCREATE("to create a new faction"), + COMMAND_CREATE_FORCREATE("for creating a new faction"), + COMMAND_CREATE_ERROR("&c&l[!]&7 There was an &cinternal error&7 while trying to create your faction. &cPlease try again&7."), + COMMAND_CREATE_CREATED("&c&l[!]&7 &c%1$s &7created a new faction &c&l%2$s"), + COMMAND_CREATE_YOUSHOULD("&c&l[!]&7 You should now: &c%1$s"), + COMMAND_CREATE_CREATEDLOG(" created a new faction: "), + COMMAND_CREATE_DESCRIPTION("Create a new faction"), + + COMMAND_DEINVITE_CANDEINVITE("&c&l[!]&7 Players you can &cdeinvite: "), + COMMAND_DEINVITE_CLICKTODEINVITE("&c&l[!]&7 Click to &crevoke&7 invite for &c%1$s"), + COMMAND_DEINVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of &c%2$s"), + COMMAND_DEINVITE_MIGHTWANT("&c&l[!]&7 You might want to: &c%1$s"), + COMMAND_DEINVITE_REVOKED("&c&l[!]&7 &7%1$s &crevoked&7 your invitation to &c%2$s&7."), + COMMAND_DEINVITE_REVOKES("&c&l[!]&7 %1$s&c revoked &7%2$s's&c invitation."), + COMMAND_DEINVITE_DESCRIPTION("Remove a pending invitation"), + + COMMAND_DELFWARP_DELETED("&c&l[!]&7 Deleted warp &c%1$s"), + COMMAND_DELFWARP_INVALID("&c&l[!]&7 Couldn't &cfind&7 warp &c%1$s"), + COMMAND_DELFWARP_TODELETE("to delete warp"), + COMMAND_DELFWARP_FORDELETE("for deleting warp"), + COMMAND_DELFWARP_DESCRIPTION("Delete a faction warp"), + + COMMAND_DESCRIPTION_CHANGES("&c&l[!]&7 You have &cchanged&7 the &cdescription&7 for &c%1$s&7 to:"), + COMMAND_DESCRIPTION_CHANGED("&c&l[!]&7 The faction&c %1$s&7 changed their &cdescription &7to:"), + COMMAND_DESCRIPTION_TOCHANGE("to change faction description"), + COMMAND_DESCRIPTION_FORCHANGE("for changing faction description"), + COMMAND_DESCRIPTION_DESCRIPTION("Change the faction description"), + + COMMAND_DISBAND_IMMUTABLE("&c&l[!]&7 &7You &ccannot&7 disband &2Wilderness&7,&e SafeZone&7, or &4WarZone."), + COMMAND_DISBAND_MARKEDPERMANENT("&c&l[!]&7 This faction is designated as&c permanent&7, so you cannot disband it."), + COMMAND_DISBAND_BROADCAST_YOURS("&c&l[!]&7 &c%1$s&7 disbanded your &cfaction."), + COMMAND_DISBAND_BROADCAST_NOTYOURS("&c&l[!]&7 &c%1$s &7disbanded the faction &c%2$s."), + COMMAND_DISBAND_HOLDINGS("&c&l[!]&7 &7You have been given the disbanded &cfaction's bank&7, totaling &c%1$s."), + COMMAND_DISBAND_PLAYER("&c&l[!] &7You have disbanded your &cfaction"), + COMMAND_DISBAND_CONFIRM("&c&l[!]&7 Your Faction has&c {tnt} &7tnt left in the bank, it will be &clost&7 if the faction is &cdisbanded&7. Type&c /f disband &7again within &c10&7 seconds to&c disband&7."), + COMMAND_DISBAND_DESCRIPTION("Disband a faction"), + + COMMAND_FLY_DISABLED("&c&l[!]&7 Sorry, Faction flight is &cdisabled &7on this server"), + COMMAND_FLY_DESCRIPTION("Enter or leave Faction flight mode"), + COMMAND_FLY_CHANGE("&c&l[!]&7 Faction flight &c%1$s"), + COMMAND_FLY_COOLDOWN("&c&l[!]&7 You will &cnot&7 take fall damage for &c{amount}&7 seconds"), + COMMAND_FLY_DAMAGE("&c&l[!]&7 Faction flight &cdisabled&7 due to entering combat"), + COMMAND_FLY_NO_ACCESS("&c&l[!]&7 &cCannot fly &7in territory of %1$s"), + COMMAND_FLY_ENEMY_NEAR("&c&l[!]&7 Flight has been&c disabled&7 an enemy is nearby"), + COMMAND_FLY_CHECK_ENEMY("&c&l[!]&7 Cannot fly here, an enemy is &cnearby"), + COMMAND_FLY_NO_EPEARL("&c&l[!] &7You &ccannot&7 throw enderpearls while flying!"), + + COMMAND_FOCUS_SAMEFACTION("&c[!] You may not focus players in your faction!"), + COMMAND_FOCUS_FOCUSING("&c&l[!] &7Your faction is now focusing &c%s"), + COMMAND_FOCUS_NO_LONGER("&c&l[!] &7Your faction is no longer focusing &c%s"), + COMMAND_FOCUS_DESCRIPTION("Focus a Specific Player"), + + + COMMAND_FWARP_CLICKTOWARP("&c&l[!]&7 Click to &cwarp!"), + COMMAND_FWARP_COMMANDFORMAT("&c&l[!]&7 /f warp &c[password]"), + COMMAND_FWARP_WARPED("&c&l[!]&7 Warped to &c%1$s"), + COMMAND_FWARP_INVALID_WARP("&c&l[!]&7 Couldn't find warp &c%1$s"), + COMMAND_FWARP_TOWARP("to warp"), + COMMAND_FWARP_FORWARPING("for warping"), + COMMAND_FWARP_WARPS("Warps: "), + COMMAND_FWARP_DESCRIPTION("Teleport to a faction warp"), + COMMAND_FWARP_INVALID_PASSWORD("&c&l[!]&7 &cInvalid password!"), + COMMAND_FWARP_PASSWORD_REQUIRED("&c&l[!]&c Warp Password:"), + COMMAND_FWARP_PASSWORD_TIMEOUT("&c&l[!]&7 Warp password &ccanceled"), + + COMMAND_HINT_PERMISSION("&aYou can manage your factions permissions using &7/f perms"), + + COMMAND_HOME_DISABLED("&c&l[!]&7 Sorry, Faction homes are &cdisabled on this server."), + COMMAND_HOME_TELEPORTDISABLED("&c&l[!]&7 Sorry, the ability to &cteleport &7to Faction homes is &cdisabled &7on this server."), + COMMAND_HOME_NOHOME("&c&l[!]&7 Your faction does &cnot &7have a home. "), + COMMAND_HOME_INENEMY("&c&l[!]&7 You &ccannot teleport &7to your &cfaction home&7 while in the territory of an &cenemy faction&7."), + COMMAND_HOME_WRONGWORLD("&c&l[!]&7 You &ccannot &7teleport to your &cfaction home&7 while in a different world."), + COMMAND_HOME_ENEMYNEAR("&c&l[!]&7 You &ccannot teleport&7 to your faction home while an enemy is within &c%s&7 blocks of you."), + COMMAND_HOME_TOTELEPORT("to teleport to your faction home"), + COMMAND_HOME_FORTELEPORT("for teleporting to your faction home"), + COMMAND_HOME_DESCRIPTION("Teleport to the faction home"), + COMMAND_HOME_BLOCKED("&c&l[!] You may not teleport to a home that is claimed by &b%1$s"), + + COMMAND_INSPECT_DISABLED_MSG("&c&l[!]&7 Inspect mode is now &cdisabled."), + COMMAND_INSPECT_DISABLED_NOFAC("&c&l[!]&7 Inspect mode is now &cdisabled,&7 because you &cdo not have a faction!"), + COMMAND_INSPECT_ENABLED("&c&l[!]&7 Inspect mode is now &aEnabled."), + COMMAND_INSPECT_HEADER("&c&m---&7Inspect Data&c&m---&c//&7x:{x},y:{y},z:{z}"), + COMMAND_INSPECT_ROW("&c{time} &7// &c{action} &7// &c{player} &7// &c{block-type}"), + COMMAND_INSPECT_NODATA("&c&l[!]&7 &7No Data was found!"), + COMMAND_INSPECT_NOTINCLAIM("&c&l[!]&7 &7You can &conly&7 inspect in &cyour &7claims!"), + COMMAND_INSPECT_BYPASS("&c&l[!]&7 Inspecting in &cbypass&7 mode"), + COMMAND_INSPECT_DESCRIPTION("Inspect blocks!"), + + COMMAND_INVITE_TOINVITE("to invite someone"), + COMMAND_INVITE_FORINVITE("for inviting someone"), + COMMAND_INVITE_CLICKTOJOIN("Click to join!"), + COMMAND_INVITE_INVITEDYOU(" &chas invited you to join "), + COMMAND_INVITE_INVITED("&c&l[!]&7 &c%1$s&7 invited &c%2$s&7 to your faction."), + COMMAND_INVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of&c %2$s"), + COMMAND_INVITE_ALREADYINVITED("&c&l[!]&7 &c%1$s&7 has already been invited"), + COMMAND_INVITE_DESCRIPTION("Invite a player to your faction"), + COMMAND_INVITE_BANNED("&c&l[!]&7 &7%1$s &cis banned &7from your Faction. &cNot &7sending an invite."), + + COMMAND_JOIN_CANNOTFORCE("&c&l[!]&7 You&c do not&7 have permission to &cmove other players&7 into a faction."), + COMMAND_JOIN_SYSTEMFACTION("&c&l[!]&7 Players may only join &cnormal factions&7. This is a &c&lsystem faction&7."), + COMMAND_JOIN_ALREADYMEMBER("&c&l[!]&7 &c%1$s %2$s already a member of&c %3$s"), + COMMAND_JOIN_ATLIMIT(" &c&l[!]&7 The faction &c%1$s &7is at the limit of&c %2$d&7 members, so&c %3$s&7 cannot currently join."), + COMMAND_JOIN_INOTHERFACTION("&c&l[!]&7 &c%1$s &7must leave&c %2$s &7current faction first."), + COMMAND_JOIN_NEGATIVEPOWER("&c&l[!]&7 &c%1$s &7cannot join a faction with a &cnegative power&7 level."), + COMMAND_JOIN_REQUIRESINVITATION("&c&l[!]&7 This faction &crequires&7 an invitation."), + COMMAND_JOIN_ATTEMPTEDJOIN("&c&l[!]&7 &c%1$s&7 tried to join your faction."), + COMMAND_JOIN_TOJOIN("to join a faction"), + COMMAND_JOIN_FORJOIN("for joining a faction"), + COMMAND_JOIN_SUCCESS("&c&l[!]&7 &c%1$s &7successfully joined &c%2$s."), + COMMAND_JOIN_MOVED("&c&l[!]&7 &c%1$s &7moved you into the faction&c %2$s."), + COMMAND_JOIN_JOINED("&c&l[!]&7 &c%1$s &7joined your faction."), + COMMAND_JOIN_JOINEDLOG("&c&l[!]&7 &c%1$s&7 joined the faction&c %2$s."), + COMMAND_JOIN_MOVEDLOG("&c&l[!]&7 &c%1$s &7moved the player&c %2$s &7into the faction&c %3$s&7."), + COMMAND_JOIN_DESCRIPTION("&a&l» &7Join a faction"), + COMMAND_JOIN_BANNED("&c&l[!]&7 You are &cbanned &7from &c%1$s."), + + COMMAND_KICK_CANDIDATES("&c&l[!]&7 Players you can kick: "), + COMMAND_KICK_CLICKTOKICK("Click to kick "), + COMMAND_KICK_SELF("&c&l[!]&7 You &ccannot &7kick&c yourself&7."), + COMMAND_KICK_NONE("&c&l[!]&7 That player&c is not&7 in a faction."), + COMMAND_KICK_NOTMEMBER("&c&l[!]&7 &c%1$s is not a member of %2$s"), + COMMAND_KICK_INSUFFICIENTRANK("&c&l[!]&7 Your rank is &ctoo low &7to kick this player."), + COMMAND_KICK_NEGATIVEPOWER("&c&l[!]&7 You &ccannot &7kick that member until their power is &apositive&7."), + COMMAND_KICK_TOKICK("to kick someone from the faction"), + COMMAND_KICK_FORKICK("for kicking someone from the faction"), + COMMAND_KICK_FACTION("&c&l[!]&7 %1$s&7 kicked %2$s&c from the faction!"), //message given to faction members + COMMAND_KICK_KICKS("&c&l[!]&7 You kicked &c%1$s&7 from the faction&c %2$s&7!"), //kicker perspective + COMMAND_KICK_KICKED("&c&l[!]&7 &c%1$s &7kicked you from&c %2$s&7!"), //kicked player perspective + COMMAND_KICK_DESCRIPTION("Kick a player from the faction"), + + COMMAND_LIST_FACTIONLIST("&c&l[!]&7 Faction List "), + COMMAND_LIST_TOLIST("to list the factions"), + COMMAND_LIST_FORLIST("for listing the factions"), + COMMAND_LIST_ONLINEFACTIONLESS("Online factionless: "), + COMMAND_LIST_DESCRIPTION("&a&l» &7See a list of the factions"), + + COMMAND_LOCK_LOCKED("&c&l[!]&7 Factions is now&c locked"), + COMMAND_LOCK_UNLOCKED("&c&l[!]&7 Factions in now&a unlocked"), + COMMAND_LOCK_DESCRIPTION("Lock all write stuff. Apparently."), + + COMMAND_LOGINS_TOGGLE("&c&l[!]&7 Set login / logout notifications for Faction members to: &c%s"), + COMMAND_LOGINS_DESCRIPTION("Toggle(?) login / logout notifications for Faction members"), + + COMMAND_LOWPOWER_HEADER("&8&m--------&8&8&m---------"), + COMMAND_LOWPOWER_FORMAT("&c{player} &8(&c{player_power}&8/&c{maxpower}&8)"), + COMMAND_LOWPOWER_DESCRIPTION("Shows a list of players in your faction with lower power levels"), + + COMMAND_MAP_TOSHOW("to show the map"), + COMMAND_MAP_FORSHOW("for showing the map"), + COMMAND_MAP_UPDATE_ENABLED("&c&l[!]&7 Map auto update &aENABLED."), + COMMAND_MAP_UPDATE_DISABLED("&c&l[!]&7 Map auto update &cDISABLED."), + COMMAND_MAP_DESCRIPTION("Show the territory map, and set optional auto update"), + + COMMAND_MAPHEIGHT_DESCRIPTION("&eUpdate the lines that /f map sends"), + COMMAND_MAPHEIGHT_SET("&c&l[!]&7 Set /f map lines to &c&a%1$d"), + COMMAND_MAPHEIGHT_CURRENT("&c&l[!]&7 Current &cmapheight: &a%1$d"), + + COMMAND_MOD_CANDIDATES("&c&l[!]&7 Players you can promote: "), + COMMAND_MOD_CLICKTOPROMOTE("Click to promote "), + COMMAND_MOD_NOTMEMBER("&c&l[!]&7 &c%1$s7 is not a member in your faction."), + COMMAND_MOD_NOTADMIN("&c&l[!]&7 You &care not&7 the faction admin."), + COMMAND_MOD_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), + COMMAND_MOD_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin.&7 Demote them first."), + COMMAND_MOD_REVOKES("&c&l[!]&7 &7You have &cremoved&7 moderator status from &c%1$s."), + COMMAND_MOD_REVOKED("&c&l[!]&7 &c%1$s&7 is &cno longer&7 moderator in your faction."), + COMMAND_MOD_PROMOTES("&c&l[!]&7 &c%1$s&7 was &cpromoted&7 to moderator in your faction."), + COMMAND_MOD_PROMOTED("&c&l[!]&7 You have promoted&c %1$s&7 to moderator."), + COMMAND_MOD_DESCRIPTION("Give or revoke moderator rights"), + + COMMAND_COLEADER_CANDIDATES("&c&l[!]&7 Players you can promote: "), + COMMAND_COLEADER_CLICKTOPROMOTE("Click to promote "), + COMMAND_COLEADER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member&7 in your faction."), + COMMAND_COLEADER_NOTADMIN("&c&l[!]&7 You are&c not&7 the faction admin."), + COMMAND_COLEADER_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), + COMMAND_COLEADER_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin&7. Demote them first."), + COMMAND_COLEADER_REVOKES("&c&l[!]&7 You have removed &ccoleader &7status from&c %1$s&7."), + COMMAND_COLEADER_REVOKED("&c&l[!]&7 &c%1$s&7 is no longer&c coleader &7in your faction."), + COMMAND_COLEADER_PROMOTES("&c&l[!]&7 &c%1$s&7 was promoted to &ccoleader &7in your faction."), + COMMAND_COLEADER_PROMOTED("&c&l[!]&7 You have &cpromoted &7%1$s to &ccoleader."), + COMMAND_COLEADER_DESCRIPTION("Give or revoke coleader rights"), + + COMMAND_MODIFYPOWER_ADDED("&c&l[!]&7 Added &c%1$f &7power to &c%2$s. &7New total rounded power: &c%3$d"), + COMMAND_MODIFYPOWER_DESCRIPTION("Modify the power of a faction/player"), + + COMMAND_MONEY_LONG("&c&l[!]&7 The faction money commands."), + COMMAND_MONEY_DESCRIPTION("Faction money commands"), + + COMMAND_MONEYBALANCE_SHORT("show faction balance"), + COMMAND_MONEYBALANCE_DESCRIPTION("Show your factions current money balance"), + + COMMAND_MONEYDEPOSIT_DESCRIPTION("Deposit money"), + COMMAND_MONEYDEPOSIT_DEPOSITED("&c&l[!]&7 &c%1$s &7deposited&c %2$s&7 in the faction bank:&c %3$s"), + + COMMAND_MONEYTRANSFERFF_DESCRIPTION("Transfer f -> f"), + COMMAND_MONEYTRANSFERFF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred&c %2$s &7from the faction &c\"%3$s\"&7 to the faction&c \"%4$s\"&7"), + + COMMAND_MONEYTRANSFERFP_DESCRIPTION("Transfer f -> plugin"), + COMMAND_MONEYTRANSFERFP_TRANSFER("&c&l[!]&7 &c%1$s &7transferred&c %2$s &7from the faction&c \"%3$s\" &7to the player &c\"%4$s\""), + + COMMAND_MONEYTRANSFERPF_DESCRIPTION("Transfer plugin -> f"), + COMMAND_MONEYTRANSFERPF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred &c%2$s&7 from the player &c\"%3$s\" &7to the faction&c \"%4$s\""), + + COMMAND_MONEYWITHDRAW_DESCRIPTION("Withdraw money"), + COMMAND_MONEYWITHDRAW_WITHDRAW("&c&l[!]&7 &c%1$s&7 withdrew&c %2$s &7from the faction bank:&c %3$s"), + + COMMAND_OPEN_TOOPEN("to open or close the faction"), + COMMAND_OPEN_FOROPEN("for opening or closing the faction"), + COMMAND_OPEN_OPEN("open"), + COMMAND_OPEN_CLOSED("closed"), + COMMAND_OPEN_CHANGES("&c&l[!]&7 &c%1$s&7 changed the faction to &c%2$s&7."), + COMMAND_OPEN_CHANGED("&c&l[!]&7 The faction &c%1$s&7 is now &c%2$s"), + COMMAND_OPEN_DESCRIPTION("Switch if invitation is required to join"), + + COMMAND_OWNER_DISABLED("&c&l[!]&7 Sorry, but &cowned areas &7are &cdisabled &7on this server."), + COMMAND_OWNER_LIMIT("&c&l[!]&7 Sorry, but you have reached the server's &climit&7 of &c%1$d&7 owned areas per faction."), + COMMAND_OWNER_WRONGFACTION("&c&l[!]&7 &7This land is &cnot claimed &7by your faction, so you &ccan't set&7 ownership of it."), + COMMAND_OWNER_NOTCLAIMED("&c&l[!]&7 This land&c is not &7claimed by a faction. Ownership &cis not &7possible."), + COMMAND_OWNER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member &7of this faction."), + COMMAND_OWNER_CLEARED("&c&l[!]&7 You have &ccleared &7ownership for this claimed area."), + COMMAND_OWNER_REMOVED("&c&l[!]&7 You have&c removed ownership &7of this &cclaimed land&7 from &c%1$s&7."), + COMMAND_OWNER_TOSET("to set ownership of claimed land"), + COMMAND_OWNER_FORSET("for setting ownership of claimed land"), + COMMAND_OWNER_ADDED("&c&l[!]&7 You have added &c%1$s&7 to the &cowner list&7 for this claimed land."), + COMMAND_OWNER_DESCRIPTION("Set ownership of claimed land"), + + COMMAND_KILLHOLOGRAMS_DESCRIPTION("Kill holograms in a radius, admin command"), + + COMMAND_OWNERLIST_DISABLED("&c&l[!]&7 &cSorry, &7but owned areas are &cdisabled&7 on this server."),//dup-> + COMMAND_OWNERLIST_WRONGFACTION("&c&l[!]&7 This land &cis not&7 claimed by your faction."),//eq + COMMAND_OWNERLIST_NOTCLAIMED("&c&l[!]&7 This land is not claimed by any faction, thus no owners."),//eq + COMMAND_OWNERLIST_NONE("&c&l[!]&7 No owners are set here; everyone in the faction has access."), + COMMAND_OWNERLIST_OWNERS("&c&l[!]&7 Current owner(s) of this land: %1$s"), + COMMAND_OWNERLIST_DESCRIPTION("List owner(s) of this claimed land"), + + COMMAND_PAYPALSET_DESCRIPTION("&c&l[!] &7Set the email of your faction to claim rewards."), + COMMAND_PAYPALSEE_DESCRIPTION("&c&l[!] &7View a specific factions paypal email with &b/f &b."), + COMMAND_PAYPALSET_CREATED("&c&l[!] &7Make sure to type &b/f &7!"), + COMMAND_PAYPALSET_SUCCESSFUL("&c&l[!] &7Successfully set your factions email - &b%1$s&7."), + COMMAND_PAYPALSEE_FACTION_PAYPAL("&c&l[!] &b%1$s's &7faction has their paypal set to &b%2$s&7."), + COMMAND_PAYPALSEE_FACTION_NOTSET("&c&l[!] &b%1$s's &7paypal has not yet been set!"), + COMMAND_PAYPALSEE_FACTION_NOFACTION("&c&l[!] &b%1$s &7does not have a faction!"), + + COMMAND_PEACEFUL_DESCRIPTION("&c&l[!]&7Set a faction to peaceful"), + COMMAND_PEACEFUL_YOURS("&c&l[!]&7%1$s has %2$s your faction"), + COMMAND_PEACEFUL_OTHER("&c&l[!]&7%s has %s the faction '%s'."), + COMMAND_PEACEFUL_GRANT("&c&l[!]&7 granted peaceful status to"), + COMMAND_PEACEFUL_REVOKE("removed peaceful status from"), + + COMMAND_PERM_DESCRIPTION("&c&l[!]&7&6Edit or list your Faction's permissions."), + COMMAND_PERM_INVALID_RELATION("&c&l[!]&7Invalid relation defined. Try something like&c 'ally'"), + COMMAND_PERM_INVALID_ACCESS("&c&l[!]&7 Invalid access defined. Try something like &c'allow'"), + COMMAND_PERM_INVALID_ACTION("&c&l[!]&7 Invalid action defined. Try something like &c'build'"), + COMMAND_PERM_SET("&c&l[!]&7 Set permission&c %1$s &7to &c%2$s &7for relation&c %3$s"), + COMMAND_PERM_TOP("RCT MEM OFF ALLY TRUCE NEUT ENEMY"), + + COMMAND_PERMANENT_DESCRIPTION("Toggles a permanent faction option"), + COMMAND_PERMANENT_GRANT("&c&l[!]&7 added permanent status to"), + COMMAND_PERMANENT_REVOKE("&c&l[!]&7 removed permanent status from"), + COMMAND_PERMANENT_YOURS("&c&l[!]&7 &c%1$s&7 has &c%2$s&7 your faction"), + COMMAND_PERMANENT_OTHER("&c&l[!]&7 &c%s &7has &c%s &7the faction &c'%s'."), + COMMAND_PROMOTE_TARGET("&c&l[!]&7 You've been &c%1$s&7 to &c%2$s"), + COMMAND_PROMOTE_SUCCESS("&c&l[!]&7 You successfully&c %1$s %2$s &cto&7 %3$s"), + COMMAND_PROMOTE_PROMOTED("promoted"), + COMMAND_PROMOTE_DEMOTED("demoted"), + COMMAND_PROMOTE_COLEADER_ADMIN("&c&l[!]&7 &cColeaders cant promote players to Admin!"), + + COMMAND_PERMANENTPOWER_DESCRIPTION("Toggle permanent faction power option"), + COMMAND_PERMANENTPOWER_GRANT("added permanentpower status to"), + COMMAND_PERMANENTPOWER_REVOKE("removed permanentpower status from"), + COMMAND_PERMANENTPOWER_SUCCESS("&c&l[!]&7 You&c %s &7%s."), + COMMAND_PERMANENTPOWER_FACTION("&c&l[!]&7 &c%s %s &7your faction"), + + COMMAND_PROMOTE_DESCRIPTION("/f promote "), + COMMAND_PROMOTE_WRONGFACTION("&c&l[!]&7 &c%1$s&7 is &cnot&7 part of your faction."), + COMMAND_NOACCESS("&c&l[!]&7 You don't have access to that."), + COMMAND_PROMOTE_NOTTHATPLAYER("&c&l[!]&7 That player &ccannot&7 be promoted."), + COMMAND_PROMOTE_NOT_ALLOWED("&c&l[!]&7 You cannot promote to the same rank as yourself!"), + COMMAND_PROMOTE_NOTSELF("&c&l[!]&7 You cannot manage your own rank."), + COMMAND_PROMOTE_NOT_SAME("&c&l[!]&7 You cannot promote to the same rank as yourself!"), + + + COMMAND_POWER_TOSHOW("to show player power info"), + COMMAND_POWER_FORSHOW("for showing player power info"), + COMMAND_POWER_POWER("&c&l[!]&7 &c%1$s » &cPower &7/ &cMaxpower&a » &c%2$d &7/&c%3$d %4$s"), + COMMAND_POWER_BONUS(" (bonus: "), + COMMAND_POWER_PENALTY(" (penalty: "), + COMMAND_POWER_DESCRIPTION("&a&l» &7Show player &apower &7info"), + + COMMAND_POWERBOOST_HELP_1("&c&l[!]&7 You must specify \"plugin\" or \"player\" to target a player or \"f\" or \"faction\" to target a faction."), + COMMAND_POWERBOOST_HELP_2("&c&l[!]&7 ex. /f powerboost plugin SomePlayer 0.5 -or- /f powerboost f SomeFaction -5"), + COMMAND_POWERBOOST_INVALIDNUM("You must specify a valid numeric value for the power bonus/penalty amount."), + COMMAND_POWERBOOST_PLAYER("Player \"%1$s\""), + COMMAND_POWERBOOST_FACTION("Faction \"%1$s\""), + COMMAND_POWERBOOST_BOOST("%1$s now has a power bonus/penalty of %2$d to min and max power levels."), + COMMAND_POWERBOOST_BOOSTLOG("%1$s has set the power bonus/penalty for %2$s to %3$d."), + COMMAND_POWERBOOST_DESCRIPTION("Apply permanent power bonus/penalty to specified player or faction"), + + COMMAND_RELATIONS_ALLTHENOPE("&c&l[!]&7 &cNope!You can't."), + COMMAND_RELATIONS_MORENOPE("&c&l[!]&7 &cNope!&7You can't declare a relation to &cyourself"), + COMMAND_RELATIONS_ALREADYINRELATIONSHIP("&c&l[!]&7 You &calready&7 have that relation wish set with&c %1$s."), + COMMAND_RELATIONS_TOMARRY("to change a relation wish"), + COMMAND_RELATIONS_FORMARRY("for changing a relation wish"), + COMMAND_RELATIONS_MUTUAL("&c&l[!]&7 Your faction is now %1$s to %2$s"), + COMMAND_RELATIONS_PEACEFUL("&c&l[!]&7 This will have no effect while your faction is peaceful."), + COMMAND_RELATIONS_PEACEFULOTHER("&c&l[!]&7 This will have &cno effect&7 while their faction is peaceful."), + COMMAND_RELATIONS_DESCRIPTION("Set relation wish to another faction"), + COMMAND_RELATIONS_EXCEEDS_ME("&c&l[!]&7 Failed to set relation wish. You can only have %1$s %2$s."), + COMMAND_RELATIONS_EXCEEDS_THEY("&c&l[!]&7 Failed to set relation wish. They can only have %1$s %2$s."), + + COMMAND_RELATIONS_PROPOSAL_1("&c&l[!]&7&c %1$s &7wishes to be your&c %2$s"), + COMMAND_RELATIONS_PROPOSAL_2("&c&l[!]&7 Type &c/%1$s %2$s %3$s&7 to accept."), + COMMAND_RELATIONS_PROPOSAL_SENT("&c&l[!]&7 &c%1$s&7 were informed that you wish to be &c%2$s"), + + COMMAND_RELOAD_TIME("&c&l[!]&7 Reloaded &call &7configuration files from disk, took &c%1$d ms."), + COMMAND_RELOAD_DESCRIPTION("Reload data file(s) from disk"), + + COMMAND_SAFEUNCLAIMALL_DESCRIPTION("Unclaim all safezone land"), + COMMAND_SAFEUNCLAIMALL_UNCLAIMED("&c&l[!]&7 You unclaimed&c ALL&7 safe zone land."), + COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG("&c&l[!]&7 &c%1$s&7 unclaimed all safe zones."), + + COMMAND_SAVEALL_SUCCESS("&c&l[!]&7 &cFactions saved to disk!"), + COMMAND_SAVEALL_DESCRIPTION("Save all data to disk"), + + COMMAND_SCOREBOARD_DESCRIPTION("Scoreboardy things"), + + COMMAND_SETBANNER_SUCCESS("&c&l[!] &7Banner Pattern Set!"), + COMMAND_SETBANNER_NOTBANNER("&c&l[!] &7The item is &cnot&7 a banner!"), + COMMAND_SETBANNER_DESCRIPTION("set banner pattern for your faction"), + + + COMMAND_SETDEFAULTROLE_DESCRIPTION("/f defaultrole - set your Faction's default role."), + COMMAND_SETDEFAULTROLE_NOTTHATROLE("&c&l[!]&7 You cannot set the default to admin."), + COMMAND_SETDEFAULTROLE_SUCCESS("Set default role of your faction to %1$s"), + COMMAND_SETDEFAULTROLE_INVALIDROLE("Couldn't find matching role for %1$s"), + + COMMAND_SETFWARP_NOTCLAIMED("&c&l[!]&7 You can &conly&7 set warps in your faction territory."), + COMMAND_SETFWARP_LIMIT("&c&l[!]&7 Your Faction already has the &cmax amount&7 of warps set &c(%1$d)."), + COMMAND_SETFWARP_SET("&c&l[!]&7 Set warp &c%1$s&7 and password &c'%2$s' &7to your location."), + COMMAND_SETFWARP_TOSET("to set warp"), + COMMAND_SETFWARP_FORSET("for setting warp"), + COMMAND_SETFWARP_DESCRIPTION("Set a faction warp"), + + COMMAND_SETHOME_DISABLED("&c&l[!]&7 &cSorry&7, Faction homes are disabled on this server."), + COMMAND_SETHOME_NOTCLAIMED("&c&l[!]&c Sorry&7, your faction home can only be set inside your &cown &7claimed territory."), + COMMAND_SETHOME_TOSET("to set the faction home"), + COMMAND_SETHOME_FORSET("for setting the faction home"), + COMMAND_SETHOME_SET("&c&l[!]&c %1$s&7 set the home for your faction. You can now use:"), + COMMAND_SETHOME_SETOTHER("&c&l[!]&7 You have set the home for the &c%1$s&7 faction."), + COMMAND_SETHOME_DESCRIPTION("Set the faction home"), + + COMMAND_SETMAXVAULTS_DESCRIPTION("Set max vaults for a Faction."), + COMMAND_SETMAXVAULTS_SUCCESS("&aSet max vaults for &e%s &ato &b%d"), + + COMMAND_VAULT_DESCRIPTION("Open your placed faction vault!"), + COMMAND_VAULT_INVALID("&c&l[!]&7 Your vault was either&c claimed&7, &cbroken&7, or has&c not been&7 placed yet."), + COMMAND_VAULT_OPENING("&c&l[!]&7 Opening faction vault."), + COMMAND_VAULT_NO_HOPPER("&c&l[!] &7You cannot place a hopper near a vault!"), + + COMMAND_GETVAULT_ALREADYSET("&c&l[!]&7 Vault has already been set!"), + COMMAND_GETVAULT_ALREADYHAVE("&c&l[!]&7 You already have a vault in your inventory!"), + COMMAND_GETVAULT_CHESTNEAR("&c&l[!]&7 &7There is a chest or hopper &cnearby"), + COMMAND_GETVAULT_SUCCESS("&cSucessfully set vault."), + COMMAND_GETVAULT_INVALIDLOCATION("&cVault can only be placed in faction land!"), + COMMAND_GETVAULT_DESCRIPTION("Get the faction vault item!"), + COMMAND_GETVAULT_RECEIVE("&cYou have recieved a faction vault!"), + COMMAND_GETVAULT_NOMONEY("&cYou do not have enough money"), + COMMAND_GETVAULT_MONEYTAKE("&c{amount} has been taken from your account"), + + COMMAND_SHOW_NOFACTION_SELF("You are not in a faction"), + COMMAND_SHOW_NOFACTION_OTHER("That's not a faction"), + COMMAND_SHOW_TOSHOW("to show faction information"), + COMMAND_SHOW_FORSHOW("for showing faction information"), + COMMAND_SHOW_DESCRIPTION("Description: %1$s"), + COMMAND_SHOW_PEACEFUL("This faction is Peaceful"), + COMMAND_SHOW_PERMANENT("This faction is permanent, remaining even with no members."), + COMMAND_SHOW_JOINING("Joining: %1$s "), + COMMAND_SHOW_INVITATION("invitation is required"), + COMMAND_SHOW_UNINVITED("no invitation is needed"), + COMMAND_SHOW_NOHOME("n/a"), + COMMAND_SHOW_POWER("Land / Power / Maxpower: %1$d/%2$d/%3$d %4$s."), + COMMAND_SHOW_BONUS(" (bonus: "), + COMMAND_SHOW_PENALTY(" (penalty: "), + COMMAND_SHOW_DEPRECIATED("(%1$s depreciated)"), //This is spelled correctly. + COMMAND_SHOW_LANDVALUE("Total land value: %1$s %2$s"), + COMMAND_SHOW_BANKCONTAINS("Bank contains: %1$s"), + COMMAND_SHOW_ALLIES("Allies: "), + COMMAND_SHOW_ENEMIES("Enemies: "), + COMMAND_SHOW_MEMBERSONLINE("Members online: "), + COMMAND_SHOW_MEMBERSOFFLINE("Members offline: "), + COMMAND_SHOW_COMMANDDESCRIPTION("Show faction information"), + COMMAND_SHOW_DEATHS_TIL_RAIDABLE("DTR: %1$d"), + COMMAND_SHOW_EXEMPT("This faction is exempt and cannot be seen."), + COMMAND_SHOW_NEEDFACTION("&cYou need to join a faction to view your own!"), + + COMMAND_SHOWCLAIMS_HEADER("&8&m-------------&8<{faction}'s claims&8>&8&m-------------"), + COMMAND_SHOWCLAIMS_FORMAT("&8[{world}]:"), + COMMAND_SHOWCLAIMS_CHUNKSFORMAT("&8(&c{x}&8,&c{z}&8)"), + COMMAND_SHOWCLAIMS_DESCRIPTION("show your factions claims!"), + + COMMAND_SHOWINVITES_PENDING("Players with pending invites: "), + COMMAND_SHOWINVITES_CLICKTOREVOKE("Click to revoke invite for %1$s"), + COMMAND_SHOWINVITES_DESCRIPTION("Show pending faction invites"), + + COMMAND_STATUS_FORMAT("%1$s Power: %2$s Last Seen: %3$s"), + COMMAND_STATUS_ONLINE("Online"), + COMMAND_STATUS_AGOSUFFIX(" ago."), + COMMAND_STATUS_DESCRIPTION("Show the status of a player"), + + COMMAND_STEALTH_DESCRIPTION("Enable and Disable Stealth Mode"), + COMMAND_STEALTH_ENABLE("&cStealth &7» &7You will no longer disable nearby players in /f fly."), + COMMAND_STEALTH_DISABLE("&cStealth &8» &7You will now disable other nearby players in /f fly."), + COMMAND_STEALTH_MUSTBEMEMBER("&cStealth &8» &4You must be in a faction to use this command"), + + COMMAND_STUCK_TIMEFORMAT("m 'minutes', s 'seconds.'"), + COMMAND_STUCK_CANCELLED("Teleport cancelled because you were damaged"), + COMMAND_STUCK_OUTSIDE("Teleport cancelled because you left %1$d block radius"), + COMMAND_STUCK_EXISTS("You are already teleporting, you must wait %1$s"), + COMMAND_STUCK_START("Teleport will commence in %s. Don't take or deal damage. "), + COMMAND_STUCK_TELEPORT("Teleported safely to %1$d, %2$d, %3$d."), + COMMAND_STUCK_TOSTUCK("to safely teleport %1$s out"), + COMMAND_STUCK_FORSTUCK("for %1$s initiating a safe teleport out"), + COMMAND_STUCK_DESCRIPTION("Safely teleports you out of enemy faction"), + + COMMAND_SEECHUNK_ENABLED("&cSeechunk enabled!"), + COMMAND_SEECHUNK_DISABLED("&cSeechunk disabled!"), + + + COMMAND_TAG_TAKEN("That tag is already taken"), + COMMAND_TAG_TOCHANGE("to change the faction tag"), + COMMAND_TAG_FORCHANGE("for changing the faction tag"), + COMMAND_TAG_FACTION("%1$s changed your faction tag to %2$s"), + COMMAND_TAG_CHANGED("The faction %1$s changed their name to %2$s."), + COMMAND_TAG_DESCRIPTION("Change the faction tag"), + + COMMAND_TITLE_TOCHANGE("to change a players title"), + COMMAND_TITLE_FORCHANGE("for changing a players title"), + COMMAND_TITLE_CHANGED("%1$s changed a title: %2$s"), + COMMAND_TITLE_DESCRIPTION("Set or remove a players title"), + + COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION("Toggles whether or not you will see alliance chat"), + COMMAND_TOGGLEALLIANCECHAT_IGNORE("Alliance chat is now ignored"), + COMMAND_TOGGLEALLIANCECHAT_UNIGNORE("Alliance chat is no longer ignored"), + + COMMAND_TOGGLESB_DISABLED("You can't toggle scoreboards while they are disabled."), + + COMMAND_TOP_DESCRIPTION("Sort Factions to see the top of some criteria."), + COMMAND_TOP_TOP("Top Factions by %s. Page %d/%d"), + COMMAND_TOP_LINE("%d. &6%s: &c%s"), // Rank. Faction: Value + COMMAND_TOP_INVALID("Could not sort by %s. Try balance, online, members, power or land."), + + COMMAND_TNT_DISABLED_MSG("&cThis command is disabled!"), + COMMAND_TNT_INVALID_NUM("The amount needs to be a number!"), + COMMAND_TNT_DEPOSIT_SUCCESS("&cSuccessfully deposited tnt."), + COMMAND_TNT_EXCEEDLIMIT("&cThis exceeds the bank limit!"), + COMMAND_TNT_WIDTHDRAW_SUCCESS("&cSuccessfully withdrew tnt."), + COMMAND_TNT_WIDTHDRAW_NOTENOUGH("&cNot enough tnt in bank."), + COMMAND_TNT_DEPOSIT_NOTENOUGH("&cNot enough tnt in tnt inventory."), + COMMAND_TNT_AMOUNT("&cYour faction has {amount} tnt in the tnt bank."), + COMMAND_TNT_POSITIVE("&cPlease use positive numbers!"), + COMMAND_TNT_DESCRIPTION("add/widthraw from faction's tnt bank"), + COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE("&cNot enough space in your inventory."), + COMMAND_TNT_ADD_DESCRIPTION("&b/f tnt add&3 "), + COMMAND_TNT_TAKE_DESCRIPTION("&b/f tnt take&3 "), + + COMMAND_TNTFILL_HEADER("&c&l[!] &7Filling tnt in dispensers..."), + COMMAND_TNTFILL_SUCCESS("&c&l[!] &7Filled &c{amount}&7 Tnt in &c{dispensers} &7dispensers"), + COMMAND_TNTFILL_NOTENOUGH("&c&l[!] &7Not enough tnt in inventory."), + COMMAND_TNTFILL_RADIUSMAX("&c&l[!] &7The max radius is {max}"), + COMMAND_TNTFILL_AMOUNTMAX("&c&l[!] &7The max amount is {max}"), + COMMAND_TNTFILL_MOD("&c&l[!] &7Tnt will be used from the faction bank because you dont have the specified amount in your inventory and you are a {role}"), + COMMAND_TNTFILL_DESCRIPTION("Fill tnt into dispensers around you"), + + COMMAND_UNBAN_DESCRIPTION("Unban someone from your Faction"), + COMMAND_UNBAN_NOTBANNED("&7%s &cisn't banned. Not doing anything."), + COMMAND_UNBAN_UNBANNED("&e%1$s &cunbanned &7%2$s"), + COMMAND_UNBAN_TARGET("&aYou were unbanned from &r%s"), + + COMMAND_UNCLAIM_SAFEZONE_SUCCESS("Safe zone was unclaimed."), + COMMAND_UNCLAIM_SAFEZONE_NOPERM("This is a safe zone. You lack permissions to unclaim."), + COMMAND_UNCLAIM_WARZONE_SUCCESS("War zone was unclaimed."), + COMMAND_UNCLAIM_WARZONE_NOPERM("This is a war zone. You lack permissions to unclaim."), + COMMAND_UNCLAIM_UNCLAIMED("%1$s unclaimed some of your land."), + COMMAND_UNCLAIM_UNCLAIMS("You unclaimed this land."), + COMMAND_UNCLAIM_LOG("%1$s unclaimed land at (%2$s) from the faction: %3$s"), + COMMAND_UNCLAIM_WRONGFACTION("You don't own this land."), + COMMAND_UNCLAIM_TOUNCLAIM("to unclaim this land"), + COMMAND_UNCLAIM_FORUNCLAIM("for unclaiming this land"), + COMMAND_UNCLAIM_FACTIONUNCLAIMED("%1$s unclaimed some land."), + COMMAND_UNCLAIM_DESCRIPTION("Unclaim the land where you are standing"), + + COMMAND_UNCLAIMALL_TOUNCLAIM("to unclaim all faction land"), + COMMAND_UNCLAIMALL_FORUNCLAIM("for unclaiming all faction land"), + COMMAND_UNCLAIMALL_UNCLAIMED("%1$s unclaimed ALL of your faction's land."), + COMMAND_UNCLAIMALL_LOG("%1$s unclaimed everything for the faction: %2$s"), + COMMAND_UNCLAIMALL_DESCRIPTION("Unclaim all of your factions land"), + COMMAND_UNCLAIM_CLICKTOUNCLAIM("Click to unclaim &2(%1$d, %2$d)"), + + COMMAND_VERSION_NAME("&c&l[!]&7 &c&k||| &r&4SavageFactions&7 &c&k|||&r &c» &7By ProSavage"), + COMMAND_VERSION_VERSION("&7Version &c» &7%1$s"), + COMMAND_VERSION_DESCRIPTION("Show plugin and translation version information"), + + COMMAND_WARUNCLAIMALL_DESCRIPTION("Unclaim all warzone land"), + COMMAND_WARUNCLAIMALL_SUCCESS("You unclaimed ALL war zone land."), + COMMAND_WARUNCLAIMALL_LOG("%1$s unclaimed all war zones."), + + COMMAND_RULES_DISABLED_MSG("&cThis command is disabled!"), + COMMAND_RULES_DESCRIPTION("set/remove/add rules!"), + COMMAND_RULES_ADD_INVALIDARGS("Please include a rule!"), + COMMAND_RULES_SET_INVALIDARGS("Please include a line number & rule!"), + COMMAND_RULES_REMOVE_INVALIDARGS("Please include a line number!"), + COMMAND_RULES_ADD_SUCCESS("&cRule added successfully!"), + COMMAND_RULES_REMOVE_SUCCESS("&cRule removed successfully!"), + COMMAND_RULES_SET_SUCCESS("&cRule set successfully!"), + COMMAND_RULES_CLEAR_SUCCESS("&cRule cleared successfully!"), + + /** + * Leaving - This is accessed through a command, and so it MAY need a COMMAND_* slug :s + */ + LEAVE_PASSADMIN("You must give the admin role to someone else first."), + LEAVE_NEGATIVEPOWER("You cannot leave until your power is positive."), + LEAVE_TOLEAVE("to leave your faction."), + LEAVE_FORLEAVE("for leaving your faction."), + LEAVE_LEFT("%s left faction %s."), + LEAVE_DISBANDED("%s was disbanded."), + LEAVE_DISBANDEDLOG("The faction %s (%s) was disbanded due to the last player (%s) leaving."), + LEAVE_DESCRIPTION("\\n &a&l» &7Leave your faction"), + + /** + * Claiming - Same as above basically. No COMMAND_* because it's not in a command class, but... + */ + CLAIM_PROTECTED("This land is protected"), + CLAIM_DISABLED("Sorry, this world has land claiming disabled."), + CLAIM_CANTCLAIM("You can't claim land for %s."), + CLAIM_ALREADYOWN("%s already own this land."), + CLAIM_MUSTBE("You must be %s to claim land."), + CLAIM_MEMBERS("Factions must have at least %s members to claim land."), + CLAIM_SAFEZONE("You can not claim a Safe Zone."), + CLAIM_WARZONE("You can not claim a War Zone."), + CLAIM_POWER("You can't claim more land!You need more power!"), + CLAIM_LIMIT("Limit reached. You can't claim more land!"), + CLAIM_ALLY("You can't claim the land of your allies."), + CLAIM_CONTIGIOUS("You can only claim additional land which is connected to your first claim or controlled by another faction!"), + CLAIM_FACTIONCONTIGUOUS("You can only claim additional land which is connected to your first claim!"), + CLAIM_PEACEFUL("%s owns this land. Your faction is peaceful, so you cannot claim land from other factions."), + CLAIM_PEACEFULTARGET("%s owns this land, and is a peaceful faction. You cannot claim land from them."), + CLAIM_THISISSPARTA("%s owns this land and is strong enough to keep it."), + CLAIM_BORDER("You must start claiming land at the border of the territory."), + CLAIM_TOCLAIM("to claim this land"), + CLAIM_FORCLAIM("for claiming this land"), + CLAIM_TOOVERCLAIM("to overclaim this land"), + CLAIM_FOROVERCLAIM("for over claiming this land"), + CLAIM_CLAIMED("%s claimed land for %s from %s."), + CLAIM_CLAIMEDLOG("%s claimed land at (%s) for the faction: %s"), + CLAIM_OVERCLAIM_DISABLED("Over claiming is disabled on this server."), + CLAIM_TOOCLOSETOOTHERFACTION("Your claim is too close to another Faction. Buffer required is %d"), + CLAIM_OUTSIDEWORLDBORDER("Your claim is outside the border."), + CLAIM_OUTSIDEBORDERBUFFER("Your claim is outside the border. %d chunks away world edge required."), + CLAIM_CLICK_TO_CLAIM("Click to try to claim &2(%1$d, %2$d)"), + CLAIM_MAP_OUTSIDEBORDER("&cThis claim is outside the worldborder!"), + CLAIM_YOUAREHERE("You are here"), + CLAIM_NO_TERRITORY_PERM("You do not have permission from your faction leader to do this!"), + + /** + * More generic, or less easily categorisable translations, which may apply to more than one class + */ + GENERIC_YOU("you"), + GENERIC_YOURFACTION("your faction"), + GENERIC_NOPERMISSION("You don't have permission to %1$s."), + GENERIC_FPERM_NOPERMISSION("&7The faction leader does not allow you to &c%1$s."), + GENERIC_DOTHAT("do that"), //Ugh nuke this from high orbit + GENERIC_NOPLAYERMATCH("No player match found for \"%1$s\"."), + GENERIC_NOPLAYERFOUND("No player \"%1$s\" could not be found."), + GENERIC_ARGS_TOOFEW("Too few arguments. Use like this:"), + GENERIC_ARGS_TOOMANY("Strange argument \"%1$s\". Use the command like this:"), + GENERIC_DEFAULTDESCRIPTION("Default faction description :("), + GENERIC_OWNERS("Owner(s): %1$s"), + GENERIC_PUBLICLAND("Public faction land."), + GENERIC_FACTIONLESS("factionless"), + GENERIC_SERVERADMIN("A server admin"), + GENERIC_DISABLED("disabled"), + GENERIC_ENABLED("enabled"), + GENERIC_INFINITY("∞"), + GENERIC_CONSOLEONLY("This command cannot be run as a player."), + GENERIC_PLAYERONLY("This command can only be used by ingame players."), + GENERIC_ASKYOURLEADER(" Ask your leader to:"), + GENERIC_YOUSHOULD("You should:"), + GENERIC_YOUMAYWANT("You may want to: "), + GENERIC_TRANSLATION_VERSION("Translation: %1$s(%2$s,%3$s) State: %4$s"), + GENERIC_TRANSLATION_CONTRIBUTORS("Translation contributors: %1$s"), + GENERIC_TRANSLATION_RESPONSIBLE("Responsible for translation: %1$s"), + GENERIC_FACTIONTAG_TOOSHORT("The faction tag can't be shorter than %1$s chars."), + GENERIC_FACTIONTAG_TOOLONG("The faction tag can't be longer than %s chars."), + GENERIC_FACTIONTAG_ALPHANUMERIC("Faction tag must be alphanumeric. \"%s\" is not allowed."), + GENERIC_PLACEHOLDER(""), + GENERIC_NOTENOUGHMONEY("&cYou dont have enough money!"), + GENERIC_MONEYTAKE("&c{amount} has been taken from your account."), + + + WARBANNER_NOFACTION("&cYou need a faction to use a warbanner!"), + WARBANNER_COOLDOWN("&cThe warbanner is on cooldown for your faction!"), + WARBANNER_INVALIDLOC("&cYou can only use warbanners in enemy land or the warzone"), + + /** + * ASCII compass (for chat map) + */ + COMPASS_SHORT_NORTH("N"), + COMPASS_SHORT_EAST("E"), + COMPASS_SHORT_SOUTH("S"), + COMPASS_SHORT_WEST("W"), + + /** + * Chat modes + */ + CHAT_MOD("mod chat"), + CHAT_FACTION("faction chat"), + CHAT_ALLIANCE("alliance chat"), + CHAT_TRUCE("truce chat"), + CHAT_PUBLIC("public chat"), + + /** + * Economy stuff + */ + + ECON_OFF("no %s"), // no balance, no value, no refund, etc + ECON_FORMAT("###,###.###"), + + /** + * Relations + */ + RELATION_MEMBER_SINGULAR("member"), + RELATION_MEMBER_PLURAL("members"), + RELATION_ALLY_SINGULAR("ally"), + RELATION_ALLY_PLURAL("allies"), + RELATION_TRUCE_SINGULAR("truce"), + RELATION_TRUCE_PLURAL("truces"), + RELATION_NEUTRAL_SINGULAR("neutral"), + RELATION_NEUTRAL_PLURAL("neutrals"), + RELATION_ENEMY_SINGULAR("enemy"), + RELATION_ENEMY_PLURAL("enemies"), + + /** + * Roles + */ + ROLE_LEADER("leader"), + ROLE_COLEADER("coleader"), + ROLE_MODERATOR("moderator"), + ROLE_NORMAL("normal member"), + ROLE_RECRUIT("recruit"), + + /** + * Region types. + */ + REGION_SAFEZONE("safezone"), + REGION_WARZONE("warzone"), + REGION_WILDERNESS("wilderness"), + + REGION_PEACEFUL("peaceful territory"), + /** + * In the player and entity listeners + */ + PLAYER_CANTHURT("You may not harm other players in %s"), + PLAYER_SAFEAUTO("This land is now a safe zone."), + PLAYER_WARAUTO("This land is now a war zone."), + PLAYER_OUCH("Ouch, that is starting to hurt. You should give it a rest."), + PLAYER_USE_WILDERNESS("You can't use %s in the wilderness."), + PLAYER_USE_SAFEZONE("You can't use %s in a safe zone."), + PLAYER_USE_WARZONE("You can't use %s in a war zone."), + PLAYER_USE_TERRITORY("You can't %s in the territory of %s."), + PLAYER_USE_OWNED("You can't use %s in this territory, it is owned by: %s."), + PLAYER_COMMAND_WARZONE("You can't use the command '%s' in warzone."), + PLAYER_COMMAND_NEUTRAL("You can't use the command '%s' in neutral territory."), + PLAYER_COMMAND_ENEMY("You can't use the command '%s' in enemy territory."), + PLAYER_COMMAND_PERMANENT("You can't use the command '%s' because you are in a permanent faction."), + PLAYER_COMMAND_ALLY("You can't use the command '%s' in ally territory."), + PLAYER_COMMAND_WILDERNESS("You can't use the command '%s' in the wilderness."), + + PLAYER_POWER_NOLOSS_PEACEFUL("You didn't lose any power since you are in a peaceful faction."), + PLAYER_POWER_NOLOSS_WORLD("You didn't lose any power due to the world you died in."), + PLAYER_POWER_NOLOSS_WILDERNESS("You didn't lose any power since you were in the wilderness."), + PLAYER_POWER_NOLOSS_WARZONE("You didn't lose any power since you were in a war zone."), + PLAYER_POWER_LOSS_WARZONE("The world you are in has power loss normally disabled, but you still lost power since you were in a war zone.\nYour power is now %d / %d"), + PLAYER_POWER_NOW("Your power is now %d / %d"), + + PLAYER_PVP_LOGIN("You can't hurt other players for %d seconds after logging in."), + PLAYER_PVP_REQUIREFACTION("You can't hurt other players until you join a faction."), + PLAYER_PVP_FACTIONLESS("You can't hurt players who are not currently in a faction."), + PLAYER_PVP_PEACEFUL("Peaceful players cannot participate in combat."), + PLAYER_PVP_NEUTRAL("You can't hurt neutral factions. Declare them as an enemy."), + PLAYER_PVP_CANTHURT("You can't hurt %s."), + + PLAYER_PVP_NEUTRALFAIL("You can't hurt %s in their own territory unless you declare them as an enemy."), + PLAYER_PVP_TRIED("%s tried to hurt you."), + + /** + * Strings lying around in other bits of the plugins + */ + NOPAGES("Sorry. No Pages available."), + INVALIDPAGE("Invalid page. Must be between 1 and %1$d"), + + /** + * The ones here before I started messing around with this + */ + TITLE("title", "&bFactions &0|&r"), + WILDERNESS("wilderness", "&2Wilderness"), + WILDERNESS_DESCRIPTION("wilderness-description", ""), + WARZONE("warzone", "&4Warzone"), + WARZONE_DESCRIPTION("warzone-description", "Not the safest place to be."), + SAFEZONE("safezone", "&6Safezone"), + SAFEZONE_DESCRIPTION("safezone-description", "Free from pvp and monsters."), + TOGGLE_SB("toggle-sb", "You now have scoreboards set to {value}"), + FACTION_LEAVE("faction-leave", "Leaving %1$s, Entering %2$s"), + FACTIONS_ANNOUNCEMENT_TOP("faction-announcement-top", "&d--Unread Faction Announcements--"), + FACTIONS_ANNOUNCEMENT_BOTTOM("faction-announcement-bottom", "&d--Unread Faction Announcements--"), + DEFAULT_PREFIX("default-prefix", "{relationcolor}[{faction}]"), + FACTION_LOGIN("faction-login", "&e%1$s &9logged in."), + FACTION_LOGOUT("faction-logout", "&e%1$s &9logged out.."), + NOFACTION_PREFIX("nofactions-prefix", "&6[&a4-&6]&r"), + DATE_FORMAT("date-format", "MM/d/yy h:ma"), // 3/31/15 07:49AM + + /** + * Raidable is used in multiple places. Allow more than just true/false. + */ + RAIDABLE_TRUE("raidable-true", "true"), + RAIDABLE_FALSE("raidable-false", "false"), + /** + * Warmups + */ + WARMUPS_NOTIFY_FLIGHT("&eFlight will enable in &d%2$d &eseconds."), + WARMUPS_NOTIFY_TELEPORT("&eYou will teleport to &d%1$s &ein &d%2$d &eseconds."), + WARMUPS_ALREADY("&cYou are already warming up."), + WARMUPS_CANCELLED("&cYou have cancelled your warmup."); + + public static SimpleDateFormat sdf; + private static YamlConfiguration LANG; + private String path; + private String def; + + /** + * Lang enum constructor. + * + * @param path The string path. + * @param start The default string. + */ + TL(String path, String start) { + this.path = path; + this.def = start; + } + + /** + * Lang enum constructor. Use this when your desired path simply exchanges '_' for '.' + * + * @param start The default string. + */ + TL(String start) { + this.path = this.name().replace('_', '.'); + if (this.path.startsWith(".")) { + path = "root" + path; + } + this.def = start; + } + + /** + * Set the {@code YamlConfiguration} to use. + * + * @param config The config to set. + */ + public static void setFile(YamlConfiguration config) { + LANG = config; + sdf = new SimpleDateFormat(DATE_FORMAT.toString()); + } + + @Override + public String toString() { + return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def)) + (this == TITLE ? " " : ""); + } + + public String format(Object... args) { + return String.format(toString(), args); + } + + /** + * Get the default value of the path. + * + * @return The default value of the path. + */ + public String getDefault() { + return this.def; + } + + /** + * Get the path to the string. + * + * @return The path to the string. + */ + public String getPath() { + return this.path; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java b/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java index 6d726ab6..3392ec7d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java @@ -17,284 +17,284 @@ import java.util.UUID; */ public enum TagReplacer { - /** - * Fancy variables, used by f show - */ - ALLIES_LIST(TagType.FANCY, "{allies-list}"), - ONLINE_LIST(TagType.FANCY, "{online-list}"), - ENEMIES_LIST(TagType.FANCY, "{enemies-list}"), - TRUCES_LIST(TagType.FANCY, "{truces-list}"), - OFFLINE_LIST(TagType.FANCY, "{offline-list}"), + /** + * Fancy variables, used by f show + */ + ALLIES_LIST(TagType.FANCY, "{allies-list}"), + ONLINE_LIST(TagType.FANCY, "{online-list}"), + ENEMIES_LIST(TagType.FANCY, "{enemies-list}"), + TRUCES_LIST(TagType.FANCY, "{truces-list}"), + OFFLINE_LIST(TagType.FANCY, "{offline-list}"), - /** - * Player variables, require a player - */ - PLAYER_GROUP(TagType.PLAYER, "{group}"), - LAST_SEEN(TagType.PLAYER, "{lastSeen}"), - PLAYER_BALANCE(TagType.PLAYER, "{balance}"), - PLAYER_POWER(TagType.PLAYER, "{player-power}"), - PLAYER_MAXPOWER(TagType.PLAYER, "{player-maxpower}"), - PLAYER_KILLS(TagType.PLAYER, "{player-kills}"), - PLAYER_DEATHS(TagType.PLAYER, "{player-deaths}"), + /** + * Player variables, require a player + */ + PLAYER_GROUP(TagType.PLAYER, "{group}"), + LAST_SEEN(TagType.PLAYER, "{lastSeen}"), + PLAYER_BALANCE(TagType.PLAYER, "{balance}"), + PLAYER_POWER(TagType.PLAYER, "{player-power}"), + PLAYER_MAXPOWER(TagType.PLAYER, "{player-maxpower}"), + PLAYER_KILLS(TagType.PLAYER, "{player-kills}"), + PLAYER_DEATHS(TagType.PLAYER, "{player-deaths}"), - /** - * Faction variables, require at least a player - */ - HOME_X(TagType.FACTION, "{x}"), - HOME_Y(TagType.FACTION, "{y}"), - HOME_Z(TagType.FACTION, "{z}"), - CHUNKS(TagType.FACTION, "{chunks}"), - WARPS(TagType.FACTION, "{warps}"), - HEADER(TagType.FACTION, "{header}"), - POWER(TagType.FACTION, "{power}"), - MAX_POWER(TagType.FACTION, "{maxPower}"), - POWER_BOOST(TagType.FACTION, "{power-boost}"), - LEADER(TagType.FACTION, "{leader}"), - JOINING(TagType.FACTION, "{joining}"), - FACTION(TagType.FACTION, "{faction}"), - PLAYER_NAME(TagType.FACTION, "{name}"), - HOME_WORLD(TagType.FACTION, "{world}"), - RAIDABLE(TagType.FACTION, "{raidable}"), - PEACEFUL(TagType.FACTION, "{peaceful}"), - PERMANENT(TagType.FACTION, "permanent"), // no braces needed - TIME_LEFT(TagType.FACTION, "{time-left}"), - LAND_VALUE(TagType.FACTION, "{land-value}"), - DESCRIPTION(TagType.FACTION, "{description}"), - CREATE_DATE(TagType.FACTION, "{create-date}"), - LAND_REFUND(TagType.FACTION, "{land-refund}"), - BANK_BALANCE(TagType.FACTION, "{faction-balance}"), - ALLIES_COUNT(TagType.FACTION, "{allies}"), - ENEMIES_COUNT(TagType.FACTION, "{enemies}"), - TRUCES_COUNT(TagType.FACTION, "{truces}"), - ONLINE_COUNT(TagType.FACTION, "{online}"), - OFFLINE_COUNT(TagType.FACTION, "{offline}"), - FACTION_SIZE(TagType.FACTION, "{members}"), - FACTION_KILLS(TagType.FACTION, "{faction-kills}"), - FACTION_DEATHS(TagType.FACTION, "{faction-deaths}"), - FACTION_BANCOUNT(TagType.FACTION, "{faction-bancount}"), + /** + * Faction variables, require at least a player + */ + HOME_X(TagType.FACTION, "{x}"), + HOME_Y(TagType.FACTION, "{y}"), + HOME_Z(TagType.FACTION, "{z}"), + CHUNKS(TagType.FACTION, "{chunks}"), + WARPS(TagType.FACTION, "{warps}"), + HEADER(TagType.FACTION, "{header}"), + POWER(TagType.FACTION, "{power}"), + MAX_POWER(TagType.FACTION, "{maxPower}"), + POWER_BOOST(TagType.FACTION, "{power-boost}"), + LEADER(TagType.FACTION, "{leader}"), + JOINING(TagType.FACTION, "{joining}"), + FACTION(TagType.FACTION, "{faction}"), + PLAYER_NAME(TagType.FACTION, "{name}"), + HOME_WORLD(TagType.FACTION, "{world}"), + RAIDABLE(TagType.FACTION, "{raidable}"), + PEACEFUL(TagType.FACTION, "{peaceful}"), + PERMANENT(TagType.FACTION, "permanent"), // no braces needed + TIME_LEFT(TagType.FACTION, "{time-left}"), + LAND_VALUE(TagType.FACTION, "{land-value}"), + DESCRIPTION(TagType.FACTION, "{description}"), + CREATE_DATE(TagType.FACTION, "{create-date}"), + LAND_REFUND(TagType.FACTION, "{land-refund}"), + BANK_BALANCE(TagType.FACTION, "{faction-balance}"), + ALLIES_COUNT(TagType.FACTION, "{allies}"), + ENEMIES_COUNT(TagType.FACTION, "{enemies}"), + TRUCES_COUNT(TagType.FACTION, "{truces}"), + ONLINE_COUNT(TagType.FACTION, "{online}"), + OFFLINE_COUNT(TagType.FACTION, "{offline}"), + FACTION_SIZE(TagType.FACTION, "{members}"), + FACTION_KILLS(TagType.FACTION, "{faction-kills}"), + FACTION_DEATHS(TagType.FACTION, "{faction-deaths}"), + FACTION_BANCOUNT(TagType.FACTION, "{faction-bancount}"), - /** - * General variables, require no faction or player - */ - MAX_WARPS(TagType.GENERAL, "{max-warps}"), - MAX_ALLIES(TagType.GENERAL, "{max-allies}"), - MAX_ENEMIES(TagType.GENERAL, "{max-enemies}"), - MAX_TRUCES(TagType.GENERAL, "{max-truces}"), - FACTIONLESS(TagType.GENERAL, "{factionless}"), - TOTAL_ONLINE(TagType.GENERAL, "{total-online}"); + /** + * General variables, require no faction or player + */ + MAX_WARPS(TagType.GENERAL, "{max-warps}"), + MAX_ALLIES(TagType.GENERAL, "{max-allies}"), + MAX_ENEMIES(TagType.GENERAL, "{max-enemies}"), + MAX_TRUCES(TagType.GENERAL, "{max-truces}"), + FACTIONLESS(TagType.GENERAL, "{factionless}"), + TOTAL_ONLINE(TagType.GENERAL, "{total-online}"); - private TagType type; - private String tag; + private TagType type; + private String tag; - TagReplacer(TagType type, String tag) { - this.type = type; - this.tag = tag; - } + TagReplacer(TagType type, String tag) { + this.type = type; + this.tag = tag; + } - /** - * Returns a list of all the variables we can use for this type
    - * - * @param type the type we want - * @return a list of all the variables with this type - */ - protected static List getByType(TagType type) { - List tagReplacers = new ArrayList<>(); - for (TagReplacer tagReplacer : TagReplacer.values()) { - if (type == TagType.FANCY) { - if (tagReplacer.type == TagType.FANCY) { - tagReplacers.add(tagReplacer); - } - } else if (tagReplacer.type.id >= type.id) { - tagReplacers.add(tagReplacer); - } - } - return tagReplacers; - } + /** + * Returns a list of all the variables we can use for this type
    + * + * @param type the type we want + * @return a list of all the variables with this type + */ + protected static List getByType(TagType type) { + List tagReplacers = new ArrayList<>(); + for (TagReplacer tagReplacer : TagReplacer.values()) { + if (type == TagType.FANCY) { + if (tagReplacer.type == TagType.FANCY) { + tagReplacers.add(tagReplacer); + } + } else if (tagReplacer.type.id >= type.id) { + tagReplacers.add(tagReplacer); + } + } + return tagReplacers; + } - /** - * Protected access to this generic server related variable - * - * @return value for this generic server related variable
    - */ - protected String getValue() { - switch (this) { - case TOTAL_ONLINE: - return String.valueOf(Bukkit.getOnlinePlayers().size()); - case FACTIONLESS: - return String.valueOf(Factions.getInstance().getWilderness().getFPlayersWhereOnline(true).size()); - case MAX_ALLIES: - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.ally", 10)); - } - return TL.GENERIC_INFINITY.toString(); - case MAX_ENEMIES: - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.enemy", 10)); - } - return TL.GENERIC_INFINITY.toString(); - case MAX_TRUCES: - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.truce", 10)); - } - return TL.GENERIC_INFINITY.toString(); - case MAX_WARPS: - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-warps", 5)); - default: - } - return null; - } + /** + * Protected access to this generic server related variable + * + * @return value for this generic server related variable
    + */ + protected String getValue() { + switch (this) { + case TOTAL_ONLINE: + return String.valueOf(Bukkit.getOnlinePlayers().size()); + case FACTIONLESS: + return String.valueOf(Factions.getInstance().getWilderness().getFPlayersWhereOnline(true).size()); + case MAX_ALLIES: + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.ally", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_ENEMIES: + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.enemy", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_TRUCES: + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.truce", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_WARPS: + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-warps", 5)); + default: + } + return null; + } - /** - * Gets the value for this (as in the instance this is called from) variable! - * - * @param fac Target faction - * @param fp Target player (can be null) - * @return the value for this enum! - */ - protected String getValue(Faction fac, FPlayer fp) { - if (this.type == TagType.GENERAL) { - return getValue(); - } + /** + * Gets the value for this (as in the instance this is called from) variable! + * + * @param fac Target faction + * @param fp Target player (can be null) + * @return the value for this enum! + */ + protected String getValue(Faction fac, FPlayer fp) { + if (this.type == TagType.GENERAL) { + return getValue(); + } - boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); + boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); - if (fp != null) { - switch (this) { - case HEADER: - return SavageFactions.plugin.txt.titleize(fac.getTag(fp)); - case PLAYER_NAME: - return fp.getName(); - case FACTION: - return !fac.isWilderness() ? fac.getTag(fp) : TL.GENERIC_FACTIONLESS.toString(); - case LAST_SEEN: - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; - return fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - case PLAYER_GROUP: - return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fp.getId()))); - case PLAYER_BALANCE: - return Econ.isSetup() ? Econ.getFriendlyBalance(fp) : TL.ECON_OFF.format("balance"); - case PLAYER_POWER: - return String.valueOf(fp.getPowerRounded()); - case PLAYER_MAXPOWER: - return String.valueOf(fp.getPowerMaxRounded()); - case PLAYER_KILLS: - return String.valueOf(fp.getKills()); - case PLAYER_DEATHS: - return String.valueOf(fp.getDeaths()); - default: - } - } + if (fp != null) { + switch (this) { + case HEADER: + return SavageFactions.plugin.txt.titleize(fac.getTag(fp)); + case PLAYER_NAME: + return fp.getName(); + case FACTION: + return !fac.isWilderness() ? fac.getTag(fp) : TL.GENERIC_FACTIONLESS.toString(); + case LAST_SEEN: + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + return fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + case PLAYER_GROUP: + return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fp.getId()))); + case PLAYER_BALANCE: + return Econ.isSetup() ? Econ.getFriendlyBalance(fp) : TL.ECON_OFF.format("balance"); + case PLAYER_POWER: + return String.valueOf(fp.getPowerRounded()); + case PLAYER_MAXPOWER: + return String.valueOf(fp.getPowerMaxRounded()); + case PLAYER_KILLS: + return String.valueOf(fp.getKills()); + case PLAYER_DEATHS: + return String.valueOf(fp.getDeaths()); + default: + } + } - switch (this) { - case DESCRIPTION: - return fac.getDescription(); - case FACTION: - return fac.getTag(); - case JOINING: - return (fac.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); - case PEACEFUL: - return fac.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; - case PERMANENT: - return fac.isPermanent() ? "permanent" : "{notPermanent}"; - case CHUNKS: - return String.valueOf(fac.getLandRounded()); - case POWER: - return String.valueOf(fac.getPowerRounded()); - case MAX_POWER: - return String.valueOf(fac.getPowerMaxRounded()); - case POWER_BOOST: - double powerBoost = fac.getPowerBoost(); - return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); - case LEADER: - FPlayer fAdmin = fac.getFPlayerAdmin(); - return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); - case WARPS: - return String.valueOf(fac.getWarps().size()); - case CREATE_DATE: - return TL.sdf.format(fac.getFoundedDate()); - case RAIDABLE: - boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && fac.getLandRounded() >= fac.getPowerRounded(); - return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); - case HOME_WORLD: - return fac.hasHome() ? fac.getHome().getWorld().getName() : minimal ? null : "{ig}"; - case HOME_X: - return fac.hasHome() ? String.valueOf(fac.getHome().getBlockX()) : minimal ? null : "{ig}"; - case HOME_Y: - return fac.hasHome() ? String.valueOf(fac.getHome().getBlockY()) : minimal ? null : "{ig}"; - case HOME_Z: - return fac.hasHome() ? String.valueOf(fac.getHome().getBlockZ()) : minimal ? null : "{ig}"; - case LAND_VALUE: - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("value"); - case LAND_REFUND: - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("refund"); - case BANK_BALANCE: - if (Econ.shouldBeUsed()) { - return Conf.bankEnabled ? Econ.moneyString(Econ.getBalance(fac.getAccountId())) : minimal ? null : TL.ECON_OFF.format("balance"); - } - return minimal ? null : TL.ECON_OFF.format("balance"); - case ALLIES_COUNT: - return String.valueOf(fac.getRelationCount(Relation.ALLY)); - case ENEMIES_COUNT: - return String.valueOf(fac.getRelationCount(Relation.ENEMY)); - case TRUCES_COUNT: - return String.valueOf(fac.getRelationCount(Relation.TRUCE)); - case ONLINE_COUNT: - if (fp != null && fp.isOnline()) { - return String.valueOf(fac.getFPlayersWhereOnline(true, fp).size()); - } else { - // Only console should ever get here. - return String.valueOf(fac.getFPlayersWhereOnline(true).size()); - } - case OFFLINE_COUNT: - return String.valueOf(fac.getFPlayers().size() - fac.getOnlinePlayers().size()); - case FACTION_SIZE: - return String.valueOf(fac.getFPlayers().size()); - case FACTION_KILLS: - return String.valueOf(fac.getKills()); - case FACTION_DEATHS: - return String.valueOf(fac.getDeaths()); - case FACTION_BANCOUNT: - return String.valueOf(fac.getBannedPlayers().size()); - default: - } - return null; - } + switch (this) { + case DESCRIPTION: + return fac.getDescription(); + case FACTION: + return fac.getTag(); + case JOINING: + return (fac.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); + case PEACEFUL: + return fac.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; + case PERMANENT: + return fac.isPermanent() ? "permanent" : "{notPermanent}"; + case CHUNKS: + return String.valueOf(fac.getLandRounded()); + case POWER: + return String.valueOf(fac.getPowerRounded()); + case MAX_POWER: + return String.valueOf(fac.getPowerMaxRounded()); + case POWER_BOOST: + double powerBoost = fac.getPowerBoost(); + return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); + case LEADER: + FPlayer fAdmin = fac.getFPlayerAdmin(); + return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); + case WARPS: + return String.valueOf(fac.getWarps().size()); + case CREATE_DATE: + return TL.sdf.format(fac.getFoundedDate()); + case RAIDABLE: + boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && fac.getLandRounded() >= fac.getPowerRounded(); + return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); + case HOME_WORLD: + return fac.hasHome() ? fac.getHome().getWorld().getName() : minimal ? null : "{ig}"; + case HOME_X: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockX()) : minimal ? null : "{ig}"; + case HOME_Y: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockY()) : minimal ? null : "{ig}"; + case HOME_Z: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockZ()) : minimal ? null : "{ig}"; + case LAND_VALUE: + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("value"); + case LAND_REFUND: + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("refund"); + case BANK_BALANCE: + if (Econ.shouldBeUsed()) { + return Conf.bankEnabled ? Econ.moneyString(Econ.getBalance(fac.getAccountId())) : minimal ? null : TL.ECON_OFF.format("balance"); + } + return minimal ? null : TL.ECON_OFF.format("balance"); + case ALLIES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.ALLY)); + case ENEMIES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.ENEMY)); + case TRUCES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.TRUCE)); + case ONLINE_COUNT: + if (fp != null && fp.isOnline()) { + return String.valueOf(fac.getFPlayersWhereOnline(true, fp).size()); + } else { + // Only console should ever get here. + return String.valueOf(fac.getFPlayersWhereOnline(true).size()); + } + case OFFLINE_COUNT: + return String.valueOf(fac.getFPlayers().size() - fac.getOnlinePlayers().size()); + case FACTION_SIZE: + return String.valueOf(fac.getFPlayers().size()); + case FACTION_KILLS: + return String.valueOf(fac.getKills()); + case FACTION_DEATHS: + return String.valueOf(fac.getDeaths()); + case FACTION_BANCOUNT: + return String.valueOf(fac.getBannedPlayers().size()); + default: + } + return null; + } - /** - * @param original raw line with variables - * @param value what to replace var in raw line with - * @return the string with the new value - */ - public String replace(String original, String value) { - return original.replace(tag, value); - } + /** + * @param original raw line with variables + * @param value what to replace var in raw line with + * @return the string with the new value + */ + public String replace(String original, String value) { + return original.replace(tag, value); + } - /** - * @param toSearch raw line with variables - * @return if the raw line contains this enums variable - */ - public boolean contains(String toSearch) { - if (tag == null) { - return false; - } - return toSearch.contains(tag); - } + /** + * @param toSearch raw line with variables + * @return if the raw line contains this enums variable + */ + public boolean contains(String toSearch) { + if (tag == null) { + return false; + } + return toSearch.contains(tag); + } - /** - * Gets the tag associated with this enum that we should replace - * - * @return the {....} variable that is located in config - */ - public String getTag() { - return this.tag; - } + /** + * Gets the tag associated with this enum that we should replace + * + * @return the {....} variable that is located in config + */ + public String getTag() { + return this.tag; + } - protected enum TagType { - FANCY(0), PLAYER(1), FACTION(2), GENERAL(3); - public int id; + protected enum TagType { + FANCY(0), PLAYER(1), FACTION(2), GENERAL(3); + public int id; - TagType(int id) { - this.id = id; - } - } + TagType(int id) { + this.id = id; + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java index da621d69..e0639037 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java @@ -19,250 +19,250 @@ import static com.massivecraft.factions.zcore.util.TagReplacer.TagType; public class TagUtil { - private static final int ARBITRARY_LIMIT = 25000; + private static final int ARBITRARY_LIMIT = 25000; - /** - * Replaces all variables in a plain raw line for a faction - * - * @param faction for faction - * @param line raw line from config with variables to replace for - * @return clean line - */ - public static String parsePlain(Faction faction, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FACTION)) { - if (tagReplacer.contains(line)) { - line = tagReplacer.replace(line, tagReplacer.getValue(faction, null)); - } - } - return line; - } + /** + * Replaces all variables in a plain raw line for a faction + * + * @param faction for faction + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(Faction faction, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FACTION)) { + if (tagReplacer.contains(line)) { + line = tagReplacer.replace(line, tagReplacer.getValue(faction, null)); + } + } + return line; + } - /** - * Replaces all variables in a plain raw line for a player - * - * @param fplayer for player - * @param line raw line from config with variables to replace for - * @return clean line - */ - public static String parsePlain(FPlayer fplayer, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { - if (tagReplacer.contains(line)) { - String rep = tagReplacer.getValue(fplayer.getFaction(), fplayer); - if (rep == null) { - rep = ""; // this should work, but it's not a good way to handle whatever is going wrong - } - line = tagReplacer.replace(line, rep); - } - } - return line; - } + /** + * Replaces all variables in a plain raw line for a player + * + * @param fplayer for player + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(FPlayer fplayer, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { + if (tagReplacer.contains(line)) { + String rep = tagReplacer.getValue(fplayer.getFaction(), fplayer); + if (rep == null) { + rep = ""; // this should work, but it's not a good way to handle whatever is going wrong + } + line = tagReplacer.replace(line, rep); + } + } + return line; + } - /** - * Replaces all variables in a plain raw line for a faction, using relations from fplayer - * - * @param faction for faction - * @param fplayer from player - * @param line raw line from config with variables to replace for - * @return clean line - */ - public static String parsePlain(Faction faction, FPlayer fplayer, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { - if (tagReplacer.contains(line)) { - String value = tagReplacer.getValue(faction, fplayer); - if (value != null) { - line = tagReplacer.replace(line, value); - } else { - return null; // minimal show, entire line to be ignored - } - } - } - return line; - } + /** + * Replaces all variables in a plain raw line for a faction, using relations from fplayer + * + * @param faction for faction + * @param fplayer from player + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(Faction faction, FPlayer fplayer, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { + if (tagReplacer.contains(line)) { + String value = tagReplacer.getValue(faction, fplayer); + if (value != null) { + line = tagReplacer.replace(line, value); + } else { + return null; // minimal show, entire line to be ignored + } + } + } + return line; + } - /** - * Scan a line and parse the fancy variable into a fancy list - * - * @param faction for faction (viewers faction) - * @param fme for player (viewer) - * @param line fancy message prefix - * @return list of fancy msgs - */ - public static List parseFancy(Faction faction, FPlayer fme, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { - if (tagReplacer.contains(line)) { - String clean = line.replace(tagReplacer.getTag(), ""); // remove tag - return getFancy(faction, fme, tagReplacer, clean); - } - } - return null; - } + /** + * Scan a line and parse the fancy variable into a fancy list + * + * @param faction for faction (viewers faction) + * @param fme for player (viewer) + * @param line fancy message prefix + * @return list of fancy msgs + */ + public static List parseFancy(Faction faction, FPlayer fme, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { + if (tagReplacer.contains(line)) { + String clean = line.replace(tagReplacer.getTag(), ""); // remove tag + return getFancy(faction, fme, tagReplacer, clean); + } + } + return null; + } - public static String parsePlaceholders(Player player, String line) { - if (SavageFactions.plugin.isClipPlaceholderAPIHooked() && player.isOnline()) { - line = PlaceholderAPI.setPlaceholders(player, line); - } + public static String parsePlaceholders(Player player, String line) { + if (SavageFactions.plugin.isClipPlaceholderAPIHooked() && player.isOnline()) { + line = PlaceholderAPI.setPlaceholders(player, line); + } - if (SavageFactions.plugin.isMVdWPlaceholderAPIHooked() && player.isOnline()) { - line = be.maximvdw.placeholderapi.PlaceholderAPI.replacePlaceholders(player, line); - } + if (SavageFactions.plugin.isMVdWPlaceholderAPIHooked() && player.isOnline()) { + line = be.maximvdw.placeholderapi.PlaceholderAPI.replacePlaceholders(player, line); + } - return line; - } + return line; + } - /** - * Checks if a line has fancy variables - * - * @param line raw line from config with variables - * @return if the line has fancy variables - */ - public static boolean hasFancy(String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { - if (tagReplacer.contains(line)) { - return true; - } - } - return false; - } + /** + * Checks if a line has fancy variables + * + * @param line raw line from config with variables + * @return if the line has fancy variables + */ + public static boolean hasFancy(String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { + if (tagReplacer.contains(line)) { + return true; + } + } + return false; + } - /** - * Lets get fancy. - * - * @param target Faction to get relate from - * @param fme Player to relate to - * @param prefix First part of the fancy message - * @return list of fancy messages to send - */ - protected static List getFancy(Faction target, FPlayer fme, TagReplacer type, String prefix) { - List fancyMessages = new ArrayList<>(); - boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); + /** + * Lets get fancy. + * + * @param target Faction to get relate from + * @param fme Player to relate to + * @param prefix First part of the fancy message + * @return list of fancy messages to send + */ + protected static List getFancy(Faction target, FPlayer fme, TagReplacer type, String prefix) { + List fancyMessages = new ArrayList<>(); + boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); - switch (type) { - case ALLIES_LIST: - FancyMessage currentAllies = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstAlly = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == target) { - continue; - } - String s = otherFaction.getTag(fme); - if (otherFaction.getRelationTo(target).isAlly()) { - currentAllies.then(firstAlly ? s : ", " + s); - currentAllies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); - firstAlly = false; - if (currentAllies.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentAllies); - currentAllies = new FancyMessage(""); - } - } - } - fancyMessages.add(currentAllies); - return firstAlly && minimal ? null : fancyMessages; // we must return here and not outside the switch - case ENEMIES_LIST: - FancyMessage currentEnemies = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstEnemy = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == target) { - continue; - } - String s = otherFaction.getTag(fme); - if (otherFaction.getRelationTo(target).isEnemy()) { - currentEnemies.then(firstEnemy ? s : ", " + s); - currentEnemies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); - firstEnemy = false; - if (currentEnemies.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentEnemies); - currentEnemies = new FancyMessage(""); - } - } - } - fancyMessages.add(currentEnemies); - return firstEnemy && minimal ? null : fancyMessages; // we must return here and not outside the switch - case TRUCES_LIST: - FancyMessage currentTruces = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstTruce = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == target) { - continue; - } - String s = otherFaction.getTag(fme); - if (otherFaction.getRelationTo(target).isTruce()) { - currentTruces.then(firstTruce ? s : ", " + s); - currentTruces.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); - firstTruce = false; - if (currentTruces.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentTruces); - currentTruces = new FancyMessage(""); - } - } - } - fancyMessages.add(currentTruces); - return firstTruce && minimal ? null : fancyMessages; // we must return here and not outside the switch - case ONLINE_LIST: - FancyMessage currentOnline = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstOnline = true; - for (FPlayer p : MiscUtil.rankOrder(target.getFPlayersWhereOnline(true, fme))) { - if (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer())) { - continue; // skip - } - String name = p.getNameAndTitle(); - currentOnline.then(firstOnline ? name : ", " + name); - currentOnline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); - firstOnline = false; - if (currentOnline.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentOnline); - currentOnline = new FancyMessage(""); - } - } - fancyMessages.add(currentOnline); - return firstOnline && minimal ? null : fancyMessages; // we must return here and not outside the switch - case OFFLINE_LIST: - FancyMessage currentOffline = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstOffline = true; - for (FPlayer p : MiscUtil.rankOrder(target.getFPlayers())) { - String name = p.getNameAndTitle(); - // Also make sure to add players that are online BUT can't be seen. - if (!p.isOnline() || (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer()))) { - currentOffline.then(firstOffline ? name : ", " + name); - currentOffline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); - firstOffline = false; - if (currentOffline.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentOffline); - currentOffline = new FancyMessage(""); - } - } - } - fancyMessages.add(currentOffline); - return firstOffline && minimal ? null : fancyMessages; // we must return here and not outside the switch - default: - } - return null; - } + switch (type) { + case ALLIES_LIST: + FancyMessage currentAllies = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstAlly = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isAlly()) { + currentAllies.then(firstAlly ? s : ", " + s); + currentAllies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); + firstAlly = false; + if (currentAllies.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentAllies); + currentAllies = new FancyMessage(""); + } + } + } + fancyMessages.add(currentAllies); + return firstAlly && minimal ? null : fancyMessages; // we must return here and not outside the switch + case ENEMIES_LIST: + FancyMessage currentEnemies = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstEnemy = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isEnemy()) { + currentEnemies.then(firstEnemy ? s : ", " + s); + currentEnemies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); + firstEnemy = false; + if (currentEnemies.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentEnemies); + currentEnemies = new FancyMessage(""); + } + } + } + fancyMessages.add(currentEnemies); + return firstEnemy && minimal ? null : fancyMessages; // we must return here and not outside the switch + case TRUCES_LIST: + FancyMessage currentTruces = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstTruce = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isTruce()) { + currentTruces.then(firstTruce ? s : ", " + s); + currentTruces.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); + firstTruce = false; + if (currentTruces.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentTruces); + currentTruces = new FancyMessage(""); + } + } + } + fancyMessages.add(currentTruces); + return firstTruce && minimal ? null : fancyMessages; // we must return here and not outside the switch + case ONLINE_LIST: + FancyMessage currentOnline = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstOnline = true; + for (FPlayer p : MiscUtil.rankOrder(target.getFPlayersWhereOnline(true, fme))) { + if (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer())) { + continue; // skip + } + String name = p.getNameAndTitle(); + currentOnline.then(firstOnline ? name : ", " + name); + currentOnline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); + firstOnline = false; + if (currentOnline.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentOnline); + currentOnline = new FancyMessage(""); + } + } + fancyMessages.add(currentOnline); + return firstOnline && minimal ? null : fancyMessages; // we must return here and not outside the switch + case OFFLINE_LIST: + FancyMessage currentOffline = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstOffline = true; + for (FPlayer p : MiscUtil.rankOrder(target.getFPlayers())) { + String name = p.getNameAndTitle(); + // Also make sure to add players that are online BUT can't be seen. + if (!p.isOnline() || (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer()))) { + currentOffline.then(firstOffline ? name : ", " + name); + currentOffline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); + firstOffline = false; + if (currentOffline.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentOffline); + currentOffline = new FancyMessage(""); + } + } + } + fancyMessages.add(currentOffline); + return firstOffline && minimal ? null : fancyMessages; // we must return here and not outside the switch + default: + } + return null; + } - /** - * Parses tooltip variables from config
    Supports variables for factions only (type 2) - * - * @param faction faction to tooltip for - * @return list of tooltips for a fancy message - */ - private static List tipFaction(Faction faction) { - List lines = new ArrayList<>(); - for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.list")) { - lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(faction, line))); - } - return lines; - } + /** + * Parses tooltip variables from config
    Supports variables for factions only (type 2) + * + * @param faction faction to tooltip for + * @return list of tooltips for a fancy message + */ + private static List tipFaction(Faction faction) { + List lines = new ArrayList<>(); + for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.list")) { + lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(faction, line))); + } + return lines; + } - /** - * Parses tooltip variables from config
    Supports variables for players and factions (types 1 and 2) - * - * @param fplayer player to tooltip for - * @return list of tooltips for a fancy message - */ - private static List tipPlayer(FPlayer fplayer) { - List lines = new ArrayList<>(); - for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.show")) { - lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(fplayer, line))); - } - return lines; - } + /** + * Parses tooltip variables from config
    Supports variables for players and factions (types 1 and 2) + * + * @param fplayer player to tooltip for + * @return list of tooltips for a fancy message + */ + private static List tipPlayer(FPlayer fplayer) { + List lines = new ArrayList<>(); + for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.show")) { + lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(fplayer, line))); + } + return lines; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java index 6b58ff69..1c6a4045 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java @@ -10,223 +10,223 @@ import java.util.regex.Pattern; public class TextUtil { - public static final transient Pattern patternTag = Pattern.compile("<([a-zA-Z0-9_]*)>"); - private final static String titleizeLine = repeat("-", 52); + public static final transient Pattern patternTag = Pattern.compile("<([a-zA-Z0-9_]*)>"); + private final static String titleizeLine = repeat("-", 52); - // -------------------------------------------- // - // Top-level parsing functions. - // -------------------------------------------- // - private final static int titleizeBalance = -1; - public Map tags; + // -------------------------------------------- // + // Top-level parsing functions. + // -------------------------------------------- // + private final static int titleizeBalance = -1; + public Map tags; - // -------------------------------------------- // - // Tag parsing - // -------------------------------------------- // + // -------------------------------------------- // + // Tag parsing + // -------------------------------------------- // - public TextUtil() { - this.tags = new HashMap<>(); - } + public TextUtil() { + this.tags = new HashMap<>(); + } - public static String replaceTags(String str, Map tags) { - StringBuffer ret = new StringBuffer(); - Matcher matcher = patternTag.matcher(str); - while (matcher.find()) { - String tag = matcher.group(1); - String repl = tags.get(tag); - if (repl == null) { - matcher.appendReplacement(ret, "<" + tag + ">"); - } else { - matcher.appendReplacement(ret, repl); - } - } - matcher.appendTail(ret); - return ret.toString(); - } + public static String replaceTags(String str, Map tags) { + StringBuffer ret = new StringBuffer(); + Matcher matcher = patternTag.matcher(str); + while (matcher.find()) { + String tag = matcher.group(1); + String repl = tags.get(tag); + if (repl == null) { + matcher.appendReplacement(ret, "<" + tag + ">"); + } else { + matcher.appendReplacement(ret, repl); + } + } + matcher.appendTail(ret); + return ret.toString(); + } - public static FancyMessage toFancy(String first) { - String text = ""; - FancyMessage message = new FancyMessage(text); - ChatColor color = null; - char[] chars = first.toCharArray(); + public static FancyMessage toFancy(String first) { + String text = ""; + FancyMessage message = new FancyMessage(text); + ChatColor color = null; + char[] chars = first.toCharArray(); - for (int i = 0; i < chars.length; i++) { - // changed this so javadocs wont throw an error - String compareChar = chars[i] + ""; - if (compareChar.equals("§")) { - if (color != null) { - if (color.isColor()) { - message.then(text).color(color); - } else { - message.then(text).style(color); - } - text = ""; - color = ChatColor.getByChar(chars[i + 1]); - } else { - color = ChatColor.getByChar(chars[i + 1]); - } - i++; // skip color char - } else { - text += chars[i]; - } - } - if (text.length() > 0) { - if (color != null) { - if (color.isColor()) { - message.then(text).color(color); - } else { - message.then(text).style(color); - } - } else { - message.text(text); - } - } - return message; - } + for (int i = 0; i < chars.length; i++) { + // changed this so javadocs wont throw an error + String compareChar = chars[i] + ""; + if (compareChar.equals("§")) { + if (color != null) { + if (color.isColor()) { + message.then(text).color(color); + } else { + message.then(text).style(color); + } + text = ""; + color = ChatColor.getByChar(chars[i + 1]); + } else { + color = ChatColor.getByChar(chars[i + 1]); + } + i++; // skip color char + } else { + text += chars[i]; + } + } + if (text.length() > 0) { + if (color != null) { + if (color.isColor()) { + message.then(text).color(color); + } else { + message.then(text).style(color); + } + } else { + message.text(text); + } + } + return message; + } - // -------------------------------------------- // - // Fancy parsing - // -------------------------------------------- // + // -------------------------------------------- // + // Fancy parsing + // -------------------------------------------- // - public static String parseColor(String string) { - string = parseColorAmp(string); - string = parseColorAcc(string); - string = parseColorTags(string); - return ChatColor.translateAlternateColorCodes('&', string); - } + public static String parseColor(String string) { + string = parseColorAmp(string); + string = parseColorAcc(string); + string = parseColorTags(string); + return ChatColor.translateAlternateColorCodes('&', string); + } - public static String parseColorAmp(String string) { - string = string.replaceAll("(§([a-z0-9]))", "\u00A7$2"); - string = string.replaceAll("(&([a-z0-9]))", "\u00A7$2"); - string = string.replace("&&", "&"); - return string; - } + public static String parseColorAmp(String string) { + string = string.replaceAll("(§([a-z0-9]))", "\u00A7$2"); + string = string.replaceAll("(&([a-z0-9]))", "\u00A7$2"); + string = string.replace("&&", "&"); + return string; + } - // -------------------------------------------- // - // Color parsing - // -------------------------------------------- // + // -------------------------------------------- // + // Color parsing + // -------------------------------------------- // - public static String parseColorAcc(String string) { - return string.replace("`e", "").replace("`r", ChatColor.RED.toString()).replace("`R", ChatColor.DARK_RED.toString()).replace("`y", ChatColor.YELLOW.toString()).replace("`Y", ChatColor.GOLD.toString()).replace("`g", ChatColor.GREEN.toString()).replace("`G", ChatColor.DARK_GREEN.toString()).replace("`a", ChatColor.AQUA.toString()).replace("`A", ChatColor.DARK_AQUA.toString()).replace("`b", ChatColor.BLUE.toString()).replace("`B", ChatColor.DARK_BLUE.toString()).replace("`plugin", ChatColor.LIGHT_PURPLE.toString()).replace("`SavageFactions", ChatColor.DARK_PURPLE.toString()).replace("`k", ChatColor.BLACK.toString()).replace("`s", ChatColor.GRAY.toString()).replace("`S", ChatColor.DARK_GRAY.toString()).replace("`w", ChatColor.WHITE.toString()); - } + public static String parseColorAcc(String string) { + return string.replace("`e", "").replace("`r", ChatColor.RED.toString()).replace("`R", ChatColor.DARK_RED.toString()).replace("`y", ChatColor.YELLOW.toString()).replace("`Y", ChatColor.GOLD.toString()).replace("`g", ChatColor.GREEN.toString()).replace("`G", ChatColor.DARK_GREEN.toString()).replace("`a", ChatColor.AQUA.toString()).replace("`A", ChatColor.DARK_AQUA.toString()).replace("`b", ChatColor.BLUE.toString()).replace("`B", ChatColor.DARK_BLUE.toString()).replace("`plugin", ChatColor.LIGHT_PURPLE.toString()).replace("`SavageFactions", ChatColor.DARK_PURPLE.toString()).replace("`k", ChatColor.BLACK.toString()).replace("`s", ChatColor.GRAY.toString()).replace("`S", ChatColor.DARK_GRAY.toString()).replace("`w", ChatColor.WHITE.toString()); + } - public static String parseColorTags(String string) { - return string.replace("", "").replace("", "\u00A70").replace("", "\u00A71").replace("", "\u00A72").replace("", "\u00A73").replace("", "\u00A74").replace("", "\u00A75").replace("", "\u00A76").replace("", "\u00A77").replace("", "\u00A78").replace("", "\u00A79").replace("", "\u00A7a").replace("", "\u00A7b").replace("", "\u00A7c").replace("", "\u00A7d").replace("", "\u00A7e").replace("", "\u00A7f"); - } + public static String parseColorTags(String string) { + return string.replace("", "").replace("", "\u00A70").replace("", "\u00A71").replace("", "\u00A72").replace("", "\u00A73").replace("", "\u00A74").replace("", "\u00A75").replace("", "\u00A76").replace("", "\u00A77").replace("", "\u00A78").replace("", "\u00A79").replace("", "\u00A7a").replace("", "\u00A7b").replace("", "\u00A7c").replace("", "\u00A7d").replace("", "\u00A7e").replace("", "\u00A7f"); + } - public static String upperCaseFirst(String string) { - return string.substring(0, 1).toUpperCase() + string.substring(1); - } + public static String upperCaseFirst(String string) { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } - public static String implode(List list, String glue) { - StringBuilder ret = new StringBuilder(); - for (int i = 0; i < list.size(); i++) - ret.append(glue).append(list.get(i)); + public static String implode(List list, String glue) { + StringBuilder ret = new StringBuilder(); + for (int i = 0; i < list.size(); i++) + ret.append(glue).append(list.get(i)); - return ret.length() > 0 ? ret.toString().substring(glue.length()) : ""; - } + return ret.length() > 0 ? ret.toString().substring(glue.length()) : ""; + } - // -------------------------------------------- // - // Standard utils like UCFirst, implode and repeat. - // -------------------------------------------- // + // -------------------------------------------- // + // Standard utils like UCFirst, implode and repeat. + // -------------------------------------------- // - public static String repeat(String s, int times) { - return times > 0 ? s + repeat(s, times - 1) : ""; - } + public static String repeat(String s, int times) { + return times > 0 ? s + repeat(s, times - 1) : ""; + } - public static String getMaterialName(Material material) { - return material.toString().replace('_', ' ').toLowerCase(); - } + public static String getMaterialName(Material material) { + return material.toString().replace('_', ' ').toLowerCase(); + } - // -------------------------------------------- // - // Material name tools - // -------------------------------------------- // + // -------------------------------------------- // + // Material name tools + // -------------------------------------------- // - public static String getBestStartWithCI(Collection candidates, String start) { - String ret = null; - int best = 0; + public static String getBestStartWithCI(Collection candidates, String start) { + String ret = null; + int best = 0; - start = start.toLowerCase(); - int minlength = start.length(); - for (String candidate : candidates) { - if (candidate.length() < minlength) { - continue; - } - if (!candidate.toLowerCase().startsWith(start)) { - continue; - } + start = start.toLowerCase(); + int minlength = start.length(); + for (String candidate : candidates) { + if (candidate.length() < minlength) { + continue; + } + if (!candidate.toLowerCase().startsWith(start)) { + continue; + } - // The closer to zero the better - int lendiff = candidate.length() - minlength; - if (lendiff == 0) { - return candidate; - } - if (lendiff < best || best == 0) { - best = lendiff; - ret = candidate; - } - } - return ret; - } + // The closer to zero the better + int lendiff = candidate.length() - minlength; + if (lendiff == 0) { + return candidate; + } + if (lendiff < best || best == 0) { + best = lendiff; + ret = candidate; + } + } + return ret; + } - public String parse(String str, Object... args) { - return String.format(this.parse(str), args); - } + public String parse(String str, Object... args) { + return String.format(this.parse(str), args); + } - // -------------------------------------------- // - // Paging and chrome-tools like titleize - // -------------------------------------------- // + // -------------------------------------------- // + // Paging and chrome-tools like titleize + // -------------------------------------------- // - public String parse(String str) { - return this.parseTags(parseColor(str)); - } + public String parse(String str) { + return this.parseTags(parseColor(str)); + } - public String parseTags(String str) { - return replaceTags(str, this.tags); - } + public String parseTags(String str) { + return replaceTags(str, this.tags); + } - public FancyMessage parseFancy(String prefix) { - return toFancy(parse(prefix)); - } + public FancyMessage parseFancy(String prefix) { + return toFancy(parse(prefix)); + } - public String titleize(String str) { - String center = ChatColor.DARK_GRAY + "< " + parseTags("") + str + parseTags("
    ") + ChatColor.DARK_GRAY + " >"; - int centerlen = ChatColor.stripColor(center).length(); - int pivot = titleizeLine.length() / 2; - int eatLeft = (centerlen / 2) - titleizeBalance; - int eatRight = (centerlen - eatLeft) + titleizeBalance; + public String titleize(String str) { + String center = ChatColor.DARK_GRAY + "< " + parseTags("") + str + parseTags("") + ChatColor.DARK_GRAY + " >"; + int centerlen = ChatColor.stripColor(center).length(); + int pivot = titleizeLine.length() / 2; + int eatLeft = (centerlen / 2) - titleizeBalance; + int eatRight = (centerlen - eatLeft) + titleizeBalance; - if (eatLeft < pivot) { - return parseTags("") + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(0, pivot - eatLeft) + center + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(pivot + eatRight); - } else { - return parseTags("") + center; - } - } + if (eatLeft < pivot) { + return parseTags("") + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(0, pivot - eatLeft) + center + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(pivot + eatRight); + } else { + return parseTags("") + center; + } + } - public ArrayList getPage(List lines, int pageHumanBased, String title) { - ArrayList ret = new ArrayList<>(); - int pageZeroBased = pageHumanBased - 1; - int pageheight = 9; - int pagecount = (lines.size() / pageheight) + 1; + public ArrayList getPage(List lines, int pageHumanBased, String title) { + ArrayList ret = new ArrayList<>(); + int pageZeroBased = pageHumanBased - 1; + int pageheight = 9; + int pagecount = (lines.size() / pageheight) + 1; - ret.add(this.titleize(title + " " + pageHumanBased + "/" + pagecount)); + ret.add(this.titleize(title + " " + pageHumanBased + "/" + pagecount)); - if (pagecount == 0) { - ret.add(this.parseTags(TL.NOPAGES.toString())); - return ret; - } else if (pageZeroBased < 0 || pageHumanBased > pagecount) { - ret.add(this.parseTags(TL.INVALIDPAGE.format(pagecount))); - return ret; - } + if (pagecount == 0) { + ret.add(this.parseTags(TL.NOPAGES.toString())); + return ret; + } else if (pageZeroBased < 0 || pageHumanBased > pagecount) { + ret.add(this.parseTags(TL.INVALIDPAGE.format(pagecount))); + return ret; + } - int from = pageZeroBased * pageheight; - int to = from + pageheight; - if (to > lines.size()) { - to = lines.size(); - } + int from = pageZeroBased * pageheight; + int to = from + pageheight; + if (to > lines.size()) { + to = lines.size(); + } - ret.addAll(lines.subList(from, to)); + ret.addAll(lines.subList(from, to)); - return ret; - } + return ret; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java b/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java index adf3e3a2..667d58b8 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java @@ -18,83 +18,83 @@ import java.util.concurrent.Callable; */ public class UUIDFetcher implements Callable> { - private static final double PROFILES_PER_REQUEST = 100; - private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; - private final JSONParser jsonParser = new JSONParser(); - private final List names; - private final boolean rateLimiting; + private static final double PROFILES_PER_REQUEST = 100; + private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; + private final JSONParser jsonParser = new JSONParser(); + private final List names; + private final boolean rateLimiting; - public UUIDFetcher(List names, boolean rateLimiting) { - this.names = ImmutableList.copyOf(names); - this.rateLimiting = rateLimiting; - } + public UUIDFetcher(List names, boolean rateLimiting) { + this.names = ImmutableList.copyOf(names); + this.rateLimiting = rateLimiting; + } - public UUIDFetcher(List names) { - this(names, true); - } + public UUIDFetcher(List names) { + this(names, true); + } - private static void writeBody(HttpURLConnection connection, String body) throws Exception { - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - } + private static void writeBody(HttpURLConnection connection, String body) throws Exception { + OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + } - private static HttpURLConnection createConnection() throws Exception { - URL url = new URL(PROFILE_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - return connection; - } + private static HttpURLConnection createConnection() throws Exception { + URL url = new URL(PROFILE_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + return connection; + } - private static UUID getUUID(String id) { - return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); - } + private static UUID getUUID(String id) { + return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); + } - public static byte[] toBytes(UUID uuid) { - ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); - byteBuffer.putLong(uuid.getMostSignificantBits()); - byteBuffer.putLong(uuid.getLeastSignificantBits()); - return byteBuffer.array(); - } + public static byte[] toBytes(UUID uuid) { + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } - public static UUID fromBytes(byte[] array) { - if (array.length != 16) { - throw new IllegalArgumentException("Illegal byte array length: " + array.length); - } - ByteBuffer byteBuffer = ByteBuffer.wrap(array); - long mostSignificant = byteBuffer.getLong(); - long leastSignificant = byteBuffer.getLong(); - return new UUID(mostSignificant, leastSignificant); - } + public static UUID fromBytes(byte[] array) { + if (array.length != 16) { + throw new IllegalArgumentException("Illegal byte array length: " + array.length); + } + ByteBuffer byteBuffer = ByteBuffer.wrap(array); + long mostSignificant = byteBuffer.getLong(); + long leastSignificant = byteBuffer.getLong(); + return new UUID(mostSignificant, leastSignificant); + } - public static UUID getUUIDOf(String name) throws Exception { - return new UUIDFetcher(Collections.singletonList(name)).call().get(name); - } + public static UUID getUUIDOf(String name) throws Exception { + return new UUIDFetcher(Collections.singletonList(name)).call().get(name); + } - public Map call() throws Exception { - Map uuidMap = new HashMap<>(); - int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); - for (int i = 0; i < requests; i++) { - HttpURLConnection connection = createConnection(); - String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); - writeBody(connection, body); - JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); - for (Object profile : array) { - JSONObject jsonProfile = (JSONObject) profile; - String id = (String) jsonProfile.get("id"); - String name = (String) jsonProfile.get("name"); - UUID uuid = UUIDFetcher.getUUID(id); - uuidMap.put(name, uuid); - } - if (rateLimiting && i != requests - 1) { - Thread.sleep(100L); - } - } - return uuidMap; - } + public Map call() throws Exception { + Map uuidMap = new HashMap<>(); + int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); + for (int i = 0; i < requests; i++) { + HttpURLConnection connection = createConnection(); + String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); + writeBody(connection, body); + JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); + for (Object profile : array) { + JSONObject jsonProfile = (JSONObject) profile; + String id = (String) jsonProfile.get("id"); + String name = (String) jsonProfile.get("name"); + UUID uuid = UUIDFetcher.getUUID(id); + uuidMap.put(name, uuid); + } + if (rateLimiting && i != requests - 1) { + Thread.sleep(100L); + } + } + return uuidMap; + } }

    + * note: for translations: %s = action, %d = delay + */ + public static void process(final FPlayer player, Warmup warmup, TL translationKey, String action, final Runnable runnable, long delay) { + if (delay > 0) { + if (player.isWarmingUp()) { + player.msg(TL.WARMUPS_ALREADY); + } else { + player.msg(translationKey.format(action, delay)); + int id = SavageFactions.plugin.getServer().getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + player.stopWarmup(); + runnable.run(); + } + }, delay * 20).getTaskId(); + player.addWarmup(warmup, id); + } + } else { + runnable.run(); + } + } - public enum Warmup { - HOME, WARP, FLIGHT, BANNER, CHECKPOINT - } + public enum Warmup { + HOME, WARP, FLIGHT, BANNER, CHECKPOINT + } } diff --git a/src/main/java/com/massivecraft/factions/util/WarpGUI.java b/src/main/java/com/massivecraft/factions/util/WarpGUI.java index 7936ffe1..702c7a6f 100644 --- a/src/main/java/com/massivecraft/factions/util/WarpGUI.java +++ b/src/main/java/com/massivecraft/factions/util/WarpGUI.java @@ -24,241 +24,241 @@ import java.util.logging.Level; public class WarpGUI implements InventoryHolder, FactionGUI { - private final ConfigurationSection section; - int guiSize; - private Inventory warpGUI; - private FPlayer fme; - private HashMap warpSlots = new HashMap<>(); - private int maxWarps; - private List dummySlots = new ArrayList<>(); + private final ConfigurationSection section; + int guiSize; + private Inventory warpGUI; + private FPlayer fme; + private HashMap warpSlots = new HashMap<>(); + private int maxWarps; + private List dummySlots = new ArrayList<>(); - public WarpGUI(FPlayer fme) { - this.fme = fme; - this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fwarp-gui"); - } + public WarpGUI(FPlayer fme) { + this.fme = fme; + this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fwarp-gui"); + } - @Override - public void build() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + @Override + public void build() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - // Build basic Inventory info - guiSize = section.getInt("rows", 3); - if (guiSize > 6) { - guiSize = 6; - SavageFactions.plugin.log(Level.INFO, "Warp GUI size out of bounds, defaulting to 6"); - } + // Build basic Inventory info + guiSize = section.getInt("rows", 3); + if (guiSize > 6) { + guiSize = 6; + SavageFactions.plugin.log(Level.INFO, "Warp GUI size out of bounds, defaulting to 6"); + } - guiSize *= 9; - String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); - warpGUI = Bukkit.createInventory(this, guiSize, guiName); + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); + warpGUI = Bukkit.createInventory(this, guiSize, guiName); - maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); + maxWarps = SavageFactions.plugin.getConfig().getInt("max-warps", 5); - Set factionWarps = fme.getFaction().getWarps().keySet(); - List warpOpenSlots = section.getIntegerList("warp-slots"); + Set factionWarps = fme.getFaction().getWarps().keySet(); + List warpOpenSlots = section.getIntegerList("warp-slots"); - buildDummyItems(); + buildDummyItems(); - if (maxWarps != warpOpenSlots.size()) { - SavageFactions.plugin.log(Level.SEVERE, "Invalid warp slots for GUI, Please use same value as max warps"); - return; - } + if (maxWarps != warpOpenSlots.size()) { + SavageFactions.plugin.log(Level.SEVERE, "Invalid warp slots for GUI, Please use same value as max warps"); + return; + } - int warpSlotIndex = 0; - for (String warp : factionWarps) { - warpSlots.put(warpOpenSlots.get(warpSlotIndex), warp); - warpSlotIndex++; - } + int warpSlotIndex = 0; + for (String warp : factionWarps) { + warpSlots.put(warpOpenSlots.get(warpSlotIndex), warp); + warpSlotIndex++; + } - buildItems(); - } + buildItems(); + } - @Override - public Inventory getInventory() { - return warpGUI; - } + @Override + public Inventory getInventory() { + return warpGUI; + } - private void buildItems() { - for (Map.Entry entry : warpSlots.entrySet()) { - warpGUI.setItem(entry.getKey(), buildItem(entry.getValue())); - } - } + private void buildItems() { + for (Map.Entry entry : warpSlots.entrySet()) { + warpGUI.setItem(entry.getKey(), buildItem(entry.getValue())); + } + } - @Override - public void onClick(int slot, ClickType action) { - if (warpSlots.containsKey(slot)) { - fme.getPlayer().closeInventory(); + @Override + public void onClick(int slot, ClickType action) { + if (warpSlots.containsKey(slot)) { + fme.getPlayer().closeInventory(); - // All clear lets TP them or ask for password - String warp = warpSlots.get(slot); - if (!fme.getFaction().hasWarpPassword(warp)) { - if (transact(fme)) { - doWarmup(warp); - } - } else { - fme.setEnteringPassword(true, warp); - fme.msg(TL.COMMAND_FWARP_PASSWORD_REQUIRED); - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - if (fme.isEnteringPassword()) { - fme.msg(TL.COMMAND_FWARP_PASSWORD_TIMEOUT); - fme.setEnteringPassword(false, ""); - } - } - }, SavageFactions.plugin.getConfig().getInt("fwarp-gui.password-timeout", 5) * 20); - } - } - } + // All clear lets TP them or ask for password + String warp = warpSlots.get(slot); + if (!fme.getFaction().hasWarpPassword(warp)) { + if (transact(fme)) { + doWarmup(warp); + } + } else { + fme.setEnteringPassword(true, warp); + fme.msg(TL.COMMAND_FWARP_PASSWORD_REQUIRED); + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + if (fme.isEnteringPassword()) { + fme.msg(TL.COMMAND_FWARP_PASSWORD_TIMEOUT); + fme.setEnteringPassword(false, ""); + } + } + }, SavageFactions.plugin.getConfig().getInt("fwarp-gui.password-timeout", 5) * 20); + } + } + } - private void doWarmup(final String warp) { - WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); - if (player != null) { - player.teleport(fme.getFaction().getWarp(warp).getLocation()); - fme.msg(TL.COMMAND_FWARP_WARPED, warp); - } - } - }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); - } + private void doWarmup(final String warp) { + WarmUpUtil.process(fme, WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warp, new Runnable() { + @Override + public void run() { + Player player = Bukkit.getPlayer(fme.getPlayer().getUniqueId()); + if (player != null) { + player.teleport(fme.getFaction().getWarp(warp).getLocation()); + fme.msg(TL.COMMAND_FWARP_WARPED, warp); + } + } + }, SavageFactions.plugin.getConfig().getLong("warmups.f-warp", 0)); + } - private boolean transact(FPlayer player) { - if (!SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing()) { - return true; - } + private boolean transact(FPlayer player) { + if (!SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing()) { + return true; + } - double cost = SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5); + double cost = SavageFactions.plugin.getConfig().getDouble("warp-cost.warp", 5); - if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { - return true; - } + if (!Econ.shouldBeUsed() || this.fme == null || cost == 0.0 || fme.isAdminBypassing()) { + return true; + } - if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { - return Econ.modifyMoney(fme.getFaction(), -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); - } else { - return Econ.modifyMoney(fme, -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); - } - } + if (Conf.bankEnabled && Conf.bankFactionPaysCosts && fme.hasFaction()) { + return Econ.modifyMoney(fme.getFaction(), -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); + } else { + return Econ.modifyMoney(fme, -cost, TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString()); + } + } - private ItemStack buildItem(String warp) { - ConfigurationSection warpItemSection = section.getConfigurationSection("warp-item"); - if (warpItemSection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + private ItemStack buildItem(String warp) { + ConfigurationSection warpItemSection = section.getConfigurationSection("warp-item"); + if (warpItemSection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - String displayName = replacePlaceholers(warpItemSection.getString("name"), warp, fme.getFaction()); - List lore = new ArrayList<>(); + String displayName = replacePlaceholers(warpItemSection.getString("name"), warp, fme.getFaction()); + List lore = new ArrayList<>(); - if (warpItemSection.getString("material") == null) { - return null; - } - Material material = Material.matchMaterial(warpItemSection.getString("material")); - if (material == null) { - material = Material.STONE; - } + if (warpItemSection.getString("material") == null) { + return null; + } + Material material = Material.matchMaterial(warpItemSection.getString("material")); + if (material == null) { + material = Material.STONE; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - for (String loreLine : warpItemSection.getStringList("lore")) { - lore.add(replacePlaceholers(loreLine, warp, fme.getFaction())); - } + for (String loreLine : warpItemSection.getStringList("lore")) { + lore.add(replacePlaceholers(loreLine, warp, fme.getFaction())); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - private String replacePlaceholers(String string, String warp, Faction faction) { - string = ChatColor.translateAlternateColorCodes('&', string); - string = string.replace("{warp}", warp); - string = string.replace("{warp-protected}", faction.hasWarpPassword(warp) ? "Enabled" : "Disabled"); - string = string.replace("{warp-cost}", !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) ? "Disabled" : Integer.toString(SavageFactions.plugin.getConfig().getInt("warp-cost.warp", 5))); - return string; - } + private String replacePlaceholers(String string, String warp, Faction faction) { + string = ChatColor.translateAlternateColorCodes('&', string); + string = string.replace("{warp}", warp); + string = string.replace("{warp-protected}", faction.hasWarpPassword(warp) ? "Enabled" : "Disabled"); + string = string.replace("{warp-cost}", !SavageFactions.plugin.getConfig().getBoolean("warp-cost.enabled", false) ? "Disabled" : Integer.toString(SavageFactions.plugin.getConfig().getInt("warp-cost.warp", 5))); + return string; + } - private void buildDummyItems() { - for (String key : section.getConfigurationSection("dummy-slots").getKeys(false)) { - int dummyId; - try { - dummyId = Integer.parseInt(key); - } catch (NumberFormatException exception) { - SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); - continue; - } + private void buildDummyItems() { + for (String key : section.getConfigurationSection("dummy-slots").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } - ItemStack dummyItem = buildDummyItem(dummyId); - if (dummyItem == null) { - continue; - } + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } - List dummyIdSlots = section.getIntegerList("dummy-slots." + key); - for (Integer slot : dummyIdSlots) { - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); - continue; - } - dummySlots.add(slot); - warpGUI.setItem(slot, dummyItem); - } - } - } + List dummyIdSlots = section.getIntegerList("dummy-slots." + key); + for (Integer slot : dummyIdSlots) { + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + dummySlots.add(slot); + warpGUI.setItem(slot, dummyItem); + } + } + } - private ItemStack buildDummyItem(int id) { - final ConfigurationSection dummySection = section.getConfigurationSection("dummy-items." + id); + private ItemStack buildDummyItem(int id) { + final ConfigurationSection dummySection = section.getConfigurationSection("dummy-items." + id); - if (dummySection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (dummySection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f warp GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - Material material = Material.matchMaterial(dummySection.getString("material", "")); - if (material == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); - return null; - } + Material material = Material.matchMaterial(dummySection.getString("material", "")); + if (material == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } - ItemStack itemStack = new ItemStack(material); + ItemStack itemStack = new ItemStack(material); - DyeColor color; - try { - color = DyeColor.valueOf(dummySection.getString("color", "")); - } catch (Exception exception) { - color = null; - } - if (color != null) { - itemStack.setDurability(color.getWoolData()); - } + DyeColor color; + try { + color = DyeColor.valueOf(dummySection.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } - ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta itemMeta = itemStack.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); - List lore = new ArrayList<>(); - for (String loreLine : dummySection.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } - itemMeta.setLore(lore); + List lore = new ArrayList<>(); + for (String loreLine : dummySection.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + itemMeta.setLore(lore); - itemStack.setItemMeta(itemMeta); + itemStack.setItemMeta(itemMeta); - return itemStack; - } + return itemStack; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java b/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java index bed3cb90..2bc4a19d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java +++ b/src/main/java/com/massivecraft/factions/zcore/CommandVisibility.java @@ -1,7 +1,7 @@ -package com.massivecraft.factions.zcore; - -public enum CommandVisibility { - VISIBLE, // Visible commands are visible to anyone. Even those who don't have permission to use it or is of invalid sender type. - SECRET, // Secret commands are visible only to those who can use the command. These commands are usually some kind of admin commands. - INVISIBLE // Invisible commands are invisible to everyone, even those who can use the command. -} +package com.massivecraft.factions.zcore; + +public enum CommandVisibility { + VISIBLE, // Visible commands are visible to anyone. Even those who don't have permission to use it or is of invalid sender type. + SECRET, // Secret commands are visible only to those who can use the command. These commands are usually some kind of admin commands. + INVISIBLE // Invisible commands are invisible to everyone, even those who can use the command. +} diff --git a/src/main/java/com/massivecraft/factions/zcore/MCommand.java b/src/main/java/com/massivecraft/factions/zcore/MCommand.java index 94919da4..013e3ae9 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MCommand.java +++ b/src/main/java/com/massivecraft/factions/zcore/MCommand.java @@ -23,463 +23,463 @@ import java.util.UUID; public abstract class MCommand { - public T p; - - // The sub-commands to this command - public List> subCommands; - // The different names this commands will react to - public List aliases; - public boolean allowNoSlashAccess; - // Information on the args - public List requiredArgs; - public LinkedHashMap optionalArgs; - public boolean errorOnToManyArgs = true; - public List helpLong; - public CommandVisibility visibility; - // Some information on permissions - public boolean senderMustBePlayer; - public boolean senderMustHaveFaction; - public String permission; - // Information available on execution of the command - public CommandSender sender; // Will always be set - public Player me; // Will only be set when the sender is a player - public boolean senderIsConsole; - public List args; // Will contain the arguments, or and empty list if there are none. - public List> commandChain = new ArrayList<>(); // The command chain used to execute this command - // FIELD: Help Short - // This field may be left blank and will in such case be loaded from the permissions node instead. - // Thus make sure the permissions node description is an action description like "eat hamburgers" or "do admin stuff". - private String helpShort; - - public MCommand(T p) { - this.p = p; - - this.permission = null; - - this.allowNoSlashAccess = false; - - this.subCommands = new ArrayList<>(); - this.aliases = new ArrayList<>(); - - this.requiredArgs = new ArrayList<>(); - this.optionalArgs = new LinkedHashMap<>(); - - this.helpShort = null; - this.helpLong = new ArrayList<>(); - this.visibility = CommandVisibility.VISIBLE; - } - - public void addSubCommand(MCommand subCommand) { - subCommand.commandChain.addAll(this.commandChain); - subCommand.commandChain.add(this); - this.subCommands.add(subCommand); - } - - public String getHelpShort() { - return this.helpShort != null ? this.helpShort : getUsageTranslation().toString(); - } - - public void setHelpShort(String val) { - this.helpShort = val; - } - - public abstract TL getUsageTranslation(); - - public void setCommandSender(CommandSender sender) { - this.sender = sender; - if (sender instanceof Player) { - this.me = (Player) sender; - this.senderIsConsole = false; - } else { - this.me = null; - this.senderIsConsole = true; - } - } - - // The commandChain is a list of the parent command chain used to get to this command. - public void execute(CommandSender sender, List args, List> commandChain) { - // Set the execution-time specific variables - setCommandSender(sender); - this.args = args; - this.commandChain = commandChain; - - // Is there a matching sub command? - if (args.size() > 0) { - for (MCommand subCommand : this.subCommands) { - if (subCommand.aliases.contains(args.get(0).toLowerCase())) { - args.remove(0); - commandChain.add(this); - subCommand.execute(sender, args, commandChain); - return; - } - } - } - - if (!validCall(this.sender, this.args)) { - return; - } - - if (!this.isEnabled()) { - return; - } - - perform(); - } - - public void execute(CommandSender sender, List args) { - execute(sender, args, new ArrayList>()); - } - - // This is where the command action is performed. - public abstract void perform(); - - - // -------------------------------------------- // - // Call Validation - // -------------------------------------------- // - - /** - * In this method we validate that all prerequisites to perform this command has been met. - * - * @param sender of the command - * @param args of the command - * @return true if valid, false if not. - */ - // TODO: There should be a boolean for silence - public boolean validCall(CommandSender sender, List args) { - return validSenderType(sender, true) && validSenderPermissions(sender, true) && validArgs(args, sender); - } - - public boolean isEnabled() { - return true; - } - - - public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { - if (this.senderMustBePlayer && !(sender instanceof Player)) { - if (informSenderIfNot) { - msg(TL.GENERIC_PLAYERONLY); - } - return false; - - } - return !this.senderMustHaveFaction || !FPlayers.getInstance().getByPlayer((Player) sender).hasFaction(); - } - - public boolean validSenderPermissions(CommandSender sender, boolean informSenderIfNot) { - return this.permission == null || p.perm.has(sender, this.permission, informSenderIfNot); - } - - public boolean validArgs(List args, CommandSender sender) { - if (args.size() < this.requiredArgs.size()) { - if (sender != null) { - msg(TL.GENERIC_ARGS_TOOFEW); - sender.sendMessage(this.getUseageTemplate()); - } - return false; - } - - if (args.size() > this.requiredArgs.size() + this.optionalArgs.size() && this.errorOnToManyArgs) { - if (sender != null) { - // Get the to many string slice - List theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size()); - msg(TL.GENERIC_ARGS_TOOMANY, TextUtil.implode(theToMany, " ")); - sender.sendMessage(this.getUseageTemplate()); - } - return false; - } - return true; - } - - public boolean validArgs(List args) { - return this.validArgs(args, null); - } - - // -------------------------------------------- // - // Help and Usage information - // -------------------------------------------- // - - public String getUseageTemplate(List> commandChain, boolean addShortHelp) { - StringBuilder ret = new StringBuilder(); - ret.append(p.txt.parseTags("")); - ret.append('/'); - - for (MCommand mc : commandChain) { - ret.append(TextUtil.implode(mc.aliases, ",")); - ret.append(' '); - } - - ret.append(TextUtil.implode(this.aliases, ",")); - - List args = new ArrayList<>(); - - for (String requiredArg : this.requiredArgs) { - args.add("<" + requiredArg + ">"); - } - - for (Entry optionalArg : this.optionalArgs.entrySet()) { - String val = optionalArg.getValue(); - if (val == null) { - val = ""; - } else { - val = "=" + val; - } - args.add("[" + optionalArg.getKey() + val + "]"); - } - - if (args.size() > 0) { - ret.append(p.txt.parseTags(" ")); - ret.append(TextUtil.implode(args, " ")); - } - - if (addShortHelp) { - ret.append(p.txt.parseTags(" ")); - ret.append(this.getHelpShort()); - } - - return ret.toString(); - } - - public String getUseageTemplate(boolean addShortHelp) { - return getUseageTemplate(this.commandChain, addShortHelp); - } - - public String getUseageTemplate() { - return getUseageTemplate(false); - } - - // -------------------------------------------- // - // Message Sending Helpers - // -------------------------------------------- // - - public void msg(String str, Object... args) { - sender.sendMessage(p.txt.parse(str, args)); - } - - public void msg(TL translation, Object... args) { - sender.sendMessage(p.txt.parse(translation.toString(), args)); - } - - public void sendMessage(String msg) { - sender.sendMessage(msg); - } - - public void sendMessage(List msgs) { - for (String msg : msgs) { - this.sendMessage(msg); - } - } - - public void sendFancyMessage(FancyMessage message) { - message.send(sender); - } - - public void sendFancyMessage(List messages) { - for (FancyMessage m : messages) { - sendFancyMessage(m); - } - } - - public List getToolTips(FPlayer player) { - List lines = new ArrayList<>(); - for (String s : p.getConfig().getStringList("tooltips.show")) { - lines.add(ChatColor.translateAlternateColorCodes('&', replaceFPlayerTags(s, player))); - } - return lines; - } - - public List getToolTips(Faction faction) { - List lines = new ArrayList<>(); - for (String s : p.getConfig().getStringList("tooltips.list")) { - lines.add(ChatColor.translateAlternateColorCodes('&', replaceFactionTags(s, faction))); - } - return lines; - } - - public String replaceFPlayerTags(String s, FPlayer player) { - if (s.contains("{balance}")) { - String balance = Econ.isSetup() ? Econ.getFriendlyBalance(player) : "no balance"; - s = s.replace("{balance}", balance); - } - if (s.contains("{lastSeen}")) { - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - player.getLastLoginTime(), true, true) + " ago"; - String lastSeen = player.isOnline() ? ChatColor.GREEN + "Online" : (System.currentTimeMillis() - player.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - s = s.replace("{lastSeen}", lastSeen); - } - if (s.contains("{power}")) { - String power = player.getPowerRounded() + "/" + player.getPowerMaxRounded(); - s = s.replace("{power}", power); - } - if (s.contains("{group}")) { - String group = SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(player.getId()))); - s = s.replace("{group}", group); - } - return s; - } - - public String replaceFactionTags(String s, Faction faction) { - if (s.contains("{power}")) { - s = s.replace("{power}", String.valueOf(faction.getPowerRounded())); - } - if (s.contains("{maxPower}")) { - s = s.replace("{maxPower}", String.valueOf(faction.getPowerMaxRounded())); - } - if (s.contains("{leader}")) { - FPlayer fLeader = faction.getFPlayerAdmin(); - String leader = fLeader == null ? "Server" : fLeader.getName().substring(0, fLeader.getName().length() > 14 ? 13 : fLeader.getName().length()); - s = s.replace("{leader}", leader); - } - if (s.contains("{chunks}")) { - s = s.replace("{chunks}", String.valueOf(faction.getLandRounded())); - } - if (s.contains("{members}")) { - s = s.replace("{members}", String.valueOf(faction.getSize())); - - } - if (s.contains("{online}")) { - s = s.replace("{online}", String.valueOf(faction.getOnlinePlayers().size())); - } - return s; - } - - // -------------------------------------------- // - // Argument Readers - // -------------------------------------------- // - - // Is set? ====================== - public boolean argIsSet(int idx) { - return this.args.size() >= idx + 1; - } - - // STRING ====================== - public String argAsString(int idx, String def) { - if (this.args.size() < idx + 1) { - return def; - } - return this.args.get(idx); - } - - public String argAsString(int idx) { - return this.argAsString(idx, null); - } - - // INT ====================== - public Integer strAsInt(String str, Integer def) { - if (str == null) { - return def; - } - try { - return Integer.parseInt(str); - } catch (Exception e) { - return def; - } - } - - public Integer argAsInt(int idx, Integer def) { - return strAsInt(this.argAsString(idx), def); - } - - public Integer argAsInt(int idx) { - return this.argAsInt(idx, null); - } - - // Double ====================== - public Double strAsDouble(String str, Double def) { - if (str == null) { - return def; - } - try { - return Double.parseDouble(str); - } catch (Exception e) { - return def; - } - } - - public Double argAsDouble(int idx, Double def) { - return strAsDouble(this.argAsString(idx), def); - } - - public Double argAsDouble(int idx) { - return this.argAsDouble(idx, null); - } - - // TODO: Go through the str conversion for the other arg-readers as well. - // Boolean ====================== - public Boolean strAsBool(String str) { - str = str.toLowerCase(); - return str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"); - } - - public Boolean argAsBool(int idx, boolean def) { - String str = this.argAsString(idx); - if (str == null) { - return def; - } - - return strAsBool(str); - } - - public Boolean argAsBool(int idx) { - return this.argAsBool(idx, false); - } - - // PLAYER ====================== - public Player strAsPlayer(String name, Player def, boolean msg) { - Player ret = def; - - if (name != null) { - Player player = Bukkit.getServer().getPlayer(name); - if (player != null) { - ret = player; - } - } - - if (msg && ret == null) { - this.msg(TL.GENERIC_NOPLAYERFOUND, name); - } - - return ret; - } - - public Player argAsPlayer(int idx, Player def, boolean msg) { - return this.strAsPlayer(this.argAsString(idx), def, msg); - } - - public Player argAsPlayer(int idx, Player def) { - return this.argAsPlayer(idx, def, true); - } - - public Player argAsPlayer(int idx) { - return this.argAsPlayer(idx, null); - } - - // BEST PLAYER MATCH ====================== - public Player strAsBestPlayerMatch(String name, Player def, boolean msg) { - Player ret = def; - - if (name != null) { - List players = Bukkit.getServer().matchPlayer(name); - if (players.size() > 0) { - ret = players.get(0); - } - } - - if (msg && ret == null) { - this.msg(TL.GENERIC_NOPLAYERMATCH, name); - } - - return ret; - } - - public Player argAsBestPlayerMatch(int idx, Player def, boolean msg) { - return this.strAsBestPlayerMatch(this.argAsString(idx), def, msg); - } - - public Player argAsBestPlayerMatch(int idx, Player def) { - return this.argAsBestPlayerMatch(idx, def, true); - } - - public Player argAsBestPlayerMatch(int idx) { - return this.argAsPlayer(idx, null); - } + public T p; + + // The sub-commands to this command + public List> subCommands; + // The different names this commands will react to + public List aliases; + public boolean allowNoSlashAccess; + // Information on the args + public List requiredArgs; + public LinkedHashMap optionalArgs; + public boolean errorOnToManyArgs = true; + public List helpLong; + public CommandVisibility visibility; + // Some information on permissions + public boolean senderMustBePlayer; + public boolean senderMustHaveFaction; + public String permission; + // Information available on execution of the command + public CommandSender sender; // Will always be set + public Player me; // Will only be set when the sender is a player + public boolean senderIsConsole; + public List args; // Will contain the arguments, or and empty list if there are none. + public List> commandChain = new ArrayList<>(); // The command chain used to execute this command + // FIELD: Help Short + // This field may be left blank and will in such case be loaded from the permissions node instead. + // Thus make sure the permissions node description is an action description like "eat hamburgers" or "do admin stuff". + private String helpShort; + + public MCommand(T p) { + this.p = p; + + this.permission = null; + + this.allowNoSlashAccess = false; + + this.subCommands = new ArrayList<>(); + this.aliases = new ArrayList<>(); + + this.requiredArgs = new ArrayList<>(); + this.optionalArgs = new LinkedHashMap<>(); + + this.helpShort = null; + this.helpLong = new ArrayList<>(); + this.visibility = CommandVisibility.VISIBLE; + } + + public void addSubCommand(MCommand subCommand) { + subCommand.commandChain.addAll(this.commandChain); + subCommand.commandChain.add(this); + this.subCommands.add(subCommand); + } + + public String getHelpShort() { + return this.helpShort != null ? this.helpShort : getUsageTranslation().toString(); + } + + public void setHelpShort(String val) { + this.helpShort = val; + } + + public abstract TL getUsageTranslation(); + + public void setCommandSender(CommandSender sender) { + this.sender = sender; + if (sender instanceof Player) { + this.me = (Player) sender; + this.senderIsConsole = false; + } else { + this.me = null; + this.senderIsConsole = true; + } + } + + // The commandChain is a list of the parent command chain used to get to this command. + public void execute(CommandSender sender, List args, List> commandChain) { + // Set the execution-time specific variables + setCommandSender(sender); + this.args = args; + this.commandChain = commandChain; + + // Is there a matching sub command? + if (args.size() > 0) { + for (MCommand subCommand : this.subCommands) { + if (subCommand.aliases.contains(args.get(0).toLowerCase())) { + args.remove(0); + commandChain.add(this); + subCommand.execute(sender, args, commandChain); + return; + } + } + } + + if (!validCall(this.sender, this.args)) { + return; + } + + if (!this.isEnabled()) { + return; + } + + perform(); + } + + public void execute(CommandSender sender, List args) { + execute(sender, args, new ArrayList>()); + } + + // This is where the command action is performed. + public abstract void perform(); + + + // -------------------------------------------- // + // Call Validation + // -------------------------------------------- // + + /** + * In this method we validate that all prerequisites to perform this command has been met. + * + * @param sender of the command + * @param args of the command + * @return true if valid, false if not. + */ + // TODO: There should be a boolean for silence + public boolean validCall(CommandSender sender, List args) { + return validSenderType(sender, true) && validSenderPermissions(sender, true) && validArgs(args, sender); + } + + public boolean isEnabled() { + return true; + } + + + public boolean validSenderType(CommandSender sender, boolean informSenderIfNot) { + if (this.senderMustBePlayer && !(sender instanceof Player)) { + if (informSenderIfNot) { + msg(TL.GENERIC_PLAYERONLY); + } + return false; + + } + return !this.senderMustHaveFaction || !FPlayers.getInstance().getByPlayer((Player) sender).hasFaction(); + } + + public boolean validSenderPermissions(CommandSender sender, boolean informSenderIfNot) { + return this.permission == null || p.perm.has(sender, this.permission, informSenderIfNot); + } + + public boolean validArgs(List args, CommandSender sender) { + if (args.size() < this.requiredArgs.size()) { + if (sender != null) { + msg(TL.GENERIC_ARGS_TOOFEW); + sender.sendMessage(this.getUseageTemplate()); + } + return false; + } + + if (args.size() > this.requiredArgs.size() + this.optionalArgs.size() && this.errorOnToManyArgs) { + if (sender != null) { + // Get the to many string slice + List theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size()); + msg(TL.GENERIC_ARGS_TOOMANY, TextUtil.implode(theToMany, " ")); + sender.sendMessage(this.getUseageTemplate()); + } + return false; + } + return true; + } + + public boolean validArgs(List args) { + return this.validArgs(args, null); + } + + // -------------------------------------------- // + // Help and Usage information + // -------------------------------------------- // + + public String getUseageTemplate(List> commandChain, boolean addShortHelp) { + StringBuilder ret = new StringBuilder(); + ret.append(p.txt.parseTags("")); + ret.append('/'); + + for (MCommand mc : commandChain) { + ret.append(TextUtil.implode(mc.aliases, ",")); + ret.append(' '); + } + + ret.append(TextUtil.implode(this.aliases, ",")); + + List args = new ArrayList<>(); + + for (String requiredArg : this.requiredArgs) { + args.add("<" + requiredArg + ">"); + } + + for (Entry optionalArg : this.optionalArgs.entrySet()) { + String val = optionalArg.getValue(); + if (val == null) { + val = ""; + } else { + val = "=" + val; + } + args.add("[" + optionalArg.getKey() + val + "]"); + } + + if (args.size() > 0) { + ret.append(p.txt.parseTags(" ")); + ret.append(TextUtil.implode(args, " ")); + } + + if (addShortHelp) { + ret.append(p.txt.parseTags(" ")); + ret.append(this.getHelpShort()); + } + + return ret.toString(); + } + + public String getUseageTemplate(boolean addShortHelp) { + return getUseageTemplate(this.commandChain, addShortHelp); + } + + public String getUseageTemplate() { + return getUseageTemplate(false); + } + + // -------------------------------------------- // + // Message Sending Helpers + // -------------------------------------------- // + + public void msg(String str, Object... args) { + sender.sendMessage(p.txt.parse(str, args)); + } + + public void msg(TL translation, Object... args) { + sender.sendMessage(p.txt.parse(translation.toString(), args)); + } + + public void sendMessage(String msg) { + sender.sendMessage(msg); + } + + public void sendMessage(List msgs) { + for (String msg : msgs) { + this.sendMessage(msg); + } + } + + public void sendFancyMessage(FancyMessage message) { + message.send(sender); + } + + public void sendFancyMessage(List messages) { + for (FancyMessage m : messages) { + sendFancyMessage(m); + } + } + + public List getToolTips(FPlayer player) { + List lines = new ArrayList<>(); + for (String s : p.getConfig().getStringList("tooltips.show")) { + lines.add(ChatColor.translateAlternateColorCodes('&', replaceFPlayerTags(s, player))); + } + return lines; + } + + public List getToolTips(Faction faction) { + List lines = new ArrayList<>(); + for (String s : p.getConfig().getStringList("tooltips.list")) { + lines.add(ChatColor.translateAlternateColorCodes('&', replaceFactionTags(s, faction))); + } + return lines; + } + + public String replaceFPlayerTags(String s, FPlayer player) { + if (s.contains("{balance}")) { + String balance = Econ.isSetup() ? Econ.getFriendlyBalance(player) : "no balance"; + s = s.replace("{balance}", balance); + } + if (s.contains("{lastSeen}")) { + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - player.getLastLoginTime(), true, true) + " ago"; + String lastSeen = player.isOnline() ? ChatColor.GREEN + "Online" : (System.currentTimeMillis() - player.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + s = s.replace("{lastSeen}", lastSeen); + } + if (s.contains("{power}")) { + String power = player.getPowerRounded() + "/" + player.getPowerMaxRounded(); + s = s.replace("{power}", power); + } + if (s.contains("{group}")) { + String group = SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(player.getId()))); + s = s.replace("{group}", group); + } + return s; + } + + public String replaceFactionTags(String s, Faction faction) { + if (s.contains("{power}")) { + s = s.replace("{power}", String.valueOf(faction.getPowerRounded())); + } + if (s.contains("{maxPower}")) { + s = s.replace("{maxPower}", String.valueOf(faction.getPowerMaxRounded())); + } + if (s.contains("{leader}")) { + FPlayer fLeader = faction.getFPlayerAdmin(); + String leader = fLeader == null ? "Server" : fLeader.getName().substring(0, fLeader.getName().length() > 14 ? 13 : fLeader.getName().length()); + s = s.replace("{leader}", leader); + } + if (s.contains("{chunks}")) { + s = s.replace("{chunks}", String.valueOf(faction.getLandRounded())); + } + if (s.contains("{members}")) { + s = s.replace("{members}", String.valueOf(faction.getSize())); + + } + if (s.contains("{online}")) { + s = s.replace("{online}", String.valueOf(faction.getOnlinePlayers().size())); + } + return s; + } + + // -------------------------------------------- // + // Argument Readers + // -------------------------------------------- // + + // Is set? ====================== + public boolean argIsSet(int idx) { + return this.args.size() >= idx + 1; + } + + // STRING ====================== + public String argAsString(int idx, String def) { + if (this.args.size() < idx + 1) { + return def; + } + return this.args.get(idx); + } + + public String argAsString(int idx) { + return this.argAsString(idx, null); + } + + // INT ====================== + public Integer strAsInt(String str, Integer def) { + if (str == null) { + return def; + } + try { + return Integer.parseInt(str); + } catch (Exception e) { + return def; + } + } + + public Integer argAsInt(int idx, Integer def) { + return strAsInt(this.argAsString(idx), def); + } + + public Integer argAsInt(int idx) { + return this.argAsInt(idx, null); + } + + // Double ====================== + public Double strAsDouble(String str, Double def) { + if (str == null) { + return def; + } + try { + return Double.parseDouble(str); + } catch (Exception e) { + return def; + } + } + + public Double argAsDouble(int idx, Double def) { + return strAsDouble(this.argAsString(idx), def); + } + + public Double argAsDouble(int idx) { + return this.argAsDouble(idx, null); + } + + // TODO: Go through the str conversion for the other arg-readers as well. + // Boolean ====================== + public Boolean strAsBool(String str) { + str = str.toLowerCase(); + return str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"); + } + + public Boolean argAsBool(int idx, boolean def) { + String str = this.argAsString(idx); + if (str == null) { + return def; + } + + return strAsBool(str); + } + + public Boolean argAsBool(int idx) { + return this.argAsBool(idx, false); + } + + // PLAYER ====================== + public Player strAsPlayer(String name, Player def, boolean msg) { + Player ret = def; + + if (name != null) { + Player player = Bukkit.getServer().getPlayer(name); + if (player != null) { + ret = player; + } + } + + if (msg && ret == null) { + this.msg(TL.GENERIC_NOPLAYERFOUND, name); + } + + return ret; + } + + public Player argAsPlayer(int idx, Player def, boolean msg) { + return this.strAsPlayer(this.argAsString(idx), def, msg); + } + + public Player argAsPlayer(int idx, Player def) { + return this.argAsPlayer(idx, def, true); + } + + public Player argAsPlayer(int idx) { + return this.argAsPlayer(idx, null); + } + + // BEST PLAYER MATCH ====================== + public Player strAsBestPlayerMatch(String name, Player def, boolean msg) { + Player ret = def; + + if (name != null) { + List players = Bukkit.getServer().matchPlayer(name); + if (players.size() > 0) { + ret = players.get(0); + } + } + + if (msg && ret == null) { + this.msg(TL.GENERIC_NOPLAYERMATCH, name); + } + + return ret; + } + + public Player argAsBestPlayerMatch(int idx, Player def, boolean msg) { + return this.strAsBestPlayerMatch(this.argAsString(idx), def, msg); + } + + public Player argAsBestPlayerMatch(int idx, Player def) { + return this.argAsBestPlayerMatch(idx, def, true); + } + + public Player argAsBestPlayerMatch(int idx) { + return this.argAsPlayer(idx, null); + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/MPlugin.java b/src/main/java/com/massivecraft/factions/zcore/MPlugin.java index 1b6bdac2..865a7a4d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MPlugin.java +++ b/src/main/java/com/massivecraft/factions/zcore/MPlugin.java @@ -27,313 +27,313 @@ import java.util.logging.Level; public abstract class MPlugin extends JavaPlugin { - // Persist related - public final Gson gson = this.getGsonBuilder().create(); - // Some utils - public Persist persist; - public TextUtil txt; - public PermUtil perm; - public String refCommand = ""; - //holds f stuck taskids - public Map stuckMap = new HashMap<>(); - // These are not supposed to be used directly. - // They are loaded and used through the TextUtil instance for the plugin. - public Map rawTags = new LinkedHashMap<>(); - protected boolean loadSuccessful = false; - private Integer saveTask = null; - private boolean autoSave = true; - // Listeners - private MPluginSecretPlayerListener mPluginSecretPlayerListener; + // Persist related + public final Gson gson = this.getGsonBuilder().create(); + // Some utils + public Persist persist; + public TextUtil txt; + public PermUtil perm; + public String refCommand = ""; + //holds f stuck taskids + public Map stuckMap = new HashMap<>(); + // These are not supposed to be used directly. + // They are loaded and used through the TextUtil instance for the plugin. + public Map rawTags = new LinkedHashMap<>(); + protected boolean loadSuccessful = false; + private Integer saveTask = null; + private boolean autoSave = true; + // Listeners + private MPluginSecretPlayerListener mPluginSecretPlayerListener; - // Our stored base commands - private List> baseCommands = new ArrayList<>(); - // holds f stuck start times - private Map timers = new HashMap<>(); - // -------------------------------------------- // - // ENABLE - // -------------------------------------------- // - private long timeEnableStart; + // Our stored base commands + private List> baseCommands = new ArrayList<>(); + // holds f stuck start times + private Map timers = new HashMap<>(); + // -------------------------------------------- // + // ENABLE + // -------------------------------------------- // + private long timeEnableStart; - public boolean getAutoSave() { - return this.autoSave; - } + public boolean getAutoSave() { + return this.autoSave; + } - public void setAutoSave(boolean val) { - this.autoSave = val; - } + public void setAutoSave(boolean val) { + this.autoSave = val; + } - public List> getBaseCommands() { - return this.baseCommands; - } + public List> getBaseCommands() { + return this.baseCommands; + } - public boolean preEnable() { - log("=== ENABLE START ==="); - timeEnableStart = System.currentTimeMillis(); + public boolean preEnable() { + log("=== ENABLE START ==="); + timeEnableStart = System.currentTimeMillis(); - // Ensure basefolder exists! - this.getDataFolder().mkdirs(); + // Ensure basefolder exists! + this.getDataFolder().mkdirs(); - // Create Utility Instances - this.perm = new PermUtil(this); - this.persist = new Persist(this); + // Create Utility Instances + this.perm = new PermUtil(this); + this.persist = new Persist(this); - this.txt = new TextUtil(); - initTXT(); + this.txt = new TextUtil(); + initTXT(); - // attempt to get first command defined in plugin.yml as reference command, if any commands are defined in there - // reference command will be used to prevent "unknown command" console messages - try { - Map> refCmd = this.getDescription().getCommands(); - if (refCmd != null && !refCmd.isEmpty()) { - this.refCommand = (String) (refCmd.keySet().toArray()[0]); - } - } catch (ClassCastException ex) { - } + // attempt to get first command defined in plugin.yml as reference command, if any commands are defined in there + // reference command will be used to prevent "unknown command" console messages + try { + Map> refCmd = this.getDescription().getCommands(); + if (refCmd != null && !refCmd.isEmpty()) { + this.refCommand = (String) (refCmd.keySet().toArray()[0]); + } + } catch (ClassCastException ex) { + } - // Create and register player command listener - this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this); - getServer().getPluginManager().registerEvents(this.mPluginSecretPlayerListener, this); + // Create and register player command listener + this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this); + getServer().getPluginManager().registerEvents(this.mPluginSecretPlayerListener, this); - // Register recurring tasks - if (saveTask == null && Conf.saveToFileEveryXMinutes > 0.0) { - long saveTicks = (long) (20 * 60 * Conf.saveToFileEveryXMinutes); // Approximately every 30 min by default - saveTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(this), saveTicks, saveTicks); - } + // Register recurring tasks + if (saveTask == null && Conf.saveToFileEveryXMinutes > 0.0) { + long saveTicks = (long) (20 * 60 * Conf.saveToFileEveryXMinutes); // Approximately every 30 min by default + saveTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(this), saveTicks, saveTicks); + } - loadLang(); + loadLang(); - loadSuccessful = true; - return true; - } + loadSuccessful = true; + return true; + } - public void postEnable() { - log("=== ENABLE DONE (Took " + (System.currentTimeMillis() - timeEnableStart) + "ms) ==="); - } + public void postEnable() { + log("=== ENABLE DONE (Took " + (System.currentTimeMillis() - timeEnableStart) + "ms) ==="); + } - public void loadLang() { - File lang = new File(getDataFolder(), "lang.yml"); - OutputStream out = null; - InputStream defLangStream = this.getResource("lang.yml"); - if (!lang.exists()) { - try { - getDataFolder().mkdir(); - lang.createNewFile(); - if (defLangStream != null) { - out = new FileOutputStream(lang); - int read; - byte[] bytes = new byte[1024]; + public void loadLang() { + File lang = new File(getDataFolder(), "lang.yml"); + OutputStream out = null; + InputStream defLangStream = this.getResource("lang.yml"); + if (!lang.exists()) { + try { + getDataFolder().mkdir(); + lang.createNewFile(); + if (defLangStream != null) { + out = new FileOutputStream(lang); + int read; + byte[] bytes = new byte[1024]; - while ((read = defLangStream.read(bytes)) != -1) { - out.write(bytes, 0, read); - } - YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(new BufferedReader(new InputStreamReader(defLangStream))); - TL.setFile(defConfig); - } - } catch (IOException e) { - e.printStackTrace(); // So they notice - getLogger().severe("[Factions] Couldn't create language file."); - getLogger().severe("[Factions] This is a fatal error. Now disabling"); - this.setEnabled(false); // Without it loaded, we can't send them messages - } finally { - if (defLangStream != null) { - try { - defLangStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (out != null) { - try { - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } + while ((read = defLangStream.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(new BufferedReader(new InputStreamReader(defLangStream))); + TL.setFile(defConfig); + } + } catch (IOException e) { + e.printStackTrace(); // So they notice + getLogger().severe("[Factions] Couldn't create language file."); + getLogger().severe("[Factions] This is a fatal error. Now disabling"); + this.setEnabled(false); // Without it loaded, we can't send them messages + } finally { + if (defLangStream != null) { + try { + defLangStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } - } - } - } + } + } + } - YamlConfiguration conf = YamlConfiguration.loadConfiguration(lang); - for (TL item : TL.values()) { - if (conf.getString(item.getPath()) == null) { - conf.set(item.getPath(), item.getDefault()); - } - } + YamlConfiguration conf = YamlConfiguration.loadConfiguration(lang); + for (TL item : TL.values()) { + if (conf.getString(item.getPath()) == null) { + conf.set(item.getPath(), item.getDefault()); + } + } - // Remove this here because I'm sick of dealing with bug reports due to bad decisions on my part. - if (conf.getString(TL.COMMAND_SHOW_POWER.getPath(), "").contains("%5$s")) { - conf.set(TL.COMMAND_SHOW_POWER.getPath(), TL.COMMAND_SHOW_POWER.getDefault()); - log(Level.INFO, "Removed errant format specifier from f show power."); - } + // Remove this here because I'm sick of dealing with bug reports due to bad decisions on my part. + if (conf.getString(TL.COMMAND_SHOW_POWER.getPath(), "").contains("%5$s")) { + conf.set(TL.COMMAND_SHOW_POWER.getPath(), TL.COMMAND_SHOW_POWER.getDefault()); + log(Level.INFO, "Removed errant format specifier from f show power."); + } - TL.setFile(conf); - try { - conf.save(lang); - } catch (IOException e) { - getLogger().log(Level.WARNING, "Factions: Failed to save lang.yml."); - getLogger().log(Level.WARNING, "Factions: Report this stack trace to prosavage."); - e.printStackTrace(); - } - } + TL.setFile(conf); + try { + conf.save(lang); + } catch (IOException e) { + getLogger().log(Level.WARNING, "Factions: Failed to save lang.yml."); + getLogger().log(Level.WARNING, "Factions: Report this stack trace to prosavage."); + e.printStackTrace(); + } + } - public void onDisable() { - if (saveTask != null) { - this.getServer().getScheduler().cancelTask(saveTask); - saveTask = null; - } - // only save data if plugin actually loaded successfully - if (loadSuccessful) { - Factions.getInstance().forceSave(); - FPlayers.getInstance().forceSave(); - Board.getInstance().forceSave(); - } - log("Disabled"); - } + public void onDisable() { + if (saveTask != null) { + this.getServer().getScheduler().cancelTask(saveTask); + saveTask = null; + } + // only save data if plugin actually loaded successfully + if (loadSuccessful) { + Factions.getInstance().forceSave(); + FPlayers.getInstance().forceSave(); + Board.getInstance().forceSave(); + } + log("Disabled"); + } - // -------------------------------------------- // - // Some inits... - // You are supposed to override these in the plugin if you aren't satisfied with the defaults - // The goal is that you always will be satisfied though. - // -------------------------------------------- // + // -------------------------------------------- // + // Some inits... + // You are supposed to override these in the plugin if you aren't satisfied with the defaults + // The goal is that you always will be satisfied though. + // -------------------------------------------- // - public void suicide() { - log("Now I suicide!"); - this.getServer().getPluginManager().disablePlugin(this); - } + public void suicide() { + log("Now I suicide!"); + this.getServer().getPluginManager().disablePlugin(this); + } - // -------------------------------------------- // - // LANG AND TAGS - // -------------------------------------------- // + // -------------------------------------------- // + // LANG AND TAGS + // -------------------------------------------- // - public GsonBuilder getGsonBuilder() { - return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE); - } + public GsonBuilder getGsonBuilder() { + return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE); + } - public void addRawTags() { - this.rawTags.put("l", ""); // logo - this.rawTags.put("a", ""); // art - this.rawTags.put("n", ""); // notice - this.rawTags.put("i", ""); // info - this.rawTags.put("g", ""); // good - this.rawTags.put("b", ""); // bad - this.rawTags.put("h", ""); // highligh - this.rawTags.put("c", ""); // command - this.rawTags.put("plugin", ""); // parameter - } + public void addRawTags() { + this.rawTags.put("l", ""); // logo + this.rawTags.put("a", ""); // art + this.rawTags.put("n", ""); // notice + this.rawTags.put("i", ""); // info + this.rawTags.put("g", ""); // good + this.rawTags.put("b", ""); // bad + this.rawTags.put("h", ""); // highligh + this.rawTags.put("c", ""); // command + this.rawTags.put("plugin", ""); // parameter + } - public void initTXT() { - this.addRawTags(); + public void initTXT() { + this.addRawTags(); - Type type = new TypeToken>() { - }.getType(); + Type type = new TypeToken>() { + }.getType(); - Map tagsFromFile = this.persist.load(type, "tags"); - if (tagsFromFile != null) { - this.rawTags.putAll(tagsFromFile); - } - this.persist.save(this.rawTags, "tags"); + Map tagsFromFile = this.persist.load(type, "tags"); + if (tagsFromFile != null) { + this.rawTags.putAll(tagsFromFile); + } + this.persist.save(this.rawTags, "tags"); - for (Entry rawTag : this.rawTags.entrySet()) { - this.txt.tags.put(rawTag.getKey(), TextUtil.parseColor(rawTag.getValue())); - } - } + for (Entry rawTag : this.rawTags.entrySet()) { + this.txt.tags.put(rawTag.getKey(), TextUtil.parseColor(rawTag.getValue())); + } + } - // -------------------------------------------- // - // COMMAND HANDLING - // -------------------------------------------- // + // -------------------------------------------- // + // COMMAND HANDLING + // -------------------------------------------- // - // can be overridden by SavageFactions method, to provide option - public boolean logPlayerCommands() { - return true; - } + // can be overridden by SavageFactions method, to provide option + public boolean logPlayerCommands() { + return true; + } - public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { - return handleCommand(sender, commandString, testOnly, false); - } + public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) { + return handleCommand(sender, commandString, testOnly, false); + } - public boolean handleCommand(final CommandSender sender, String commandString, boolean testOnly, boolean async) { - boolean noSlash = true; - if (commandString.startsWith("/")) { - noSlash = false; - commandString = commandString.substring(1); - } + public boolean handleCommand(final CommandSender sender, String commandString, boolean testOnly, boolean async) { + boolean noSlash = true; + if (commandString.startsWith("/")) { + noSlash = false; + commandString = commandString.substring(1); + } - for (final MCommand command : this.getBaseCommands()) { - if (noSlash && !command.allowNoSlashAccess) { - continue; - } + for (final MCommand command : this.getBaseCommands()) { + if (noSlash && !command.allowNoSlashAccess) { + continue; + } - for (String alias : command.aliases) { - // disallow double-space after alias, so specific commands can be prevented (preventing "f home" won't prevent "f home") - if (commandString.startsWith(alias + " ")) { - return false; - } + for (String alias : command.aliases) { + // disallow double-space after alias, so specific commands can be prevented (preventing "f home" won't prevent "f home") + if (commandString.startsWith(alias + " ")) { + return false; + } - if (commandString.startsWith(alias + " ") || commandString.equals(alias)) { - final List args = new ArrayList<>(Arrays.asList(commandString.split("\\s+"))); - args.remove(0); + if (commandString.startsWith(alias + " ") || commandString.equals(alias)) { + final List args = new ArrayList<>(Arrays.asList(commandString.split("\\s+"))); + args.remove(0); - if (testOnly) { - return true; - } + if (testOnly) { + return true; + } - if (async) { - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { - @Override - public void run() { - command.execute(sender, args); - } - }); - } else { - command.execute(sender, args); - } + if (async) { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { + @Override + public void run() { + command.execute(sender, args); + } + }); + } else { + command.execute(sender, args); + } - return true; - } - } - } - return false; - } + return true; + } + } + } + return false; + } - public boolean handleCommand(CommandSender sender, String commandString) { - return this.handleCommand(sender, commandString, false); - } + public boolean handleCommand(CommandSender sender, String commandString) { + return this.handleCommand(sender, commandString, false); + } - // -------------------------------------------- // - // HOOKS - // -------------------------------------------- // - public void preAutoSave() { + // -------------------------------------------- // + // HOOKS + // -------------------------------------------- // + public void preAutoSave() { - } + } - public void postAutoSave() { + public void postAutoSave() { - } + } - public Map getStuckMap() { - return this.stuckMap; - } + public Map getStuckMap() { + return this.stuckMap; + } - public Map getTimers() { - return this.timers; - } + public Map getTimers() { + return this.timers; + } - // -------------------------------------------- // - // LOGGING - // -------------------------------------------- // - public void log(Object msg) { - log(Level.INFO, msg); - } + // -------------------------------------------- // + // LOGGING + // -------------------------------------------- // + public void log(Object msg) { + log(Level.INFO, msg); + } - public void log(String str, Object... args) { - log(Level.INFO, this.txt.parse(str, args)); - } + public void log(String str, Object... args) { + log(Level.INFO, this.txt.parse(str, args)); + } - public void log(Level level, String str, Object... args) { - log(level, this.txt.parse(str, args)); - } + public void log(Level level, String str, Object... args) { + log(level, this.txt.parse(str, args)); + } - public void log(Level level, Object msg) { - getLogger().log(level, "[" + this.getDescription().getFullName() + "] " + msg); - } + public void log(Level level, Object msg) { + getLogger().log(level, "[" + this.getDescription().getFullName() + "] " + msg); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java b/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java index ea4474c9..e82bae1d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java @@ -12,30 +12,30 @@ import org.bukkit.event.player.PlayerLoginEvent; public class MPluginSecretPlayerListener implements Listener { - private MPlugin p; + private MPlugin p; - public MPluginSecretPlayerListener(MPlugin p) { - this.p = p; - } + public MPluginSecretPlayerListener(MPlugin p) { + this.p = p; + } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - if (FactionsPlayerListener.preventCommand(event.getMessage(), event.getPlayer())) { - if (p.logPlayerCommands()) { - Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); - } - event.setCancelled(true); - } - } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + if (FactionsPlayerListener.preventCommand(event.getMessage(), event.getPlayer())) { + if (p.logPlayerCommands()) { + Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); + } + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerChat(AsyncPlayerChatEvent event) { - if (p.handleCommand(event.getPlayer(), event.getMessage(), false, true)) { - if (p.logPlayerCommands()) { - Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); - } - event.setCancelled(true); - } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerChat(AsyncPlayerChatEvent event) { + if (p.handleCommand(event.getPlayer(), event.getMessage(), false, true)) { + if (p.logPlayerCommands()) { + Bukkit.getLogger().info("[PLAYER_COMMAND] " + event.getPlayer().getName() + ": " + event.getMessage()); + } + event.setCancelled(true); + } /* Should be handled by stuff in FactionsChatListener Player speaker = event.getPlayer(); @@ -43,10 +43,10 @@ public class MPluginSecretPlayerListener implements Listener { format = format.replace(Conf.chatTagReplaceString, SavageFactions.plugin.getPlayerFactionTag(speaker)).replace("[FACTION_TITLE]", SavageFactions.plugin.getPlayerTitle(speaker)); event.setFormat(format); */ - } + } - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerPreLogin(PlayerLoginEvent event) { - FPlayers.getInstance().getByPlayer(event.getPlayer()); - } + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerPreLogin(PlayerLoginEvent event) { + FPlayers.getInstance().getByPlayer(event.getPlayer()); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java b/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java index 87243fc2..ed6c607b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java @@ -3,41 +3,41 @@ package com.massivecraft.factions.zcore.fperms; import org.bukkit.ChatColor; public enum Access { - ALLOW("Allow", ChatColor.GREEN), - DENY("Deny", ChatColor.DARK_RED), - UNDEFINED("Undefined", ChatColor.GRAY); + ALLOW("Allow", ChatColor.GREEN), + DENY("Deny", ChatColor.DARK_RED), + UNDEFINED("Undefined", ChatColor.GRAY); - private final String name; - private final ChatColor color; + private final String name; + private final ChatColor color; - Access(String name, ChatColor color) { - this.name = name; - this.color = color; - } + Access(String name, ChatColor color) { + this.name = name; + this.color = color; + } - /** - * Case insensitive check for access. - * - * @param check - * @return - */ - public static Access fromString(String check) { - for (Access access : values()) - if (access.name().equalsIgnoreCase(check)) - return access; - return null; - } + /** + * Case insensitive check for access. + * + * @param check + * @return + */ + public static Access fromString(String check) { + for (Access access : values()) + if (access.name().equalsIgnoreCase(check)) + return access; + return null; + } - public String getName() { - return this.name; - } + public String getName() { + return this.name; + } - public ChatColor getColor() { - return color; - } + public ChatColor getColor() { + return color; + } - @Override - public String toString() { - return name(); - } + @Override + public String toString() { + return name(); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java b/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java index be3f7f3c..b1d472b4 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/DefaultPermissions.java @@ -1,147 +1,152 @@ package com.massivecraft.factions.zcore.fperms; public class DefaultPermissions { - public DefaultPermissions() { } - public DefaultPermissions(boolean def) { - this.ban = def; - this.build = def; - this.destroy = def; - this.frostwalk = def; - this.painbuild = def; - this.door = def; - this.button = def; - this.lever = def; - this.container = def; - this.invite = def; - this.kick = def; - this.items = def; - this.sethome = def; - this.territory = def; - this.access = def; - this.home = def; - this.disband = def; - this.promote = def; - this.setwarp = def; - this.warp = def; - this.fly = def; - this.vault = def; - this.tntbank = def; - this.tntfill = def; - this.withdraw = def; - this.chest = def; - this.spawner = def; - } - public DefaultPermissions(boolean canBan, - boolean canBuild, - boolean canDestory, - boolean canFrostwalk, - boolean canPainbuild, - boolean canDoor, - boolean canButton, - boolean canLever, - boolean canContainer, - boolean canInvite, - boolean canKick, - boolean canItems, - boolean canSethome, - boolean canTerritory, - boolean canAccess, - boolean canHome, - boolean canDisband, - boolean canPromote, - boolean canSetwarp, - boolean canWarp, - boolean canFly, - boolean canVault, - boolean canTntbank, - boolean canTntfill, - boolean canWithdraw, - boolean canChest, - boolean canSpawners) { - this.ban = canBan; - this.build = canBuild; - this.destroy = canDestory; - this.frostwalk = canFrostwalk; - this.painbuild = canPainbuild; - this.door = canDoor; - this.button = canButton; - this.lever = canLever; - this.container = canContainer; - this.invite = canInvite; - this.kick = canKick; - this.items = canItems; - this.sethome = canSethome; - this.territory = canTerritory; - this.access = canAccess; - this.home = canHome; - this.disband = canDisband; - this.promote = canPromote; - this.setwarp = canSetwarp; - this.warp = canWarp; - this.fly = canFly; - this.vault = canVault; - this.tntbank = canTntbank; - this.tntfill = canTntfill; - this.withdraw = canWithdraw; - this.chest = canChest; - this.spawner = canSpawners; - } - public boolean ban; - public boolean build; - public boolean destroy; - public boolean frostwalk; - public boolean painbuild; - public boolean door; - public boolean button; - public boolean lever; - public boolean container; - public boolean invite; - public boolean kick; - public boolean items; - public boolean sethome; - public boolean territory; - public boolean access; - public boolean home; - public boolean disband; - public boolean promote; - public boolean setwarp; - public boolean warp; - public boolean fly; - public boolean vault; - public boolean tntbank; - public boolean tntfill; - public boolean withdraw; - public boolean chest; - public boolean spawner; - @Deprecated - public boolean getbyName(String name) { - if (name == "ban") return this.ban; - else if (name == "build") return this.build; - else if (name == "destroy") return this.destroy; - else if (name == "frostwalk") return this.frostwalk; - else if (name == "painbuild") return this.painbuild; - else if (name == "door") return this.door; - else if (name == "button") return this.button; - else if (name == "lever") return this.lever; - else if (name == "container") return this.container; - else if (name == "invite") return this.invite; - else if (name == "kick") return this.kick; - else if (name == "items") return this.items; - else if (name == "sethome") return this.sethome; - else if (name == "territory") return this.territory; - else if (name == "access") return this.access; - else if (name == "home") return this.disband; - else if (name == "disband") return this.disband; - else if (name == "promote") return this.promote; - else if (name == "setwarp") return this.setwarp; - else if (name == "warp") return this.warp; - else if (name == "fly") return this.fly; - else if (name == "vault") return this.vault; - else if (name == "tntbank") return this.tntbank; - else if (name == "tntfill") return this.tntfill; - else if (name == "withdraw") return this.withdraw; - else if (name == "chest") return this.chest; - else if (name == "spawner") return this.spawner; - else return false; - } + public DefaultPermissions() { + } + + public DefaultPermissions(boolean def) { + this.ban = def; + this.build = def; + this.destroy = def; + this.frostwalk = def; + this.painbuild = def; + this.door = def; + this.button = def; + this.lever = def; + this.container = def; + this.invite = def; + this.kick = def; + this.items = def; + this.sethome = def; + this.territory = def; + this.access = def; + this.home = def; + this.disband = def; + this.promote = def; + this.setwarp = def; + this.warp = def; + this.fly = def; + this.vault = def; + this.tntbank = def; + this.tntfill = def; + this.withdraw = def; + this.chest = def; + this.spawner = def; + } + + public DefaultPermissions(boolean canBan, + boolean canBuild, + boolean canDestory, + boolean canFrostwalk, + boolean canPainbuild, + boolean canDoor, + boolean canButton, + boolean canLever, + boolean canContainer, + boolean canInvite, + boolean canKick, + boolean canItems, + boolean canSethome, + boolean canTerritory, + boolean canAccess, + boolean canHome, + boolean canDisband, + boolean canPromote, + boolean canSetwarp, + boolean canWarp, + boolean canFly, + boolean canVault, + boolean canTntbank, + boolean canTntfill, + boolean canWithdraw, + boolean canChest, + boolean canSpawners) { + this.ban = canBan; + this.build = canBuild; + this.destroy = canDestory; + this.frostwalk = canFrostwalk; + this.painbuild = canPainbuild; + this.door = canDoor; + this.button = canButton; + this.lever = canLever; + this.container = canContainer; + this.invite = canInvite; + this.kick = canKick; + this.items = canItems; + this.sethome = canSethome; + this.territory = canTerritory; + this.access = canAccess; + this.home = canHome; + this.disband = canDisband; + this.promote = canPromote; + this.setwarp = canSetwarp; + this.warp = canWarp; + this.fly = canFly; + this.vault = canVault; + this.tntbank = canTntbank; + this.tntfill = canTntfill; + this.withdraw = canWithdraw; + this.chest = canChest; + this.spawner = canSpawners; + } + + public boolean ban; + public boolean build; + public boolean destroy; + public boolean frostwalk; + public boolean painbuild; + public boolean door; + public boolean button; + public boolean lever; + public boolean container; + public boolean invite; + public boolean kick; + public boolean items; + public boolean sethome; + public boolean territory; + public boolean access; + public boolean home; + public boolean disband; + public boolean promote; + public boolean setwarp; + public boolean warp; + public boolean fly; + public boolean vault; + public boolean tntbank; + public boolean tntfill; + public boolean withdraw; + public boolean chest; + public boolean spawner; + + @Deprecated + public boolean getbyName(String name) { + if (name == "ban") return this.ban; + else if (name == "build") return this.build; + else if (name == "destroy") return this.destroy; + else if (name == "frostwalk") return this.frostwalk; + else if (name == "painbuild") return this.painbuild; + else if (name == "door") return this.door; + else if (name == "button") return this.button; + else if (name == "lever") return this.lever; + else if (name == "container") return this.container; + else if (name == "invite") return this.invite; + else if (name == "kick") return this.kick; + else if (name == "items") return this.items; + else if (name == "sethome") return this.sethome; + else if (name == "territory") return this.territory; + else if (name == "access") return this.access; + else if (name == "home") return this.disband; + else if (name == "disband") return this.disband; + else if (name == "promote") return this.promote; + else if (name == "setwarp") return this.setwarp; + else if (name == "warp") return this.warp; + else if (name == "fly") return this.fly; + else if (name == "vault") return this.vault; + else if (name == "tntbank") return this.tntbank; + else if (name == "tntfill") return this.tntfill; + else if (name == "withdraw") return this.withdraw; + else if (name == "chest") return this.chest; + else if (name == "spawner") return this.spawner; + else return false; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java b/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java index 3441f9d3..3412581b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java @@ -4,10 +4,10 @@ import org.bukkit.inventory.ItemStack; public interface Permissable { - ItemStack buildItem(); + ItemStack buildItem(); - String replacePlaceholders(String string); + String replacePlaceholders(String string); - String name(); + String name(); } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java index 3fc99e83..3c5c32e7 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java @@ -16,169 +16,169 @@ import java.util.Map; import java.util.logging.Level; public enum PermissableAction { - BAN("ban"), - BUILD("build"), - DESTROY("destroy"), - FROST_WALK("frostwalk"), - PAIN_BUILD("painbuild"), - DOOR("door"), - BUTTON("button"), - LEVER("lever"), - CONTAINER("container"), - INVITE("invite"), - KICK("kick"), - ITEM("items"), // generic for most items - SETHOME("sethome"), - TERRITORY("territory"), - ACCESS("access"), - HOME("home"), - DISBAND("disband"), - PROMOTE("promote"), - SETWARP("setwarp"), - WARP("warp"), - FLY("fly"), - VAULT("vault"), - TNTBANK("tntbank"), - TNTFILL("tntfill"), - WITHDRAW("withdraw"), - CHEST("chest"), - SPAWNER("spawner"); + BAN("ban"), + BUILD("build"), + DESTROY("destroy"), + FROST_WALK("frostwalk"), + PAIN_BUILD("painbuild"), + DOOR("door"), + BUTTON("button"), + LEVER("lever"), + CONTAINER("container"), + INVITE("invite"), + KICK("kick"), + ITEM("items"), // generic for most items + SETHOME("sethome"), + TERRITORY("territory"), + ACCESS("access"), + HOME("home"), + DISBAND("disband"), + PROMOTE("promote"), + SETWARP("setwarp"), + WARP("warp"), + FLY("fly"), + VAULT("vault"), + TNTBANK("tntbank"), + TNTFILL("tntfill"), + WITHDRAW("withdraw"), + CHEST("chest"), + SPAWNER("spawner"); - private String name; + private String name; - PermissableAction(String name) { - this.name = name; - } + PermissableAction(String name) { + this.name = name; + } - /** - * Case insensitive check for action. - * - * @param check - * @return - action - */ - public static PermissableAction fromString(String check) { - for (PermissableAction permissableAction : values()) { - if (permissableAction.name().equalsIgnoreCase(check)) { - return permissableAction; - } - } + /** + * Case insensitive check for action. + * + * @param check + * @return - action + */ + public static PermissableAction fromString(String check) { + for (PermissableAction permissableAction : values()) { + if (permissableAction.name().equalsIgnoreCase(check)) { + return permissableAction; + } + } - return null; - } + return null; + } - /** - * Get the friendly name of this action. Used for editing in commands. - * - * @return friendly name of the action as a String. - */ - public String getName() { - return this.name; - } + /** + * Get the friendly name of this action. Used for editing in commands. + * + * @return friendly name of the action as a String. + */ + public String getName() { + return this.name; + } - @Override - public String toString() { - return name; - } + @Override + public String toString() { + return name; + } - // Utility method to build items for F Perm GUI - public ItemStack buildItem(FPlayer fme, Permissable permissable) { - final ConfigurationSection section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); + // Utility method to build items for F Perm GUI + public ItemStack buildItem(FPlayer fme, Permissable permissable) { + final ConfigurationSection section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - String displayName = replacePlaceholders(section.getString("placeholder-item.name"), fme, permissable); - List lore = new ArrayList<>(); + String displayName = replacePlaceholders(section.getString("placeholder-item.name"), fme, permissable); + List lore = new ArrayList<>(); - if (section.getString("materials." + name().toLowerCase().replace('_', '-')) == null) { - return null; - } - Material material = Material.matchMaterial(section.getString("materials." + name().toLowerCase().replace('_', '-'))); - if (material == null) { - material = SavageFactions.plugin.STAINED_CLAY; - } + if (section.getString("materials." + name().toLowerCase().replace('_', '-')) == null) { + return null; + } + Material material = Material.matchMaterial(section.getString("materials." + name().toLowerCase().replace('_', '-'))); + if (material == null) { + material = SavageFactions.plugin.STAINED_CLAY; + } - Access access = fme.getFaction().getAccess(permissable, this); - if (access == null) { - access = Access.UNDEFINED; - } + Access access = fme.getFaction().getAccess(permissable, this); + if (access == null) { + access = Access.UNDEFINED; + } - ItemStack item = new ItemStack(material); - ItemMeta itemMeta = item.getItemMeta(); + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); - String accessValue = null; + String accessValue = null; - switch (access) { - case ALLOW: - accessValue = "allow"; - break; - case DENY: - accessValue = "deny"; - break; - case UNDEFINED: - accessValue = "undefined"; - break; - } + switch (access) { + case ALLOW: + accessValue = "allow"; + break; + case DENY: + accessValue = "deny"; + break; + case UNDEFINED: + accessValue = "undefined"; + break; + } - // If under the 1.13 version we will use the colorable option. - if (!SavageFactions.plugin.mc113) { - DyeColor dyeColor = null; + // If under the 1.13 version we will use the colorable option. + if (!SavageFactions.plugin.mc113) { + DyeColor dyeColor = null; - try { - dyeColor = DyeColor.valueOf(section.getString("access." + access.name().toLowerCase())); - } catch (Exception exception) { - } + try { + dyeColor = DyeColor.valueOf(section.getString("access." + access.name().toLowerCase())); + } catch (Exception exception) { + } - if (dyeColor != null) { - item.setDurability(dyeColor.getWoolData()); - } - } else { - // so this is in 1.13 mode, our config will automatically be updated to a material instead of color because of it being removed in the new api - item.setType(Material.valueOf(SavageFactions.plugin.getConfig().getString("fperm-gui.action.access." + accessValue))); - } + if (dyeColor != null) { + item.setDurability(dyeColor.getWoolData()); + } + } else { + // so this is in 1.13 mode, our config will automatically be updated to a material instead of color because of it being removed in the new api + item.setType(Material.valueOf(SavageFactions.plugin.getConfig().getString("fperm-gui.action.access." + accessValue))); + } - for (String loreLine : section.getStringList("placeholder-item.lore")) { - lore.add(replacePlaceholders(loreLine, fme, permissable)); - } + for (String loreLine : section.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine, fme, permissable)); + } - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemMeta.setDisplayName(displayName); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); - return item; - } + return item; + } - public String replacePlaceholders(String string, FPlayer fme, Permissable permissable) { - // Run Permissable placeholders - string = permissable.replacePlaceholders(string); + public String replacePlaceholders(String string, FPlayer fme, Permissable permissable) { + // Run Permissable placeholders + string = permissable.replacePlaceholders(string); - String actionName = name.substring(0, 1).toUpperCase() + name.substring(1); - string = string.replace("{action}", actionName); + String actionName = name.substring(0, 1).toUpperCase() + name.substring(1); + string = string.replace("{action}", actionName); - Access access = fme.getFaction().getAccess(permissable, this); - if (access == null) { - access = Access.UNDEFINED; - } - String actionAccess = access.getName(); - string = string.replace("{action-access}", actionAccess); - string = string.replace("{action-access-color}", access.getColor().toString()); + Access access = fme.getFaction().getAccess(permissable, this); + if (access == null) { + access = Access.UNDEFINED; + } + String actionAccess = access.getName(); + string = string.replace("{action-access}", actionAccess); + string = string.replace("{action-access-color}", access.getColor().toString()); - return string; - } + return string; + } - public static Map fromDefaults(DefaultPermissions defaultPermissions) { - Map defaultMap = new HashMap<>(); - for (PermissableAction permissableAction : PermissableAction.values()) { - defaultMap.put(permissableAction, defaultPermissions.getbyName(permissableAction.name) ? Access.ALLOW : Access.DENY); - } - return defaultMap; - } + public static Map fromDefaults(DefaultPermissions defaultPermissions) { + Map defaultMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + defaultMap.put(permissableAction, defaultPermissions.getbyName(permissableAction.name) ? Access.ALLOW : Access.DENY); + } + return defaultMap; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java index c26ad9a4..5608e972 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java @@ -24,291 +24,291 @@ import java.util.logging.Level; public class PermissableActionGUI implements InventoryHolder, FactionGUI { - private final ConfigurationSection section; - private Inventory actionGUI; - private FPlayer fme; - private int guiSize; - private Permissable permissable; - private HashMap actionSlots = new HashMap<>(); - private HashMap specialSlots = new HashMap<>(); - private ArrayList usedDummySlots = new ArrayList<>(); + private final ConfigurationSection section; + private Inventory actionGUI; + private FPlayer fme; + private int guiSize; + private Permissable permissable; + private HashMap actionSlots = new HashMap<>(); + private HashMap specialSlots = new HashMap<>(); + private ArrayList usedDummySlots = new ArrayList<>(); - public PermissableActionGUI(FPlayer fme, Permissable permissable) { - this.fme = fme; - this.permissable = permissable; - this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); - } + public PermissableActionGUI(FPlayer fme, Permissable permissable) { + this.fme = fme; + this.permissable = permissable; + this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.action"); + } - public void build() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + public void build() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - guiSize = section.getInt("rows", 3); - if (guiSize > 6) { - guiSize = 6; - SavageFactions.plugin.log(Level.INFO, "Action GUI size out of bounds, defaulting to 6"); - } + guiSize = section.getInt("rows", 3); + if (guiSize > 6) { + guiSize = 6; + SavageFactions.plugin.log(Level.INFO, "Action GUI size out of bounds, defaulting to 6"); + } - guiSize *= 9; - String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPerms")); - actionGUI = Bukkit.createInventory(this, guiSize, guiName); - boolean disabled = false; - for (String key : section.getConfigurationSection("slots").getKeys(false)) { - int slot = section.getInt("slots." + key); - if (slot == -1) { - disabled = true; - continue; - } - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot for: " + key.toUpperCase()); - continue; - } + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPerms")); + actionGUI = Bukkit.createInventory(this, guiSize, guiName); + boolean disabled = false; + for (String key : section.getConfigurationSection("slots").getKeys(false)) { + int slot = section.getInt("slots." + key); + if (slot == -1) { + disabled = true; + continue; + } + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot for: " + key.toUpperCase()); + continue; + } - if (SpecialItem.isSpecial(key)) { - specialSlots.put(slot, SpecialItem.fromString(key)); - continue; - } + if (SpecialItem.isSpecial(key)) { + specialSlots.put(slot, SpecialItem.fromString(key)); + continue; + } - PermissableAction permissableAction = PermissableAction.fromString(key.toUpperCase().replace('-', '_')); - if (permissableAction == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid permissable action: " + key.toUpperCase()); - continue; - } + PermissableAction permissableAction = PermissableAction.fromString(key.toUpperCase().replace('-', '_')); + if (permissableAction == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid permissable action: " + key.toUpperCase()); + continue; + } - actionSlots.put(section.getInt("slots." + key), permissableAction); - } + actionSlots.put(section.getInt("slots." + key), permissableAction); + } - buildDummyItems(); + buildDummyItems(); - if (actionSlots.values().toArray().length != PermissableAction.values().length) { - // Missing actions add them forcefully to the GUI and log error - Set missingActions = new HashSet<>(Arrays.asList(PermissableAction.values())); - missingActions.removeAll(actionSlots.values()); + if (actionSlots.values().toArray().length != PermissableAction.values().length) { + // Missing actions add them forcefully to the GUI and log error + Set missingActions = new HashSet<>(Arrays.asList(PermissableAction.values())); + missingActions.removeAll(actionSlots.values()); - for (PermissableAction action : missingActions) { - if (disabled) { - break; - } - if (!usedDummySlots.isEmpty()) { - int slot = usedDummySlots.get(0); - actionSlots.put(slot, action); - } else { - int slot = actionGUI.firstEmpty(); - if (slot != -1) { - actionSlots.put(slot, action); - } - } - SavageFactions.plugin.log(Level.WARNING, "Missing action: " + action.name()); - } + for (PermissableAction action : missingActions) { + if (disabled) { + break; + } + if (!usedDummySlots.isEmpty()) { + int slot = usedDummySlots.get(0); + actionSlots.put(slot, action); + } else { + int slot = actionGUI.firstEmpty(); + if (slot != -1) { + actionSlots.put(slot, action); + } + } + SavageFactions.plugin.log(Level.WARNING, "Missing action: " + action.name()); + } - } + } - buildSpecialItems(); - buildItems(); - } + buildSpecialItems(); + buildItems(); + } - @Override - public Inventory getInventory() { - return actionGUI; - } + @Override + public Inventory getInventory() { + return actionGUI; + } - @Override - public void onClick(int slot, ClickType click) { - if (specialSlots.containsKey(slot)) { - if (specialSlots.get(slot) == SpecialItem.BACK) { - PermissableRelationGUI relationGUI = new PermissableRelationGUI(fme); - relationGUI.build(); + @Override + public void onClick(int slot, ClickType click) { + if (specialSlots.containsKey(slot)) { + if (specialSlots.get(slot) == SpecialItem.BACK) { + PermissableRelationGUI relationGUI = new PermissableRelationGUI(fme); + relationGUI.build(); - fme.getPlayer().openInventory(relationGUI.getInventory()); - } - return; - } - if (!actionSlots.containsKey(slot)) { - return; - } + fme.getPlayer().openInventory(relationGUI.getInventory()); + } + return; + } + if (!actionSlots.containsKey(slot)) { + return; + } - PermissableAction action = actionSlots.get(slot); - Access access; - if (click == ClickType.LEFT) { - access = Access.ALLOW; - fme.getFaction().setPermission(permissable, action, access); - } else if (click == ClickType.RIGHT) { - access = Access.DENY; - fme.getFaction().setPermission(permissable, action, access); - } else if (click == ClickType.MIDDLE) { - access = Access.UNDEFINED; - fme.getFaction().setPermission(permissable, action, access); - } else { - return; - } + PermissableAction action = actionSlots.get(slot); + Access access; + if (click == ClickType.LEFT) { + access = Access.ALLOW; + fme.getFaction().setPermission(permissable, action, access); + } else if (click == ClickType.RIGHT) { + access = Access.DENY; + fme.getFaction().setPermission(permissable, action, access); + } else if (click == ClickType.MIDDLE) { + access = Access.UNDEFINED; + fme.getFaction().setPermission(permissable, action, access); + } else { + return; + } - actionGUI.setItem(slot, action.buildItem(fme, permissable)); - fme.msg(TL.COMMAND_PERM_SET, action.name(), access.name(), permissable.name()); - SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), action.name(), access.name(), permissable.name()) + " for faction " + fme.getTag()); - } + actionGUI.setItem(slot, action.buildItem(fme, permissable)); + fme.msg(TL.COMMAND_PERM_SET, action.name(), access.name(), permissable.name()); + SavageFactions.plugin.log(String.format(TL.COMMAND_PERM_SET.toString(), action.name(), access.name(), permissable.name()) + " for faction " + fme.getTag()); + } - private void buildItems() { - for (Map.Entry entry : actionSlots.entrySet()) { - PermissableAction permissableAction = entry.getValue(); + private void buildItems() { + for (Map.Entry entry : actionSlots.entrySet()) { + PermissableAction permissableAction = entry.getValue(); - ItemStack item = permissableAction.buildItem(fme, permissable); + ItemStack item = permissableAction.buildItem(fme, permissable); - if (item == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid item for: " + permissableAction.toString().toUpperCase()); - continue; - } + if (item == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid item for: " + permissableAction.toString().toUpperCase()); + continue; + } - actionGUI.setItem(entry.getKey(), item); - } - } + actionGUI.setItem(entry.getKey(), item); + } + } - private void buildSpecialItems() { - for (Map.Entry entry : specialSlots.entrySet()) { - actionGUI.setItem(entry.getKey(), getSpecialItem(entry.getValue())); - } - } + private void buildSpecialItems() { + for (Map.Entry entry : specialSlots.entrySet()) { + actionGUI.setItem(entry.getKey(), getSpecialItem(entry.getValue())); + } + } - private ItemStack getSpecialItem(SpecialItem specialItem) { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + private ItemStack getSpecialItem(SpecialItem specialItem) { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - switch (specialItem) { - case RELATION: - return permissable.buildItem(); - case BACK: - ConfigurationSection backButtonConfig = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.back-item"); + switch (specialItem) { + case RELATION: + return permissable.buildItem(); + case BACK: + ConfigurationSection backButtonConfig = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.back-item"); - ItemStack backButton = new ItemStack(Material.matchMaterial(backButtonConfig.getString("material"))); - ItemMeta backButtonMeta = backButton.getItemMeta(); + ItemStack backButton = new ItemStack(Material.matchMaterial(backButtonConfig.getString("material"))); + ItemMeta backButtonMeta = backButton.getItemMeta(); - backButtonMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', backButtonConfig.getString("name"))); - List lore = new ArrayList<>(); - for (String loreLine : backButtonConfig.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } + backButtonMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', backButtonConfig.getString("name"))); + List lore = new ArrayList<>(); + for (String loreLine : backButtonConfig.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } - backButtonMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - backButtonMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + backButtonMeta.setLore(lore); + if (!SavageFactions.plugin.mc17) { + backButtonMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - backButton.setItemMeta(backButtonMeta); + backButton.setItemMeta(backButtonMeta); - return backButton; - default: - return null; - } - } + return backButton; + default: + return null; + } + } - private void buildDummyItems() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + private void buildDummyItems() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { - int dummyId; - try { - dummyId = Integer.parseInt(key); - } catch (NumberFormatException exception) { - SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); - continue; - } + for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } - ItemStack dummyItem = buildDummyItem(dummyId); - if (dummyItem == null) { - continue; - } + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } - ItemMeta meta = dummyItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + ItemMeta meta = dummyItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - dummyItem.setItemMeta(meta); + dummyItem.setItemMeta(meta); - List dummySlots = section.getIntegerList("dummy-items." + key); - for (Integer slot : dummySlots) { - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); - continue; - } - usedDummySlots.add(slot); - actionGUI.setItem(slot, dummyItem); - } - } - } + List dummySlots = section.getIntegerList("dummy-items." + key); + for (Integer slot : dummySlots) { + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + usedDummySlots.add(slot); + actionGUI.setItem(slot, dummyItem); + } + } + } - private ItemStack buildDummyItem(int id) { - final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); + private ItemStack buildDummyItem(int id) { + final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); - if (dummySection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build dummy items for F PERM GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (dummySection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build dummy items for F PERM GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - Material material = Material.matchMaterial(dummySection.getString("material", "")); - if (material == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); - return null; - } + Material material = Material.matchMaterial(dummySection.getString("material", "")); + if (material == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } - ItemStack itemStack = new ItemStack(material); + ItemStack itemStack = new ItemStack(material); - DyeColor color; - try { - color = DyeColor.valueOf(dummySection.getString("color", "")); - } catch (Exception exception) { - color = null; - } - if (color != null) { - itemStack.setDurability(color.getWoolData()); - } + DyeColor color; + try { + color = DyeColor.valueOf(dummySection.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } - ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); - List lore = new ArrayList<>(); - for (String loreLine : dummySection.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } + List lore = new ArrayList<>(); + for (String loreLine : dummySection.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } - itemMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + itemMeta.setLore(lore); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemStack.setItemMeta(itemMeta); + itemStack.setItemMeta(itemMeta); - return itemStack; - } + return itemStack; + } - public enum SpecialItem { - BACK, - RELATION; + public enum SpecialItem { + BACK, + RELATION; - static boolean isSpecial(String string) { - return fromString(string) != null; - } + static boolean isSpecial(String string) { + return fromString(string) != null; + } - static SpecialItem fromString(String string) { - for (SpecialItem specialItem : SpecialItem.values()) { - if (string.equalsIgnoreCase(specialItem.name())) { - return specialItem; - } - } - return null; - } - } + static SpecialItem fromString(String string) { + for (SpecialItem specialItem : SpecialItem.values()) { + if (string.equalsIgnoreCase(specialItem.name())) { + return specialItem; + } + } + return null; + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java index 871ee281..200af74d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java @@ -26,184 +26,184 @@ import java.util.logging.Level; public class PermissableRelationGUI implements InventoryHolder, FactionGUI { - private final ConfigurationSection section; - private Inventory relationGUI; - private FPlayer fme; - private int guiSize; - private HashMap relationSlots = new HashMap<>(); + private final ConfigurationSection section; + private Inventory relationGUI; + private FPlayer fme; + private int guiSize; + private HashMap relationSlots = new HashMap<>(); - public PermissableRelationGUI(FPlayer fme) { - this.fme = fme; - this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); - } + public PermissableRelationGUI(FPlayer fme) { + this.fme = fme; + this.section = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.relation"); + } - public void build() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + public void build() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - // Build basic Inventory info - guiSize = section.getInt("rows", 3); - if (guiSize > 5) { - guiSize = 5; - SavageFactions.plugin.log(Level.INFO, "Relation GUI size out of bounds, defaulting to 5"); - } + // Build basic Inventory info + guiSize = section.getInt("rows", 3); + if (guiSize > 5) { + guiSize = 5; + SavageFactions.plugin.log(Level.INFO, "Relation GUI size out of bounds, defaulting to 5"); + } - guiSize *= 9; - String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); - relationGUI = Bukkit.createInventory(this, guiSize, guiName); + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', section.getString("name", "FactionPermissions")); + relationGUI = Bukkit.createInventory(this, guiSize, guiName); - for (String key : section.getConfigurationSection("slots").getKeys(false)) { - int slot = section.getInt("slots." + key); - if (slot == -1) { - continue; - } - if (slot + 1 > guiSize && slot > 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot of " + key.toUpperCase() + " in relation GUI skipping it"); - continue; - } + for (String key : section.getConfigurationSection("slots").getKeys(false)) { + int slot = section.getInt("slots." + key); + if (slot == -1) { + continue; + } + if (slot + 1 > guiSize && slot > 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot of " + key.toUpperCase() + " in relation GUI skipping it"); + continue; + } - if (getPermissable(key) == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid permissable " + key.toUpperCase() + " skipping it"); - continue; - } + if (getPermissable(key) == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid permissable " + key.toUpperCase() + " skipping it"); + continue; + } - relationSlots.put(slot, getPermissable(key)); - } + relationSlots.put(slot, getPermissable(key)); + } - buildDummyItems(); - buildItems(); - } + buildDummyItems(); + buildItems(); + } - @Override - public Inventory getInventory() { - return relationGUI; - } + @Override + public Inventory getInventory() { + return relationGUI; + } - @Override - public void onClick(int slot, ClickType clickType) { - if (!relationSlots.containsKey(slot)) { - return; - } + @Override + public void onClick(int slot, ClickType clickType) { + if (!relationSlots.containsKey(slot)) { + return; + } - PermissableActionGUI actionGUI = new PermissableActionGUI(fme, relationSlots.get(slot)); - actionGUI.build(); + PermissableActionGUI actionGUI = new PermissableActionGUI(fme, relationSlots.get(slot)); + actionGUI.build(); - fme.getPlayer().openInventory(actionGUI.getInventory()); - } + fme.getPlayer().openInventory(actionGUI.getInventory()); + } - private Permissable getPermissable(String name) { - if (Role.fromString(name.toUpperCase()) != null) { - return Role.fromString(name.toUpperCase()); - } else if (Relation.fromString(name.toUpperCase()) != null) { - return Relation.fromString(name.toUpperCase()); - } else { - return null; - } - } + private Permissable getPermissable(String name) { + if (Role.fromString(name.toUpperCase()) != null) { + return Role.fromString(name.toUpperCase()); + } else if (Relation.fromString(name.toUpperCase()) != null) { + return Relation.fromString(name.toUpperCase()); + } else { + return null; + } + } - private void buildItems() { - for (Map.Entry entry : relationSlots.entrySet()) { - Permissable permissable = entry.getValue(); + private void buildItems() { + for (Map.Entry entry : relationSlots.entrySet()) { + Permissable permissable = entry.getValue(); - ItemStack item = permissable.buildItem(); + ItemStack item = permissable.buildItem(); - if (item == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for " + permissable.toString().toUpperCase() + " skipping it"); - continue; - } + if (item == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for " + permissable.toString().toUpperCase() + " skipping it"); + continue; + } - relationGUI.setItem(entry.getKey(), item); - } - } + relationGUI.setItem(entry.getKey(), item); + } + } - private void buildDummyItems() { - if (section == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return; - } + private void buildDummyItems() { + if (section == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return; + } - for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { - int dummyId; - try { - dummyId = Integer.parseInt(key); - } catch (NumberFormatException exception) { - SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); - continue; - } + for (String key : section.getConfigurationSection("dummy-items").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + SavageFactions.plugin.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } - ItemStack dummyItem = buildDummyItem(dummyId); - if (dummyItem == null) { - continue; - } + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } - ItemMeta meta = dummyItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + ItemMeta meta = dummyItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - dummyItem.setItemMeta(meta); + dummyItem.setItemMeta(meta); - List dummySlots = section.getIntegerList("dummy-items." + key); - for (Integer slot : dummySlots) { - if (slot + 1 > guiSize || slot < 0) { - SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); - continue; - } - relationGUI.setItem(slot, dummyItem); - } - } - } + List dummySlots = section.getIntegerList("dummy-items." + key); + for (Integer slot : dummySlots) { + if (slot + 1 > guiSize || slot < 0) { + SavageFactions.plugin.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + relationGUI.setItem(slot, dummyItem); + } + } + } - private ItemStack buildDummyItem(int id) { - final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); + private ItemStack buildDummyItem(int id) { + final ConfigurationSection dummySection = SavageFactions.plugin.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); - if (dummySection == null) { - SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); - SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); - return new ItemStack(Material.AIR); - } + if (dummySection == null) { + SavageFactions.plugin.log(Level.WARNING, "Attempted to build f perm GUI but config section not present."); + SavageFactions.plugin.log(Level.WARNING, "Copy your config, allow the section to generate, then copy it back to your old config."); + return new ItemStack(Material.AIR); + } - Material material = Material.matchMaterial(dummySection.getString("material", "")); - if (material == null) { - SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); - return null; - } + Material material = Material.matchMaterial(dummySection.getString("material", "")); + if (material == null) { + SavageFactions.plugin.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } - ItemStack itemStack = new ItemStack(material); + ItemStack itemStack = new ItemStack(material); - DyeColor color; - try { - color = DyeColor.valueOf(dummySection.getString("color", "")); - } catch (Exception exception) { - color = null; - } - if (color != null) { - itemStack.setDurability(color.getWoolData()); - } + DyeColor color; + try { + color = DyeColor.valueOf(dummySection.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } - ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', dummySection.getString("name", " "))); - List lore = new ArrayList<>(); - for (String loreLine : dummySection.getStringList("lore")) { - lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); - } - itemMeta.setLore(lore); + List lore = new ArrayList<>(); + for (String loreLine : dummySection.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + itemMeta.setLore(lore); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); - } + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + } - itemStack.setItemMeta(itemMeta); + itemStack.setItemMeta(itemMeta); - return itemStack; - } + return itemStack; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java index a12f496d..a98490ac 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/CropUpgrades.java @@ -17,62 +17,62 @@ import java.util.concurrent.ThreadLocalRandom; public class CropUpgrades implements Listener { - @EventHandler - public void onCropGrow(BlockGrowEvent e) { - FLocation floc = new FLocation(e.getBlock().getLocation()); - Faction factionAtLoc = Board.getInstance().getFactionAt(floc); + @EventHandler + public void onCropGrow(BlockGrowEvent e) { + FLocation floc = new FLocation(e.getBlock().getLocation()); + Faction factionAtLoc = Board.getInstance().getFactionAt(floc); - if (!factionAtLoc.isWilderness()) { - int level = factionAtLoc.getUpgrade(Upgrade.CROP); - if (level != 0) { - int chance = -1; + if (!factionAtLoc.isWilderness()) { + int level = factionAtLoc.getUpgrade(Upgrade.CROP); + if (level != 0) { + int chance = -1; - switch (level) { - case 1: - chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-1"); - break; - case 2: - chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-2"); - break; - case 3: - chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-3"); - break; - } + switch (level) { + case 1: + chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-1"); + break; + case 2: + chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-2"); + break; + case 3: + chance = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Crop-Boost.level-3"); + break; + } - if (chance >= 0) { - int randomNum = ThreadLocalRandom.current().nextInt(1, 100 + 1); - if (randomNum <= chance) - growCrop(e); - } - } - } - } + if (chance >= 0) { + int randomNum = ThreadLocalRandom.current().nextInt(1, 100 + 1); + if (randomNum <= chance) + growCrop(e); + } + } + } + } - private void growCrop(BlockGrowEvent e) { + private void growCrop(BlockGrowEvent e) { - if (e.getBlock().getType().equals(SavageFactions.plugin.CROPS)) { - e.setCancelled(true); - Crops c = new Crops(CropState.RIPE); - BlockState bs = e.getBlock().getState(); - bs.setData(c); - bs.update(); - } + if (e.getBlock().getType().equals(SavageFactions.plugin.CROPS)) { + e.setCancelled(true); + Crops c = new Crops(CropState.RIPE); + BlockState bs = e.getBlock().getState(); + bs.setData(c); + bs.update(); + } - Block below = e.getBlock().getLocation().subtract(0, 1, 0).getBlock(); + Block below = e.getBlock().getLocation().subtract(0, 1, 0).getBlock(); - if (below.getType() == SavageFactions.plugin.SUGAR_CANE_BLOCK) { - Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); + if (below.getType() == SavageFactions.plugin.SUGAR_CANE_BLOCK) { + Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); - if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { - above.setType(SavageFactions.plugin.SUGAR_CANE_BLOCK); - } + if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { + above.setType(SavageFactions.plugin.SUGAR_CANE_BLOCK); + } - } else if (below.getType() == Material.CACTUS) { - Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); + } else if (below.getType() == Material.CACTUS) { + Block above = e.getBlock().getLocation().add(0, 1, 0).getBlock(); - if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { - above.setType(Material.CACTUS); - } - } - } + if (above.getType() == Material.AIR && above.getLocation().add(0, -2, 0).getBlock().getType() != Material.AIR) { + above.setType(Material.CACTUS); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java index 473f70f0..a5a13594 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/EXPUpgrade.java @@ -12,42 +12,42 @@ import org.bukkit.event.entity.EntityDeathEvent; public class EXPUpgrade implements Listener { - @EventHandler - public void onDeath(EntityDeathEvent e) { - Entity killer = e.getEntity().getKiller(); + @EventHandler + public void onDeath(EntityDeathEvent e) { + Entity killer = e.getEntity().getKiller(); - if (killer == null || !(killer instanceof Player)) - return; + if (killer == null || !(killer instanceof Player)) + return; - FLocation floc = new FLocation(e.getEntity().getLocation()); - Faction faction = Board.getInstance().getFactionAt(floc); + FLocation floc = new FLocation(e.getEntity().getLocation()); + Faction faction = Board.getInstance().getFactionAt(floc); - if (!faction.isWilderness()) { - int level = faction.getUpgrade(Upgrade.EXP); - if (level != 0) { + if (!faction.isWilderness()) { + int level = faction.getUpgrade(Upgrade.EXP); + if (level != 0) { - double multiplier = -1; + double multiplier = -1; - switch (level) { - case 1: - multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-1"); - break; - case 2: - multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-2"); - break; - case 3: - multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-3"); - break; - } + switch (level) { + case 1: + multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-1"); + break; + case 2: + multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-2"); + break; + case 3: + multiplier = SavageFactions.plugin.getConfig().getDouble("fupgrades.MainMenu.EXP.EXP-Boost.level-3"); + break; + } - if (multiplier >= 0) - spawnMoreExp(e, multiplier); - } - } - } + if (multiplier >= 0) + spawnMoreExp(e, multiplier); + } + } + } - private void spawnMoreExp(EntityDeathEvent e, double multiplier) { - double newExp = e.getDroppedExp() * multiplier; - e.setDroppedExp((int) newExp); - } + private void spawnMoreExp(EntityDeathEvent e, double multiplier) { + double newExp = e.getDroppedExp() * multiplier; + e.setDroppedExp((int) newExp); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java index 0e14eb6e..b98b8d93 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/FUpgradesGUI.java @@ -20,278 +20,278 @@ import java.util.List; public class FUpgradesGUI implements Listener { - public void openMainMenu(FPlayer fme) { - Inventory inventory = Bukkit.createInventory(null, 27, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag()))); - List dummySlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.DummyItem.slots"); - Material dummyMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Type")); - int dummyAmount = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Amount"); - short dummyData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Damage") + ""); - ItemStack dummyItem = SavageFactions.plugin.createItem(dummyMaterial, - dummyAmount, - dummyData, - SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Name")), - SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.DummyItem.Lore"))); + public void openMainMenu(FPlayer fme) { + Inventory inventory = Bukkit.createInventory(null, 27, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag()))); + List dummySlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.DummyItem.slots"); + Material dummyMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Type")); + int dummyAmount = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Amount"); + short dummyData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.DummyItem.Damage") + ""); + ItemStack dummyItem = SavageFactions.plugin.createItem(dummyMaterial, + dummyAmount, + dummyData, + SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.DummyItem.Name")), + SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.DummyItem.Lore"))); - for (int i = 0; i <= dummySlots.size() - 1; i++) { - inventory.setItem(dummySlots.get(i), dummyItem); - } + for (int i = 0; i <= dummySlots.size() - 1; i++) { + inventory.setItem(dummySlots.get(i), dummyItem); + } - ItemStack[] items = buildItems(fme); - List cropSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Crops.CropItem.slots"); - List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); - List expSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.EXP.EXPItem.slots"); - List chestSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Chest.ChestItem.slots"); + ItemStack[] items = buildItems(fme); + List cropSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Crops.CropItem.slots"); + List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); + List expSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.EXP.EXPItem.slots"); + List chestSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Chest.ChestItem.slots"); - for (int i = 0; i < cropSlots.size(); i++) - inventory.setItem(cropSlots.get(i), items[2]); + for (int i = 0; i < cropSlots.size(); i++) + inventory.setItem(cropSlots.get(i), items[2]); - for (int i = 0; i < spawnerSlots.size(); i++) - inventory.setItem(spawnerSlots.get(i), items[1]); + for (int i = 0; i < spawnerSlots.size(); i++) + inventory.setItem(spawnerSlots.get(i), items[1]); - for (int i = 0; i < expSlots.size(); i++) - inventory.setItem(expSlots.get(i), items[0]); + for (int i = 0; i < expSlots.size(); i++) + inventory.setItem(expSlots.get(i), items[0]); - for (int i = 0; i < chestSlots.size(); i++) - inventory.setItem(chestSlots.get(i), items[3]); + for (int i = 0; i < chestSlots.size(); i++) + inventory.setItem(chestSlots.get(i), items[3]); - fme.getPlayer().openInventory(inventory); - } + fme.getPlayer().openInventory(inventory); + } - @EventHandler - public void onClick(InventoryClickEvent e) { - if (e.getClickedInventory() == null || e.getCurrentItem() == null || e.getCurrentItem().getItemMeta() == null || e.getCursor() == null) - return; + @EventHandler + public void onClick(InventoryClickEvent e) { + if (e.getClickedInventory() == null || e.getCurrentItem() == null || e.getCurrentItem().getItemMeta() == null || e.getCursor() == null) + return; - FPlayer fme = FPlayers.getInstance().getByPlayer((Player) e.getWhoClicked()); - if (e.getClickedInventory().getTitle().equalsIgnoreCase(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag())))) { - e.setCancelled(true); - ItemStack[] items = buildItems(fme); - ItemStack cropItem = items[2]; - ItemStack expItem = items[0]; - ItemStack chestitem = items[3]; - ItemStack spawnerItem = items[1]; + FPlayer fme = FPlayers.getInstance().getByPlayer((Player) e.getWhoClicked()); + if (e.getClickedInventory().getTitle().equalsIgnoreCase(SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Title").replace("{faction}", fme.getFaction().getTag())))) { + e.setCancelled(true); + ItemStack[] items = buildItems(fme); + ItemStack cropItem = items[2]; + ItemStack expItem = items[0]; + ItemStack chestitem = items[3]; + ItemStack spawnerItem = items[1]; - if (e.getCurrentItem().equals(cropItem)) { - int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); + if (e.getCurrentItem().equals(cropItem)) { + int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); - switch (cropLevel) { - case 3: - return; - case 2: - upgradeItem(fme, Upgrade.CROP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-3")); - break; - case 1: - upgradeItem(fme, Upgrade.CROP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-2")); - break; - case 0: - upgradeItem(fme, Upgrade.CROP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-1")); - break; - } - } else if (e.getCurrentItem().equals(spawnerItem)) { - int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); + switch (cropLevel) { + case 3: + return; + case 2: + upgradeItem(fme, Upgrade.CROP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-3")); + break; + case 1: + upgradeItem(fme, Upgrade.CROP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-2")); + break; + case 0: + upgradeItem(fme, Upgrade.CROP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.Cost.level-1")); + break; + } + } else if (e.getCurrentItem().equals(spawnerItem)) { + int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); - switch (spawnerLevel) { - case 3: - return; - case 2: - upgradeItem(fme, Upgrade.SPAWNER, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-3")); - break; - case 1: - upgradeItem(fme, Upgrade.SPAWNER, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-2")); - break; - case 0: - upgradeItem(fme, Upgrade.SPAWNER, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-1")); - break; - } - } else if (e.getCurrentItem().equals(expItem)) { - int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); + switch (spawnerLevel) { + case 3: + return; + case 2: + upgradeItem(fme, Upgrade.SPAWNER, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-3")); + break; + case 1: + upgradeItem(fme, Upgrade.SPAWNER, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-2")); + break; + case 0: + upgradeItem(fme, Upgrade.SPAWNER, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Cost.level-1")); + break; + } + } else if (e.getCurrentItem().equals(expItem)) { + int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); - switch (expLevel) { - case 3: - return; - case 2: - upgradeItem(fme, Upgrade.EXP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-3")); - break; - case 1: - upgradeItem(fme, Upgrade.EXP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-2")); - break; - case 0: - upgradeItem(fme, Upgrade.EXP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-1")); - break; - } - } else if (e.getCurrentItem().equals(chestitem)) { - int chestLevel = fme.getFaction().getUpgrade(Upgrade.CHEST); + switch (expLevel) { + case 3: + return; + case 2: + upgradeItem(fme, Upgrade.EXP, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-3")); + break; + case 1: + upgradeItem(fme, Upgrade.EXP, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-2")); + break; + case 0: + upgradeItem(fme, Upgrade.EXP, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.Cost.level-1")); + break; + } + } else if (e.getCurrentItem().equals(chestitem)) { + int chestLevel = fme.getFaction().getUpgrade(Upgrade.CHEST); - switch (chestLevel) { - case 3: - return; - case 2: { - if (upgradeItem(fme, Upgrade.CHEST, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-3"))) - updateChests(fme.getFaction()); - break; - } - case 1: { - if (upgradeItem(fme, Upgrade.CHEST, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-2"))) - updateChests(fme.getFaction()); - break; - } - case 0: { - if (upgradeItem(fme, Upgrade.CHEST, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-1"))) - updateChests(fme.getFaction()); - break; - } - } - } - } - } + switch (chestLevel) { + case 3: + return; + case 2: { + if (upgradeItem(fme, Upgrade.CHEST, 3, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-3"))) + updateChests(fme.getFaction()); + break; + } + case 1: { + if (upgradeItem(fme, Upgrade.CHEST, 2, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-2"))) + updateChests(fme.getFaction()); + break; + } + case 0: { + if (upgradeItem(fme, Upgrade.CHEST, 1, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Cost.level-1"))) + updateChests(fme.getFaction()); + break; + } + } + } + } + } - private void updateChests(Faction faction) { - String invName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title")); + private void updateChests(Faction faction) { + String invName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title")); - for (Player player : faction.getOnlinePlayers()) { - if (player.getInventory().getTitle() != null && player.getInventory().getTitle().equalsIgnoreCase(invName)) - player.closeInventory(); - } + for (Player player : faction.getOnlinePlayers()) { + if (player.getInventory().getTitle() != null && player.getInventory().getTitle().equalsIgnoreCase(invName)) + player.closeInventory(); + } - int level = faction.getUpgrade(Upgrade.CHEST); - int size = 1; + int level = faction.getUpgrade(Upgrade.CHEST); + int size = 1; - switch (level) { - case 1: - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1"); - break; - case 2: - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2"); - break; - case 3: - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3"); - break; - } - faction.setChestSize(size * 9); - } + switch (level) { + case 1: + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1"); + break; + case 2: + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2"); + break; + case 3: + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3"); + break; + } + faction.setChestSize(size * 9); + } - private ItemStack[] buildItems(FPlayer fme) { - Material expMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Type")); - int expAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Amount"); - short expData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Damage") + ""); - String expName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Name")); - List expLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.EXP.EXPItem.Lore")); - int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); + private ItemStack[] buildItems(FPlayer fme) { + Material expMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Type")); + int expAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Amount"); + short expData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.EXP.EXPItem.Damage") + ""); + String expName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.EXP.EXPItem.Name")); + List expLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.EXP.EXPItem.Lore")); + int expLevel = fme.getFaction().getUpgrade(Upgrade.EXP); - for (int i = 0; i <= expLore.size() - 1; i++) - expLore.set(i, expLore.get(i).replace("{level}", expLevel + "")); + for (int i = 0; i <= expLore.size() - 1; i++) + expLore.set(i, expLore.get(i).replace("{level}", expLevel + "")); - ItemStack expItem = SavageFactions.plugin.createItem(expMaterial, expAmt, expData, expName, expLore); + ItemStack expItem = SavageFactions.plugin.createItem(expMaterial, expAmt, expData, expName, expLore); - if (expLevel >= 1) { - ItemMeta itemMeta = expItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + if (expLevel >= 1) { + ItemMeta itemMeta = expItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - expItem.setItemMeta(itemMeta); - expItem.setAmount(expLevel); - } + expItem.setItemMeta(itemMeta); + expItem.setAmount(expLevel); + } - Material spawnerMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Type")); - int spawnerAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Amount"); - short spawnerData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Damage") + ""); - String spawnerName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Name")); - List spawnerLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Spawners.SpawnerItem.Lore")); + Material spawnerMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Type")); + int spawnerAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Amount"); + short spawnerData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.SpawnerItem.Damage") + ""); + String spawnerName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Spawners.SpawnerItem.Name")); + List spawnerLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Spawners.SpawnerItem.Lore")); - List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); - int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); + List spawnerSlots = SavageFactions.plugin.getConfig().getIntegerList("fupgrades.MainMenu.Spawners.SpawnerItem.slots"); + int spawnerLevel = fme.getFaction().getUpgrade(Upgrade.SPAWNER); - for (int i = 0; i <= spawnerLore.size() - 1; i++) { - spawnerLore.set(i, spawnerLore.get(i).replace("{level}", spawnerLevel + "")); - } + for (int i = 0; i <= spawnerLore.size() - 1; i++) { + spawnerLore.set(i, spawnerLore.get(i).replace("{level}", spawnerLevel + "")); + } - Material cropMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Type")); - int cropAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Amount"); - short cropData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Damage") + ""); - String cropName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Name")); - List cropLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Crops.CropItem.Lore")); - int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); + Material cropMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Type")); + int cropAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Amount"); + short cropData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Crops.CropItem.Damage") + ""); + String cropName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Crops.CropItem.Name")); + List cropLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Crops.CropItem.Lore")); + int cropLevel = fme.getFaction().getUpgrade(Upgrade.CROP); - for (int i = 0; i <= cropLore.size() - 1; i++) { - String line = cropLore.get(i); - line = line.replace("{level}", cropLevel + ""); - cropLore.set(i, line); - } + for (int i = 0; i <= cropLore.size() - 1; i++) { + String line = cropLore.get(i); + line = line.replace("{level}", cropLevel + ""); + cropLore.set(i, line); + } - ItemStack cropItem = SavageFactions.plugin.createItem(cropMaterial, cropAmt, cropData, cropName, cropLore); - cropItem.getItemMeta().setLore(cropLore); + ItemStack cropItem = SavageFactions.plugin.createItem(cropMaterial, cropAmt, cropData, cropName, cropLore); + cropItem.getItemMeta().setLore(cropLore); - if (cropLevel >= 1) { - ItemMeta itemMeta = cropItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - cropItem.setItemMeta(itemMeta); + if (cropLevel >= 1) { + ItemMeta itemMeta = cropItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + cropItem.setItemMeta(itemMeta); - cropItem.setAmount(cropLevel); - } + cropItem.setAmount(cropLevel); + } - ItemStack spawnerItem = SavageFactions.plugin.createItem(spawnerMaterial, spawnerAmt, spawnerData, spawnerName, spawnerLore); - spawnerItem.getItemMeta().setLore(spawnerLore); - if (spawnerLevel >= 1) { - ItemMeta itemMeta = spawnerItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + ItemStack spawnerItem = SavageFactions.plugin.createItem(spawnerMaterial, spawnerAmt, spawnerData, spawnerName, spawnerLore); + spawnerItem.getItemMeta().setLore(spawnerLore); + if (spawnerLevel >= 1) { + ItemMeta itemMeta = spawnerItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - spawnerItem.setItemMeta(itemMeta); - spawnerItem.setAmount(spawnerLevel); - } + spawnerItem.setItemMeta(itemMeta); + spawnerItem.setAmount(spawnerLevel); + } - Material chestMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Type")); - int chesttAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Amount"); - short chestData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Damage") + ""); - String chestName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Name", "&e&lUpgrade Chest Size")); - List chestLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Chest.ChestItem.Lore")); - int chestlevel = fme.getFaction().getUpgrade(Upgrade.CHEST); + Material chestMaterial = Material.getMaterial(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Type")); + int chesttAmt = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Amount"); + short chestData = Short.parseShort(SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.ChestItem.Damage") + ""); + String chestName = SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fupgrades.MainMenu.Chest.ChestItem.Name", "&e&lUpgrade Chest Size")); + List chestLore = SavageFactions.plugin.colorList(SavageFactions.plugin.getConfig().getStringList("fupgrades.MainMenu.Chest.ChestItem.Lore")); + int chestlevel = fme.getFaction().getUpgrade(Upgrade.CHEST); - for (int i = 0; i <= chestLore.size() - 1; i++) { - String line = chestLore.get(i); - line = line.replace("{level}", chestlevel + ""); - chestLore.set(i, line); - } + for (int i = 0; i <= chestLore.size() - 1; i++) { + String line = chestLore.get(i); + line = line.replace("{level}", chestlevel + ""); + chestLore.set(i, line); + } - ItemStack chestItem = SavageFactions.plugin.createItem(chestMaterial, chesttAmt, chestData, chestName, chestLore); + ItemStack chestItem = SavageFactions.plugin.createItem(chestMaterial, chesttAmt, chestData, chestName, chestLore); - if (chestlevel >= 1) { - ItemMeta itemMeta = chestItem.getItemMeta(); - if (!SavageFactions.plugin.mc17) { - itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - } - itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); + if (chestlevel >= 1) { + ItemMeta itemMeta = chestItem.getItemMeta(); + if (!SavageFactions.plugin.mc17) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } + itemMeta.addEnchant(Enchantment.DURABILITY, 3, true); - chestItem.setItemMeta(itemMeta); - chestItem.setAmount(chestlevel); - } + chestItem.setItemMeta(itemMeta); + chestItem.setAmount(chestlevel); + } - ItemStack[] items = {expItem, spawnerItem, cropItem, chestItem}; - return items; - } + ItemStack[] items = {expItem, spawnerItem, cropItem, chestItem}; + return items; + } - private boolean hasMoney(FPlayer fme, int amt) { - return fme.hasMoney(amt); - } + private boolean hasMoney(FPlayer fme, int amt) { + return fme.hasMoney(amt); + } - private void takeMoney(FPlayer fme, int amt) { - fme.takeMoney(amt); - } + private void takeMoney(FPlayer fme, int amt) { + fme.takeMoney(amt); + } - private boolean upgradeItem(FPlayer fme, Upgrade upgrade, int level, int cost) { - if (hasMoney(fme, cost)) { - takeMoney(fme, cost); - fme.getFaction().setUpgrade(upgrade, level); - fme.getPlayer().closeInventory(); - return true; - } - return false; - } + private boolean upgradeItem(FPlayer fme, Upgrade upgrade, int level, int cost) { + if (hasMoney(fme, cost)) { + takeMoney(fme, cost); + fme.getFaction().setUpgrade(upgrade, level); + fme.getPlayer().closeInventory(); + return true; + } + return false; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java index 209859f5..ad36505f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/SpawnerUpgrades.java @@ -10,32 +10,32 @@ import org.bukkit.event.entity.SpawnerSpawnEvent; public class SpawnerUpgrades implements Listener { - @EventHandler - public void onSpawn(SpawnerSpawnEvent e) { - FLocation floc = new FLocation(e.getLocation()); - Faction factionAtLoc = Board.getInstance().getFactionAt(floc); + @EventHandler + public void onSpawn(SpawnerSpawnEvent e) { + FLocation floc = new FLocation(e.getLocation()); + Faction factionAtLoc = Board.getInstance().getFactionAt(floc); - if (!factionAtLoc.isWilderness()) { - int level = factionAtLoc.getUpgrade(Upgrade.SPAWNER); - if (level != 0) { - switch (level) { - case 1: - lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-1")); - break; - case 2: - lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-2")); - break; - case 3: - lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-3")); - break; - } - } - } - } + if (!factionAtLoc.isWilderness()) { + int level = factionAtLoc.getUpgrade(Upgrade.SPAWNER); + if (level != 0) { + switch (level) { + case 1: + lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-1")); + break; + case 2: + lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-2")); + break; + case 3: + lowerSpawnerDelay(e, SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Spawners.Spawner-Boost.level-3")); + break; + } + } + } + } - private void lowerSpawnerDelay(SpawnerSpawnEvent e, double multiplier) { - int lowerby = (int) Math.round(e.getSpawner().getDelay() * multiplier); - e.getSpawner().setDelay(e.getSpawner().getDelay() - lowerby); - } + private void lowerSpawnerDelay(SpawnerSpawnEvent e, double multiplier) { + int lowerby = (int) Math.round(e.getSpawner().getDelay() * multiplier); + e.getSpawner().setDelay(e.getSpawner().getDelay() - lowerby); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java b/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java index 98e02172..ef7aa8dc 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java +++ b/src/main/java/com/massivecraft/factions/zcore/fupgrades/Upgrade.java @@ -2,17 +2,17 @@ package com.massivecraft.factions.zcore.fupgrades; public enum Upgrade { - CHEST("Chest"), SPAWNER("Spawner"), EXP("Exp"), CROP("Crop"); + CHEST("Chest"), SPAWNER("Spawner"), EXP("Exp"), CROP("Crop"); - private String id; + private String id; - Upgrade(String id) { - this.id = id; - } + Upgrade(String id) { + this.id = id; + } - @Override - public String toString() { - return this.id; - } + @Override + public String toString() { + return this.id; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java index 8cec2e41..70d4a387 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTCompound.java @@ -7,191 +7,191 @@ import java.util.Set; public class NBTCompound { - private String compundName; - private NBTCompound parent; + private String compundName; + private NBTCompound parent; - protected NBTCompound() { - } + protected NBTCompound() { + } - protected NBTCompound(NBTCompound owner, String name) { - this.compundName = name; - this.parent = owner; - } + protected NBTCompound(NBTCompound owner, String name) { + this.compundName = name; + this.parent = owner; + } - public String getName() { - return compundName; - } + public String getName() { + return compundName; + } - protected Object getCompound() { - return parent.getCompound(); - } + protected Object getCompound() { + return parent.getCompound(); + } - protected void setCompound(Object compound) { - parent.setCompound(compound); - } + protected void setCompound(Object compound) { + parent.setCompound(compound); + } - public NBTCompound getParent() { - return parent; - } + public NBTCompound getParent() { + return parent; + } - public void mergeCompound(NBTCompound comp) { - NBTReflectionUtil.addOtherNBTCompound(this, comp); - } + public void mergeCompound(NBTCompound comp) { + NBTReflectionUtil.addOtherNBTCompound(this, comp); + } - public void setString(String key, String value) { - NBTReflectionUtil.setString(this, key, value); - } + public void setString(String key, String value) { + NBTReflectionUtil.setString(this, key, value); + } - public String getString(String key) { - return NBTReflectionUtil.getString(this, key); - } + public String getString(String key) { + return NBTReflectionUtil.getString(this, key); + } - protected String getContent(String key) { - return NBTReflectionUtil.getContent(this, key); - } + protected String getContent(String key) { + return NBTReflectionUtil.getContent(this, key); + } - public void setInteger(String key, Integer value) { - NBTReflectionUtil.setInt(this, key, value); - } + public void setInteger(String key, Integer value) { + NBTReflectionUtil.setInt(this, key, value); + } - public Integer getInteger(String key) { - return NBTReflectionUtil.getInt(this, key); - } + public Integer getInteger(String key) { + return NBTReflectionUtil.getInt(this, key); + } - public void setDouble(String key, Double value) { - NBTReflectionUtil.setDouble(this, key, value); - } + public void setDouble(String key, Double value) { + NBTReflectionUtil.setDouble(this, key, value); + } - public Double getDouble(String key) { - return NBTReflectionUtil.getDouble(this, key); - } + public Double getDouble(String key) { + return NBTReflectionUtil.getDouble(this, key); + } - public void setByte(String key, Byte value) { - NBTReflectionUtil.setByte(this, key, value); - } + public void setByte(String key, Byte value) { + NBTReflectionUtil.setByte(this, key, value); + } - public Byte getByte(String key) { - return NBTReflectionUtil.getByte(this, key); - } + public Byte getByte(String key) { + return NBTReflectionUtil.getByte(this, key); + } - public void setShort(String key, Short value) { - NBTReflectionUtil.setShort(this, key, value); - } + public void setShort(String key, Short value) { + NBTReflectionUtil.setShort(this, key, value); + } - public Short getShort(String key) { - return NBTReflectionUtil.getShort(this, key); - } + public Short getShort(String key) { + return NBTReflectionUtil.getShort(this, key); + } - public void setLong(String key, Long value) { - NBTReflectionUtil.setLong(this, key, value); - } + public void setLong(String key, Long value) { + NBTReflectionUtil.setLong(this, key, value); + } - public Long getLong(String key) { - return NBTReflectionUtil.getLong(this, key); - } + public Long getLong(String key) { + return NBTReflectionUtil.getLong(this, key); + } - public void setFloat(String key, Float value) { - NBTReflectionUtil.setFloat(this, key, value); - } + public void setFloat(String key, Float value) { + NBTReflectionUtil.setFloat(this, key, value); + } - public Float getFloat(String key) { - return NBTReflectionUtil.getFloat(this, key); - } + public Float getFloat(String key) { + return NBTReflectionUtil.getFloat(this, key); + } - public void setByteArray(String key, byte[] value) { - NBTReflectionUtil.setByteArray(this, key, value); - } + public void setByteArray(String key, byte[] value) { + NBTReflectionUtil.setByteArray(this, key, value); + } - public byte[] getByteArray(String key) { - return NBTReflectionUtil.getByteArray(this, key); - } + public byte[] getByteArray(String key) { + return NBTReflectionUtil.getByteArray(this, key); + } - public void setIntArray(String key, int[] value) { - NBTReflectionUtil.setIntArray(this, key, value); - } + public void setIntArray(String key, int[] value) { + NBTReflectionUtil.setIntArray(this, key, value); + } - public int[] getIntArray(String key) { - return NBTReflectionUtil.getIntArray(this, key); - } + public int[] getIntArray(String key) { + return NBTReflectionUtil.getIntArray(this, key); + } - public void setBoolean(String key, Boolean value) { - NBTReflectionUtil.setBoolean(this, key, value); - } + public void setBoolean(String key, Boolean value) { + NBTReflectionUtil.setBoolean(this, key, value); + } - protected void set(String key, Object val) { - NBTReflectionUtil.set(this, key, val); - } + protected void set(String key, Object val) { + NBTReflectionUtil.set(this, key, val); + } - public Boolean getBoolean(String key) { - return NBTReflectionUtil.getBoolean(this, key); - } + public Boolean getBoolean(String key) { + return NBTReflectionUtil.getBoolean(this, key); + } - public void setObject(String key, Object value) { - NBTReflectionUtil.setObject(this, key, value); - } + public void setObject(String key, Object value) { + NBTReflectionUtil.setObject(this, key, value); + } - public T getObject(String key, Class type) { - return NBTReflectionUtil.getObject(this, key, type); - } + public T getObject(String key, Class type) { + return NBTReflectionUtil.getObject(this, key, type); + } - public Boolean hasKey(String key) { - return NBTReflectionUtil.hasKey(this, key); - } + public Boolean hasKey(String key) { + return NBTReflectionUtil.hasKey(this, key); + } - public void removeKey(String key) { - NBTReflectionUtil.remove(this, key); - } + public void removeKey(String key) { + NBTReflectionUtil.remove(this, key); + } - public Set getKeys() { - return NBTReflectionUtil.getKeys(this); - } + public Set getKeys() { + return NBTReflectionUtil.getKeys(this); + } - public NBTCompound addCompound(String name) { - NBTReflectionUtil.addNBTTagCompound(this, name); - return getCompound(name); - } + public NBTCompound addCompound(String name) { + NBTReflectionUtil.addNBTTagCompound(this, name); + return getCompound(name); + } - public NBTCompound getCompound(String name) { - NBTCompound next = new NBTCompound(this, name); - if (NBTReflectionUtil.valideCompound(next)) return next; - return null; - } + public NBTCompound getCompound(String name) { + NBTCompound next = new NBTCompound(this, name); + if (NBTReflectionUtil.valideCompound(next)) return next; + return null; + } - public NBTList getList(String name, NBTType type) { - return NBTReflectionUtil.getList(this, name, type); - } + public NBTList getList(String name, NBTType type) { + return NBTReflectionUtil.getList(this, name, type); + } - public NBTType getType(String name) { - if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) - return NBTType.NBTTagEnd; - return NBTType.valueOf(NBTReflectionUtil.getType(this, name)); - } + public NBTType getType(String name) { + if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) + return NBTType.NBTTagEnd; + return NBTType.valueOf(NBTReflectionUtil.getType(this, name)); + } - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for (String key : getKeys()) { - result.append(toString(key)); - } - return result.toString(); - } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for (String key : getKeys()) { + result.append(toString(key)); + } + return result.toString(); + } - public String toString(String key) { - StringBuilder result = new StringBuilder(); - NBTCompound compound = this; - while (compound.getParent() != null) { - result.append(" "); - compound = compound.getParent(); - } - if (this.getType(key) == NBTType.NBTTagCompound) { - return this.getCompound(key).toString(); - } else { - return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); - } - } + public String toString(String key) { + StringBuilder result = new StringBuilder(); + NBTCompound compound = this; + while (compound.getParent() != null) { + result.append(" "); + compound = compound.getParent(); + } + if (this.getType(key) == NBTType.NBTTagCompound) { + return this.getCompound(key).toString(); + } else { + return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); + } + } - public String asNBTString() { - return NBTReflectionUtil.gettoCompount(getCompound(), this).toString(); - } + public String asNBTString() { + return NBTReflectionUtil.gettoCompount(getCompound(), this).toString(); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java index 4652dbc4..6d79ad01 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTContainer.java @@ -2,31 +2,31 @@ package com.massivecraft.factions.zcore.nbtapi; public class NBTContainer extends NBTCompound { - private Object nbt; + private Object nbt; - public NBTContainer() { - this(NBTReflectionUtil.getNewNBTTag()); - } + public NBTContainer() { + this(NBTReflectionUtil.getNewNBTTag()); + } - protected NBTContainer(Object nbt) { - this.nbt = nbt; - } + protected NBTContainer(Object nbt) { + this.nbt = nbt; + } - public NBTContainer(String nbtString) throws IllegalArgumentException { - try { - nbt = NBTReflectionUtil.parseNBT(nbtString); - } catch (Exception ex) { - ex.printStackTrace(); - throw new IllegalArgumentException("Malformed Json: " + ex.getMessage()); - } - } + public NBTContainer(String nbtString) throws IllegalArgumentException { + try { + nbt = NBTReflectionUtil.parseNBT(nbtString); + } catch (Exception ex) { + ex.printStackTrace(); + throw new IllegalArgumentException("Malformed Json: " + ex.getMessage()); + } + } - protected Object getCompound() { - return nbt; - } + protected Object getCompound() { + return nbt; + } - protected void setCompound(Object tag) { - nbt = tag; - } + protected void setCompound(Object tag) { + nbt = tag; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java index 2417393c..4176dfdc 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTEntity.java @@ -4,18 +4,18 @@ import org.bukkit.entity.Entity; public class NBTEntity extends NBTCompound { - private final Entity ent; + private final Entity ent; - public NBTEntity(Entity entity) { - ent = entity; - } + public NBTEntity(Entity entity) { + ent = entity; + } - protected Object getCompound() { - return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent)); - } + protected Object getCompound() { + return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent)); + } - protected void setCompound(Object compound) { - NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); - } + protected void setCompound(Object compound) { + NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java index 20ecd57f..26da8dc0 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTFile.java @@ -7,39 +7,39 @@ import java.io.IOException; public class NBTFile extends NBTCompound { - private final File file; - private Object nbt; + private final File file; + private Object nbt; - public NBTFile(File file) throws IOException { - this.file = file; - if (file.exists()) { - FileInputStream inputsteam = new FileInputStream(file); - nbt = NBTReflectionUtil.readNBTFile(inputsteam); - } else { - nbt = NBTReflectionUtil.getNewNBTTag(); - save(); - } - } + public NBTFile(File file) throws IOException { + this.file = file; + if (file.exists()) { + FileInputStream inputsteam = new FileInputStream(file); + nbt = NBTReflectionUtil.readNBTFile(inputsteam); + } else { + nbt = NBTReflectionUtil.getNewNBTTag(); + save(); + } + } - public void save() throws IOException { - if (!file.exists()) { - file.getParentFile().mkdirs(); - file.createNewFile(); - } - FileOutputStream outStream = new FileOutputStream(file); - NBTReflectionUtil.saveNBTFile(nbt, outStream); - } + public void save() throws IOException { + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + FileOutputStream outStream = new FileOutputStream(file); + NBTReflectionUtil.saveNBTFile(nbt, outStream); + } - public File getFile() { - return file; - } + public File getFile() { + return file; + } - protected Object getCompound() { - return nbt; - } + protected Object getCompound() { + return nbt; + } - protected void setCompound(Object compound) { - nbt = compound; - } + protected void setCompound(Object compound) { + nbt = compound; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java index 1bd3528c..86d49245 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTItem.java @@ -4,34 +4,34 @@ import org.bukkit.inventory.ItemStack; public class NBTItem extends NBTCompound { - private ItemStack bukkitItem; + private ItemStack bukkitItem; - public NBTItem(ItemStack item) { - bukkitItem = item.clone(); - } + public NBTItem(ItemStack item) { + bukkitItem = item.clone(); + } - public static NBTContainer convertItemtoNBT(ItemStack item) { - return NBTReflectionUtil.convertNMSItemtoNBTCompound(NBTReflectionUtil.getNMSItemStack(item)); - } + public static NBTContainer convertItemtoNBT(ItemStack item) { + return NBTReflectionUtil.convertNMSItemtoNBTCompound(NBTReflectionUtil.getNMSItemStack(item)); + } - public static ItemStack convertNBTtoItem(NBTCompound comp) { - return NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); - } + public static ItemStack convertNBTtoItem(NBTCompound comp) { + return NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); + } - protected Object getCompound() { - return NBTReflectionUtil.getItemRootNBTTagCompound(NBTReflectionUtil.getNMSItemStack(bukkitItem)); - } + protected Object getCompound() { + return NBTReflectionUtil.getItemRootNBTTagCompound(NBTReflectionUtil.getNMSItemStack(bukkitItem)); + } - protected void setCompound(Object compound) { - bukkitItem = NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.setNBTTag(compound, NBTReflectionUtil.getNMSItemStack(bukkitItem))); - } + protected void setCompound(Object compound) { + bukkitItem = NBTReflectionUtil.getBukkitItemStack(NBTReflectionUtil.setNBTTag(compound, NBTReflectionUtil.getNMSItemStack(bukkitItem))); + } - public ItemStack getItem() { - return bukkitItem; - } + public ItemStack getItem() { + return bukkitItem; + } - protected void setItem(ItemStack item) { - bukkitItem = item; - } + protected void setItem(ItemStack item) { + bukkitItem = item; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java index a3d5a985..91726778 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTList.java @@ -6,120 +6,120 @@ import java.lang.reflect.Method; public class NBTList { - private String listName; - private NBTCompound parent; - private NBTType type; - private Object listObject; + private String listName; + private NBTCompound parent; + private NBTType type; + private Object listObject; - protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { - parent = owner; - listName = name; - this.type = type; - this.listObject = list; - if (!(type == NBTType.NBTTagString || type == NBTType.NBTTagCompound)) { - System.err.println("List types != String/Compound are currently not implemented!"); - } - } + protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { + parent = owner; + listName = name; + this.type = type; + this.listObject = list; + if (!(type == NBTType.NBTTagString || type == NBTType.NBTTagCompound)) { + System.err.println("List types != String/Compound are currently not implemented!"); + } + } - protected void save() { - parent.set(listName, listObject); - } + protected void save() { + parent.set(listName, listObject); + } - public NBTListCompound addCompound() { - if (type != NBTType.NBTTagCompound) { - new Throwable("Using Compound method on a non Compound list!").printStackTrace(); - return null; - } - try { - Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); - Object compound = NBTReflectionUtil.getNBTTagCompound().newInstance(); - method.invoke(listObject, compound); - return new NBTListCompound(this, compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + public NBTListCompound addCompound() { + if (type != NBTType.NBTTagCompound) { + new Throwable("Using Compound method on a non Compound list!").printStackTrace(); + return null; + } + try { + Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); + Object compound = NBTReflectionUtil.getNBTTagCompound().newInstance(); + method.invoke(listObject, compound); + return new NBTListCompound(this, compound); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } - public NBTListCompound getCompound(int id) { - if (type != NBTType.NBTTagCompound) { - new Throwable("Using Compound method on a non Compound list!").printStackTrace(); - return null; - } - try { - Method method = listObject.getClass().getMethod("get", int.class); - Object compound = method.invoke(listObject, id); - return new NBTListCompound(this, compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + public NBTListCompound getCompound(int id) { + if (type != NBTType.NBTTagCompound) { + new Throwable("Using Compound method on a non Compound list!").printStackTrace(); + return null; + } + try { + Method method = listObject.getClass().getMethod("get", int.class); + Object compound = method.invoke(listObject, id); + return new NBTListCompound(this, compound); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } - public String getString(int i) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return null; - } - try { - Method method = listObject.getClass().getMethod("getString", int.class); - return (String) method.invoke(listObject, i); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + public String getString(int i) { + if (type != NBTType.NBTTagString) { + new Throwable("Using String method on a non String list!").printStackTrace(); + return null; + } + try { + Method method = listObject.getClass().getMethod("getString", int.class); + return (String) method.invoke(listObject, i); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } - public void addString(String s) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return; - } - try { - Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); - method.invoke(listObject, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void addString(String s) { + if (type != NBTType.NBTTagString) { + new Throwable("Using String method on a non String list!").printStackTrace(); + return; + } + try { + Method method = listObject.getClass().getMethod("add", NBTReflectionUtil.getNBTBase()); + method.invoke(listObject, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); + save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public void setString(int i, String s) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return; - } - try { - Method method = listObject.getClass().getMethod("a", int.class, NBTReflectionUtil.getNBTBase()); - method.invoke(listObject, i, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setString(int i, String s) { + if (type != NBTType.NBTTagString) { + new Throwable("Using String method on a non String list!").printStackTrace(); + return; + } + try { + Method method = listObject.getClass().getMethod("a", int.class, NBTReflectionUtil.getNBTBase()); + method.invoke(listObject, i, NBTReflectionUtil.getNBTTagString().getConstructor(String.class).newInstance(s)); + save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public void remove(int i) { - try { - Method method = listObject.getClass().getMethod(MethodNames.getRemoveMethodName(), int.class); - method.invoke(listObject, i); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void remove(int i) { + try { + Method method = listObject.getClass().getMethod(MethodNames.getRemoveMethodName(), int.class); + method.invoke(listObject, i); + save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public int size() { - try { - Method method = listObject.getClass().getMethod("size"); - return (int) method.invoke(listObject); - } catch (Exception ex) { - ex.printStackTrace(); - } - return -1; - } + public int size() { + try { + Method method = listObject.getClass().getMethod("size"); + return (int) method.invoke(listObject); + } catch (Exception ex) { + ex.printStackTrace(); + } + return -1; + } - public NBTType getType() { - return type; - } + public NBTType getType() { + return type; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java index e3d92716..59a1ce5f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTListCompound.java @@ -5,98 +5,98 @@ import java.util.Set; public class NBTListCompound { - private NBTList owner; - private Object compound; + private NBTList owner; + private Object compound; - protected NBTListCompound(NBTList parent, Object obj) { - owner = parent; - compound = obj; - } + protected NBTListCompound(NBTList parent, Object obj) { + owner = parent; + compound = obj; + } - public void setString(String key, String value) { - if (value == null) { - remove(key); - return; - } - try { - compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setString(String key, String value) { + if (value == null) { + remove(key); + return; + } + try { + compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value); + owner.save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public void setInteger(String key, int value) { - try { - compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setInteger(String key, int value) { + try { + compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value); + owner.save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public int getInteger(String value) { - try { - return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } + public int getInteger(String value) { + try { + return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value); + } catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } - public void setDouble(String key, double value) { - try { - compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void setDouble(String key, double value) { + try { + compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value); + owner.save(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } - public double getDouble(String key) { - try { - return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } + public double getDouble(String key) { + try { + return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } - public String getString(String key) { - try { - return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return ""; - } + public String getString(String key) { + try { + return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return ""; + } - public boolean hasKey(String key) { - try { - return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return false; - } + public boolean hasKey(String key) { + try { + return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return false; + } - @SuppressWarnings("unchecked") - public Set getKeys() { - try { - return (Set) compound.getClass().getMethod("c").invoke(compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return new HashSet<>(); - } + @SuppressWarnings("unchecked") + public Set getKeys() { + try { + return (Set) compound.getClass().getMethod("c").invoke(compound); + } catch (Exception ex) { + ex.printStackTrace(); + } + return new HashSet<>(); + } - public void remove(String key) { - try { - compound.getClass().getMethod("remove", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public void remove(String key) { + try { + compound.getClass().getMethod("remove", String.class).invoke(compound, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java index a35684ef..5df3308e 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTReflectionUtil.java @@ -19,904 +19,904 @@ import java.util.Stack; // TODO: finish codestyle cleanup -sgdc3 public class NBTReflectionUtil { - private static final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - - private static Class getCraftItemStack() { - - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - private static Class getCraftEntity() { - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftEntity"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTBase() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTBase"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTTagString() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTTagString"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNMSItemStack() { - try { - return Class.forName("net.minecraft.server." + version + ".ItemStack"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTTagCompound() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getNBTCompressedStreamTools() { - try { - return Class.forName("net.minecraft.server." + version + ".NBTCompressedStreamTools"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getMojangsonParser() { - try { - return Class.forName("net.minecraft.server." + version + ".MojangsonParser"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getTileEntity() { - try { - return Class.forName("net.minecraft.server." + version + ".TileEntity"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - protected static Class getCraftWorld() { - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld"); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - public static Object getNewNBTTag() { - String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - try { - Class c = Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); - return c.newInstance(); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - private static Object getNewBlockPosition(int x, int y, int z) { - String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - try { - Class clazz = Class.forName("net.minecraft.server." + version + ".BlockPosition"); - return clazz.getConstructor(int.class, int.class, int.class).newInstance(x, y, z); - } catch (Exception ex) { - System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); - ex.printStackTrace(); - return null; - } - } - - public static Object setNBTTag(Object NBTTag, Object NMSItem) { - try { - Method method = NMSItem.getClass().getMethod("setTag", NBTTag.getClass()); - method.invoke(NMSItem, NBTTag); - return NMSItem; - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static Object getNMSItemStack(ItemStack item) { - Class clazz = getCraftItemStack(); - - try { - Method method = clazz.getMethod("asNMSCopy", ItemStack.class); - return method.invoke(clazz, item); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object getNMSEntity(Entity entity) { - Class clazz = getCraftEntity(); - - try { - Method method = clazz.getMethod("getHandle"); - return method.invoke(getCraftEntity().cast(entity)); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object parseNBT(String json) { - Class cis = getMojangsonParser(); - - try { - Method method = cis.getMethod("parse", String.class); - return method.invoke(null, json); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object readNBTFile(FileInputStream stream) { - Class clazz = getNBTCompressedStreamTools(); - - try { - Method method = clazz.getMethod("a", InputStream.class); - return method.invoke(clazz, stream); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object saveNBTFile(Object nbt, FileOutputStream stream) { - Class clazz = getNBTCompressedStreamTools(); - - try { - Method method = clazz.getMethod("a", getNBTTagCompound(), OutputStream.class); - return method.invoke(clazz, nbt, stream); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static ItemStack getBukkitItemStack(Object item) { - Class clazz = getCraftItemStack(); - - try { - Method method = clazz.getMethod("asCraftMirror", item.getClass()); - return (ItemStack) method.invoke(clazz, item); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object getItemRootNBTTagCompound(Object nmsitem) { - Class clazz = nmsitem.getClass(); - - try { - Method method = clazz.getMethod("getTag"); - return method.invoke(nmsitem); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { - Class clazz = getNMSItemStack(); - try { - return clazz.getConstructor(getNBTTagCompound()).newInstance(gettoCompount(nbtcompound.getCompound(), nbtcompound)); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) { - Class clazz = nmsitem.getClass(); - - try { - Method method = clazz.getMethod("save", getNBTTagCompound()); - Object answer = method.invoke(nmsitem, getNewNBTTag()); - return new NBTContainer(answer); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object getEntityNBTTagCompound(Object nmsitem) { - Class c = nmsitem.getClass(); - - try { - Method method = c.getMethod(MethodNames.getEntityNbtGetterMethodName(), getNBTTagCompound()); - Object nbt = getNBTTagCompound().newInstance(); - Object answer = method.invoke(nmsitem, nbt); - return answer != null ? answer : nbt; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static Object setEntityNBTTag(Object NBTTag, Object NMSItem) { - try { - Method method; - method = NMSItem.getClass().getMethod(MethodNames.getEntityNbtSetterMethodName(), getNBTTagCompound()); - method.invoke(NMSItem, NBTTag); - return NMSItem; - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static Object getTileEntityNBTTagCompound(BlockState tile) { - try { - Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); - Object cworld = getCraftWorld().cast(tile.getWorld()); - Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); - Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); - Method method = getTileEntity().getMethod(MethodNames.getTileDataMethodName(), getNBTTagCompound()); - Object tag = getNBTTagCompound().newInstance(); - Object answer = method.invoke(o, tag); - - return answer != null ? answer : tag; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { - try { - Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); - Object cworld = getCraftWorld().cast(tile.getWorld()); - Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); - Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); - Method method = getTileEntity().getMethod("a", getNBTTagCompound()); - method.invoke(o, comp); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static Object getSubNBTTagCompound(Object compound, String name) { - Class c = compound.getClass(); - - try { - Method method = c.getMethod("getCompound", String.class); - return method.invoke(compound, name); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static void addNBTTagCompound(NBTCompound comp, String name) { - if (name == null) { - remove(comp, name); - return; - } - Object nbttag = comp.getCompound(); - if (nbttag == null) { - nbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(nbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); - method.invoke(workingtag, name, getNBTTagCompound().newInstance()); - comp.setCompound(nbttag); - return; - } catch (Exception ex) { - ex.printStackTrace(); - } - return; - } - - public static Boolean valideCompound(NBTCompound comp) { - Object root = comp.getCompound(); - if (root == null) { - root = getNewNBTTag(); - } - return gettoCompount(root, comp) != null; - } - - public static Object gettoCompount(Object nbttag, NBTCompound comp) { - Stack structure = new Stack<>(); - while (comp.getParent() != null) { - structure.add(comp.getName()); - comp = comp.getParent(); - } - while (!structure.isEmpty()) { - nbttag = getSubNBTTagCompound(nbttag, structure.pop()); - if (nbttag == null) { - return null; - } - } - return nbttag; - } - - public static void addOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("a", getNBTTagCompound()); - method.invoke(workingtag, nbtcompound.getCompound()); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static void setString(NBTCompound comp, String key, String text) { - if (text == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setString", String.class, String.class); - method.invoke(workingtag, key, text); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static String getString(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getString", String.class); - return (String) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static String getContent(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("get", String.class); - return method.invoke(workingtag, key).toString(); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setInt(NBTCompound comp, String key, Integer i) { - if (i == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setInt", String.class, int.class); - method.invoke(workingtag, key, i); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Integer getInt(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getInt", String.class); - return (Integer) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setByteArray(NBTCompound comp, String key, byte[] b) { - if (b == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setByteArray", String.class, byte[].class); - method.invoke(workingtag, key, b); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - return; - } - - public static byte[] getByteArray(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getByteArray", String.class); - return (byte[]) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setIntArray(NBTCompound comp, String key, int[] i) { - if (i == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setIntArray", String.class, int[].class); - method.invoke(workingtag, key, i); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static int[] getIntArray(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getIntArray", String.class); - return (int[]) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setFloat(NBTCompound comp, String key, Float f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setFloat", String.class, float.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Float getFloat(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getFloat", String.class); - return (Float) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setLong(NBTCompound comp, String key, Long f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setLong", String.class, long.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Long getLong(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getLong", String.class); - return (Long) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setShort(NBTCompound comp, String key, Short f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setShort", String.class, short.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Short getShort(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getShort", String.class); - return (Short) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setByte(NBTCompound comp, String key, Byte f) { - if (f == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setByte", String.class, byte.class); - method.invoke(workingtag, key, f); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Byte getByte(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getByte", String.class); - return (Byte) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setDouble(NBTCompound comp, String key, Double d) { - if (d == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setDouble", String.class, double.class); - method.invoke(workingtag, key, d); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Double getDouble(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getDouble", String.class); - return (Double) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static byte getType(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return 0; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod(MethodNames.getTypeMethodName(), String.class); - return (byte) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } - - public static void setBoolean(NBTCompound comp, String key, Boolean d) { - if (d == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("setBoolean", String.class, boolean.class); - method.invoke(workingtag, key, d); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Boolean getBoolean(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getBoolean", String.class); - return (Boolean) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void set(NBTCompound comp, String key, Object val) { - if (val == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) { - new Throwable("InvalideCompound").printStackTrace(); - return; - } - Object workingtag = gettoCompount(rootnbttag, comp); - try { - Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); - method.invoke(workingtag, key, val); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static NBTList getList(NBTCompound comp, String key, NBTType type) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("getList", String.class, int.class); - return new NBTList(comp, key, type, method.invoke(workingtag, key, type.getId())); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - public static void setObject(NBTCompound comp, String key, Object value) { - if (!MinecraftVersion.hasGsonSupport()) return; - try { - String json = GsonWrapper.getString(value); - setString(comp, key, json); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static T getObject(NBTCompound comp, String key, Class type) { - if (!MinecraftVersion.hasGsonSupport()) return null; - String json = getString(comp, key); - - return json != null ? GsonWrapper.deserializeJson(json, type) : null; - } - - public static void remove(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("remove", String.class); - method.invoke(workingtag, key); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public static Boolean hasKey(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - - try { - Method method = workingtag.getClass().getMethod("hasKey", String.class); - return (Boolean) method.invoke(workingtag, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - - @SuppressWarnings("unchecked") - public static Set getKeys(NBTCompound comp) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = getNewNBTTag(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - Method method; - try { - method = workingtag.getClass().getMethod("c"); - return (Set) method.invoke(workingtag); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + private static final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + + private static Class getCraftItemStack() { + + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + private static Class getCraftEntity() { + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftEntity"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTBase() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTBase"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTTagString() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTTagString"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNMSItemStack() { + try { + return Class.forName("net.minecraft.server." + version + ".ItemStack"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTTagCompound() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getNBTCompressedStreamTools() { + try { + return Class.forName("net.minecraft.server." + version + ".NBTCompressedStreamTools"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getMojangsonParser() { + try { + return Class.forName("net.minecraft.server." + version + ".MojangsonParser"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getTileEntity() { + try { + return Class.forName("net.minecraft.server." + version + ".TileEntity"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + protected static Class getCraftWorld() { + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld"); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + public static Object getNewNBTTag() { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + try { + Class c = Class.forName("net.minecraft.server." + version + ".NBTTagCompound"); + return c.newInstance(); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + private static Object getNewBlockPosition(int x, int y, int z) { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + try { + Class clazz = Class.forName("net.minecraft.server." + version + ".BlockPosition"); + return clazz.getConstructor(int.class, int.class, int.class).newInstance(x, y, z); + } catch (Exception ex) { + System.out.println("Error in ItemNBTAPI!(Outdated plugin?)"); + ex.printStackTrace(); + return null; + } + } + + public static Object setNBTTag(Object NBTTag, Object NMSItem) { + try { + Method method = NMSItem.getClass().getMethod("setTag", NBTTag.getClass()); + method.invoke(NMSItem, NBTTag); + return NMSItem; + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static Object getNMSItemStack(ItemStack item) { + Class clazz = getCraftItemStack(); + + try { + Method method = clazz.getMethod("asNMSCopy", ItemStack.class); + return method.invoke(clazz, item); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getNMSEntity(Entity entity) { + Class clazz = getCraftEntity(); + + try { + Method method = clazz.getMethod("getHandle"); + return method.invoke(getCraftEntity().cast(entity)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object parseNBT(String json) { + Class cis = getMojangsonParser(); + + try { + Method method = cis.getMethod("parse", String.class); + return method.invoke(null, json); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object readNBTFile(FileInputStream stream) { + Class clazz = getNBTCompressedStreamTools(); + + try { + Method method = clazz.getMethod("a", InputStream.class); + return method.invoke(clazz, stream); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object saveNBTFile(Object nbt, FileOutputStream stream) { + Class clazz = getNBTCompressedStreamTools(); + + try { + Method method = clazz.getMethod("a", getNBTTagCompound(), OutputStream.class); + return method.invoke(clazz, nbt, stream); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static ItemStack getBukkitItemStack(Object item) { + Class clazz = getCraftItemStack(); + + try { + Method method = clazz.getMethod("asCraftMirror", item.getClass()); + return (ItemStack) method.invoke(clazz, item); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getItemRootNBTTagCompound(Object nmsitem) { + Class clazz = nmsitem.getClass(); + + try { + Method method = clazz.getMethod("getTag"); + return method.invoke(nmsitem); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { + Class clazz = getNMSItemStack(); + try { + return clazz.getConstructor(getNBTTagCompound()).newInstance(gettoCompount(nbtcompound.getCompound(), nbtcompound)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) { + Class clazz = nmsitem.getClass(); + + try { + Method method = clazz.getMethod("save", getNBTTagCompound()); + Object answer = method.invoke(nmsitem, getNewNBTTag()); + return new NBTContainer(answer); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getEntityNBTTagCompound(Object nmsitem) { + Class c = nmsitem.getClass(); + + try { + Method method = c.getMethod(MethodNames.getEntityNbtGetterMethodName(), getNBTTagCompound()); + Object nbt = getNBTTagCompound().newInstance(); + Object answer = method.invoke(nmsitem, nbt); + return answer != null ? answer : nbt; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object setEntityNBTTag(Object NBTTag, Object NMSItem) { + try { + Method method; + method = NMSItem.getClass().getMethod(MethodNames.getEntityNbtSetterMethodName(), getNBTTagCompound()); + method.invoke(NMSItem, NBTTag); + return NMSItem; + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static Object getTileEntityNBTTagCompound(BlockState tile) { + try { + Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); + Object cworld = getCraftWorld().cast(tile.getWorld()); + Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); + Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); + Method method = getTileEntity().getMethod(MethodNames.getTileDataMethodName(), getNBTTagCompound()); + Object tag = getNBTTagCompound().newInstance(); + Object answer = method.invoke(o, tag); + + return answer != null ? answer : tag; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { + try { + Object pos = getNewBlockPosition(tile.getX(), tile.getY(), tile.getZ()); + Object cworld = getCraftWorld().cast(tile.getWorld()); + Object nmsworld = cworld.getClass().getMethod("getHandle").invoke(cworld); + Object o = nmsworld.getClass().getMethod("getTileEntity", pos.getClass()).invoke(nmsworld, pos); + Method method = getTileEntity().getMethod("a", getNBTTagCompound()); + method.invoke(o, comp); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static Object getSubNBTTagCompound(Object compound, String name) { + Class c = compound.getClass(); + + try { + Method method = c.getMethod("getCompound", String.class); + return method.invoke(compound, name); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void addNBTTagCompound(NBTCompound comp, String name) { + if (name == null) { + remove(comp, name); + return; + } + Object nbttag = comp.getCompound(); + if (nbttag == null) { + nbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(nbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); + method.invoke(workingtag, name, getNBTTagCompound().newInstance()); + comp.setCompound(nbttag); + return; + } catch (Exception ex) { + ex.printStackTrace(); + } + return; + } + + public static Boolean valideCompound(NBTCompound comp) { + Object root = comp.getCompound(); + if (root == null) { + root = getNewNBTTag(); + } + return gettoCompount(root, comp) != null; + } + + public static Object gettoCompount(Object nbttag, NBTCompound comp) { + Stack structure = new Stack<>(); + while (comp.getParent() != null) { + structure.add(comp.getName()); + comp = comp.getParent(); + } + while (!structure.isEmpty()) { + nbttag = getSubNBTTagCompound(nbttag, structure.pop()); + if (nbttag == null) { + return null; + } + } + return nbttag; + } + + public static void addOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("a", getNBTTagCompound()); + method.invoke(workingtag, nbtcompound.getCompound()); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static void setString(NBTCompound comp, String key, String text) { + if (text == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setString", String.class, String.class); + method.invoke(workingtag, key, text); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static String getString(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getString", String.class); + return (String) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static String getContent(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("get", String.class); + return method.invoke(workingtag, key).toString(); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setInt(NBTCompound comp, String key, Integer i) { + if (i == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setInt", String.class, int.class); + method.invoke(workingtag, key, i); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Integer getInt(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getInt", String.class); + return (Integer) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setByteArray(NBTCompound comp, String key, byte[] b) { + if (b == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setByteArray", String.class, byte[].class); + method.invoke(workingtag, key, b); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + return; + } + + public static byte[] getByteArray(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getByteArray", String.class); + return (byte[]) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setIntArray(NBTCompound comp, String key, int[] i) { + if (i == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setIntArray", String.class, int[].class); + method.invoke(workingtag, key, i); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static int[] getIntArray(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getIntArray", String.class); + return (int[]) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setFloat(NBTCompound comp, String key, Float f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setFloat", String.class, float.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Float getFloat(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getFloat", String.class); + return (Float) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setLong(NBTCompound comp, String key, Long f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setLong", String.class, long.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Long getLong(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getLong", String.class); + return (Long) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setShort(NBTCompound comp, String key, Short f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setShort", String.class, short.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Short getShort(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getShort", String.class); + return (Short) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setByte(NBTCompound comp, String key, Byte f) { + if (f == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setByte", String.class, byte.class); + method.invoke(workingtag, key, f); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Byte getByte(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getByte", String.class); + return (Byte) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setDouble(NBTCompound comp, String key, Double d) { + if (d == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setDouble", String.class, double.class); + method.invoke(workingtag, key, d); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Double getDouble(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getDouble", String.class); + return (Double) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static byte getType(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return 0; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod(MethodNames.getTypeMethodName(), String.class); + return (byte) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } + + public static void setBoolean(NBTCompound comp, String key, Boolean d) { + if (d == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("setBoolean", String.class, boolean.class); + method.invoke(workingtag, key, d); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Boolean getBoolean(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getBoolean", String.class); + return (Boolean) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void set(NBTCompound comp, String key, Object val) { + if (val == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) { + new Throwable("InvalideCompound").printStackTrace(); + return; + } + Object workingtag = gettoCompount(rootnbttag, comp); + try { + Method method = workingtag.getClass().getMethod("set", String.class, getNBTBase()); + method.invoke(workingtag, key, val); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static NBTList getList(NBTCompound comp, String key, NBTType type) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("getList", String.class, int.class); + return new NBTList(comp, key, type, method.invoke(workingtag, key, type.getId())); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + public static void setObject(NBTCompound comp, String key, Object value) { + if (!MinecraftVersion.hasGsonSupport()) return; + try { + String json = GsonWrapper.getString(value); + setString(comp, key, json); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static T getObject(NBTCompound comp, String key, Class type) { + if (!MinecraftVersion.hasGsonSupport()) return null; + String json = getString(comp, key); + + return json != null ? GsonWrapper.deserializeJson(json, type) : null; + } + + public static void remove(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("remove", String.class); + method.invoke(workingtag, key); + comp.setCompound(rootnbttag); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static Boolean hasKey(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + + try { + Method method = workingtag.getClass().getMethod("hasKey", String.class); + return (Boolean) method.invoke(workingtag, key); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + @SuppressWarnings("unchecked") + public static Set getKeys(NBTCompound comp) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = getNewNBTTag(); + } + if (!valideCompound(comp)) return null; + Object workingtag = gettoCompount(rootnbttag, comp); + Method method; + try { + method = workingtag.getClass().getMethod("c"); + return (Set) method.invoke(workingtag); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java index dc78290e..cfc56e06 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTTileEntity.java @@ -4,18 +4,18 @@ import org.bukkit.block.BlockState; public class NBTTileEntity extends NBTCompound { - private final BlockState tile; + private final BlockState tile; - public NBTTileEntity(BlockState tile) { - this.tile = tile; - } + public NBTTileEntity(BlockState tile) { + this.tile = tile; + } - protected Object getCompound() { - return NBTReflectionUtil.getTileEntityNBTTagCompound(tile); - } + protected Object getCompound() { + return NBTReflectionUtil.getTileEntityNBTTagCompound(tile); + } - protected void setCompound(Object compound) { - NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); - } + protected void setCompound(Object compound) { + NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java index afa9d60a..37d87ec6 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/NBTType.java @@ -1,34 +1,34 @@ package com.massivecraft.factions.zcore.nbtapi; public enum NBTType { - NBTTagEnd(0), - NBTTagByte(1), - NBTTagShort(2), - NBTTagInt(3), - NBTTagLong(4), - NBTTagFloat(5), - NBTTagDouble(6), - NBTTagByteArray(7), - NBTTagIntArray(11), - NBTTagString(8), - NBTTagList(9), - NBTTagCompound(10); + NBTTagEnd(0), + NBTTagByte(1), + NBTTagShort(2), + NBTTagInt(3), + NBTTagLong(4), + NBTTagFloat(5), + NBTTagDouble(6), + NBTTagByteArray(7), + NBTTagIntArray(11), + NBTTagString(8), + NBTTagList(9), + NBTTagCompound(10); - private final int id; + private final int id; - NBTType(int i) { - id = i; - } + NBTType(int i) { + id = i; + } - public static NBTType valueOf(int id) { - for (NBTType t : values()) - if (t.getId() == id) - return t; - return NBTType.NBTTagEnd; - } + public static NBTType valueOf(int id) { + for (NBTType t : values()) + if (t.getId() == id) + return t; + return NBTType.NBTTagEnd; + } - public int getId() { - return id; - } + public int getId() { + return id; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java index 77492633..4a8eaf55 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/GsonWrapper.java @@ -4,24 +4,24 @@ import com.google.gson.Gson; public class GsonWrapper { - private static final Gson gson = new Gson(); + private static final Gson gson = new Gson(); - public static String getString(Object obj) { - return gson.toJson(obj); - } + public static String getString(Object obj) { + return gson.toJson(obj); + } - public static T deserializeJson(String json, Class type) { - try { - if (json == null) { - return null; - } + public static T deserializeJson(String json, Class type) { + try { + if (json == null) { + return null; + } - T obj = gson.fromJson(json, type); - return type.cast(obj); - } catch (Exception ex) { - ex.printStackTrace(); - return null; - } - } + T obj = gson.fromJson(json, type); + return type.cast(obj); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java index 126ad031..f45ba7f6 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MethodNames.java @@ -2,25 +2,25 @@ package com.massivecraft.factions.zcore.nbtapi.utils; public class MethodNames { - private final static MinecraftVersion MINECRAFT_VERSION = MinecraftVersion.getVersion(); + private final static MinecraftVersion MINECRAFT_VERSION = MinecraftVersion.getVersion(); - public static String getTileDataMethodName() { - return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "save"; - } + public static String getTileDataMethodName() { + return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "save"; + } - public static String getTypeMethodName() { - return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "d"; - } + public static String getTypeMethodName() { + return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "b" : "d"; + } - public static String getEntityNbtGetterMethodName() { - return "b"; - } + public static String getEntityNbtGetterMethodName() { + return "b"; + } - public static String getEntityNbtSetterMethodName() { - return "a"; - } + public static String getEntityNbtSetterMethodName() { + return "a"; + } - public static String getRemoveMethodName() { - return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "a" : "remove"; - } + public static String getRemoveMethodName() { + return MINECRAFT_VERSION == MinecraftVersion.MC1_8_R3 ? "a" : "remove"; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java index 372610c1..3b3ea260 100644 --- a/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java +++ b/src/main/java/com/massivecraft/factions/zcore/nbtapi/utils/MinecraftVersion.java @@ -3,58 +3,58 @@ package com.massivecraft.factions.zcore.nbtapi.utils; import org.bukkit.Bukkit; public enum MinecraftVersion { - Unknown(0), - MC1_7_R4(174), - MC1_8_R3(183), - MC1_9_R1(191), - MC1_9_R2(192), - MC1_10_R1(1101), - MC1_11_R1(1111), - MC1_12_R1(1121); + Unknown(0), + MC1_7_R4(174), + MC1_8_R3(183), + MC1_9_R1(191), + MC1_9_R2(192), + MC1_10_R1(1101), + MC1_11_R1(1111), + MC1_12_R1(1121); - private static MinecraftVersion version; - private static Boolean hasGsonSupport; + private static MinecraftVersion version; + private static Boolean hasGsonSupport; - private final int versionId; + private final int versionId; - MinecraftVersion(int versionId) { - this.versionId = versionId; - } + MinecraftVersion(int versionId) { + this.versionId = versionId; + } - public static MinecraftVersion getVersion() { - if (version == null) { - final String ver = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - System.out.println("[NBTAPI] Found Spigot: " + ver + "!Trying to find NMS support"); + public static MinecraftVersion getVersion() { + if (version == null) { + final String ver = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + System.out.println("[NBTAPI] Found Spigot: " + ver + "!Trying to find NMS support"); - try { - version = MinecraftVersion.valueOf(ver.replace("v", "MC")); - } catch (IllegalArgumentException ex) { - version = MinecraftVersion.Unknown; - } + try { + version = MinecraftVersion.valueOf(ver.replace("v", "MC")); + } catch (IllegalArgumentException ex) { + version = MinecraftVersion.Unknown; + } - if (version != Unknown) { - System.out.println("[NBTAPI] NMS support '" + version.name() + "' loaded!"); - } else { - System.out.println("[NBTAPI] Wasn't able to find NMS Support!Some functions will not work!"); - } - } - return version; - } + if (version != Unknown) { + System.out.println("[NBTAPI] NMS support '" + version.name() + "' loaded!"); + } else { + System.out.println("[NBTAPI] Wasn't able to find NMS Support!Some functions will not work!"); + } + } + return version; + } - public static boolean hasGsonSupport() { - if (hasGsonSupport == null) { - try { - System.out.println("Found Gson: " + Class.forName("com.google.gson.Gson")); - hasGsonSupport = true; - } catch (Exception ex) { - hasGsonSupport = false; - } - } - return hasGsonSupport; - } + public static boolean hasGsonSupport() { + if (hasGsonSupport == null) { + try { + System.out.println("Found Gson: " + Class.forName("com.google.gson.Gson")); + hasGsonSupport = true; + } catch (Exception ex) { + hasGsonSupport = false; + } + } + return hasGsonSupport; + } - public int getVersionId() { - return versionId; - } + public int getVersionId() { + return versionId; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java index 8dd916e6..c01d007d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java @@ -20,372 +20,372 @@ import java.util.Map.Entry; public abstract class MemoryBoard extends Board { - public MemoryBoardMap flocationIds = new MemoryBoardMap(); + public MemoryBoardMap flocationIds = new MemoryBoardMap(); - //----------------------------------------------// - // Get and Set - //----------------------------------------------// - public String getIdAt(FLocation flocation) { - if (!flocationIds.containsKey(flocation)) { - return "0"; - } + //----------------------------------------------// + // Get and Set + //----------------------------------------------// + public String getIdAt(FLocation flocation) { + if (!flocationIds.containsKey(flocation)) { + return "0"; + } - return flocationIds.get(flocation); - } + return flocationIds.get(flocation); + } - public Faction getFactionAt(FLocation flocation) { - return Factions.getInstance().getFactionById(getIdAt(flocation)); - } + public Faction getFactionAt(FLocation flocation) { + return Factions.getInstance().getFactionById(getIdAt(flocation)); + } - public void setIdAt(String id, FLocation flocation) { - clearOwnershipAt(flocation); + public void setIdAt(String id, FLocation flocation) { + clearOwnershipAt(flocation); - if (id.equals("0")) { - removeAt(flocation); - } + if (id.equals("0")) { + removeAt(flocation); + } - flocationIds.put(flocation, id); - } + flocationIds.put(flocation, id); + } - public void setFactionAt(Faction faction, FLocation flocation) { - setIdAt(faction.getId(), flocation); - } + public void setFactionAt(Faction faction, FLocation flocation) { + setIdAt(faction.getId(), flocation); + } - public void removeAt(FLocation flocation) { - Faction faction = getFactionAt(flocation); - Iterator it = faction.getWarps().values().iterator(); - while (it.hasNext()) { - if (flocation.isInChunk(it.next().getLocation())) { - it.remove(); - } - } - clearOwnershipAt(flocation); - flocationIds.remove(flocation); - } + public void removeAt(FLocation flocation) { + Faction faction = getFactionAt(flocation); + Iterator it = faction.getWarps().values().iterator(); + while (it.hasNext()) { + if (flocation.isInChunk(it.next().getLocation())) { + it.remove(); + } + } + clearOwnershipAt(flocation); + flocationIds.remove(flocation); + } - public Set getAllClaims(String factionId) { - Set locs = new HashSet<>(); - for (Entry entry : flocationIds.entrySet()) { - if (entry.getValue().equals(factionId)) { - locs.add(entry.getKey()); - } - } - return locs; - } + public Set getAllClaims(String factionId) { + Set locs = new HashSet<>(); + for (Entry entry : flocationIds.entrySet()) { + if (entry.getValue().equals(factionId)) { + locs.add(entry.getKey()); + } + } + return locs; + } - public Set getAllClaims(Faction faction) { - return getAllClaims(faction.getId()); - } + public Set getAllClaims(Faction faction) { + return getAllClaims(faction.getId()); + } - // not to be confused with claims, ownership referring to further member-specific ownership of a claim - public void clearOwnershipAt(FLocation flocation) { - Faction faction = getFactionAt(flocation); - if (faction != null && faction.isNormal()) { - faction.clearClaimOwnership(flocation); - } - } + // not to be confused with claims, ownership referring to further member-specific ownership of a claim + public void clearOwnershipAt(FLocation flocation) { + Faction faction = getFactionAt(flocation); + if (faction != null && faction.isNormal()) { + faction.clearClaimOwnership(flocation); + } + } - public void unclaimAll(String factionId) { - Faction faction = Factions.getInstance().getFactionById(factionId); - if (faction != null && faction.isNormal()) { - faction.clearAllClaimOwnership(); - faction.clearWarps(); - } - clean(factionId); - } + public void unclaimAll(String factionId) { + Faction faction = Factions.getInstance().getFactionById(factionId); + if (faction != null && faction.isNormal()) { + faction.clearAllClaimOwnership(); + faction.clearWarps(); + } + clean(factionId); + } - public void unclaimAllInWorld(String factionId, World world) { - for (FLocation loc : getAllClaims(factionId)) { - if (loc.getWorldName().equals(world.getName())) { - removeAt(loc); - } - } - } + public void unclaimAllInWorld(String factionId, World world) { + for (FLocation loc : getAllClaims(factionId)) { + if (loc.getWorldName().equals(world.getName())) { + removeAt(loc); + } + } + } - public void clean(String factionId) { - flocationIds.removeFaction(factionId); - } + public void clean(String factionId) { + flocationIds.removeFaction(factionId); + } - // Is this coord NOT completely surrounded by coords claimed by the same faction? - // Simpler: Is there any nearby coord with a faction other than the faction here? - public boolean isBorderLocation(FLocation flocation) { - Faction faction = getFactionAt(flocation); - FLocation a = flocation.getRelative(1, 0); - FLocation b = flocation.getRelative(-1, 0); - FLocation c = flocation.getRelative(0, 1); - FLocation d = flocation.getRelative(0, -1); - return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d); - } + // Is this coord NOT completely surrounded by coords claimed by the same faction? + // Simpler: Is there any nearby coord with a faction other than the faction here? + public boolean isBorderLocation(FLocation flocation) { + Faction faction = getFactionAt(flocation); + FLocation a = flocation.getRelative(1, 0); + FLocation b = flocation.getRelative(-1, 0); + FLocation c = flocation.getRelative(0, 1); + FLocation d = flocation.getRelative(0, -1); + return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d); + } - // Is this coord connected to any coord claimed by the specified faction? - public boolean isConnectedLocation(FLocation flocation, Faction faction) { - FLocation a = flocation.getRelative(1, 0); - FLocation b = flocation.getRelative(-1, 0); - FLocation c = flocation.getRelative(0, 1); - FLocation d = flocation.getRelative(0, -1); - return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d); - } + // Is this coord connected to any coord claimed by the specified faction? + public boolean isConnectedLocation(FLocation flocation, Faction faction) { + FLocation a = flocation.getRelative(1, 0); + FLocation b = flocation.getRelative(-1, 0); + FLocation c = flocation.getRelative(0, 1); + FLocation d = flocation.getRelative(0, -1); + return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d); + } - /** - * Checks if there is another faction within a given radius other than Wilderness. Used for HCF feature that - * requires a 'buffer' between factions. - * - * @param flocation - center location. - * @param faction - faction checking for. - * @param radius - chunk radius to check. - * @return true if another Faction is within the radius, otherwise false. - */ - public boolean hasFactionWithin(FLocation flocation, Faction faction, int radius) { - for (int x = -radius; x <= radius; x++) { - for (int z = -radius; z <= radius; z++) { - if (x == 0 && z == 0) { - continue; - } + /** + * Checks if there is another faction within a given radius other than Wilderness. Used for HCF feature that + * requires a 'buffer' between factions. + * + * @param flocation - center location. + * @param faction - faction checking for. + * @param radius - chunk radius to check. + * @return true if another Faction is within the radius, otherwise false. + */ + public boolean hasFactionWithin(FLocation flocation, Faction faction, int radius) { + for (int x = -radius; x <= radius; x++) { + for (int z = -radius; z <= radius; z++) { + if (x == 0 && z == 0) { + continue; + } - FLocation relative = flocation.getRelative(x, z); - Faction other = getFactionAt(relative); + FLocation relative = flocation.getRelative(x, z); + Faction other = getFactionAt(relative); - if (other.isNormal() && other != faction) { - return true; - } - } - } - return false; - } + if (other.isNormal() && other != faction) { + return true; + } + } + } + return false; + } - public void clean() { - Iterator> iter = flocationIds.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - if (!Factions.getInstance().isValidFactionId(entry.getValue())) { - SavageFactions.plugin.log("Board cleaner removed " + entry.getValue() + " from " + entry.getKey()); - iter.remove(); - } - } - } + public void clean() { + Iterator> iter = flocationIds.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (!Factions.getInstance().isValidFactionId(entry.getValue())) { + SavageFactions.plugin.log("Board cleaner removed " + entry.getValue() + " from " + entry.getKey()); + iter.remove(); + } + } + } - //----------------------------------------------// - // Cleaner. Remove orphaned foreign keys - //----------------------------------------------// + //----------------------------------------------// + // Cleaner. Remove orphaned foreign keys + //----------------------------------------------// - public int getFactionCoordCount(String factionId) { - return flocationIds.getOwnedLandCount(factionId); - } + public int getFactionCoordCount(String factionId) { + return flocationIds.getOwnedLandCount(factionId); + } - //----------------------------------------------// - // Coord count - //----------------------------------------------// + //----------------------------------------------// + // Coord count + //----------------------------------------------// - public int getFactionCoordCount(Faction faction) { - return getFactionCoordCount(faction.getId()); - } + public int getFactionCoordCount(Faction faction) { + return getFactionCoordCount(faction.getId()); + } - public int getFactionCoordCountInWorld(Faction faction, String worldName) { - String factionId = faction.getId(); - int ret = 0; - for (Entry entry : flocationIds.entrySet()) { - if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { - ret += 1; - } - } - return ret; - } + public int getFactionCoordCountInWorld(Faction faction, String worldName) { + String factionId = faction.getId(); + int ret = 0; + for (Entry entry : flocationIds.entrySet()) { + if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { + ret += 1; + } + } + return ret; + } - /** - * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction - * of decreasing z - */ - public ArrayList getMap(FPlayer fplayer, FLocation flocation, double inDegrees) { - Faction faction = fplayer.getFaction(); - ArrayList ret = new ArrayList<>(); - Faction factionLoc = getFactionAt(flocation); - ret.add(new FancyMessage(ChatColor.DARK_GRAY + SavageFactions.plugin.txt.titleize("(" + flocation.getCoordString() + ") " + factionLoc.getTag(fplayer)))); - int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); + /** + * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction + * of decreasing z + */ + public ArrayList getMap(FPlayer fplayer, FLocation flocation, double inDegrees) { + Faction faction = fplayer.getFaction(); + ArrayList ret = new ArrayList<>(); + Faction factionLoc = getFactionAt(flocation); + ret.add(new FancyMessage(ChatColor.DARK_GRAY + SavageFactions.plugin.txt.titleize("(" + flocation.getCoordString() + ") " + factionLoc.getTag(fplayer)))); + int buffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); - // Get the compass - ArrayList asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.DARK_GREEN, SavageFactions.plugin.txt.parse("")); + // Get the compass + ArrayList asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.DARK_GREEN, SavageFactions.plugin.txt.parse("")); - int halfWidth = Conf.mapWidth / 2; - // Use player's value for height - int halfHeight = fplayer.getMapHeight() / 2; - FLocation topLeft = flocation.getRelative(-halfWidth, -halfHeight); - int width = halfWidth * 2 + 1; - int height = halfHeight * 2 + 1; + int halfWidth = Conf.mapWidth / 2; + // Use player's value for height + int halfHeight = fplayer.getMapHeight() / 2; + FLocation topLeft = flocation.getRelative(-halfWidth, -halfHeight); + int width = halfWidth * 2 + 1; + int height = halfHeight * 2 + 1; - if (Conf.showMapFactionKey) { - height--; - } + if (Conf.showMapFactionKey) { + height--; + } - Map fList = new HashMap<>(); - int chrIdx = 0; + Map fList = new HashMap<>(); + int chrIdx = 0; - // For each row - for (int dz = 0; dz < height; dz++) { - // Draw and add that row - FancyMessage row = new FancyMessage(""); + // For each row + for (int dz = 0; dz < height; dz++) { + // Draw and add that row + FancyMessage row = new FancyMessage(""); - if (dz < 3) { - row.then(asciiCompass.get(dz)); - } - for (int dx = (dz < 3 ? 6 : 3); dx < width; dx++) { - if (dx == halfWidth && dz == halfHeight) { - row.then("+").color(ChatColor.AQUA).tooltip(TL.CLAIM_YOUAREHERE.toString()); - } else { - FLocation flocationHere = topLeft.getRelative(dx, dz); - Faction factionHere = getFactionAt(flocationHere); - Relation relation = fplayer.getRelationTo(factionHere); - if (flocationHere.isOutsideWorldBorder(buffer)) { - row.then("-").color(ChatColor.BLACK).tooltip(TL.CLAIM_MAP_OUTSIDEBORDER.toString()); - } else if (factionHere.isWilderness()) { - row.then("-").color(Conf.colorWilderness); - // Lol someone didnt add the x and z making it claim the wrong position Can i copyright this xD - if (fplayer.getPlayer().hasPermission(Permission.CLAIMAT.node)) { - row.tooltip(TL.CLAIM_CLICK_TO_CLAIM.format(dx + topLeft.getX(), dz + topLeft.getZ())) - .command(String.format("/f claimat %s %d %d", flocation.getWorldName(), dx + topLeft.getX(), dz + topLeft.getZ())); - } - } else if (factionHere.isSafeZone()) { - row.then("+").color(Conf.colorSafezone).tooltip(oneLineToolTip(factionHere, fplayer)); - } else if (factionHere.isWarZone()) { - row.then("+").color(Conf.colorWar).tooltip(oneLineToolTip(factionHere, fplayer)); - } else if (factionHere == faction || factionHere == factionLoc || relation.isAtLeast(Relation.ALLY) || - (Conf.showNeutralFactionsOnMap && relation.equals(Relation.NEUTRAL)) || - (Conf.showEnemyFactionsOnMap && relation.equals(Relation.ENEMY)) || - (Conf.showTrucesFactionsOnMap && relation.equals(Relation.TRUCE))) { - if (!fList.containsKey(factionHere.getTag())) { - fList.put(factionHere.getTag(), Conf.mapKeyChrs[Math.min(chrIdx++, Conf.mapKeyChrs.length - 1)]); - } - char tag = fList.get(factionHere.getTag()); + if (dz < 3) { + row.then(asciiCompass.get(dz)); + } + for (int dx = (dz < 3 ? 6 : 3); dx < width; dx++) { + if (dx == halfWidth && dz == halfHeight) { + row.then("+").color(ChatColor.AQUA).tooltip(TL.CLAIM_YOUAREHERE.toString()); + } else { + FLocation flocationHere = topLeft.getRelative(dx, dz); + Faction factionHere = getFactionAt(flocationHere); + Relation relation = fplayer.getRelationTo(factionHere); + if (flocationHere.isOutsideWorldBorder(buffer)) { + row.then("-").color(ChatColor.BLACK).tooltip(TL.CLAIM_MAP_OUTSIDEBORDER.toString()); + } else if (factionHere.isWilderness()) { + row.then("-").color(Conf.colorWilderness); + // Lol someone didnt add the x and z making it claim the wrong position Can i copyright this xD + if (fplayer.getPlayer().hasPermission(Permission.CLAIMAT.node)) { + row.tooltip(TL.CLAIM_CLICK_TO_CLAIM.format(dx + topLeft.getX(), dz + topLeft.getZ())) + .command(String.format("/f claimat %s %d %d", flocation.getWorldName(), dx + topLeft.getX(), dz + topLeft.getZ())); + } + } else if (factionHere.isSafeZone()) { + row.then("+").color(Conf.colorSafezone).tooltip(oneLineToolTip(factionHere, fplayer)); + } else if (factionHere.isWarZone()) { + row.then("+").color(Conf.colorWar).tooltip(oneLineToolTip(factionHere, fplayer)); + } else if (factionHere == faction || factionHere == factionLoc || relation.isAtLeast(Relation.ALLY) || + (Conf.showNeutralFactionsOnMap && relation.equals(Relation.NEUTRAL)) || + (Conf.showEnemyFactionsOnMap && relation.equals(Relation.ENEMY)) || + (Conf.showTrucesFactionsOnMap && relation.equals(Relation.TRUCE))) { + if (!fList.containsKey(factionHere.getTag())) { + fList.put(factionHere.getTag(), Conf.mapKeyChrs[Math.min(chrIdx++, Conf.mapKeyChrs.length - 1)]); + } + char tag = fList.get(factionHere.getTag()); - //row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(getToolTip(factionHere, fplayer)); - //changed out with a performance friendly one line tooltip :D - row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(oneLineToolTip(factionHere, fplayer)); - } else { - row.then("-").color(ChatColor.GRAY); - } - } - } - ret.add(row); - } + //row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(getToolTip(factionHere, fplayer)); + //changed out with a performance friendly one line tooltip :D + row.then(String.valueOf(tag)).color(factionHere.getColorTo(faction)).tooltip(oneLineToolTip(factionHere, fplayer)); + } else { + row.then("-").color(ChatColor.GRAY); + } + } + } + ret.add(row); + } - // Add the faction key - if (Conf.showMapFactionKey) { - FancyMessage fRow = new FancyMessage(""); - for (String key : fList.keySet()) { - fRow.then(String.format("%s: %s ", fList.get(key), key)).color(ChatColor.GRAY); - } - ret.add(fRow); - } + // Add the faction key + if (Conf.showMapFactionKey) { + FancyMessage fRow = new FancyMessage(""); + for (String key : fList.keySet()) { + fRow.then(String.format("%s: %s ", fList.get(key), key)).color(ChatColor.GRAY); + } + ret.add(fRow); + } - return ret; - } + return ret; + } - //----------------------------------------------// - // Map generation - //----------------------------------------------// + //----------------------------------------------// + // Map generation + //----------------------------------------------// - private List oneLineToolTip(Faction faction, FPlayer to) { - return Arrays.asList(faction.describeTo(to)); - } + private List oneLineToolTip(Faction faction, FPlayer to) { + return Arrays.asList(faction.describeTo(to)); + } - @SuppressWarnings("unused") - private List getToolTip(Faction faction, FPlayer to) { - List ret = new ArrayList<>(); - List show = SavageFactions.plugin.getConfig().getStringList("map"); + @SuppressWarnings("unused") + private List getToolTip(Faction faction, FPlayer to) { + List ret = new ArrayList<>(); + List show = SavageFactions.plugin.getConfig().getStringList("map"); - if (!faction.isNormal()) { - String tag = faction.getTag(to); - // send header and that's all - String header = show.get(0); - if (TagReplacer.HEADER.contains(header)) { - ret.add(SavageFactions.plugin.txt.titleize(tag)); - } else { - ret.add(SavageFactions.plugin.txt.parse(TagReplacer.FACTION.replace(header, tag))); - } - return ret; // we only show header for non-normal factions - } + if (!faction.isNormal()) { + String tag = faction.getTag(to); + // send header and that's all + String header = show.get(0); + if (TagReplacer.HEADER.contains(header)) { + ret.add(SavageFactions.plugin.txt.titleize(tag)); + } else { + ret.add(SavageFactions.plugin.txt.parse(TagReplacer.FACTION.replace(header, tag))); + } + return ret; // we only show header for non-normal factions + } - for (String raw : show) { - // Hack to get rid of the extra underscores in title normally used to center tag - if (raw.contains("{header}")) { - raw = raw.replace("{header}", faction.getTag(to)); - } + for (String raw : show) { + // Hack to get rid of the extra underscores in title normally used to center tag + if (raw.contains("{header}")) { + raw = raw.replace("{header}", faction.getTag(to)); + } - String parsed = TagUtil.parsePlain(faction, to, raw); // use relations - if (parsed == null) { - continue; // Due to minimal f show. - } + String parsed = TagUtil.parsePlain(faction, to, raw); // use relations + if (parsed == null) { + continue; // Due to minimal f show. + } - if (TagUtil.hasFancy(parsed)) { - List fancy = TagUtil.parseFancy(faction, to, parsed); - if (fancy != null) { - for (FancyMessage msg : fancy) { - ret.add((SavageFactions.plugin.txt.parse(msg.toOldMessageFormat()))); - } - } - continue; - } + if (TagUtil.hasFancy(parsed)) { + List fancy = TagUtil.parseFancy(faction, to, parsed); + if (fancy != null) { + for (FancyMessage msg : fancy) { + ret.add((SavageFactions.plugin.txt.parse(msg.toOldMessageFormat()))); + } + } + continue; + } - if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { - if (parsed.contains("{ig}")) { - // replaces all variables with no home TL - parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); - } - if (parsed.contains("%")) { - parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. - } - ret.add(SavageFactions.plugin.txt.parse(parsed)); - } - } + if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { + if (parsed.contains("{ig}")) { + // replaces all variables with no home TL + parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); + } + if (parsed.contains("%")) { + parsed = parsed.replaceAll("%", ""); // Just in case it got in there before we disallowed it. + } + ret.add(SavageFactions.plugin.txt.parse(parsed)); + } + } - return ret; - } + return ret; + } - public abstract void convertFrom(MemoryBoard old); + public abstract void convertFrom(MemoryBoard old); - public class MemoryBoardMap extends HashMap { - private static final long serialVersionUID = -6689617828610585368L; + public class MemoryBoardMap extends HashMap { + private static final long serialVersionUID = -6689617828610585368L; - Multimap factionToLandMap = HashMultimap.create(); + Multimap factionToLandMap = HashMultimap.create(); - @Override - public String put(FLocation floc, String factionId) { - String previousValue = super.put(floc, factionId); - if (previousValue != null) { - factionToLandMap.remove(previousValue, floc); - } + @Override + public String put(FLocation floc, String factionId) { + String previousValue = super.put(floc, factionId); + if (previousValue != null) { + factionToLandMap.remove(previousValue, floc); + } - factionToLandMap.put(factionId, floc); - return previousValue; - } + factionToLandMap.put(factionId, floc); + return previousValue; + } - @Override - public String remove(Object key) { - String result = super.remove(key); - if (result != null) { - FLocation floc = (FLocation) key; - factionToLandMap.remove(result, floc); - } + @Override + public String remove(Object key) { + String result = super.remove(key); + if (result != null) { + FLocation floc = (FLocation) key; + factionToLandMap.remove(result, floc); + } - return result; - } + return result; + } - @Override - public void clear() { - super.clear(); - factionToLandMap.clear(); - } + @Override + public void clear() { + super.clear(); + factionToLandMap.clear(); + } - public int getOwnedLandCount(String factionId) { - return factionToLandMap.get(factionId).size(); - } + public int getOwnedLandCount(String factionId) { + return factionToLandMap.get(factionId).size(); + } - public void removeFaction(String factionId) { - Collection flocations = factionToLandMap.removeAll(factionId); - for (FLocation floc : flocations) { - super.remove(floc); - } - } - } + public void removeFaction(String factionId) { + Collection flocations = factionToLandMap.removeAll(factionId); + for (FLocation floc : flocations) { + super.remove(floc); + } + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java index 380cd548..647f4395 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java @@ -44,1187 +44,1187 @@ import java.util.UUID; public abstract class MemoryFPlayer implements FPlayer { - public boolean inVault = false; - protected String factionId; - protected Role role; - protected String title; - protected double power; - protected double powerBoost; - protected long lastPowerUpdateTime; - protected long lastLoginTime; - protected ChatMode chatMode; - protected boolean ignoreAllianceChat = false; - protected String id; - protected String name; - protected boolean monitorJoins; - protected boolean spyingChat = false; - protected boolean showScoreboard = true; - protected WarmUpUtil.Warmup warmup; - protected int warmupTask; - protected boolean isAdminBypassing = false; - protected int kills, deaths; - protected boolean willAutoLeave = true; - protected int mapHeight = 8; // default to old value - protected boolean isFlying = false; - protected boolean enteringPassword = false; - protected String enteringPasswordWarp = ""; - protected transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked? - protected transient boolean mapAutoUpdating; - protected transient Faction autoClaimFor; - protected transient boolean autoSafeZoneEnabled; - protected transient boolean autoWarZoneEnabled; - protected transient boolean loginPvpDisabled; - protected transient long lastFrostwalkerMessage; - protected transient boolean shouldTakeFallDamage = true; - protected boolean isStealthEnabled = false; - boolean playerAlerts = false; - boolean inspectMode = false; - - public MemoryFPlayer() { - } - - public MemoryFPlayer(String id) { - this.id = id; - this.resetFactionData(false); - this.power = Conf.powerPlayerStarting; - this.lastPowerUpdateTime = System.currentTimeMillis(); - this.lastLoginTime = System.currentTimeMillis(); - this.mapAutoUpdating = false; - this.autoClaimFor = null; - this.autoSafeZoneEnabled = false; - this.autoWarZoneEnabled = false; - this.loginPvpDisabled = Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0; - this.powerBoost = 0.0; - this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false); - this.kills = 0; - this.deaths = 0; - this.mapHeight = Conf.mapHeight; - - if (!Conf.newPlayerStartingFactionID.equals("0") && Factions.getInstance().isValidFactionId(Conf.newPlayerStartingFactionID)) { - this.factionId = Conf.newPlayerStartingFactionID; - } - } - - public MemoryFPlayer(MemoryFPlayer other) { - this.factionId = other.factionId; - this.id = other.id; - this.power = other.power; - this.lastLoginTime = other.lastLoginTime; - this.mapAutoUpdating = other.mapAutoUpdating; - this.autoClaimFor = other.autoClaimFor; - this.autoSafeZoneEnabled = other.autoSafeZoneEnabled; - this.autoWarZoneEnabled = other.autoWarZoneEnabled; - this.loginPvpDisabled = other.loginPvpDisabled; - this.powerBoost = other.powerBoost; - this.role = other.role; - this.title = other.title; - this.chatMode = other.chatMode; - this.spyingChat = other.spyingChat; - this.lastStoodAt = other.lastStoodAt; - this.isAdminBypassing = other.isAdminBypassing; - this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", true); - this.kills = other.kills; - this.deaths = other.deaths; - this.mapHeight = Conf.mapHeight; - } - - public boolean isStealthEnabled() { - return this.isStealthEnabled; - } - - public void setStealth(boolean stealth) { - this.isStealthEnabled = stealth; - } - - public void login() { - this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); - this.deaths = getPlayer().getStatistic(Statistic.DEATHS); - } - - public void logout() { - this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); - this.deaths = getPlayer().getStatistic(Statistic.DEATHS); - } - - public Faction getFaction() { - if (this.factionId == null) { - this.factionId = "0"; - } - return Factions.getInstance().getFactionById(this.factionId); - } - - public void setFaction(Faction faction) { - Faction oldFaction = this.getFaction(); - if (oldFaction != null) { - oldFaction.removeFPlayer(this); - } - faction.addFPlayer(this); - this.factionId = faction.getId(); - } - - public String getFactionId() { - return this.factionId; - } - - public boolean hasFaction() { - return !factionId.equals("0"); - } - - public void setMonitorJoins(boolean monitor) { - this.monitorJoins = monitor; - } - - public boolean isMonitoringJoins() { - return this.monitorJoins; - } - - public Role getRole() { - // Hack to fix null roles.. - if (role == null) { - this.role = Role.NORMAL; - } - - return this.role; - } - - public void setRole(Role role) { - this.role = role; - } - - public double getPowerBoost() { - return this.powerBoost; - } - - public void setPowerBoost(double powerBoost) { - this.powerBoost = powerBoost; - } - - public boolean willAutoLeave() { - return this.willAutoLeave; - } - - public void setAutoLeave(boolean willLeave) { - this.willAutoLeave = willLeave; - SavageFactions.plugin.debug(name + " set autoLeave to " + willLeave); - } - - public long getLastFrostwalkerMessage() { - return this.lastFrostwalkerMessage; - } - - public void setLastFrostwalkerMessage() { - this.lastFrostwalkerMessage = System.currentTimeMillis(); - } - - public Faction getAutoClaimFor() { - return autoClaimFor; - } - - public void setAutoClaimFor(Faction faction) { - this.autoClaimFor = faction; - if (this.autoClaimFor != null) { - // TODO: merge these into same autoclaim - this.autoSafeZoneEnabled = false; - this.autoWarZoneEnabled = false; - } - } - - public boolean isAutoSafeClaimEnabled() { - return autoSafeZoneEnabled; - } - - public void setIsAutoSafeClaimEnabled(boolean enabled) { - this.autoSafeZoneEnabled = enabled; - if (enabled) { - this.autoClaimFor = null; - this.autoWarZoneEnabled = false; - } - } - - public boolean isAutoWarClaimEnabled() { - return autoWarZoneEnabled; - } - - public void setIsAutoWarClaimEnabled(boolean enabled) { - this.autoWarZoneEnabled = enabled; - if (enabled) { - this.autoClaimFor = null; - this.autoSafeZoneEnabled = false; - } - } - - public boolean isAdminBypassing() { - return this.isAdminBypassing; - } - - public boolean isVanished() { - return Essentials.isVanished(getPlayer()); - } - - public void setIsAdminBypassing(boolean val) { - this.isAdminBypassing = val; - } - - public ChatMode getChatMode() { - if (this.factionId.equals("0") || !Conf.factionOnlyChat) { - this.chatMode = ChatMode.PUBLIC; - } - return chatMode; - } - - public void setChatMode(ChatMode chatMode) { - this.chatMode = chatMode; - } - - public boolean isIgnoreAllianceChat() { - return ignoreAllianceChat; - } - - public void setIgnoreAllianceChat(boolean ignore) { - this.ignoreAllianceChat = ignore; - } - - public boolean isSpyingChat() { - return spyingChat; - } - - public void setSpyingChat(boolean chatSpying) { - this.spyingChat = chatSpying; - } - - // -------------------------------------------- // - // Getters And Setters - // -------------------------------------------- // - - // FIELD: account - public String getAccountId() { - return this.getId(); - } - - public void resetFactionData(boolean doSpoutUpdate) { - // clean up any territory ownership in old faction, if there is one - if (factionId != null && Factions.getInstance().isValidFactionId(this.getFactionId())) { - Faction currentFaction = this.getFaction(); - currentFaction.removeFPlayer(this); - if (currentFaction.isNormal()) { - currentFaction.clearClaimOwnership(this); - } - } - - this.factionId = "0"; // The default neutral faction - this.chatMode = ChatMode.PUBLIC; - this.role = Role.NORMAL; - this.title = ""; - this.autoClaimFor = null; - } - - public void resetFactionData() { - this.resetFactionData(true); - } - - public long getLastLoginTime() { - return lastLoginTime; - } - - public void setLastLoginTime(long lastLoginTime) { - losePowerFromBeingOffline(); - this.lastLoginTime = lastLoginTime; - this.lastPowerUpdateTime = lastLoginTime; - if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { - this.loginPvpDisabled = true; - } - } - - public boolean isMapAutoUpdating() { - return mapAutoUpdating; - } - - public void setMapAutoUpdating(boolean mapAutoUpdating) { - this.mapAutoUpdating = mapAutoUpdating; - } - - //----------------------------------------------// - // Title, Name, Faction Tag and Chat - //----------------------------------------------// - - // Base: - - public boolean hasLoginPvpDisabled() { - if (!loginPvpDisabled) { - return false; - } - if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) { - this.loginPvpDisabled = false; - return false; - } - return true; - } - - public FLocation getLastStoodAt() { - return this.lastStoodAt; - } - - public void setLastStoodAt(FLocation flocation) { - this.lastStoodAt = flocation; - } - - public String getTitle() { - return this.hasFaction() ? title : TL.NOFACTION_PREFIX.toString(); - } - - public void setTitle(CommandSender sender, String title) { - // Check if the setter has it. - if (sender.hasPermission(Permission.TITLE_COLOR.node)) { - title = ChatColor.translateAlternateColorCodes('&', title); - } - - this.title = title; - } - - // Base concatenations: - - public String getName() { - if (this.name == null) { - // Older versions of FactionsUUID don't save the name, - // so `name` will be null the first time it's retrieved - // after updating - OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(getId())); - this.name = offline.getName() != null ? offline.getName() : getId(); - } - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getTag() { - return this.hasFaction() ? this.getFaction().getTag() : ""; - } - - // Colored concatenations: - // These are used in information messages - - public String getNameAndSomething(String something) { - String ret = this.role.getPrefix(); - if (something.length() > 0) { - ret += something + " "; - } - ret += this.getName(); - return ret; - } - - public String getNameAndTitle() { - return this.getNameAndSomething(this.getTitle()); - } - - // Chat Tag: - // These are injected into the format of global chat messages. - - public String getNameAndTag() { - return this.getNameAndSomething(this.getTag()); - } - - public String getNameAndTitle(Faction faction) { - return this.getColorTo(faction) + this.getNameAndTitle(); - } - - public String getNameAndTitle(MemoryFPlayer fplayer) { - return this.getColorTo(fplayer) + this.getNameAndTitle(); - } - - public String getChatTag() { - return this.hasFaction() ? String.format(Conf.chatTagFormat, this.getRole().getPrefix() + this.getTag()) : TL.NOFACTION_PREFIX.toString(); - } - - // Colored Chat Tag - public String getChatTag(Faction faction) { - return this.hasFaction() ? this.getRelationTo(faction).getColor() + getChatTag() : ""; - } - - // ------------------------------- - // Relation and relation colors - // ------------------------------- - - public String getChatTag(MemoryFPlayer fplayer) { - return this.hasFaction() ? this.getColorTo(fplayer) + getChatTag() : ""; - } - - public int getKills() { - return isOnline() ? getPlayer().getStatistic(Statistic.PLAYER_KILLS) : this.kills; - } - - public int getDeaths() { - return isOnline() ? getPlayer().getStatistic(Statistic.DEATHS) : this.deaths; - - } - - @Override - public String describeTo(RelationParticipator that, boolean ucfirst) { - return RelationUtil.describeThatToMe(this, that, ucfirst); - } - - @Override - public String describeTo(RelationParticipator that) { - return RelationUtil.describeThatToMe(this, that); - } - - @Override - public Relation getRelationTo(RelationParticipator rp) { - return RelationUtil.getRelationTo(this, rp); - } - - @Override - public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { - return RelationUtil.getRelationTo(this, rp, ignorePeaceful); - } - - public Relation getRelationToLocation() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this); - } - - @Override - public ChatColor getColorTo(RelationParticipator rp) { - return RelationUtil.getColorOfThatToMe(this, rp); - } - - //----------------------------------------------// - // Health - //----------------------------------------------// - public void heal(int amnt) { - Player player = this.getPlayer(); - if (player == null) { - return; - } - player.setHealth(player.getHealth() + amnt); - } - - //----------------------------------------------// - // Power - //----------------------------------------------// - public double getPower() { - this.updatePower(); - return this.power; - } - - public void alterPower(double delta) { - this.power += delta; - if (this.power > this.getPowerMax()) { - this.power = this.getPowerMax(); - } else if (this.power < this.getPowerMin()) { - this.power = this.getPowerMin(); - } - } - - public double getPowerMax() { - return Conf.powerPlayerMax + this.powerBoost; - } - - public double getPowerMin() { - return Conf.powerPlayerMin + this.powerBoost; - } - - public int getPowerRounded() { - return (int) Math.round(this.getPower()); - } - - public int getPowerMaxRounded() { - return (int) Math.round(this.getPowerMax()); - } - - public int getPowerMinRounded() { - return (int) Math.round(this.getPowerMin()); - } - - public void updatePower() { - if (this.isOffline()) { - losePowerFromBeingOffline(); - if (!Conf.powerRegenOffline) { - return; - } - } else if (hasFaction() && getFaction().isPowerFrozen()) { - return; // Don't let power regen if faction power is frozen. - } - - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - Player thisPlayer = this.getPlayer(); - if (thisPlayer != null && thisPlayer.isDead()) { - return; // don't let dead players regain power until they respawn - } - - PowerRegenEvent powerRegenEvent = new PowerRegenEvent(getFaction(), this); - Bukkit.getServer().getPluginManager().callEvent(powerRegenEvent); - - if (!powerRegenEvent.isCancelled()) - this.alterPower(millisPassed * Conf.powerPerMinute / 60000); // millisPerMinute : 60 * 1000 - } - - public void losePowerFromBeingOffline() { - if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - double loss = millisPassed * Conf.powerOfflineLossPerDay / (24 * 60 * 60 * 1000); - if (this.power - loss < Conf.powerOfflineLossLimit) { - loss = this.power; - } - this.alterPower(-loss); - } - } - - public void onDeath() { - this.updatePower(); - this.alterPower(-Conf.powerPerDeath); - if (hasFaction()) { - getFaction().setLastDeath(System.currentTimeMillis()); - } - } - - //----------------------------------------------// - // Territory - //----------------------------------------------// - public boolean isInOwnTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)) == this.getFaction(); - } - - public boolean isInOthersTerritory() { - Faction factionHere = Board.getInstance().getFactionAt(new FLocation(this)); - return factionHere != null && factionHere.isNormal() && factionHere != this.getFaction(); - } - - public boolean isInAllyTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isAlly(); - } - - public boolean isInNeutralTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isNeutral(); - } - - public boolean isInEnemyTerritory() { - return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isEnemy(); - } - - public void sendFactionHereMessage(Faction from) { - Faction toShow = Board.getInstance().getFactionAt(getLastStoodAt()); - boolean showChat = true; - if (showInfoBoard(toShow)) { - FScoreboard.get(this).setTemporarySidebar(new FInfoSidebar(toShow)); - showChat = SavageFactions.plugin.getConfig().getBoolean("scoreboard.also-send-chat", true); - } - if (showChat) { - this.sendMessage(SavageFactions.plugin.txt.parse(TL.FACTION_LEAVE.format(from.getTag(this), toShow.getTag(this)))); - } - } - - // ------------------------------- - // Actions - // ------------------------------- - - /** - * Check if the scoreboard should be shown. Simple method to be used by above method. - * - * @param toShow Faction to be shown. - * @return true if should show, otherwise false. - */ - public boolean showInfoBoard(Faction toShow) { - return showScoreboard && !toShow.isWarZone() && !toShow.isWilderness() && !toShow.isSafeZone() && SavageFactions.plugin.getConfig().contains("scoreboard.finfo") && SavageFactions.plugin.getConfig().getBoolean("scoreboard.finfo-enabled", false) && FScoreboard.get(this) != null; - } - - @Override - public boolean showScoreboard() { - return this.showScoreboard; - } - - @Override - public void setShowScoreboard(boolean show) { - this.showScoreboard = show; - } - - public void leave(boolean makePay) { - Faction myFaction = this.getFaction(); - makePay = makePay && Econ.shouldBeUsed() && !this.isAdminBypassing(); - - if (myFaction == null) { - resetFactionData(); - return; - } - - boolean perm = myFaction.isPermanent(); - - if (!perm && this.getRole() == Role.LEADER && myFaction.getFPlayers().size() > 1) { - msg(TL.LEAVE_PASSADMIN); - return; - } - - if (!Conf.canLeaveWithNegativePower && this.getPower() < 0) { - msg(TL.LEAVE_NEGATIVEPOWER); - return; - } - - // if economy is enabled and they're not on the bypass list, make sure they can pay - if (makePay && !Econ.hasAtLeast(this, Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString())) { - return; - } - - FPlayerLeaveEvent leaveEvent = new FPlayerLeaveEvent(this, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.LEAVE); - Bukkit.getServer().getPluginManager().callEvent(leaveEvent); - if (leaveEvent.isCancelled()) { - return; - } - - // then make 'em pay (if applicable) - if (makePay && !Econ.modifyMoney(this, -Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString(), TL.LEAVE_FORLEAVE.toString())) { - return; - } - - // Am I the last one in the faction? - if (myFaction.getFPlayers().size() == 1) { - // Transfer all money - if (Econ.shouldBeUsed()) { - Econ.transferMoney(this, myFaction, this, Econ.getBalance(myFaction.getAccountId())); - } - } - - if (myFaction.isNormal()) { - for (FPlayer fplayer : myFaction.getFPlayersWhereOnline(true)) { - fplayer.msg(TL.LEAVE_LEFT, this.describeTo(fplayer, true), myFaction.describeTo(fplayer)); - } - - if (Conf.logFactionLeave) { - SavageFactions.plugin.log(TL.LEAVE_LEFT.format(this.getName(), myFaction.getTag())); - } - } - - myFaction.removeAnnouncements(this); - this.resetFactionData(); - - if (myFaction.isNormal() && !perm && myFaction.getFPlayers().isEmpty()) { - // Remove this faction - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg(TL.LEAVE_DISBANDED, myFaction.describeTo(fplayer, true)); - } - - FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), PlayerDisbandReason.LEAVE); - Bukkit.getPluginManager().callEvent(disbandEvent); - - Factions.getInstance().removeFaction(myFaction.getId()); - if (Conf.logFactionDisband) { - SavageFactions.plugin.log(TL.LEAVE_DISBANDEDLOG.format(myFaction.getTag(), myFaction.getId(), this.getName())); - } - } - } - - public boolean canClaimForFaction(Faction forFaction) { - return this.isAdminBypassing() || !forFaction.isWilderness() && (forFaction == this.getFaction() && this.getRole().isAtLeast(Role.MODERATOR)) || (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) || (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())); - } - - public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure) { - return canClaimForFactionAtLocation(forFaction, new FLocation(location), notifyFailure); - } - - public boolean canClaimForFactionAtLocation(Faction forFaction, FLocation flocation, boolean notifyFailure) { - String error = null; - Faction myFaction = getFaction(); - Faction currentFaction = Board.getInstance().getFactionAt(flocation); - int ownedLand = forFaction.getLandRounded(); - int factionBuffer = SavageFactions.plugin.getConfig().getInt("hcf.buffer-zone", 0); - int worldBuffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); - - if (Conf.worldGuardChecking && Worldguard.checkForRegionsInChunk(flocation)) { - // Checks for WorldGuard regions in the chunk attempting to be claimed - error = SavageFactions.plugin.txt.parse(TL.CLAIM_PROTECTED.toString()); - } else if (flocation.isOutsideWorldBorder(SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0))) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); - } else if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_DISABLED.toString()); - } else if (this.isAdminBypassing()) { - return true; - } else if (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) { - return true; - } else if (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())) { - return true; - } else if (currentFaction.getAccess(this, PermissableAction.TERRITORY) == Access.ALLOW) { - return true; - } else if (myFaction != forFaction) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_CANTCLAIM.toString(), forFaction.describeTo(this)); - } else if (forFaction == currentFaction) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALREADYOWN.toString(), forFaction.describeTo(this, true)); - } else if (this.getRole().value < Role.MODERATOR.value) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_MUSTBE.toString(), Role.MODERATOR.getTranslation()); - } else if (forFaction.getFPlayers().size() < Conf.claimsRequireMinFactionMembers) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_MEMBERS.toString(), Conf.claimsRequireMinFactionMembers); - } else if (currentFaction.isSafeZone()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_SAFEZONE.toString()); - } else if (currentFaction.isWarZone()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_WARZONE.toString()); - } else if (SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true) && ownedLand >= forFaction.getPowerRounded()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_POWER.toString()); - } else if (Conf.claimedLandsMax != 0 && ownedLand >= Conf.claimedLandsMax && forFaction.isNormal()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_LIMIT.toString()); - } else if (currentFaction.getRelationTo(forFaction) == Relation.ALLY) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALLY.toString()); - } else if (Conf.claimsMustBeConnected && !this.isAdminBypassing() && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, myFaction) && (!Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction || !currentFaction.isNormal())) { - if (Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_CONTIGIOUS.toString()); - } else { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_FACTIONCONTIGUOUS.toString()); - } - } else if (factionBuffer > 0 && Board.getInstance().hasFactionWithin(flocation, myFaction, factionBuffer)) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_TOOCLOSETOOTHERFACTION.format(factionBuffer)); - } else if (flocation.isOutsideWorldBorder(worldBuffer)) { - if (worldBuffer > 0) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEBORDERBUFFER.format(worldBuffer)); - } else { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); - } - } else if (currentFaction.isNormal()) { - if (myFaction.isPeaceful()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFUL.toString(), currentFaction.getTag(this)); - } else if (currentFaction.isPeaceful()) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFULTARGET.toString(), currentFaction.getTag(this)); - } else if (!currentFaction.hasLandInflation()) { - // TODO more messages WARN current faction most importantly - error = SavageFactions.plugin.txt.parse(TL.CLAIM_THISISSPARTA.toString(), currentFaction.getTag(this)); - } else if (currentFaction.hasLandInflation() && !SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true)) { - // deny over claim when it normally would be allowed. - error = SavageFactions.plugin.txt.parse(TL.CLAIM_OVERCLAIM_DISABLED.toString()); - } else if (!Board.getInstance().isBorderLocation(flocation)) { - error = SavageFactions.plugin.txt.parse(TL.CLAIM_BORDER.toString()); - } - } - // TODO: Add more else if statements. - - if (notifyFailure && error != null) { - msg(error); - } - return error == null; - } - - public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure) { - return attemptClaim(forFaction, new FLocation(location), notifyFailure); - } - - public boolean shouldBeSaved() { - return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); - } - - public void msg(String str, Object... args) { - this.sendMessage(SavageFactions.plugin.txt.parse(str, args)); - } - - public void msg(TL translation, Object... args) { - this.msg(translation.toString(), args); - } - - public Player getPlayer() { - return Bukkit.getPlayer(UUID.fromString(this.getId())); - } - - public boolean isOnline() { - return this.getPlayer() != null; - } - - // make sure target player should be able to detect that this player is online - public boolean isOnlineAndVisibleTo(Player player) { - Player target = this.getPlayer(); - return target != null && player.canSee(target); - } - - public boolean isOffline() { - return !isOnline(); - } - - public boolean isFlying() { - return isFlying; - } - - public void setFlying(boolean fly) { - setFFlying(fly, false); - } - - public void setFFlying(boolean fly, boolean damage) { - Player player = getPlayer(); - if (player != null) { - player.setAllowFlight(fly); - player.setFlying(fly); - } - - if (!damage) { - msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); - if (!fly) { - sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3) + "")); - } - - } else { - msg(TL.COMMAND_FLY_DAMAGE); - } - - // If leaving fly mode, don't let them take fall damage for x seconds. - if (!fly) { - int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); - CmdFly.flyMap.remove(player.getName()); - - // If the value is 0 or lower, make them take fall damage. - // Otherwise, start a timer and have this cancel after a few seconds. - // Short task so we're just doing it in method. Not clean but eh. - if (cooldown > 0) { - setTakeFallDamage(false); - Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - setTakeFallDamage(true); - } - }, 20L * cooldown); - } - } - - isFlying = fly; - } - - public boolean isInVault() { - return inVault; - } - - public void setInVault(boolean status) { - inVault = status; - } - - public boolean canFlyAtLocation() { - return canFlyAtLocation(lastStoodAt); - } - - public boolean canFlyAtLocation(FLocation location) { - Faction faction = Board.getInstance().getFactionAt(location); - if ((faction == getFaction() && getRole() == Role.LEADER) || isAdminBypassing) { - return true; - } - - Access access = faction.getAccess(this, PermissableAction.FLY); - return access == null || access == Access.UNDEFINED || access == Access.ALLOW; - } - - public boolean shouldTakeFallDamage() { - return this.shouldTakeFallDamage; - } - - public void setTakeFallDamage(boolean fallDamage) { - this.shouldTakeFallDamage = fallDamage; - } - - public boolean isEnteringPassword() { - return enteringPassword; - } - - public void setEnteringPassword(boolean toggle, String warp) { - enteringPassword = toggle; - enteringPasswordWarp = warp; - } - - // -------------------------------------------- // - // Message Sending Helpers - // -------------------------------------------- // - - public String getEnteringWarp() { - return enteringPasswordWarp; - } - - public void sendMessage(String msg) { - if (msg.contains("{null}")) { - return; // user wants this message to not send - } - if (msg.contains("/n/")) { - for (String s : msg.split("/n/")) { - sendMessage(s); - } - return; - } - Player player = this.getPlayer(); - if (player == null) { - return; - } - player.sendMessage(msg); - } - - public void sendMessage(List msgs) { - for (String msg : msgs) { - this.sendMessage(msg); - } - } - - public void sendFancyMessage(FancyMessage message) { - Player player = getPlayer(); - if (player == null || !player.isOnGround()) { - return; - } - - message.send(player); - } - - public void sendFancyMessage(List messages) { - Player player = getPlayer(); - if (player == null) { - return; - } - - for (FancyMessage msg : messages) { - msg.send(player); - } - } - - public int getMapHeight() { - if (this.mapHeight < 1) { - this.mapHeight = Conf.mapHeight; - } - - return this.mapHeight; - } - - public void setMapHeight(int height) { - this.mapHeight = height > (Conf.mapHeight * 2) ? (Conf.mapHeight * 2) : height; - } - - public String getNameAndTitle(FPlayer fplayer) { - return this.getColorTo(fplayer) + this.getNameAndTitle(); - } - - @Override - public String getChatTag(FPlayer fplayer) { - return this.hasFaction() ? this.getRelationTo(fplayer).getColor() + getChatTag() : ""; - } - - @Override - public String getId() { - return id; - } - - @Override - public void setId(String id) { - this.id = id; - } - - public abstract void remove(); - - @Override - public void clearWarmup() { - if (warmup != null) { - Bukkit.getScheduler().cancelTask(warmupTask); - this.stopWarmup(); - } - } - - @Override - public void stopWarmup() { - warmup = null; - } - - @Override - public boolean isWarmingUp() { - return warmup != null; - } - - @Override - public WarmUpUtil.Warmup getWarmupType() { - return warmup; - } - - @Override - public void addWarmup(WarmUpUtil.Warmup warmup, int taskId) { - if (this.warmup != null) { - this.clearWarmup(); - } - this.warmup = warmup; - this.warmupTask = taskId; - } - - @Override - public boolean checkIfNearbyEnemies() { - Player me = this.getPlayer(); - int radius = Conf.stealthFlyCheckRadius; - for (Entity e : me.getNearbyEntities(radius, 255, radius)) { - if (e == null) { - continue; - } - if (e instanceof Player) { - Player eplayer = (((Player) e).getPlayer()); - if (eplayer == null) { - continue; - } - FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); - if (efplayer == null) { - continue; - } - if (efplayer != null && this.getRelationTo(efplayer).equals(Relation.ENEMY) && !efplayer.isStealthEnabled()) { - setFlying(false); - msg(TL.COMMAND_FLY_ENEMY_NEAR); - Bukkit.getServer().getPluginManager().callEvent(new FPlayerStoppedFlying(this)); - return true; - } - } - } - return false; - } - - @Override - public Boolean canflyinWilderness() { - return getPlayer().hasPermission("factions.fly.wilderness"); - } - - @Override - public Boolean canflyinWarzone() { - return getPlayer().hasPermission("factions.fly.warzone"); - - } - - @Override - public Boolean canflyinSafezone() { - return getPlayer().hasPermission("factions.fly.safezone"); - - } - - @Override - public Boolean canflyinEnemy() { - return getPlayer().hasPermission("factions.fly.enemy"); - - } - - @Override - public Boolean canflyinAlly() { - return getPlayer().hasPermission("factions.fly.ally"); - - } - - @Override - public Boolean canflyinTruce() { - return getPlayer().hasPermission("factions.fly.truce"); - - } - - @Override - public Boolean canflyinNeutral() { - return getPlayer().hasPermission("factions.fly.neutral"); - - } - - @Override - public boolean isInspectMode() { - return inspectMode; - } - - @Override - public void setInspectMode(boolean status) { - inspectMode = status; - } - - public boolean attemptClaim(Faction forFaction, FLocation flocation, boolean notifyFailure) { - // notifyFailure is false if called by auto-claim; no need to notify on every failure for it - // return value is false on failure, true on success - - Faction currentFaction = Board.getInstance().getFactionAt(flocation); - int ownedLand = forFaction.getLandRounded(); - - if (!this.canClaimForFactionAtLocation(forFaction, flocation, notifyFailure)) { - return false; - } - - // if economy is enabled and they're not on the bypass list, make sure they can pay - boolean mustPay = Econ.shouldBeUsed() && !this.isAdminBypassing() && !forFaction.isSafeZone() && !forFaction.isWarZone(); - double cost = 0.0; - EconomyParticipator payee = null; - if (mustPay) { - cost = Econ.calculateClaimCost(ownedLand, currentFaction.isNormal()); - - - if (Conf.econClaimUnconnectedFee != 0.0 && forFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, forFaction)) { - cost += Conf.econClaimUnconnectedFee; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts && this.hasFaction()) { - payee = this.getFaction(); - } else { - payee = this; - } - - if (!Econ.hasAtLeast(payee, cost, TL.CLAIM_TOCLAIM.toString())) { - return false; - } - } - - LandClaimEvent claimEvent = new LandClaimEvent(flocation, forFaction, this); - Bukkit.getPluginManager().callEvent(claimEvent); - if (claimEvent.isCancelled()) { - return false; - } - - // then make 'em pay (if applicable) - if (mustPay && !Econ.modifyMoney(payee, -cost, TL.CLAIM_TOCLAIM.toString(), TL.CLAIM_FORCLAIM.toString())) { - return false; - } - - // Was an over claim - if (currentFaction.isNormal() && currentFaction.hasLandInflation()) { - // Give them money for over claiming. - Econ.modifyMoney(payee, Conf.econOverclaimRewardMultiplier, TL.CLAIM_TOOVERCLAIM.toString(), TL.CLAIM_FOROVERCLAIM.toString()); - } - - // announce success - Set informTheseFPlayers = new HashSet<>(); - informTheseFPlayers.add(this); - informTheseFPlayers.addAll(forFaction.getFPlayersWhereOnline(true)); - for (FPlayer fp : informTheseFPlayers) { - fp.msg(TL.CLAIM_CLAIMED, this.describeTo(fp, true), forFaction.describeTo(fp), currentFaction.describeTo(fp)); - } - - Board.getInstance().setFactionAt(forFaction, flocation); - - if (Conf.logLandClaims) { - SavageFactions.plugin.log(TL.CLAIM_CLAIMEDLOG.toString(), this.getName(), flocation.getCoordString(), forFaction.getTag()); - } - - return true; - } - - - @Override - public String getRolePrefix() { - - switch (getRole()) { - case RECRUIT: - return Conf.prefixRecruit; - case NORMAL: - return Conf.prefixNormal; - case MODERATOR: - return Conf.prefixMod; - case COLEADER: - return Conf.prefixCoLeader; - case LEADER: - return Conf.prefixLeader; - } - - return null; - } - - @Override - public boolean hasMoney(int amt) { - Economy econ = SavageFactions.plugin.getEcon(); - if (econ.getBalance(getPlayer()) >= amt) { - return true; - } else { - getPlayer().closeInventory(); - msg(TL.GENERIC_NOTENOUGHMONEY); - return false; - } - } - - @Override - public void takeMoney(int amt) { - if (hasMoney(amt)) { - Economy econ = SavageFactions.plugin.getEcon(); - econ.withdrawPlayer(getPlayer(), amt); - sendMessage(TL.GENERIC_MONEYTAKE.toString().replace("{amount}", amt + "")); - } - } + public boolean inVault = false; + protected String factionId; + protected Role role; + protected String title; + protected double power; + protected double powerBoost; + protected long lastPowerUpdateTime; + protected long lastLoginTime; + protected ChatMode chatMode; + protected boolean ignoreAllianceChat = false; + protected String id; + protected String name; + protected boolean monitorJoins; + protected boolean spyingChat = false; + protected boolean showScoreboard = true; + protected WarmUpUtil.Warmup warmup; + protected int warmupTask; + protected boolean isAdminBypassing = false; + protected int kills, deaths; + protected boolean willAutoLeave = true; + protected int mapHeight = 8; // default to old value + protected boolean isFlying = false; + protected boolean enteringPassword = false; + protected String enteringPasswordWarp = ""; + protected transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked? + protected transient boolean mapAutoUpdating; + protected transient Faction autoClaimFor; + protected transient boolean autoSafeZoneEnabled; + protected transient boolean autoWarZoneEnabled; + protected transient boolean loginPvpDisabled; + protected transient long lastFrostwalkerMessage; + protected transient boolean shouldTakeFallDamage = true; + protected boolean isStealthEnabled = false; + boolean playerAlerts = false; + boolean inspectMode = false; + + public MemoryFPlayer() { + } + + public MemoryFPlayer(String id) { + this.id = id; + this.resetFactionData(false); + this.power = Conf.powerPlayerStarting; + this.lastPowerUpdateTime = System.currentTimeMillis(); + this.lastLoginTime = System.currentTimeMillis(); + this.mapAutoUpdating = false; + this.autoClaimFor = null; + this.autoSafeZoneEnabled = false; + this.autoWarZoneEnabled = false; + this.loginPvpDisabled = Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0; + this.powerBoost = 0.0; + this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", false); + this.kills = 0; + this.deaths = 0; + this.mapHeight = Conf.mapHeight; + + if (!Conf.newPlayerStartingFactionID.equals("0") && Factions.getInstance().isValidFactionId(Conf.newPlayerStartingFactionID)) { + this.factionId = Conf.newPlayerStartingFactionID; + } + } + + public MemoryFPlayer(MemoryFPlayer other) { + this.factionId = other.factionId; + this.id = other.id; + this.power = other.power; + this.lastLoginTime = other.lastLoginTime; + this.mapAutoUpdating = other.mapAutoUpdating; + this.autoClaimFor = other.autoClaimFor; + this.autoSafeZoneEnabled = other.autoSafeZoneEnabled; + this.autoWarZoneEnabled = other.autoWarZoneEnabled; + this.loginPvpDisabled = other.loginPvpDisabled; + this.powerBoost = other.powerBoost; + this.role = other.role; + this.title = other.title; + this.chatMode = other.chatMode; + this.spyingChat = other.spyingChat; + this.lastStoodAt = other.lastStoodAt; + this.isAdminBypassing = other.isAdminBypassing; + this.showScoreboard = SavageFactions.plugin.getConfig().getBoolean("scoreboard.default-enabled", true); + this.kills = other.kills; + this.deaths = other.deaths; + this.mapHeight = Conf.mapHeight; + } + + public boolean isStealthEnabled() { + return this.isStealthEnabled; + } + + public void setStealth(boolean stealth) { + this.isStealthEnabled = stealth; + } + + public void login() { + this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); + this.deaths = getPlayer().getStatistic(Statistic.DEATHS); + } + + public void logout() { + this.kills = getPlayer().getStatistic(Statistic.PLAYER_KILLS); + this.deaths = getPlayer().getStatistic(Statistic.DEATHS); + } + + public Faction getFaction() { + if (this.factionId == null) { + this.factionId = "0"; + } + return Factions.getInstance().getFactionById(this.factionId); + } + + public void setFaction(Faction faction) { + Faction oldFaction = this.getFaction(); + if (oldFaction != null) { + oldFaction.removeFPlayer(this); + } + faction.addFPlayer(this); + this.factionId = faction.getId(); + } + + public String getFactionId() { + return this.factionId; + } + + public boolean hasFaction() { + return !factionId.equals("0"); + } + + public void setMonitorJoins(boolean monitor) { + this.monitorJoins = monitor; + } + + public boolean isMonitoringJoins() { + return this.monitorJoins; + } + + public Role getRole() { + // Hack to fix null roles.. + if (role == null) { + this.role = Role.NORMAL; + } + + return this.role; + } + + public void setRole(Role role) { + this.role = role; + } + + public double getPowerBoost() { + return this.powerBoost; + } + + public void setPowerBoost(double powerBoost) { + this.powerBoost = powerBoost; + } + + public boolean willAutoLeave() { + return this.willAutoLeave; + } + + public void setAutoLeave(boolean willLeave) { + this.willAutoLeave = willLeave; + SavageFactions.plugin.debug(name + " set autoLeave to " + willLeave); + } + + public long getLastFrostwalkerMessage() { + return this.lastFrostwalkerMessage; + } + + public void setLastFrostwalkerMessage() { + this.lastFrostwalkerMessage = System.currentTimeMillis(); + } + + public Faction getAutoClaimFor() { + return autoClaimFor; + } + + public void setAutoClaimFor(Faction faction) { + this.autoClaimFor = faction; + if (this.autoClaimFor != null) { + // TODO: merge these into same autoclaim + this.autoSafeZoneEnabled = false; + this.autoWarZoneEnabled = false; + } + } + + public boolean isAutoSafeClaimEnabled() { + return autoSafeZoneEnabled; + } + + public void setIsAutoSafeClaimEnabled(boolean enabled) { + this.autoSafeZoneEnabled = enabled; + if (enabled) { + this.autoClaimFor = null; + this.autoWarZoneEnabled = false; + } + } + + public boolean isAutoWarClaimEnabled() { + return autoWarZoneEnabled; + } + + public void setIsAutoWarClaimEnabled(boolean enabled) { + this.autoWarZoneEnabled = enabled; + if (enabled) { + this.autoClaimFor = null; + this.autoSafeZoneEnabled = false; + } + } + + public boolean isAdminBypassing() { + return this.isAdminBypassing; + } + + public boolean isVanished() { + return Essentials.isVanished(getPlayer()); + } + + public void setIsAdminBypassing(boolean val) { + this.isAdminBypassing = val; + } + + public ChatMode getChatMode() { + if (this.factionId.equals("0") || !Conf.factionOnlyChat) { + this.chatMode = ChatMode.PUBLIC; + } + return chatMode; + } + + public void setChatMode(ChatMode chatMode) { + this.chatMode = chatMode; + } + + public boolean isIgnoreAllianceChat() { + return ignoreAllianceChat; + } + + public void setIgnoreAllianceChat(boolean ignore) { + this.ignoreAllianceChat = ignore; + } + + public boolean isSpyingChat() { + return spyingChat; + } + + public void setSpyingChat(boolean chatSpying) { + this.spyingChat = chatSpying; + } + + // -------------------------------------------- // + // Getters And Setters + // -------------------------------------------- // + + // FIELD: account + public String getAccountId() { + return this.getId(); + } + + public void resetFactionData(boolean doSpoutUpdate) { + // clean up any territory ownership in old faction, if there is one + if (factionId != null && Factions.getInstance().isValidFactionId(this.getFactionId())) { + Faction currentFaction = this.getFaction(); + currentFaction.removeFPlayer(this); + if (currentFaction.isNormal()) { + currentFaction.clearClaimOwnership(this); + } + } + + this.factionId = "0"; // The default neutral faction + this.chatMode = ChatMode.PUBLIC; + this.role = Role.NORMAL; + this.title = ""; + this.autoClaimFor = null; + } + + public void resetFactionData() { + this.resetFactionData(true); + } + + public long getLastLoginTime() { + return lastLoginTime; + } + + public void setLastLoginTime(long lastLoginTime) { + losePowerFromBeingOffline(); + this.lastLoginTime = lastLoginTime; + this.lastPowerUpdateTime = lastLoginTime; + if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { + this.loginPvpDisabled = true; + } + } + + public boolean isMapAutoUpdating() { + return mapAutoUpdating; + } + + public void setMapAutoUpdating(boolean mapAutoUpdating) { + this.mapAutoUpdating = mapAutoUpdating; + } + + //----------------------------------------------// + // Title, Name, Faction Tag and Chat + //----------------------------------------------// + + // Base: + + public boolean hasLoginPvpDisabled() { + if (!loginPvpDisabled) { + return false; + } + if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) { + this.loginPvpDisabled = false; + return false; + } + return true; + } + + public FLocation getLastStoodAt() { + return this.lastStoodAt; + } + + public void setLastStoodAt(FLocation flocation) { + this.lastStoodAt = flocation; + } + + public String getTitle() { + return this.hasFaction() ? title : TL.NOFACTION_PREFIX.toString(); + } + + public void setTitle(CommandSender sender, String title) { + // Check if the setter has it. + if (sender.hasPermission(Permission.TITLE_COLOR.node)) { + title = ChatColor.translateAlternateColorCodes('&', title); + } + + this.title = title; + } + + // Base concatenations: + + public String getName() { + if (this.name == null) { + // Older versions of FactionsUUID don't save the name, + // so `name` will be null the first time it's retrieved + // after updating + OfflinePlayer offline = Bukkit.getOfflinePlayer(UUID.fromString(getId())); + this.name = offline.getName() != null ? offline.getName() : getId(); + } + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTag() { + return this.hasFaction() ? this.getFaction().getTag() : ""; + } + + // Colored concatenations: + // These are used in information messages + + public String getNameAndSomething(String something) { + String ret = this.role.getPrefix(); + if (something.length() > 0) { + ret += something + " "; + } + ret += this.getName(); + return ret; + } + + public String getNameAndTitle() { + return this.getNameAndSomething(this.getTitle()); + } + + // Chat Tag: + // These are injected into the format of global chat messages. + + public String getNameAndTag() { + return this.getNameAndSomething(this.getTag()); + } + + public String getNameAndTitle(Faction faction) { + return this.getColorTo(faction) + this.getNameAndTitle(); + } + + public String getNameAndTitle(MemoryFPlayer fplayer) { + return this.getColorTo(fplayer) + this.getNameAndTitle(); + } + + public String getChatTag() { + return this.hasFaction() ? String.format(Conf.chatTagFormat, this.getRole().getPrefix() + this.getTag()) : TL.NOFACTION_PREFIX.toString(); + } + + // Colored Chat Tag + public String getChatTag(Faction faction) { + return this.hasFaction() ? this.getRelationTo(faction).getColor() + getChatTag() : ""; + } + + // ------------------------------- + // Relation and relation colors + // ------------------------------- + + public String getChatTag(MemoryFPlayer fplayer) { + return this.hasFaction() ? this.getColorTo(fplayer) + getChatTag() : ""; + } + + public int getKills() { + return isOnline() ? getPlayer().getStatistic(Statistic.PLAYER_KILLS) : this.kills; + } + + public int getDeaths() { + return isOnline() ? getPlayer().getStatistic(Statistic.DEATHS) : this.deaths; + + } + + @Override + public String describeTo(RelationParticipator that, boolean ucfirst) { + return RelationUtil.describeThatToMe(this, that, ucfirst); + } + + @Override + public String describeTo(RelationParticipator that) { + return RelationUtil.describeThatToMe(this, that); + } + + @Override + public Relation getRelationTo(RelationParticipator rp) { + return RelationUtil.getRelationTo(this, rp); + } + + @Override + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { + return RelationUtil.getRelationTo(this, rp, ignorePeaceful); + } + + public Relation getRelationToLocation() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this); + } + + @Override + public ChatColor getColorTo(RelationParticipator rp) { + return RelationUtil.getColorOfThatToMe(this, rp); + } + + //----------------------------------------------// + // Health + //----------------------------------------------// + public void heal(int amnt) { + Player player = this.getPlayer(); + if (player == null) { + return; + } + player.setHealth(player.getHealth() + amnt); + } + + //----------------------------------------------// + // Power + //----------------------------------------------// + public double getPower() { + this.updatePower(); + return this.power; + } + + public void alterPower(double delta) { + this.power += delta; + if (this.power > this.getPowerMax()) { + this.power = this.getPowerMax(); + } else if (this.power < this.getPowerMin()) { + this.power = this.getPowerMin(); + } + } + + public double getPowerMax() { + return Conf.powerPlayerMax + this.powerBoost; + } + + public double getPowerMin() { + return Conf.powerPlayerMin + this.powerBoost; + } + + public int getPowerRounded() { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() { + return (int) Math.round(this.getPowerMax()); + } + + public int getPowerMinRounded() { + return (int) Math.round(this.getPowerMin()); + } + + public void updatePower() { + if (this.isOffline()) { + losePowerFromBeingOffline(); + if (!Conf.powerRegenOffline) { + return; + } + } else if (hasFaction() && getFaction().isPowerFrozen()) { + return; // Don't let power regen if faction power is frozen. + } + + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + Player thisPlayer = this.getPlayer(); + if (thisPlayer != null && thisPlayer.isDead()) { + return; // don't let dead players regain power until they respawn + } + + PowerRegenEvent powerRegenEvent = new PowerRegenEvent(getFaction(), this); + Bukkit.getServer().getPluginManager().callEvent(powerRegenEvent); + + if (!powerRegenEvent.isCancelled()) + this.alterPower(millisPassed * Conf.powerPerMinute / 60000); // millisPerMinute : 60 * 1000 + } + + public void losePowerFromBeingOffline() { + if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + double loss = millisPassed * Conf.powerOfflineLossPerDay / (24 * 60 * 60 * 1000); + if (this.power - loss < Conf.powerOfflineLossLimit) { + loss = this.power; + } + this.alterPower(-loss); + } + } + + public void onDeath() { + this.updatePower(); + this.alterPower(-Conf.powerPerDeath); + if (hasFaction()) { + getFaction().setLastDeath(System.currentTimeMillis()); + } + } + + //----------------------------------------------// + // Territory + //----------------------------------------------// + public boolean isInOwnTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)) == this.getFaction(); + } + + public boolean isInOthersTerritory() { + Faction factionHere = Board.getInstance().getFactionAt(new FLocation(this)); + return factionHere != null && factionHere.isNormal() && factionHere != this.getFaction(); + } + + public boolean isInAllyTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isAlly(); + } + + public boolean isInNeutralTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isNeutral(); + } + + public boolean isInEnemyTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isEnemy(); + } + + public void sendFactionHereMessage(Faction from) { + Faction toShow = Board.getInstance().getFactionAt(getLastStoodAt()); + boolean showChat = true; + if (showInfoBoard(toShow)) { + FScoreboard.get(this).setTemporarySidebar(new FInfoSidebar(toShow)); + showChat = SavageFactions.plugin.getConfig().getBoolean("scoreboard.also-send-chat", true); + } + if (showChat) { + this.sendMessage(SavageFactions.plugin.txt.parse(TL.FACTION_LEAVE.format(from.getTag(this), toShow.getTag(this)))); + } + } + + // ------------------------------- + // Actions + // ------------------------------- + + /** + * Check if the scoreboard should be shown. Simple method to be used by above method. + * + * @param toShow Faction to be shown. + * @return true if should show, otherwise false. + */ + public boolean showInfoBoard(Faction toShow) { + return showScoreboard && !toShow.isWarZone() && !toShow.isWilderness() && !toShow.isSafeZone() && SavageFactions.plugin.getConfig().contains("scoreboard.finfo") && SavageFactions.plugin.getConfig().getBoolean("scoreboard.finfo-enabled", false) && FScoreboard.get(this) != null; + } + + @Override + public boolean showScoreboard() { + return this.showScoreboard; + } + + @Override + public void setShowScoreboard(boolean show) { + this.showScoreboard = show; + } + + public void leave(boolean makePay) { + Faction myFaction = this.getFaction(); + makePay = makePay && Econ.shouldBeUsed() && !this.isAdminBypassing(); + + if (myFaction == null) { + resetFactionData(); + return; + } + + boolean perm = myFaction.isPermanent(); + + if (!perm && this.getRole() == Role.LEADER && myFaction.getFPlayers().size() > 1) { + msg(TL.LEAVE_PASSADMIN); + return; + } + + if (!Conf.canLeaveWithNegativePower && this.getPower() < 0) { + msg(TL.LEAVE_NEGATIVEPOWER); + return; + } + + // if economy is enabled and they're not on the bypass list, make sure they can pay + if (makePay && !Econ.hasAtLeast(this, Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString())) { + return; + } + + FPlayerLeaveEvent leaveEvent = new FPlayerLeaveEvent(this, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.LEAVE); + Bukkit.getServer().getPluginManager().callEvent(leaveEvent); + if (leaveEvent.isCancelled()) { + return; + } + + // then make 'em pay (if applicable) + if (makePay && !Econ.modifyMoney(this, -Conf.econCostLeave, TL.LEAVE_TOLEAVE.toString(), TL.LEAVE_FORLEAVE.toString())) { + return; + } + + // Am I the last one in the faction? + if (myFaction.getFPlayers().size() == 1) { + // Transfer all money + if (Econ.shouldBeUsed()) { + Econ.transferMoney(this, myFaction, this, Econ.getBalance(myFaction.getAccountId())); + } + } + + if (myFaction.isNormal()) { + for (FPlayer fplayer : myFaction.getFPlayersWhereOnline(true)) { + fplayer.msg(TL.LEAVE_LEFT, this.describeTo(fplayer, true), myFaction.describeTo(fplayer)); + } + + if (Conf.logFactionLeave) { + SavageFactions.plugin.log(TL.LEAVE_LEFT.format(this.getName(), myFaction.getTag())); + } + } + + myFaction.removeAnnouncements(this); + this.resetFactionData(); + + if (myFaction.isNormal() && !perm && myFaction.getFPlayers().isEmpty()) { + // Remove this faction + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg(TL.LEAVE_DISBANDED, myFaction.describeTo(fplayer, true)); + } + + FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), PlayerDisbandReason.LEAVE); + Bukkit.getPluginManager().callEvent(disbandEvent); + + Factions.getInstance().removeFaction(myFaction.getId()); + if (Conf.logFactionDisband) { + SavageFactions.plugin.log(TL.LEAVE_DISBANDEDLOG.format(myFaction.getTag(), myFaction.getId(), this.getName())); + } + } + } + + public boolean canClaimForFaction(Faction forFaction) { + return this.isAdminBypassing() || !forFaction.isWilderness() && (forFaction == this.getFaction() && this.getRole().isAtLeast(Role.MODERATOR)) || (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) || (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())); + } + + public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure) { + return canClaimForFactionAtLocation(forFaction, new FLocation(location), notifyFailure); + } + + public boolean canClaimForFactionAtLocation(Faction forFaction, FLocation flocation, boolean notifyFailure) { + String error = null; + Faction myFaction = getFaction(); + Faction currentFaction = Board.getInstance().getFactionAt(flocation); + int ownedLand = forFaction.getLandRounded(); + int factionBuffer = SavageFactions.plugin.getConfig().getInt("hcf.buffer-zone", 0); + int worldBuffer = SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0); + + if (Conf.worldGuardChecking && Worldguard.checkForRegionsInChunk(flocation)) { + // Checks for WorldGuard regions in the chunk attempting to be claimed + error = SavageFactions.plugin.txt.parse(TL.CLAIM_PROTECTED.toString()); + } else if (flocation.isOutsideWorldBorder(SavageFactions.plugin.getConfig().getInt("world-border.buffer", 0))) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); + } else if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_DISABLED.toString()); + } else if (this.isAdminBypassing()) { + return true; + } else if (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) { + return true; + } else if (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())) { + return true; + } else if (currentFaction.getAccess(this, PermissableAction.TERRITORY) == Access.ALLOW) { + return true; + } else if (myFaction != forFaction) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_CANTCLAIM.toString(), forFaction.describeTo(this)); + } else if (forFaction == currentFaction) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALREADYOWN.toString(), forFaction.describeTo(this, true)); + } else if (this.getRole().value < Role.MODERATOR.value) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_MUSTBE.toString(), Role.MODERATOR.getTranslation()); + } else if (forFaction.getFPlayers().size() < Conf.claimsRequireMinFactionMembers) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_MEMBERS.toString(), Conf.claimsRequireMinFactionMembers); + } else if (currentFaction.isSafeZone()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_SAFEZONE.toString()); + } else if (currentFaction.isWarZone()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_WARZONE.toString()); + } else if (SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true) && ownedLand >= forFaction.getPowerRounded()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_POWER.toString()); + } else if (Conf.claimedLandsMax != 0 && ownedLand >= Conf.claimedLandsMax && forFaction.isNormal()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_LIMIT.toString()); + } else if (currentFaction.getRelationTo(forFaction) == Relation.ALLY) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_ALLY.toString()); + } else if (Conf.claimsMustBeConnected && !this.isAdminBypassing() && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, myFaction) && (!Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction || !currentFaction.isNormal())) { + if (Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_CONTIGIOUS.toString()); + } else { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_FACTIONCONTIGUOUS.toString()); + } + } else if (factionBuffer > 0 && Board.getInstance().hasFactionWithin(flocation, myFaction, factionBuffer)) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_TOOCLOSETOOTHERFACTION.format(factionBuffer)); + } else if (flocation.isOutsideWorldBorder(worldBuffer)) { + if (worldBuffer > 0) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEBORDERBUFFER.format(worldBuffer)); + } else { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OUTSIDEWORLDBORDER.toString()); + } + } else if (currentFaction.isNormal()) { + if (myFaction.isPeaceful()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFUL.toString(), currentFaction.getTag(this)); + } else if (currentFaction.isPeaceful()) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_PEACEFULTARGET.toString(), currentFaction.getTag(this)); + } else if (!currentFaction.hasLandInflation()) { + // TODO more messages WARN current faction most importantly + error = SavageFactions.plugin.txt.parse(TL.CLAIM_THISISSPARTA.toString(), currentFaction.getTag(this)); + } else if (currentFaction.hasLandInflation() && !SavageFactions.plugin.getConfig().getBoolean("hcf.allow-overclaim", true)) { + // deny over claim when it normally would be allowed. + error = SavageFactions.plugin.txt.parse(TL.CLAIM_OVERCLAIM_DISABLED.toString()); + } else if (!Board.getInstance().isBorderLocation(flocation)) { + error = SavageFactions.plugin.txt.parse(TL.CLAIM_BORDER.toString()); + } + } + // TODO: Add more else if statements. + + if (notifyFailure && error != null) { + msg(error); + } + return error == null; + } + + public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure) { + return attemptClaim(forFaction, new FLocation(location), notifyFailure); + } + + public boolean shouldBeSaved() { + return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); + } + + public void msg(String str, Object... args) { + this.sendMessage(SavageFactions.plugin.txt.parse(str, args)); + } + + public void msg(TL translation, Object... args) { + this.msg(translation.toString(), args); + } + + public Player getPlayer() { + return Bukkit.getPlayer(UUID.fromString(this.getId())); + } + + public boolean isOnline() { + return this.getPlayer() != null; + } + + // make sure target player should be able to detect that this player is online + public boolean isOnlineAndVisibleTo(Player player) { + Player target = this.getPlayer(); + return target != null && player.canSee(target); + } + + public boolean isOffline() { + return !isOnline(); + } + + public boolean isFlying() { + return isFlying; + } + + public void setFlying(boolean fly) { + setFFlying(fly, false); + } + + public void setFFlying(boolean fly, boolean damage) { + Player player = getPlayer(); + if (player != null) { + player.setAllowFlight(fly); + player.setFlying(fly); + } + + if (!damage) { + msg(TL.COMMAND_FLY_CHANGE, fly ? "enabled" : "disabled"); + if (!fly) { + sendMessage(TL.COMMAND_FLY_COOLDOWN.toString().replace("{amount}", SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3) + "")); + } + + } else { + msg(TL.COMMAND_FLY_DAMAGE); + } + + // If leaving fly mode, don't let them take fall damage for x seconds. + if (!fly) { + int cooldown = SavageFactions.plugin.getConfig().getInt("fly-falldamage-cooldown", 3); + CmdFly.flyMap.remove(player.getName()); + + // If the value is 0 or lower, make them take fall damage. + // Otherwise, start a timer and have this cancel after a few seconds. + // Short task so we're just doing it in method. Not clean but eh. + if (cooldown > 0) { + setTakeFallDamage(false); + Bukkit.getScheduler().runTaskLater(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + setTakeFallDamage(true); + } + }, 20L * cooldown); + } + } + + isFlying = fly; + } + + public boolean isInVault() { + return inVault; + } + + public void setInVault(boolean status) { + inVault = status; + } + + public boolean canFlyAtLocation() { + return canFlyAtLocation(lastStoodAt); + } + + public boolean canFlyAtLocation(FLocation location) { + Faction faction = Board.getInstance().getFactionAt(location); + if ((faction == getFaction() && getRole() == Role.LEADER) || isAdminBypassing) { + return true; + } + + Access access = faction.getAccess(this, PermissableAction.FLY); + return access == null || access == Access.UNDEFINED || access == Access.ALLOW; + } + + public boolean shouldTakeFallDamage() { + return this.shouldTakeFallDamage; + } + + public void setTakeFallDamage(boolean fallDamage) { + this.shouldTakeFallDamage = fallDamage; + } + + public boolean isEnteringPassword() { + return enteringPassword; + } + + public void setEnteringPassword(boolean toggle, String warp) { + enteringPassword = toggle; + enteringPasswordWarp = warp; + } + + // -------------------------------------------- // + // Message Sending Helpers + // -------------------------------------------- // + + public String getEnteringWarp() { + return enteringPasswordWarp; + } + + public void sendMessage(String msg) { + if (msg.contains("{null}")) { + return; // user wants this message to not send + } + if (msg.contains("/n/")) { + for (String s : msg.split("/n/")) { + sendMessage(s); + } + return; + } + Player player = this.getPlayer(); + if (player == null) { + return; + } + player.sendMessage(msg); + } + + public void sendMessage(List msgs) { + for (String msg : msgs) { + this.sendMessage(msg); + } + } + + public void sendFancyMessage(FancyMessage message) { + Player player = getPlayer(); + if (player == null || !player.isOnGround()) { + return; + } + + message.send(player); + } + + public void sendFancyMessage(List messages) { + Player player = getPlayer(); + if (player == null) { + return; + } + + for (FancyMessage msg : messages) { + msg.send(player); + } + } + + public int getMapHeight() { + if (this.mapHeight < 1) { + this.mapHeight = Conf.mapHeight; + } + + return this.mapHeight; + } + + public void setMapHeight(int height) { + this.mapHeight = height > (Conf.mapHeight * 2) ? (Conf.mapHeight * 2) : height; + } + + public String getNameAndTitle(FPlayer fplayer) { + return this.getColorTo(fplayer) + this.getNameAndTitle(); + } + + @Override + public String getChatTag(FPlayer fplayer) { + return this.hasFaction() ? this.getRelationTo(fplayer).getColor() + getChatTag() : ""; + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public abstract void remove(); + + @Override + public void clearWarmup() { + if (warmup != null) { + Bukkit.getScheduler().cancelTask(warmupTask); + this.stopWarmup(); + } + } + + @Override + public void stopWarmup() { + warmup = null; + } + + @Override + public boolean isWarmingUp() { + return warmup != null; + } + + @Override + public WarmUpUtil.Warmup getWarmupType() { + return warmup; + } + + @Override + public void addWarmup(WarmUpUtil.Warmup warmup, int taskId) { + if (this.warmup != null) { + this.clearWarmup(); + } + this.warmup = warmup; + this.warmupTask = taskId; + } + + @Override + public boolean checkIfNearbyEnemies() { + Player me = this.getPlayer(); + int radius = Conf.stealthFlyCheckRadius; + for (Entity e : me.getNearbyEntities(radius, 255, radius)) { + if (e == null) { + continue; + } + if (e instanceof Player) { + Player eplayer = (((Player) e).getPlayer()); + if (eplayer == null) { + continue; + } + FPlayer efplayer = FPlayers.getInstance().getByPlayer(eplayer); + if (efplayer == null) { + continue; + } + if (efplayer != null && this.getRelationTo(efplayer).equals(Relation.ENEMY) && !efplayer.isStealthEnabled()) { + setFlying(false); + msg(TL.COMMAND_FLY_ENEMY_NEAR); + Bukkit.getServer().getPluginManager().callEvent(new FPlayerStoppedFlying(this)); + return true; + } + } + } + return false; + } + + @Override + public Boolean canflyinWilderness() { + return getPlayer().hasPermission("factions.fly.wilderness"); + } + + @Override + public Boolean canflyinWarzone() { + return getPlayer().hasPermission("factions.fly.warzone"); + + } + + @Override + public Boolean canflyinSafezone() { + return getPlayer().hasPermission("factions.fly.safezone"); + + } + + @Override + public Boolean canflyinEnemy() { + return getPlayer().hasPermission("factions.fly.enemy"); + + } + + @Override + public Boolean canflyinAlly() { + return getPlayer().hasPermission("factions.fly.ally"); + + } + + @Override + public Boolean canflyinTruce() { + return getPlayer().hasPermission("factions.fly.truce"); + + } + + @Override + public Boolean canflyinNeutral() { + return getPlayer().hasPermission("factions.fly.neutral"); + + } + + @Override + public boolean isInspectMode() { + return inspectMode; + } + + @Override + public void setInspectMode(boolean status) { + inspectMode = status; + } + + public boolean attemptClaim(Faction forFaction, FLocation flocation, boolean notifyFailure) { + // notifyFailure is false if called by auto-claim; no need to notify on every failure for it + // return value is false on failure, true on success + + Faction currentFaction = Board.getInstance().getFactionAt(flocation); + int ownedLand = forFaction.getLandRounded(); + + if (!this.canClaimForFactionAtLocation(forFaction, flocation, notifyFailure)) { + return false; + } + + // if economy is enabled and they're not on the bypass list, make sure they can pay + boolean mustPay = Econ.shouldBeUsed() && !this.isAdminBypassing() && !forFaction.isSafeZone() && !forFaction.isWarZone(); + double cost = 0.0; + EconomyParticipator payee = null; + if (mustPay) { + cost = Econ.calculateClaimCost(ownedLand, currentFaction.isNormal()); + + + if (Conf.econClaimUnconnectedFee != 0.0 && forFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, forFaction)) { + cost += Conf.econClaimUnconnectedFee; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts && this.hasFaction()) { + payee = this.getFaction(); + } else { + payee = this; + } + + if (!Econ.hasAtLeast(payee, cost, TL.CLAIM_TOCLAIM.toString())) { + return false; + } + } + + LandClaimEvent claimEvent = new LandClaimEvent(flocation, forFaction, this); + Bukkit.getPluginManager().callEvent(claimEvent); + if (claimEvent.isCancelled()) { + return false; + } + + // then make 'em pay (if applicable) + if (mustPay && !Econ.modifyMoney(payee, -cost, TL.CLAIM_TOCLAIM.toString(), TL.CLAIM_FORCLAIM.toString())) { + return false; + } + + // Was an over claim + if (currentFaction.isNormal() && currentFaction.hasLandInflation()) { + // Give them money for over claiming. + Econ.modifyMoney(payee, Conf.econOverclaimRewardMultiplier, TL.CLAIM_TOOVERCLAIM.toString(), TL.CLAIM_FOROVERCLAIM.toString()); + } + + // announce success + Set informTheseFPlayers = new HashSet<>(); + informTheseFPlayers.add(this); + informTheseFPlayers.addAll(forFaction.getFPlayersWhereOnline(true)); + for (FPlayer fp : informTheseFPlayers) { + fp.msg(TL.CLAIM_CLAIMED, this.describeTo(fp, true), forFaction.describeTo(fp), currentFaction.describeTo(fp)); + } + + Board.getInstance().setFactionAt(forFaction, flocation); + + if (Conf.logLandClaims) { + SavageFactions.plugin.log(TL.CLAIM_CLAIMEDLOG.toString(), this.getName(), flocation.getCoordString(), forFaction.getTag()); + } + + return true; + } + + + @Override + public String getRolePrefix() { + + switch (getRole()) { + case RECRUIT: + return Conf.prefixRecruit; + case NORMAL: + return Conf.prefixNormal; + case MODERATOR: + return Conf.prefixMod; + case COLEADER: + return Conf.prefixCoLeader; + case LEADER: + return Conf.prefixLeader; + } + + return null; + } + + @Override + public boolean hasMoney(int amt) { + Economy econ = SavageFactions.plugin.getEcon(); + if (econ.getBalance(getPlayer()) >= amt) { + return true; + } else { + getPlayer().closeInventory(); + msg(TL.GENERIC_NOTENOUGHMONEY); + return false; + } + } + + @Override + public void takeMoney(int amt) { + if (hasMoney(amt)) { + Economy econ = SavageFactions.plugin.getEcon(); + econ.withdrawPlayer(getPlayer(), amt); + sendMessage(TL.GENERIC_MONEYTAKE.toString().replace("{amount}", amt + "")); + } + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java index b120e028..02138532 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java @@ -12,55 +12,55 @@ import java.util.*; import java.util.concurrent.ConcurrentSkipListMap; public abstract class MemoryFPlayers extends FPlayers { - public Map fPlayers = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER); + public Map fPlayers = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER); - public void clean() { - for (FPlayer fplayer : this.fPlayers.values()) { - if (!Factions.getInstance().isValidFactionId(fplayer.getFactionId())) { - SavageFactions.plugin.log("Reset faction data (invalid faction:" + fplayer.getFactionId() + ") for player " + fplayer.getName()); - fplayer.resetFactionData(false); - } - } - } + public void clean() { + for (FPlayer fplayer : this.fPlayers.values()) { + if (!Factions.getInstance().isValidFactionId(fplayer.getFactionId())) { + SavageFactions.plugin.log("Reset faction data (invalid faction:" + fplayer.getFactionId() + ") for player " + fplayer.getName()); + fplayer.resetFactionData(false); + } + } + } - public Collection getOnlinePlayers() { - Set entities = new HashSet<>(); - for (Player player : Bukkit.getServer().getOnlinePlayers()) { - entities.add(this.getByPlayer(player)); - } - return entities; - } + public Collection getOnlinePlayers() { + Set entities = new HashSet<>(); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + entities.add(this.getByPlayer(player)); + } + return entities; + } - @Override - public FPlayer getByPlayer(Player player) { - return getById(player.getUniqueId().toString()); - } + @Override + public FPlayer getByPlayer(Player player) { + return getById(player.getUniqueId().toString()); + } - @Override - public List getAllFPlayers() { - return new ArrayList<>(fPlayers.values()); - } + @Override + public List getAllFPlayers() { + return new ArrayList<>(fPlayers.values()); + } - @Override - public abstract void forceSave(); + @Override + public abstract void forceSave(); - public abstract void load(); + public abstract void load(); - @Override - public FPlayer getByOfflinePlayer(OfflinePlayer player) { - return getById(player.getUniqueId().toString()); - } + @Override + public FPlayer getByOfflinePlayer(OfflinePlayer player) { + return getById(player.getUniqueId().toString()); + } - @Override - public FPlayer getById(String id) { - FPlayer player = fPlayers.get(id); - if (player == null) { - player = generateFPlayer(id); - } - return player; - } + @Override + public FPlayer getById(String id) { + FPlayer player = fPlayers.get(id); + if (player == null) { + player = generateFPlayer(id); + } + return player; + } - public abstract FPlayer generateFPlayer(String id); + public abstract FPlayer generateFPlayer(String id); - public abstract void convertFrom(MemoryFPlayers old); + public abstract void convertFrom(MemoryFPlayers old); } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java index 306826d4..c66bce5f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java @@ -34,1211 +34,1211 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; public abstract class MemoryFaction implements Faction, EconomyParticipator { - public HashMap rules = new HashMap(); - public int tnt; - public Location checkpoint; - public LazyLocation vault; - public HashMap upgrades = new HashMap<>(); - protected String id = null; - protected boolean peacefulExplosionsEnabled; - protected boolean permanent; - protected String tag; - protected String description; - protected boolean open; - protected boolean peaceful; - protected Integer permanentPower; - protected LazyLocation home; - protected long foundedDate; - protected transient long lastPlayerLoggedOffTime; - protected double money; - protected double powerBoost; - protected String paypal; - protected Map relationWish = new HashMap<>(); - protected Map> claimOwnership = new ConcurrentHashMap<>(); - protected transient Set fplayers = new HashSet<>(); - protected Set invites = new HashSet<>(); - protected HashMap> announcements = new HashMap<>(); - protected ConcurrentHashMap warps = new ConcurrentHashMap<>(); - protected ConcurrentHashMap warpPasswords = new ConcurrentHashMap<>(); - protected int maxVaults; - protected Role defaultRole; - protected Map> permissions = new HashMap<>(); - protected Set bans = new HashSet<>(); - protected String player; - Inventory chest; - Map bannerSerialized; - private long lastDeath; - - // -------------------------------------------- // - // Construct - // -------------------------------------------- // - public MemoryFaction() { - } - - public MemoryFaction(String id) { - this.id = id; - this.open = Conf.newFactionsDefaultOpen; - this.tag = "???"; - this.description = TL.GENERIC_DEFAULTDESCRIPTION.toString(); - this.lastPlayerLoggedOffTime = 0; - this.peaceful = false; - this.peacefulExplosionsEnabled = false; - this.permanent = false; - this.money = 0.0; - this.powerBoost = 0.0; - this.foundedDate = System.currentTimeMillis(); - this.maxVaults = Conf.defaultMaxVaults; - this.defaultRole = Role.RECRUIT; - - resetPerms(); // Reset on new Faction so it has default values. - } - - public MemoryFaction(MemoryFaction old) { - id = old.id; - peacefulExplosionsEnabled = old.peacefulExplosionsEnabled; - permanent = old.permanent; - tag = old.tag; - description = old.description; - open = old.open; - foundedDate = old.foundedDate; - peaceful = old.peaceful; - permanentPower = old.permanentPower; - home = old.home; - lastPlayerLoggedOffTime = old.lastPlayerLoggedOffTime; - money = old.money; - powerBoost = old.powerBoost; - relationWish = old.relationWish; - claimOwnership = old.claimOwnership; - fplayers = new HashSet<>(); - invites = old.invites; - announcements = old.announcements; - this.defaultRole = Role.NORMAL; - - resetPerms(); // Reset on new Faction so it has default values. - } - - public HashMap> getAnnouncements() { - return this.announcements; - } - - public void addAnnouncement(FPlayer fPlayer, String msg) { - List list = announcements.containsKey(fPlayer.getId()) ? announcements.get(fPlayer.getId()) : new ArrayList(); - list.add(msg); - announcements.put(fPlayer.getId(), list); - } - - public void sendUnreadAnnouncements(FPlayer fPlayer) { - if (!announcements.containsKey(fPlayer.getId())) { - return; - } - fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_TOP); - for (String s : announcements.get(fPlayer.getPlayer().getUniqueId().toString())) { - fPlayer.sendMessage(s); - } - fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_BOTTOM); - announcements.remove(fPlayer.getId()); - } - - public void removeAnnouncements(FPlayer fPlayer) { - announcements.remove(fPlayer.getId()); - } - - public ConcurrentHashMap getWarps() { - return this.warps; - } - - public LazyLocation getWarp(String name) { - return this.warps.get(name); - } - - public void setWarp(String name, LazyLocation loc) { - this.warps.put(name, loc); - } - - public boolean isWarp(String name) { - return this.warps.containsKey(name); - } - - public boolean removeWarp(String name) { - warpPasswords.remove(name); // remove password no matter what. - return warps.remove(name) != null; - } - - public boolean isWarpPassword(String warp, String password) { - return hasWarpPassword(warp) && warpPasswords.get(warp.toLowerCase()).equals(password); - } - - public String getPaypal() { - return this.paypal; - } - - public void paypalSet(String paypal) { - this.paypal = paypal; - } - - public boolean hasWarpPassword(String warp) { - return warpPasswords.containsKey(warp.toLowerCase()); - } - - public void setWarpPassword(String warp, String password) { - warpPasswords.put(warp.toLowerCase(), password); - } - - public void clearWarps() { - warps.clear(); - } - - public int getMaxVaults() { - return this.maxVaults; - } - - public void setMaxVaults(int value) { - this.maxVaults = value; - } - - public String getFocused() { - return this.player; - } - - public void setFocused(String fp) { - this.player = fp; - } - - public Set getInvites() { - return invites; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public void invite(FPlayer fplayer) { - this.invites.add(fplayer.getId()); - } - - public void deinvite(FPlayer fplayer) { - this.invites.remove(fplayer.getId()); - } - - public boolean isInvited(FPlayer fplayer) { - return this.invites.contains(fplayer.getId()); - } - - public void ban(FPlayer target, FPlayer banner) { - BanInfo info = new BanInfo(banner.getId(), target.getId(), System.currentTimeMillis()); - this.bans.add(info); - } - - public void unban(FPlayer player) { - Iterator iter = bans.iterator(); - while (iter.hasNext()) { - if (iter.next().getBanned().equalsIgnoreCase(player.getId())) { - iter.remove(); - } - } - } - - @Override - public void disband(Player disbander) { - disband(disbander, PlayerDisbandReason.PLUGIN); - } - - @Override - public void disband(Player disbander, PlayerDisbandReason reason) { - - boolean disbanderIsConsole = disbander == null; - FPlayer fdisbander = FPlayers.getInstance().getByOfflinePlayer(disbander); - - FactionDisbandEvent disbandEvent = new FactionDisbandEvent(disbander, this.getId(), reason); - Bukkit.getServer().getPluginManager().callEvent(disbandEvent); - if (disbandEvent.isCancelled()) { - return; - } - - // Send FPlayerLeaveEvent for each player in the faction - for (FPlayer fplayer : this.getFPlayers()) { - Bukkit.getServer().getPluginManager().callEvent(new FPlayerLeaveEvent(fplayer, this, FPlayerLeaveEvent.PlayerLeaveReason.DISBAND)); - } - - if (Conf.logFactionDisband) { - //TODO: Format this correctly and translate. - SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") was disbanded by " + (disbanderIsConsole ? "console command" : fdisbander.getName()) + "."); - } - - if (Econ.shouldBeUsed() && !disbanderIsConsole) { - //Give all the faction's money to the disbander - double amount = Econ.getBalance(this.getAccountId()); - Econ.transferMoney(fdisbander, this, fdisbander, amount, false); - - if (amount > 0.0) { - String amountString = Econ.moneyString(amount); - msg(TL.COMMAND_DISBAND_HOLDINGS, amountString); - //TODO: Format this correctly and translate - SavageFactions.plugin.log(fdisbander.getName() + " has been given bank holdings of " + amountString + " from disbanding " + this.getTag() + "."); - } - } - - Factions.getInstance().removeFaction(this.getId()); - FTeamWrapper.applyUpdates(this); - } - - public boolean isBanned(FPlayer player) { - for (BanInfo info : bans) { - if (info.getBanned().equalsIgnoreCase(player.getId())) { - return true; - } - } - - return false; - } - - public Set getBannedPlayers() { - return this.bans; - } - - public String getRule(int index) { - if (rules.size() == 0) return null; - return rules.get(index); - } - - public HashMap getRulesMap() { - return rules; - } - - public void setRule(int index, String rule) { - rules.put(index, rule); - } - - public void removeRule(int index) { - HashMap newRule = rules; - newRule.remove(index); - rules = newRule; - } - - public void addTnt(int amt) { - tnt += amt; - } - - public void takeTnt(int amt) { - tnt -= amt; - } - - public int getTnt() { - return tnt; - } - - - public Location getVault() { - if (vault == null) { - return null; - } - return vault.getLocation(); - } - - public void setVault(Location vaultLocation) { - if (vaultLocation == null) { - vault = null; - return; - } - LazyLocation newlocation = new LazyLocation(vaultLocation); - vault = newlocation; - } - - public int getUpgrade(Upgrade upgrade) { - if (upgrades.keySet().contains(upgrade.toString())) { - return upgrades.get(upgrade.toString()); - } - return 0; - } - - @Override - public Inventory getChestInventory() { - if (chest != null) { - return chest; - } else { - int level = getUpgrade(Upgrade.CHEST); - int size = 9; - if (level == 1) { - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1") * 9; - } else if (level == 2) { - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2") * 9; - } else if (level == 3) { - size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3") * 9; - } - - chest = Bukkit.createInventory(null, size, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); - return chest; - - } - - } - - @Override - public void setChestSize(int chestSize) { - ItemStack[] contents = this.getChestInventory().getContents(); - chest = Bukkit.createInventory(null, chestSize, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); - chest.setContents(contents); - } - - - @Override - public void setBannerPattern(ItemStack banner) { - bannerSerialized = banner.serialize(); - } - - @Override - public ItemStack getBanner() { - if (bannerSerialized == null) { - return null; - } - return ItemStack.deserialize(bannerSerialized); - } - - public void setUpgrade(Upgrade upgrade, int level) { - upgrades.put(upgrade.toString(), level); - } - - public Location getCheckpoint() { - return checkpoint; - } - - public void setCheckpoint(Location location) { - checkpoint = location; - } - - public void clearRules() { - rules.clear(); - } - - public void addRule(String rule) { - rules.put(rules.size(), rule); - } - - public boolean getOpen() { - return open; - } - - public void setOpen(boolean isOpen) { - open = isOpen; - } - - public boolean isPeaceful() { - return this.peaceful; - } - - public void setPeaceful(boolean isPeaceful) { - this.peaceful = isPeaceful; - } - - public boolean getPeacefulExplosionsEnabled() { - return this.peacefulExplosionsEnabled; - } - - public void setPeacefulExplosionsEnabled(boolean val) { - peacefulExplosionsEnabled = val; - } - - public boolean noExplosionsInTerritory() { - return this.peaceful && !peacefulExplosionsEnabled; - } - - public boolean isPermanent() { - return permanent || !this.isNormal(); - } - - public void setPermanent(boolean isPermanent) { - permanent = isPermanent; - } - - public String getTag() { - return this.tag; - } - - public void setTag(String str) { - if (Conf.factionTagForceUpperCase) { - str = str.toUpperCase(); - } - this.tag = str; - } - - public String getTag(String prefix) { - return prefix + this.tag; - } - - public String getTag(Faction otherFaction) { - if (otherFaction == null) { - return getTag(); - } - return this.getTag(this.getColorTo(otherFaction).toString()); - } - - public String getTag(FPlayer otherFplayer) { - if (otherFplayer == null) { - return getTag(); - } - return this.getTag(this.getColorTo(otherFplayer).toString()); - } - - public String getComparisonTag() { - return MiscUtil.getComparisonString(this.tag); - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String value) { - this.description = value; - } - - public boolean hasHome() { - return this.getHome() != null; - } - - public Location getHome() { - confirmValidHome(); - return (this.home != null) ? this.home.getLocation() : null; - } - - public void setHome(Location home) { - this.home = new LazyLocation(home); - } - - public long getFoundedDate() { - if (this.foundedDate == 0) { - setFoundedDate(System.currentTimeMillis()); - } - return this.foundedDate; - } - - public void setFoundedDate(long newDate) { - this.foundedDate = newDate; - } - - public void confirmValidHome() { - if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getInstance().getFactionAt(new FLocation(this.home.getLocation())) == this)) { - return; - } - - msg("Your faction home has been un-set since it is no longer in your territory."); - this.home = null; - } - - public String getAccountId() { - String aid = "faction-" + this.getId(); - - // We need to override the default money given to players. - if (!Econ.hasAccount(aid)) { - Econ.setBalance(aid, 0); - } - - return aid; - } - - public Integer getPermanentPower() { - return this.permanentPower; - } - - public void setPermanentPower(Integer permanentPower) { - this.permanentPower = permanentPower; - } - - public boolean hasPermanentPower() { - return this.permanentPower != null; - } - - public double getPowerBoost() { - return this.powerBoost; - } - - public void setPowerBoost(double powerBoost) { - this.powerBoost = powerBoost; - } - - public boolean isPowerFrozen() { - int freezeSeconds = SavageFactions.plugin.getConfig().getInt("hcf.powerfreeze", 0); - return freezeSeconds != 0 && System.currentTimeMillis() - lastDeath < freezeSeconds * 1000; - - } - - public long getLastDeath() { - return this.lastDeath; - } - - // -------------------------------------------- // - // F Permissions stuff - // -------------------------------------------- // - - public void setLastDeath(long time) { - this.lastDeath = time; - } - - public int getKills() { - int kills = 0; - for (FPlayer fp : getFPlayers()) { - kills += fp.getKills(); - } - - return kills; - } - - public int getDeaths() { - int deaths = 0; - for (FPlayer fp : getFPlayers()) { - deaths += fp.getDeaths(); - } - - return deaths; - } - - public Access getAccess(Permissable permissable, PermissableAction permissableAction) { - if (permissable == null || permissableAction == null) { - return Access.UNDEFINED; - } - - Map accessMap = permissions.get(permissable); - if (accessMap != null && accessMap.containsKey(permissableAction)) { - return accessMap.get(permissableAction); - } - - return Access.UNDEFINED; - } - - /** - * Get the Access of a player. Will use player's Role if they are a faction member. Otherwise, uses their Relation. - * - * @param player - * @param permissableAction - * @return - */ - public Access getAccess(FPlayer player, PermissableAction permissableAction) { - if (player == null || permissableAction == null) { - return Access.UNDEFINED; - } - - Permissable perm; - - if (player.getFaction() == this) { - perm = player.getRole(); - } else { - perm = player.getFaction().getRelationTo(this); - } - - Map accessMap = permissions.get(perm); - if (accessMap != null && accessMap.containsKey(permissableAction)) { - return accessMap.get(permissableAction); - } - - return Access.UNDEFINED; - } - - public void setPermission(Permissable permissable, PermissableAction permissableAction, Access access) { - Map accessMap = permissions.get(permissable); - if (accessMap == null) { - accessMap = new HashMap<>(); - } - - accessMap.put(permissableAction, access); - } - - public void resetPerms() { - SavageFactions.plugin.log(Level.WARNING, "Resetting permissions for Faction: " + tag); - - permissions.clear(); - - // First populate a map with undefined as the permission for each action. - Map freshMap = new HashMap<>(); - for (PermissableAction permissableAction : PermissableAction.values()) { - freshMap.put(permissableAction, Access.UNDEFINED); - } - - // Put the map in there for each relation. - for (Relation relation : Relation.values()) { - if (relation != Relation.MEMBER) { - permissions.put(relation, new HashMap<>(freshMap)); - } - } - - // And each role. - for (Role role : Role.values()) { - if (role != Role.LEADER) { - permissions.put(role, new HashMap<>(freshMap)); - } - } - } - - public void setDefaultPerms() { - if (!Conf.useCustomDefaultPermissions) return; - Map defaultMap = new HashMap<>(); - for (PermissableAction permissableAction : PermissableAction.values()) { - defaultMap.put(permissableAction, Access.UNDEFINED); - } - // Put the map in there for each relation. - for (Relation relation : Relation.values()) { - if (relation != Relation.MEMBER) { - if (!Conf.defaultFactionPermissions.containsKey(relation.nicename)) - permissions.put(relation, new HashMap<>(defaultMap)); - else - permissions.put(relation, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(relation.nicename))); - } - } - - // And each role. - for (Role role : Role.values()) { - if (role != Role.LEADER) { - if (!Conf.defaultFactionPermissions.containsKey(role.nicename)) - permissions.put(role, new HashMap<>(defaultMap)); - else - permissions.put(role, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(role.nicename))); - } - } - } - - /** - * Read only map of Permissions. - * - * @return - */ - public Map> getPermissions() { - return Collections.unmodifiableMap(permissions); - } - - public Role getDefaultRole() { - return this.defaultRole; - } - - public void setDefaultRole(Role role) { - this.defaultRole = role; - } - - // -------------------------------------------- // - // Extra Getters And Setters - // -------------------------------------------- // - public boolean noPvPInTerritory() { - return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); - } - - public boolean noMonstersInTerritory() { - return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); - } - - // ------------------------------- - // Understand the types - // ------------------------------- - - public boolean isNormal() { - return !(this.isWilderness() || this.isSafeZone() || this.isWarZone()); - } - - public boolean isNone() { - return this.getId().equals("0"); - } - - public boolean isWilderness() { - return this.getId().equals("0"); - } - - public boolean isSafeZone() { - return this.getId().equals("-1"); - } - - public boolean isWarZone() { - return this.getId().equals("-2"); - } - - public boolean isPlayerFreeType() { - return this.isSafeZone() || this.isWarZone(); - } - - // ------------------------------- - // Relation and relation colors - // ------------------------------- - - @Override - public String describeTo(RelationParticipator that, boolean ucfirst) { - return RelationUtil.describeThatToMe(this, that, ucfirst); - } - - @Override - public String describeTo(RelationParticipator that) { - return RelationUtil.describeThatToMe(this, that); - } - - @Override - public Relation getRelationTo(RelationParticipator rp) { - return RelationUtil.getRelationTo(this, rp); - } - - @Override - public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { - return RelationUtil.getRelationTo(this, rp, ignorePeaceful); - } - - @Override - public ChatColor getColorTo(RelationParticipator rp) { - return RelationUtil.getColorOfThatToMe(this, rp); - } - - public Relation getRelationWish(Faction otherFaction) { - if (this.relationWish.containsKey(otherFaction.getId())) { - return this.relationWish.get(otherFaction.getId()); - } - return Relation.fromString(SavageFactions.plugin.getConfig().getString("default-relation", "neutral")); // Always default to old behavior. - } - - public void setRelationWish(Faction otherFaction, Relation relation) { - if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)) { - this.relationWish.remove(otherFaction.getId()); - } else { - this.relationWish.put(otherFaction.getId(), relation); - } - } - - public int getRelationCount(Relation relation) { - int count = 0; - for (Faction faction : Factions.getInstance().getAllFactions()) { - if (faction.getRelationTo(this) == relation) { - count++; - } - } - return count; - } - - // ----------------------------------------------// - // Power - // ----------------------------------------------// - public double getPower() { - if (this.hasPermanentPower()) { - return this.getPermanentPower(); - } - - double ret = 0; - for (FPlayer fplayer : fplayers) { - ret += fplayer.getPower(); - } - if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { - ret = Conf.powerFactionMax; - } - return ret + this.powerBoost; - } - - public double getPowerMax() { - if (this.hasPermanentPower()) { - return this.getPermanentPower(); - } - - double ret = 0; - for (FPlayer fplayer : fplayers) { - ret += fplayer.getPowerMax(); - } - if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { - ret = Conf.powerFactionMax; - } - return ret + this.powerBoost; - } - - public int getPowerRounded() { - return (int) Math.round(this.getPower()); - } - - public int getPowerMaxRounded() { - return (int) Math.round(this.getPowerMax()); - } - - public int getLandRounded() { - return Board.getInstance().getFactionCoordCount(this); - } - - public int getLandRoundedInWorld(String worldName) { - return Board.getInstance().getFactionCoordCountInWorld(this, worldName); - } - - public boolean hasLandInflation() { - return this.getLandRounded() > this.getPowerRounded(); - } - - // ------------------------------- - // FPlayers - // ------------------------------- - - // maintain the reference list of FPlayers in this faction - public void refreshFPlayers() { - fplayers.clear(); - if (this.isPlayerFreeType()) { - return; - } - - for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { - if (fplayer.getFactionId().equalsIgnoreCase(id)) { - fplayers.add(fplayer); - } - } - } - - public boolean addFPlayer(FPlayer fplayer) { - return !this.isPlayerFreeType() && fplayers.add(fplayer); - } - - public boolean removeFPlayer(FPlayer fplayer) { - return !this.isPlayerFreeType() && fplayers.remove(fplayer); - } - - public int getSize() { - return fplayers.size(); - } - - public Set getFPlayers() { - // return a shallow copy of the FPlayer list, to prevent tampering and - // concurrency issues - return new HashSet<>(fplayers); - } - - public Set getFPlayersWhereOnline(boolean online) { - Set ret = new HashSet<>(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.isOnline() == online) { - ret.add(fplayer); - } - } - - return ret; - } - - public Set getFPlayersWhereOnline(boolean online, FPlayer viewer) { - Set ret = new HashSet<>(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer viewed : fplayers) { - // Add if their online status is what we want - if (viewed.isOnline() == online) { - // If we want online, check to see if we are able to see this player - // This checks if they are in vanish. - if (online - && viewed.getPlayer() != null - && viewer.getPlayer() != null - && viewer.getPlayer().canSee(viewed.getPlayer())) { - ret.add(viewed); - // If we want offline, just add them. - // Prob a better way to do this but idk. - } else if (!online) { - ret.add(viewed); - } - } - } - - return ret; - } - - - public FPlayer getFPlayerAdmin() { - if (!this.isNormal()) { - return null; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.getRole() == Role.LEADER) { - return fplayer; - } - } - return null; - } - - public FPlayer getFPlayerLeader() { - return getFPlayerAdmin(); - } - - public ArrayList getFPlayersWhereRole(Role role) { - ArrayList ret = new ArrayList<>(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.getRole() == role) { - ret.add(fplayer); - } - } - - return ret; - } - - public ArrayList getOnlinePlayers() { - ArrayList ret = new ArrayList<>(); - if (this.isPlayerFreeType()) { - return ret; - } - - for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fplayer.getFaction() == this) { - ret.add(player); - } - } - - return ret; - } - - // slightly faster check than getOnlinePlayers() if you just want to see if - // there are any players online - public boolean hasPlayersOnline() { - // only real factions can have players online, not safe zone / war zone - if (this.isPlayerFreeType()) { - return false; - } - - for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { - FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); - if (fplayer != null && fplayer.getFaction() == this) { - return true; - } - } - - // even if all players are technically logged off, maybe someone was on - // recently enough to not consider them officially offline yet - return Conf.considerFactionsReallyOfflineAfterXMinutes > 0 && System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000); - } - - public void memberLoggedOff() { - if (this.isNormal()) { - lastPlayerLoggedOffTime = System.currentTimeMillis(); - } - } - - // used when current leader is about to be removed from the faction; - // promotes new leader, or disbands faction if no other members left - @Override - public void promoteNewLeader() { - promoteNewLeader(false); - } - - @Override - public void promoteNewLeader(boolean autoLeave) { - if (!this.isNormal()) { - return; - } - if (this.isPermanent() && Conf.permanentFactionsDisableLeaderPromotion) { - return; - } - - FPlayer oldLeader = this.getFPlayerAdmin(); - - // get list of moderators, or list of normal members if there are no moderators - ArrayList replacements = this.getFPlayersWhereRole(Role.MODERATOR); - if (replacements == null || replacements.isEmpty()) { - replacements = this.getFPlayersWhereRole(Role.NORMAL); - } - - if (replacements == null || replacements.isEmpty()) { // faction admin is the only member; one-man faction - if (this.isPermanent()) { - if (oldLeader != null) { - oldLeader.setRole(Role.NORMAL); - } - return; - } - - // no members left and faction isn't permanent, so disband it - if (Conf.logFactionDisband) { - SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") has been disbanded since it has no members left" + (autoLeave ? " and by inactivity" : "") + "."); - } - - for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { - fplayer.msg("The faction %s was disbanded.", this.getTag(fplayer)); - } - - FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), autoLeave ? PlayerDisbandReason.INACTIVITY : PlayerDisbandReason.LEAVE); - Bukkit.getPluginManager().callEvent(disbandEvent); - - Factions.getInstance().removeFaction(getId()); - } else { // promote new faction admin - if (oldLeader != null) { - oldLeader.setRole(Role.NORMAL); - } - replacements.get(0).setRole(Role.LEADER); - //TODO:TL - this.msg("Faction admin %s has been removed. %s has been promoted as the new faction admin.", oldLeader == null ? "" : oldLeader.getName(), replacements.get(0).getName()); - SavageFactions.plugin.log("Faction " + this.getTag() + " (" + this.getId() + ") admin was removed. Replacement admin: " + replacements.get(0).getName()); - } - } - - // ----------------------------------------------// - // Messages - // ----------------------------------------------// - public void msg(String message, Object... args) { - message = SavageFactions.plugin.txt.parse(message, args); - - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(message); - } - } - - public void msg(TL translation, Object... args) { - msg(translation.toString(), args); - } - - public void sendMessage(String message) { - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(message); - } - } - - public void sendMessage(List messages) { - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(messages); - } - } - - // ----------------------------------------------// - // Ownership of specific claims - // ----------------------------------------------// - - public Map> getClaimOwnership() { - return claimOwnership; - } - - public void clearAllClaimOwnership() { - claimOwnership.clear(); - } - - public void clearClaimOwnership(FLocation loc) { - claimOwnership.remove(loc); - } - - public void clearClaimOwnership(FPlayer player) { - if (id == null || id.isEmpty()) { - return; - } - - Set ownerData; - - for (Entry> entry : claimOwnership.entrySet()) { - ownerData = entry.getValue(); - - if (ownerData == null) { - continue; - } - - Iterator iter = ownerData.iterator(); - while (iter.hasNext()) { - if (iter.next().equals(player.getId())) { - iter.remove(); - } - } - - if (ownerData.isEmpty()) { - claimOwnership.remove(entry.getKey()); - } - } - } - - public int getCountOfClaimsWithOwners() { - return claimOwnership.isEmpty() ? 0 : claimOwnership.size(); - } - - public boolean doesLocationHaveOwnersSet(FLocation loc) { - if (claimOwnership.isEmpty() || !claimOwnership.containsKey(loc)) { - return false; - } - - Set ownerData = claimOwnership.get(loc); - return ownerData != null && !ownerData.isEmpty(); - } - - public boolean isPlayerInOwnerList(FPlayer player, FLocation loc) { - if (claimOwnership.isEmpty()) { - return false; - } - Set ownerData = claimOwnership.get(loc); - return ownerData != null && ownerData.contains(player.getId()); - } - - public void setPlayerAsOwner(FPlayer player, FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - ownerData = new HashSet<>(); - } - ownerData.add(player.getId()); - claimOwnership.put(loc, ownerData); - } - - public void removePlayerAsOwner(FPlayer player, FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - return; - } - ownerData.remove(player.getId()); - claimOwnership.put(loc, ownerData); - } - - public Set getOwnerList(FLocation loc) { - return claimOwnership.get(loc); - } - - public String getOwnerListString(FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null || ownerData.isEmpty()) { - return ""; - } - - StringBuilder ownerList = new StringBuilder(); - - for (String anOwnerData : ownerData) { - if (ownerList.length() > 0) { - ownerList.append(", "); - } - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(anOwnerData)); - //TODO:TL - ownerList.append(offlinePlayer != null ? offlinePlayer.getName() : "null player"); - } - return ownerList.toString(); - } - - public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { - // in own faction, with sufficient role or permission to bypass - // ownership? - if (fplayer.getFaction() == this && (fplayer.getRole().isAtLeast(Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.LEADER) || Permission.OWNERSHIP_BYPASS.has(fplayer.getPlayer()))) { - return true; - } - - // make sure claimOwnership is initialized - if (claimOwnership.isEmpty()) { - return true; - } - - // need to check the ownership list, then - Set ownerData = claimOwnership.get(loc); - - // if no owner list, owner list is empty, or player is in owner list, - // they're allowed - return ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getId()); - } - - // ----------------------------------------------// - // Persistance and entity management - // ----------------------------------------------// - public void remove() { - if (Econ.shouldBeUsed()) { - Econ.setBalance(getAccountId(), 0); - } - - // Clean the board - ((MemoryBoard) Board.getInstance()).clean(id); - - for (FPlayer fPlayer : fplayers) { - fPlayer.resetFactionData(false); - } - } - - public Set getAllClaims() { - return Board.getInstance().getAllClaims(this); - } + public HashMap rules = new HashMap(); + public int tnt; + public Location checkpoint; + public LazyLocation vault; + public HashMap upgrades = new HashMap<>(); + protected String id = null; + protected boolean peacefulExplosionsEnabled; + protected boolean permanent; + protected String tag; + protected String description; + protected boolean open; + protected boolean peaceful; + protected Integer permanentPower; + protected LazyLocation home; + protected long foundedDate; + protected transient long lastPlayerLoggedOffTime; + protected double money; + protected double powerBoost; + protected String paypal; + protected Map relationWish = new HashMap<>(); + protected Map> claimOwnership = new ConcurrentHashMap<>(); + protected transient Set fplayers = new HashSet<>(); + protected Set invites = new HashSet<>(); + protected HashMap> announcements = new HashMap<>(); + protected ConcurrentHashMap warps = new ConcurrentHashMap<>(); + protected ConcurrentHashMap warpPasswords = new ConcurrentHashMap<>(); + protected int maxVaults; + protected Role defaultRole; + protected Map> permissions = new HashMap<>(); + protected Set bans = new HashSet<>(); + protected String player; + Inventory chest; + Map bannerSerialized; + private long lastDeath; + + // -------------------------------------------- // + // Construct + // -------------------------------------------- // + public MemoryFaction() { + } + + public MemoryFaction(String id) { + this.id = id; + this.open = Conf.newFactionsDefaultOpen; + this.tag = "???"; + this.description = TL.GENERIC_DEFAULTDESCRIPTION.toString(); + this.lastPlayerLoggedOffTime = 0; + this.peaceful = false; + this.peacefulExplosionsEnabled = false; + this.permanent = false; + this.money = 0.0; + this.powerBoost = 0.0; + this.foundedDate = System.currentTimeMillis(); + this.maxVaults = Conf.defaultMaxVaults; + this.defaultRole = Role.RECRUIT; + + resetPerms(); // Reset on new Faction so it has default values. + } + + public MemoryFaction(MemoryFaction old) { + id = old.id; + peacefulExplosionsEnabled = old.peacefulExplosionsEnabled; + permanent = old.permanent; + tag = old.tag; + description = old.description; + open = old.open; + foundedDate = old.foundedDate; + peaceful = old.peaceful; + permanentPower = old.permanentPower; + home = old.home; + lastPlayerLoggedOffTime = old.lastPlayerLoggedOffTime; + money = old.money; + powerBoost = old.powerBoost; + relationWish = old.relationWish; + claimOwnership = old.claimOwnership; + fplayers = new HashSet<>(); + invites = old.invites; + announcements = old.announcements; + this.defaultRole = Role.NORMAL; + + resetPerms(); // Reset on new Faction so it has default values. + } + + public HashMap> getAnnouncements() { + return this.announcements; + } + + public void addAnnouncement(FPlayer fPlayer, String msg) { + List list = announcements.containsKey(fPlayer.getId()) ? announcements.get(fPlayer.getId()) : new ArrayList(); + list.add(msg); + announcements.put(fPlayer.getId(), list); + } + + public void sendUnreadAnnouncements(FPlayer fPlayer) { + if (!announcements.containsKey(fPlayer.getId())) { + return; + } + fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_TOP); + for (String s : announcements.get(fPlayer.getPlayer().getUniqueId().toString())) { + fPlayer.sendMessage(s); + } + fPlayer.msg(TL.FACTIONS_ANNOUNCEMENT_BOTTOM); + announcements.remove(fPlayer.getId()); + } + + public void removeAnnouncements(FPlayer fPlayer) { + announcements.remove(fPlayer.getId()); + } + + public ConcurrentHashMap getWarps() { + return this.warps; + } + + public LazyLocation getWarp(String name) { + return this.warps.get(name); + } + + public void setWarp(String name, LazyLocation loc) { + this.warps.put(name, loc); + } + + public boolean isWarp(String name) { + return this.warps.containsKey(name); + } + + public boolean removeWarp(String name) { + warpPasswords.remove(name); // remove password no matter what. + return warps.remove(name) != null; + } + + public boolean isWarpPassword(String warp, String password) { + return hasWarpPassword(warp) && warpPasswords.get(warp.toLowerCase()).equals(password); + } + + public String getPaypal() { + return this.paypal; + } + + public void paypalSet(String paypal) { + this.paypal = paypal; + } + + public boolean hasWarpPassword(String warp) { + return warpPasswords.containsKey(warp.toLowerCase()); + } + + public void setWarpPassword(String warp, String password) { + warpPasswords.put(warp.toLowerCase(), password); + } + + public void clearWarps() { + warps.clear(); + } + + public int getMaxVaults() { + return this.maxVaults; + } + + public void setMaxVaults(int value) { + this.maxVaults = value; + } + + public String getFocused() { + return this.player; + } + + public void setFocused(String fp) { + this.player = fp; + } + + public Set getInvites() { + return invites; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void invite(FPlayer fplayer) { + this.invites.add(fplayer.getId()); + } + + public void deinvite(FPlayer fplayer) { + this.invites.remove(fplayer.getId()); + } + + public boolean isInvited(FPlayer fplayer) { + return this.invites.contains(fplayer.getId()); + } + + public void ban(FPlayer target, FPlayer banner) { + BanInfo info = new BanInfo(banner.getId(), target.getId(), System.currentTimeMillis()); + this.bans.add(info); + } + + public void unban(FPlayer player) { + Iterator iter = bans.iterator(); + while (iter.hasNext()) { + if (iter.next().getBanned().equalsIgnoreCase(player.getId())) { + iter.remove(); + } + } + } + + @Override + public void disband(Player disbander) { + disband(disbander, PlayerDisbandReason.PLUGIN); + } + + @Override + public void disband(Player disbander, PlayerDisbandReason reason) { + + boolean disbanderIsConsole = disbander == null; + FPlayer fdisbander = FPlayers.getInstance().getByOfflinePlayer(disbander); + + FactionDisbandEvent disbandEvent = new FactionDisbandEvent(disbander, this.getId(), reason); + Bukkit.getServer().getPluginManager().callEvent(disbandEvent); + if (disbandEvent.isCancelled()) { + return; + } + + // Send FPlayerLeaveEvent for each player in the faction + for (FPlayer fplayer : this.getFPlayers()) { + Bukkit.getServer().getPluginManager().callEvent(new FPlayerLeaveEvent(fplayer, this, FPlayerLeaveEvent.PlayerLeaveReason.DISBAND)); + } + + if (Conf.logFactionDisband) { + //TODO: Format this correctly and translate. + SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") was disbanded by " + (disbanderIsConsole ? "console command" : fdisbander.getName()) + "."); + } + + if (Econ.shouldBeUsed() && !disbanderIsConsole) { + //Give all the faction's money to the disbander + double amount = Econ.getBalance(this.getAccountId()); + Econ.transferMoney(fdisbander, this, fdisbander, amount, false); + + if (amount > 0.0) { + String amountString = Econ.moneyString(amount); + msg(TL.COMMAND_DISBAND_HOLDINGS, amountString); + //TODO: Format this correctly and translate + SavageFactions.plugin.log(fdisbander.getName() + " has been given bank holdings of " + amountString + " from disbanding " + this.getTag() + "."); + } + } + + Factions.getInstance().removeFaction(this.getId()); + FTeamWrapper.applyUpdates(this); + } + + public boolean isBanned(FPlayer player) { + for (BanInfo info : bans) { + if (info.getBanned().equalsIgnoreCase(player.getId())) { + return true; + } + } + + return false; + } + + public Set getBannedPlayers() { + return this.bans; + } + + public String getRule(int index) { + if (rules.size() == 0) return null; + return rules.get(index); + } + + public HashMap getRulesMap() { + return rules; + } + + public void setRule(int index, String rule) { + rules.put(index, rule); + } + + public void removeRule(int index) { + HashMap newRule = rules; + newRule.remove(index); + rules = newRule; + } + + public void addTnt(int amt) { + tnt += amt; + } + + public void takeTnt(int amt) { + tnt -= amt; + } + + public int getTnt() { + return tnt; + } + + + public Location getVault() { + if (vault == null) { + return null; + } + return vault.getLocation(); + } + + public void setVault(Location vaultLocation) { + if (vaultLocation == null) { + vault = null; + return; + } + LazyLocation newlocation = new LazyLocation(vaultLocation); + vault = newlocation; + } + + public int getUpgrade(Upgrade upgrade) { + if (upgrades.keySet().contains(upgrade.toString())) { + return upgrades.get(upgrade.toString()); + } + return 0; + } + + @Override + public Inventory getChestInventory() { + if (chest != null) { + return chest; + } else { + int level = getUpgrade(Upgrade.CHEST); + int size = 9; + if (level == 1) { + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-1") * 9; + } else if (level == 2) { + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-2") * 9; + } else if (level == 3) { + size = SavageFactions.plugin.getConfig().getInt("fupgrades.MainMenu.Chest.Chest-Size.level-3") * 9; + } + + chest = Bukkit.createInventory(null, size, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); + return chest; + + } + + } + + @Override + public void setChestSize(int chestSize) { + ItemStack[] contents = this.getChestInventory().getContents(); + chest = Bukkit.createInventory(null, chestSize, SavageFactions.plugin.color(SavageFactions.plugin.getConfig().getString("fchest.Inventory-Title"))); + chest.setContents(contents); + } + + + @Override + public void setBannerPattern(ItemStack banner) { + bannerSerialized = banner.serialize(); + } + + @Override + public ItemStack getBanner() { + if (bannerSerialized == null) { + return null; + } + return ItemStack.deserialize(bannerSerialized); + } + + public void setUpgrade(Upgrade upgrade, int level) { + upgrades.put(upgrade.toString(), level); + } + + public Location getCheckpoint() { + return checkpoint; + } + + public void setCheckpoint(Location location) { + checkpoint = location; + } + + public void clearRules() { + rules.clear(); + } + + public void addRule(String rule) { + rules.put(rules.size(), rule); + } + + public boolean getOpen() { + return open; + } + + public void setOpen(boolean isOpen) { + open = isOpen; + } + + public boolean isPeaceful() { + return this.peaceful; + } + + public void setPeaceful(boolean isPeaceful) { + this.peaceful = isPeaceful; + } + + public boolean getPeacefulExplosionsEnabled() { + return this.peacefulExplosionsEnabled; + } + + public void setPeacefulExplosionsEnabled(boolean val) { + peacefulExplosionsEnabled = val; + } + + public boolean noExplosionsInTerritory() { + return this.peaceful && !peacefulExplosionsEnabled; + } + + public boolean isPermanent() { + return permanent || !this.isNormal(); + } + + public void setPermanent(boolean isPermanent) { + permanent = isPermanent; + } + + public String getTag() { + return this.tag; + } + + public void setTag(String str) { + if (Conf.factionTagForceUpperCase) { + str = str.toUpperCase(); + } + this.tag = str; + } + + public String getTag(String prefix) { + return prefix + this.tag; + } + + public String getTag(Faction otherFaction) { + if (otherFaction == null) { + return getTag(); + } + return this.getTag(this.getColorTo(otherFaction).toString()); + } + + public String getTag(FPlayer otherFplayer) { + if (otherFplayer == null) { + return getTag(); + } + return this.getTag(this.getColorTo(otherFplayer).toString()); + } + + public String getComparisonTag() { + return MiscUtil.getComparisonString(this.tag); + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String value) { + this.description = value; + } + + public boolean hasHome() { + return this.getHome() != null; + } + + public Location getHome() { + confirmValidHome(); + return (this.home != null) ? this.home.getLocation() : null; + } + + public void setHome(Location home) { + this.home = new LazyLocation(home); + } + + public long getFoundedDate() { + if (this.foundedDate == 0) { + setFoundedDate(System.currentTimeMillis()); + } + return this.foundedDate; + } + + public void setFoundedDate(long newDate) { + this.foundedDate = newDate; + } + + public void confirmValidHome() { + if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getInstance().getFactionAt(new FLocation(this.home.getLocation())) == this)) { + return; + } + + msg("Your faction home has been un-set since it is no longer in your territory."); + this.home = null; + } + + public String getAccountId() { + String aid = "faction-" + this.getId(); + + // We need to override the default money given to players. + if (!Econ.hasAccount(aid)) { + Econ.setBalance(aid, 0); + } + + return aid; + } + + public Integer getPermanentPower() { + return this.permanentPower; + } + + public void setPermanentPower(Integer permanentPower) { + this.permanentPower = permanentPower; + } + + public boolean hasPermanentPower() { + return this.permanentPower != null; + } + + public double getPowerBoost() { + return this.powerBoost; + } + + public void setPowerBoost(double powerBoost) { + this.powerBoost = powerBoost; + } + + public boolean isPowerFrozen() { + int freezeSeconds = SavageFactions.plugin.getConfig().getInt("hcf.powerfreeze", 0); + return freezeSeconds != 0 && System.currentTimeMillis() - lastDeath < freezeSeconds * 1000; + + } + + public long getLastDeath() { + return this.lastDeath; + } + + // -------------------------------------------- // + // F Permissions stuff + // -------------------------------------------- // + + public void setLastDeath(long time) { + this.lastDeath = time; + } + + public int getKills() { + int kills = 0; + for (FPlayer fp : getFPlayers()) { + kills += fp.getKills(); + } + + return kills; + } + + public int getDeaths() { + int deaths = 0; + for (FPlayer fp : getFPlayers()) { + deaths += fp.getDeaths(); + } + + return deaths; + } + + public Access getAccess(Permissable permissable, PermissableAction permissableAction) { + if (permissable == null || permissableAction == null) { + return Access.UNDEFINED; + } + + Map accessMap = permissions.get(permissable); + if (accessMap != null && accessMap.containsKey(permissableAction)) { + return accessMap.get(permissableAction); + } + + return Access.UNDEFINED; + } + + /** + * Get the Access of a player. Will use player's Role if they are a faction member. Otherwise, uses their Relation. + * + * @param player + * @param permissableAction + * @return + */ + public Access getAccess(FPlayer player, PermissableAction permissableAction) { + if (player == null || permissableAction == null) { + return Access.UNDEFINED; + } + + Permissable perm; + + if (player.getFaction() == this) { + perm = player.getRole(); + } else { + perm = player.getFaction().getRelationTo(this); + } + + Map accessMap = permissions.get(perm); + if (accessMap != null && accessMap.containsKey(permissableAction)) { + return accessMap.get(permissableAction); + } + + return Access.UNDEFINED; + } + + public void setPermission(Permissable permissable, PermissableAction permissableAction, Access access) { + Map accessMap = permissions.get(permissable); + if (accessMap == null) { + accessMap = new HashMap<>(); + } + + accessMap.put(permissableAction, access); + } + + public void resetPerms() { + SavageFactions.plugin.log(Level.WARNING, "Resetting permissions for Faction: " + tag); + + permissions.clear(); + + // First populate a map with undefined as the permission for each action. + Map freshMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + freshMap.put(permissableAction, Access.UNDEFINED); + } + + // Put the map in there for each relation. + for (Relation relation : Relation.values()) { + if (relation != Relation.MEMBER) { + permissions.put(relation, new HashMap<>(freshMap)); + } + } + + // And each role. + for (Role role : Role.values()) { + if (role != Role.LEADER) { + permissions.put(role, new HashMap<>(freshMap)); + } + } + } + + public void setDefaultPerms() { + if (!Conf.useCustomDefaultPermissions) return; + Map defaultMap = new HashMap<>(); + for (PermissableAction permissableAction : PermissableAction.values()) { + defaultMap.put(permissableAction, Access.UNDEFINED); + } + // Put the map in there for each relation. + for (Relation relation : Relation.values()) { + if (relation != Relation.MEMBER) { + if (!Conf.defaultFactionPermissions.containsKey(relation.nicename)) + permissions.put(relation, new HashMap<>(defaultMap)); + else + permissions.put(relation, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(relation.nicename))); + } + } + + // And each role. + for (Role role : Role.values()) { + if (role != Role.LEADER) { + if (!Conf.defaultFactionPermissions.containsKey(role.nicename)) + permissions.put(role, new HashMap<>(defaultMap)); + else + permissions.put(role, PermissableAction.fromDefaults(Conf.defaultFactionPermissions.get(role.nicename))); + } + } + } + + /** + * Read only map of Permissions. + * + * @return + */ + public Map> getPermissions() { + return Collections.unmodifiableMap(permissions); + } + + public Role getDefaultRole() { + return this.defaultRole; + } + + public void setDefaultRole(Role role) { + this.defaultRole = role; + } + + // -------------------------------------------- // + // Extra Getters And Setters + // -------------------------------------------- // + public boolean noPvPInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); + } + + public boolean noMonstersInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); + } + + // ------------------------------- + // Understand the types + // ------------------------------- + + public boolean isNormal() { + return !(this.isWilderness() || this.isSafeZone() || this.isWarZone()); + } + + public boolean isNone() { + return this.getId().equals("0"); + } + + public boolean isWilderness() { + return this.getId().equals("0"); + } + + public boolean isSafeZone() { + return this.getId().equals("-1"); + } + + public boolean isWarZone() { + return this.getId().equals("-2"); + } + + public boolean isPlayerFreeType() { + return this.isSafeZone() || this.isWarZone(); + } + + // ------------------------------- + // Relation and relation colors + // ------------------------------- + + @Override + public String describeTo(RelationParticipator that, boolean ucfirst) { + return RelationUtil.describeThatToMe(this, that, ucfirst); + } + + @Override + public String describeTo(RelationParticipator that) { + return RelationUtil.describeThatToMe(this, that); + } + + @Override + public Relation getRelationTo(RelationParticipator rp) { + return RelationUtil.getRelationTo(this, rp); + } + + @Override + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { + return RelationUtil.getRelationTo(this, rp, ignorePeaceful); + } + + @Override + public ChatColor getColorTo(RelationParticipator rp) { + return RelationUtil.getColorOfThatToMe(this, rp); + } + + public Relation getRelationWish(Faction otherFaction) { + if (this.relationWish.containsKey(otherFaction.getId())) { + return this.relationWish.get(otherFaction.getId()); + } + return Relation.fromString(SavageFactions.plugin.getConfig().getString("default-relation", "neutral")); // Always default to old behavior. + } + + public void setRelationWish(Faction otherFaction, Relation relation) { + if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)) { + this.relationWish.remove(otherFaction.getId()); + } else { + this.relationWish.put(otherFaction.getId(), relation); + } + } + + public int getRelationCount(Relation relation) { + int count = 0; + for (Faction faction : Factions.getInstance().getAllFactions()) { + if (faction.getRelationTo(this) == relation) { + count++; + } + } + return count; + } + + // ----------------------------------------------// + // Power + // ----------------------------------------------// + public double getPower() { + if (this.hasPermanentPower()) { + return this.getPermanentPower(); + } + + double ret = 0; + for (FPlayer fplayer : fplayers) { + ret += fplayer.getPower(); + } + if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { + ret = Conf.powerFactionMax; + } + return ret + this.powerBoost; + } + + public double getPowerMax() { + if (this.hasPermanentPower()) { + return this.getPermanentPower(); + } + + double ret = 0; + for (FPlayer fplayer : fplayers) { + ret += fplayer.getPowerMax(); + } + if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { + ret = Conf.powerFactionMax; + } + return ret + this.powerBoost; + } + + public int getPowerRounded() { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() { + return (int) Math.round(this.getPowerMax()); + } + + public int getLandRounded() { + return Board.getInstance().getFactionCoordCount(this); + } + + public int getLandRoundedInWorld(String worldName) { + return Board.getInstance().getFactionCoordCountInWorld(this, worldName); + } + + public boolean hasLandInflation() { + return this.getLandRounded() > this.getPowerRounded(); + } + + // ------------------------------- + // FPlayers + // ------------------------------- + + // maintain the reference list of FPlayers in this faction + public void refreshFPlayers() { + fplayers.clear(); + if (this.isPlayerFreeType()) { + return; + } + + for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { + if (fplayer.getFactionId().equalsIgnoreCase(id)) { + fplayers.add(fplayer); + } + } + } + + public boolean addFPlayer(FPlayer fplayer) { + return !this.isPlayerFreeType() && fplayers.add(fplayer); + } + + public boolean removeFPlayer(FPlayer fplayer) { + return !this.isPlayerFreeType() && fplayers.remove(fplayer); + } + + public int getSize() { + return fplayers.size(); + } + + public Set getFPlayers() { + // return a shallow copy of the FPlayer list, to prevent tampering and + // concurrency issues + return new HashSet<>(fplayers); + } + + public Set getFPlayersWhereOnline(boolean online) { + Set ret = new HashSet<>(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.isOnline() == online) { + ret.add(fplayer); + } + } + + return ret; + } + + public Set getFPlayersWhereOnline(boolean online, FPlayer viewer) { + Set ret = new HashSet<>(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer viewed : fplayers) { + // Add if their online status is what we want + if (viewed.isOnline() == online) { + // If we want online, check to see if we are able to see this player + // This checks if they are in vanish. + if (online + && viewed.getPlayer() != null + && viewer.getPlayer() != null + && viewer.getPlayer().canSee(viewed.getPlayer())) { + ret.add(viewed); + // If we want offline, just add them. + // Prob a better way to do this but idk. + } else if (!online) { + ret.add(viewed); + } + } + } + + return ret; + } + + + public FPlayer getFPlayerAdmin() { + if (!this.isNormal()) { + return null; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.getRole() == Role.LEADER) { + return fplayer; + } + } + return null; + } + + public FPlayer getFPlayerLeader() { + return getFPlayerAdmin(); + } + + public ArrayList getFPlayersWhereRole(Role role) { + ArrayList ret = new ArrayList<>(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.getRole() == role) { + ret.add(fplayer); + } + } + + return ret; + } + + public ArrayList getOnlinePlayers() { + ArrayList ret = new ArrayList<>(); + if (this.isPlayerFreeType()) { + return ret; + } + + for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer.getFaction() == this) { + ret.add(player); + } + } + + return ret; + } + + // slightly faster check than getOnlinePlayers() if you just want to see if + // there are any players online + public boolean hasPlayersOnline() { + // only real factions can have players online, not safe zone / war zone + if (this.isPlayerFreeType()) { + return false; + } + + for (Player player : SavageFactions.plugin.getServer().getOnlinePlayers()) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer != null && fplayer.getFaction() == this) { + return true; + } + } + + // even if all players are technically logged off, maybe someone was on + // recently enough to not consider them officially offline yet + return Conf.considerFactionsReallyOfflineAfterXMinutes > 0 && System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000); + } + + public void memberLoggedOff() { + if (this.isNormal()) { + lastPlayerLoggedOffTime = System.currentTimeMillis(); + } + } + + // used when current leader is about to be removed from the faction; + // promotes new leader, or disbands faction if no other members left + @Override + public void promoteNewLeader() { + promoteNewLeader(false); + } + + @Override + public void promoteNewLeader(boolean autoLeave) { + if (!this.isNormal()) { + return; + } + if (this.isPermanent() && Conf.permanentFactionsDisableLeaderPromotion) { + return; + } + + FPlayer oldLeader = this.getFPlayerAdmin(); + + // get list of moderators, or list of normal members if there are no moderators + ArrayList replacements = this.getFPlayersWhereRole(Role.MODERATOR); + if (replacements == null || replacements.isEmpty()) { + replacements = this.getFPlayersWhereRole(Role.NORMAL); + } + + if (replacements == null || replacements.isEmpty()) { // faction admin is the only member; one-man faction + if (this.isPermanent()) { + if (oldLeader != null) { + oldLeader.setRole(Role.NORMAL); + } + return; + } + + // no members left and faction isn't permanent, so disband it + if (Conf.logFactionDisband) { + SavageFactions.plugin.log("The faction " + this.getTag() + " (" + this.getId() + ") has been disbanded since it has no members left" + (autoLeave ? " and by inactivity" : "") + "."); + } + + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg("The faction %s was disbanded.", this.getTag(fplayer)); + } + + FactionDisbandEvent disbandEvent = new FactionDisbandEvent(null, getId(), autoLeave ? PlayerDisbandReason.INACTIVITY : PlayerDisbandReason.LEAVE); + Bukkit.getPluginManager().callEvent(disbandEvent); + + Factions.getInstance().removeFaction(getId()); + } else { // promote new faction admin + if (oldLeader != null) { + oldLeader.setRole(Role.NORMAL); + } + replacements.get(0).setRole(Role.LEADER); + //TODO:TL + this.msg("Faction admin %s has been removed. %s has been promoted as the new faction admin.", oldLeader == null ? "" : oldLeader.getName(), replacements.get(0).getName()); + SavageFactions.plugin.log("Faction " + this.getTag() + " (" + this.getId() + ") admin was removed. Replacement admin: " + replacements.get(0).getName()); + } + } + + // ----------------------------------------------// + // Messages + // ----------------------------------------------// + public void msg(String message, Object... args) { + message = SavageFactions.plugin.txt.parse(message, args); + + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(message); + } + } + + public void msg(TL translation, Object... args) { + msg(translation.toString(), args); + } + + public void sendMessage(String message) { + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(message); + } + } + + public void sendMessage(List messages) { + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(messages); + } + } + + // ----------------------------------------------// + // Ownership of specific claims + // ----------------------------------------------// + + public Map> getClaimOwnership() { + return claimOwnership; + } + + public void clearAllClaimOwnership() { + claimOwnership.clear(); + } + + public void clearClaimOwnership(FLocation loc) { + claimOwnership.remove(loc); + } + + public void clearClaimOwnership(FPlayer player) { + if (id == null || id.isEmpty()) { + return; + } + + Set ownerData; + + for (Entry> entry : claimOwnership.entrySet()) { + ownerData = entry.getValue(); + + if (ownerData == null) { + continue; + } + + Iterator iter = ownerData.iterator(); + while (iter.hasNext()) { + if (iter.next().equals(player.getId())) { + iter.remove(); + } + } + + if (ownerData.isEmpty()) { + claimOwnership.remove(entry.getKey()); + } + } + } + + public int getCountOfClaimsWithOwners() { + return claimOwnership.isEmpty() ? 0 : claimOwnership.size(); + } + + public boolean doesLocationHaveOwnersSet(FLocation loc) { + if (claimOwnership.isEmpty() || !claimOwnership.containsKey(loc)) { + return false; + } + + Set ownerData = claimOwnership.get(loc); + return ownerData != null && !ownerData.isEmpty(); + } + + public boolean isPlayerInOwnerList(FPlayer player, FLocation loc) { + if (claimOwnership.isEmpty()) { + return false; + } + Set ownerData = claimOwnership.get(loc); + return ownerData != null && ownerData.contains(player.getId()); + } + + public void setPlayerAsOwner(FPlayer player, FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + ownerData = new HashSet<>(); + } + ownerData.add(player.getId()); + claimOwnership.put(loc, ownerData); + } + + public void removePlayerAsOwner(FPlayer player, FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + return; + } + ownerData.remove(player.getId()); + claimOwnership.put(loc, ownerData); + } + + public Set getOwnerList(FLocation loc) { + return claimOwnership.get(loc); + } + + public String getOwnerListString(FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null || ownerData.isEmpty()) { + return ""; + } + + StringBuilder ownerList = new StringBuilder(); + + for (String anOwnerData : ownerData) { + if (ownerList.length() > 0) { + ownerList.append(", "); + } + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(anOwnerData)); + //TODO:TL + ownerList.append(offlinePlayer != null ? offlinePlayer.getName() : "null player"); + } + return ownerList.toString(); + } + + public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { + // in own faction, with sufficient role or permission to bypass + // ownership? + if (fplayer.getFaction() == this && (fplayer.getRole().isAtLeast(Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.LEADER) || Permission.OWNERSHIP_BYPASS.has(fplayer.getPlayer()))) { + return true; + } + + // make sure claimOwnership is initialized + if (claimOwnership.isEmpty()) { + return true; + } + + // need to check the ownership list, then + Set ownerData = claimOwnership.get(loc); + + // if no owner list, owner list is empty, or player is in owner list, + // they're allowed + return ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getId()); + } + + // ----------------------------------------------// + // Persistance and entity management + // ----------------------------------------------// + public void remove() { + if (Econ.shouldBeUsed()) { + Econ.setBalance(getAccountId(), 0); + } + + // Clean the board + ((MemoryBoard) Board.getInstance()).clean(id); + + for (FPlayer fPlayer : fplayers) { + fPlayer.resetFactionData(false); + } + } + + public Set getAllClaims() { + return Board.getInstance().getAllClaims(this); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java index 76d1caee..292f083f 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java @@ -13,164 +13,164 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public abstract class MemoryFactions extends Factions { - public final Map factions = new ConcurrentHashMap<>(); - public int nextId = 1; + public final Map factions = new ConcurrentHashMap<>(); + public int nextId = 1; - public void load() { - // Make sure the default neutral faction exists - if (!factions.containsKey("0")) { - Faction faction = generateFactionObject("0"); - factions.put("0", faction); - faction.setTag(TL.WILDERNESS.toString()); - faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); - } else { - Faction faction = factions.get("0"); - if (!faction.getTag().equalsIgnoreCase(TL.WILDERNESS.toString())) { - faction.setTag(TL.WILDERNESS.toString()); - } - if (!faction.getDescription().equalsIgnoreCase(TL.WILDERNESS_DESCRIPTION.toString())) { - faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); - } - } + public void load() { + // Make sure the default neutral faction exists + if (!factions.containsKey("0")) { + Faction faction = generateFactionObject("0"); + factions.put("0", faction); + faction.setTag(TL.WILDERNESS.toString()); + faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("0"); + if (!faction.getTag().equalsIgnoreCase(TL.WILDERNESS.toString())) { + faction.setTag(TL.WILDERNESS.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.WILDERNESS_DESCRIPTION.toString())) { + faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); + } + } - // Make sure the safe zone faction exists - if (!factions.containsKey("-1")) { - Faction faction = generateFactionObject("-1"); - factions.put("-1", faction); - faction.setTag(TL.SAFEZONE.toString()); - faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); - } else { - Faction faction = factions.get("-1"); - if (!faction.getTag().equalsIgnoreCase(TL.SAFEZONE.toString())) { - faction.setTag(TL.SAFEZONE.toString()); - } - if (!faction.getDescription().equalsIgnoreCase(TL.SAFEZONE_DESCRIPTION.toString())) { - faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); - } - // if SafeZone has old pre-1.6.0 name, rename it to remove troublesome " " - if (faction.getTag().contains(" ")) { - faction.setTag(TL.SAFEZONE.toString()); - } - } + // Make sure the safe zone faction exists + if (!factions.containsKey("-1")) { + Faction faction = generateFactionObject("-1"); + factions.put("-1", faction); + faction.setTag(TL.SAFEZONE.toString()); + faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("-1"); + if (!faction.getTag().equalsIgnoreCase(TL.SAFEZONE.toString())) { + faction.setTag(TL.SAFEZONE.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.SAFEZONE_DESCRIPTION.toString())) { + faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); + } + // if SafeZone has old pre-1.6.0 name, rename it to remove troublesome " " + if (faction.getTag().contains(" ")) { + faction.setTag(TL.SAFEZONE.toString()); + } + } - // Make sure the war zone faction exists - if (!factions.containsKey("-2")) { - Faction faction = generateFactionObject("-2"); - factions.put("-2", faction); - faction.setTag(TL.WARZONE.toString()); - faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); - } else { - Faction faction = factions.get("-2"); - if (!faction.getTag().equalsIgnoreCase(TL.WARZONE.toString())) { - faction.setTag(TL.WARZONE.toString()); - } - if (!faction.getDescription().equalsIgnoreCase(TL.WARZONE_DESCRIPTION.toString())) { - faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); - } - // if WarZone has old pre-1.6.0 name, rename it to remove troublesome " " - if (faction.getTag().contains(" ")) { - faction.setTag(TL.WARZONE.toString()); - } - } - } + // Make sure the war zone faction exists + if (!factions.containsKey("-2")) { + Faction faction = generateFactionObject("-2"); + factions.put("-2", faction); + faction.setTag(TL.WARZONE.toString()); + faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("-2"); + if (!faction.getTag().equalsIgnoreCase(TL.WARZONE.toString())) { + faction.setTag(TL.WARZONE.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.WARZONE_DESCRIPTION.toString())) { + faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); + } + // if WarZone has old pre-1.6.0 name, rename it to remove troublesome " " + if (faction.getTag().contains(" ")) { + faction.setTag(TL.WARZONE.toString()); + } + } + } - public Faction getFactionById(String id) { - return factions.get(id); - } + public Faction getFactionById(String id) { + return factions.get(id); + } - public abstract Faction generateFactionObject(String string); + public abstract Faction generateFactionObject(String string); - public Faction getByTag(String str) { - String compStr = MiscUtil.getComparisonString(str); - for (Faction faction : factions.values()) { - if (faction.getComparisonTag().equals(compStr)) { - return faction; - } - } - return null; - } + public Faction getByTag(String str) { + String compStr = MiscUtil.getComparisonString(str); + for (Faction faction : factions.values()) { + if (faction.getComparisonTag().equals(compStr)) { + return faction; + } + } + return null; + } - public Faction getBestTagMatch(String start) { - int best = 0; - start = start.toLowerCase(); - int minlength = start.length(); - Faction bestMatch = null; - for (Faction faction : factions.values()) { - String candidate = faction.getTag(); - candidate = ChatColor.stripColor(candidate); - if (candidate.length() < minlength) { - continue; - } - if (!candidate.toLowerCase().startsWith(start)) { - continue; - } + public Faction getBestTagMatch(String start) { + int best = 0; + start = start.toLowerCase(); + int minlength = start.length(); + Faction bestMatch = null; + for (Faction faction : factions.values()) { + String candidate = faction.getTag(); + candidate = ChatColor.stripColor(candidate); + if (candidate.length() < minlength) { + continue; + } + if (!candidate.toLowerCase().startsWith(start)) { + continue; + } - // The closer to zero the better - int lendiff = candidate.length() - minlength; - if (lendiff == 0) { - return faction; - } - if (lendiff < best || best == 0) { - best = lendiff; - bestMatch = faction; - } - } + // The closer to zero the better + int lendiff = candidate.length() - minlength; + if (lendiff == 0) { + return faction; + } + if (lendiff < best || best == 0) { + best = lendiff; + bestMatch = faction; + } + } - return bestMatch; - } + return bestMatch; + } - public boolean isTagTaken(String str) { - return this.getByTag(str) != null; - } + public boolean isTagTaken(String str) { + return this.getByTag(str) != null; + } - public boolean isValidFactionId(String id) { - return factions.containsKey(id); - } + public boolean isValidFactionId(String id) { + return factions.containsKey(id); + } - public Faction createFaction() { - Faction faction = generateFactionObject(); - factions.put(faction.getId(), faction); - return faction; - } + public Faction createFaction() { + Faction faction = generateFactionObject(); + factions.put(faction.getId(), faction); + return faction; + } - public Set getFactionTags() { - Set tags = new HashSet<>(); - for (Faction faction : factions.values()) { - tags.add(faction.getTag()); - } - return tags; - } + public Set getFactionTags() { + Set tags = new HashSet<>(); + for (Faction faction : factions.values()) { + tags.add(faction.getTag()); + } + return tags; + } - public abstract Faction generateFactionObject(); + public abstract Faction generateFactionObject(); - public void removeFaction(String id) { - factions.remove(id).remove(); - } + public void removeFaction(String id) { + factions.remove(id).remove(); + } - @Override - public ArrayList getAllFactions() { - return new ArrayList<>(factions.values()); - } + @Override + public ArrayList getAllFactions() { + return new ArrayList<>(factions.values()); + } - @Override - public Faction getNone() { - return factions.get("0"); - } + @Override + public Faction getNone() { + return factions.get("0"); + } - @Override - public Faction getWilderness() { - return factions.get("0"); - } + @Override + public Faction getWilderness() { + return factions.get("0"); + } - @Override - public Faction getSafeZone() { - return factions.get("-1"); - } + @Override + public Faction getSafeZone() { + return factions.get("-1"); + } - @Override - public Faction getWarZone() { - return factions.get("-2"); - } + @Override + public Faction getWarZone() { + return factions.get("-2"); + } - public abstract void convertFrom(MemoryFactions old); + public abstract void convertFrom(MemoryFactions old); } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java b/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java index 232c9d21..892b0853 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java @@ -7,24 +7,24 @@ import com.massivecraft.factions.zcore.MPlugin; public class SaveTask implements Runnable { - private static boolean running = false; + private static boolean running = false; - MPlugin p; + MPlugin p; - public SaveTask(MPlugin p) { - this.p = p; - } + public SaveTask(MPlugin p) { + this.p = p; + } - public void run() { - if (!p.getAutoSave() || running) { - return; - } - running = true; - p.preAutoSave(); - Factions.getInstance().forceSave(false); - FPlayers.getInstance().forceSave(false); - Board.getInstance().forceSave(false); - p.postAutoSave(); - running = false; - } + public void run() { + if (!p.getAutoSave() || running) { + return; + } + running = true; + p.preAutoSave(); + Factions.getInstance().forceSave(false); + FPlayers.getInstance().forceSave(false); + Board.getInstance().forceSave(false); + p.postAutoSave(); + running = false; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java index 2ee4d2da..f72c2aac 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java @@ -10,36 +10,36 @@ import java.util.logging.Logger; public class FactionsJSON { - public static void convertTo() { - if (!(Factions.getInstance() instanceof MemoryFactions)) { - return; - } - if (!(FPlayers.getInstance() instanceof MemoryFPlayers)) { - return; - } - if (!(Board.getInstance() instanceof MemoryBoard)) { - return; - } - new BukkitRunnable() { - @Override - public void run() { - Logger logger = SavageFactions.plugin.getLogger(); - logger.info("Beginning Board conversion to JSON"); - new JSONBoard().convertFrom((MemoryBoard) Board.getInstance()); - logger.info("Board Converted"); - logger.info("Beginning FPlayers conversion to JSON"); - new JSONFPlayers().convertFrom((MemoryFPlayers) FPlayers.getInstance()); - logger.info("FPlayers Converted"); - logger.info("Beginning Factions conversion to JSON"); - new JSONFactions().convertFrom((MemoryFactions) Factions.getInstance()); - logger.info("Factions Converted"); - logger.info("Refreshing object caches"); - for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { - Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); - faction.addFPlayer(fPlayer); - } - logger.info("Conversion Complete"); - } - }.runTaskAsynchronously(SavageFactions.plugin); - } + public static void convertTo() { + if (!(Factions.getInstance() instanceof MemoryFactions)) { + return; + } + if (!(FPlayers.getInstance() instanceof MemoryFPlayers)) { + return; + } + if (!(Board.getInstance() instanceof MemoryBoard)) { + return; + } + new BukkitRunnable() { + @Override + public void run() { + Logger logger = SavageFactions.plugin.getLogger(); + logger.info("Beginning Board conversion to JSON"); + new JSONBoard().convertFrom((MemoryBoard) Board.getInstance()); + logger.info("Board Converted"); + logger.info("Beginning FPlayers conversion to JSON"); + new JSONFPlayers().convertFrom((MemoryFPlayers) FPlayers.getInstance()); + logger.info("FPlayers Converted"); + logger.info("Beginning Factions conversion to JSON"); + new JSONFactions().convertFrom((MemoryFactions) Factions.getInstance()); + logger.info("Factions Converted"); + logger.info("Refreshing object caches"); + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); + faction.addFPlayer(fPlayer); + } + logger.info("Conversion Complete"); + } + }.runTaskAsynchronously(SavageFactions.plugin); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java index d2b447ac..618d39d8 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java @@ -16,88 +16,88 @@ import java.util.TreeMap; public class JSONBoard extends MemoryBoard { - private static transient File file = new File(SavageFactions.plugin.getDataFolder(), "board.json"); + private static transient File file = new File(SavageFactions.plugin.getDataFolder(), "board.json"); - // -------------------------------------------- // - // Persistance - // -------------------------------------------- // + // -------------------------------------------- // + // Persistance + // -------------------------------------------- // - public Map> dumpAsSaveFormat() { - Map> worldCoordIds = new HashMap<>(); + public Map> dumpAsSaveFormat() { + Map> worldCoordIds = new HashMap<>(); - String worldName, coords; - String id; + String worldName, coords; + String id; - for (Entry entry : flocationIds.entrySet()) { - worldName = entry.getKey().getWorldName(); - coords = entry.getKey().getCoordString(); - id = entry.getValue(); - if (!worldCoordIds.containsKey(worldName)) { - worldCoordIds.put(worldName, new TreeMap()); - } + for (Entry entry : flocationIds.entrySet()) { + worldName = entry.getKey().getWorldName(); + coords = entry.getKey().getCoordString(); + id = entry.getValue(); + if (!worldCoordIds.containsKey(worldName)) { + worldCoordIds.put(worldName, new TreeMap()); + } - worldCoordIds.get(worldName).put(coords, id); - } + worldCoordIds.get(worldName).put(coords, id); + } - return worldCoordIds; - } + return worldCoordIds; + } - public void loadFromSaveFormat(Map> worldCoordIds) { - flocationIds.clear(); + public void loadFromSaveFormat(Map> worldCoordIds) { + flocationIds.clear(); - String worldName; - String[] coords; - int x, z; - String factionId; + String worldName; + String[] coords; + int x, z; + String factionId; - for (Entry> entry : worldCoordIds.entrySet()) { - worldName = entry.getKey(); - for (Entry entry2 : entry.getValue().entrySet()) { - coords = entry2.getKey().trim().split("[,\\s]+"); - x = Integer.parseInt(coords[0]); - z = Integer.parseInt(coords[1]); - factionId = entry2.getValue(); - flocationIds.put(new FLocation(worldName, x, z), factionId); - } - } - } + for (Entry> entry : worldCoordIds.entrySet()) { + worldName = entry.getKey(); + for (Entry entry2 : entry.getValue().entrySet()) { + coords = entry2.getKey().trim().split("[,\\s]+"); + x = Integer.parseInt(coords[0]); + z = Integer.parseInt(coords[1]); + factionId = entry2.getValue(); + flocationIds.put(new FLocation(worldName, x, z), factionId); + } + } + } - public void forceSave() { - forceSave(true); - } + public void forceSave() { + forceSave(true); + } - public void forceSave(boolean sync) { - DiscUtil.writeCatch(file, SavageFactions.plugin.gson.toJson(dumpAsSaveFormat()), sync); - } + public void forceSave(boolean sync) { + DiscUtil.writeCatch(file, SavageFactions.plugin.gson.toJson(dumpAsSaveFormat()), sync); + } - public boolean load() { - SavageFactions.plugin.log("Loading board from disk"); + public boolean load() { + SavageFactions.plugin.log("Loading board from disk"); - if (!file.exists()) { - SavageFactions.plugin.log("No board to load from disk. Creating new file."); - forceSave(); - return true; - } + if (!file.exists()) { + SavageFactions.plugin.log("No board to load from disk. Creating new file."); + forceSave(); + return true; + } - try { - Type type = new TypeToken>>() { - }.getType(); - Map> worldCoordIds = SavageFactions.plugin.gson.fromJson(DiscUtil.read(file), type); - loadFromSaveFormat(worldCoordIds); - SavageFactions.plugin.log("Loaded " + flocationIds.size() + " board locations"); - } catch (Exception e) { - e.printStackTrace(); - SavageFactions.plugin.log("Failed to load the board from disk."); - return false; - } + try { + Type type = new TypeToken>>() { + }.getType(); + Map> worldCoordIds = SavageFactions.plugin.gson.fromJson(DiscUtil.read(file), type); + loadFromSaveFormat(worldCoordIds); + SavageFactions.plugin.log("Loaded " + flocationIds.size() + " board locations"); + } catch (Exception e) { + e.printStackTrace(); + SavageFactions.plugin.log("Failed to load the board from disk."); + return false; + } - return true; - } + return true; + } - @Override - public void convertFrom(MemoryBoard old) { - this.flocationIds = old.flocationIds; - forceSave(); - Board.instance = this; - } + @Override + public void convertFrom(MemoryBoard old) { + this.flocationIds = old.flocationIds; + forceSave(); + Board.instance = this; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java index ade236a0..d2e0618c 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java @@ -6,20 +6,20 @@ import com.massivecraft.factions.zcore.persist.MemoryFPlayer; public class JSONFPlayer extends MemoryFPlayer { - public JSONFPlayer(MemoryFPlayer arg0) { - super(arg0); - } + public JSONFPlayer(MemoryFPlayer arg0) { + super(arg0); + } - public JSONFPlayer(String id) { - super(id); - } + public JSONFPlayer(String id) { + super(id); + } - @Override - public void remove() { - ((JSONFPlayers) FPlayers.getInstance()).fPlayers.remove(getId()); - } + @Override + public void remove() { + ((JSONFPlayers) FPlayers.getInstance()).fPlayers.remove(getId()); + } - public boolean shouldBeSaved() { - return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); - } + public boolean shouldBeSaved() { + return this.hasFaction() || (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(Conf.powerPlayerStarting)); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java index c6c843ad..9851824a 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java @@ -21,170 +21,170 @@ import java.util.Map.Entry; import java.util.logging.Level; public class JSONFPlayers extends MemoryFPlayers { - // Info on how to persist - private Gson gson; - private File file; + // Info on how to persist + private Gson gson; + private File file; - public JSONFPlayers() { - file = new File(SavageFactions.plugin.getDataFolder(), "players.json"); - gson = SavageFactions.plugin.gson; - } + public JSONFPlayers() { + file = new File(SavageFactions.plugin.getDataFolder(), "players.json"); + gson = SavageFactions.plugin.gson; + } - public Gson getGson() { - return gson; - } + public Gson getGson() { + return gson; + } - public void setGson(Gson gson) { - this.gson = gson; - } + public void setGson(Gson gson) { + this.gson = gson; + } - public void convertFrom(MemoryFPlayers old) { - this.fPlayers.putAll(Maps.transformValues(old.fPlayers, new Function() { - @Override - public JSONFPlayer apply(FPlayer arg0) { - return new JSONFPlayer((MemoryFPlayer) arg0); - } - })); - forceSave(); - FPlayers.instance = this; - } + public void convertFrom(MemoryFPlayers old) { + this.fPlayers.putAll(Maps.transformValues(old.fPlayers, new Function() { + @Override + public JSONFPlayer apply(FPlayer arg0) { + return new JSONFPlayer((MemoryFPlayer) arg0); + } + })); + forceSave(); + FPlayers.instance = this; + } - public void forceSave() { - forceSave(true); - } + public void forceSave() { + forceSave(true); + } - public void forceSave(boolean sync) { - final Map entitiesThatShouldBeSaved = new HashMap<>(); - for (FPlayer entity : this.fPlayers.values()) { - if (((MemoryFPlayer) entity).shouldBeSaved()) { - entitiesThatShouldBeSaved.put(entity.getId(), (JSONFPlayer) entity); - } - } + public void forceSave(boolean sync) { + final Map entitiesThatShouldBeSaved = new HashMap<>(); + for (FPlayer entity : this.fPlayers.values()) { + if (((MemoryFPlayer) entity).shouldBeSaved()) { + entitiesThatShouldBeSaved.put(entity.getId(), (JSONFPlayer) entity); + } + } - saveCore(file, entitiesThatShouldBeSaved, sync); - } + saveCore(file, entitiesThatShouldBeSaved, sync); + } - private boolean saveCore(File target, Map data, boolean sync) { - return DiscUtil.writeCatch(target, this.gson.toJson(data), sync); - } + private boolean saveCore(File target, Map data, boolean sync) { + return DiscUtil.writeCatch(target, this.gson.toJson(data), sync); + } - public void load() { - Map fplayers = this.loadCore(); - if (fplayers == null) { - return; - } - this.fPlayers.clear(); - this.fPlayers.putAll(fplayers); - SavageFactions.plugin.log("Loaded " + fPlayers.size() + " players"); - } + public void load() { + Map fplayers = this.loadCore(); + if (fplayers == null) { + return; + } + this.fPlayers.clear(); + this.fPlayers.putAll(fplayers); + SavageFactions.plugin.log("Loaded " + fPlayers.size() + " players"); + } - private Map loadCore() { - if (!this.file.exists()) { - return new HashMap<>(); - } + private Map loadCore() { + if (!this.file.exists()) { + return new HashMap<>(); + } - String content = DiscUtil.readCatch(this.file); - if (content == null) { - return null; - } + String content = DiscUtil.readCatch(this.file); + if (content == null) { + return null; + } - Map data = this.gson.fromJson(content, new TypeToken>() { - }.getType()); - Set list = new HashSet<>(); - Set invalidList = new HashSet<>(); - for (Entry entry : data.entrySet()) { - String key = entry.getKey(); - entry.getValue().setId(key); - if (doesKeyNeedMigration(key)) { - if (!isKeyInvalid(key)) { - list.add(key); - } else { - invalidList.add(key); - } - } - } + Map data = this.gson.fromJson(content, new TypeToken>() { + }.getType()); + Set list = new HashSet<>(); + Set invalidList = new HashSet<>(); + for (Entry entry : data.entrySet()) { + String key = entry.getKey(); + entry.getValue().setId(key); + if (doesKeyNeedMigration(key)) { + if (!isKeyInvalid(key)) { + list.add(key); + } else { + invalidList.add(key); + } + } + } - if (list.size() > 0) { - // We've got some converting to do! - Bukkit.getLogger().log(Level.INFO, "Factions is now updating players.json"); + if (list.size() > 0) { + // We've got some converting to do! + Bukkit.getLogger().log(Level.INFO, "Factions is now updating players.json"); - // First we'll make a backup, because god forbid anybody heed a - // warning - File file = new File(this.file.getParentFile(), "players.json.old"); - try { - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - saveCore(file, data, true); - Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); + // First we'll make a backup, because god forbid anybody heed a + // warning + File file = new File(this.file.getParentFile(), "players.json.old"); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + saveCore(file, data, true); + Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); - // Start fetching those UUIDs - Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + list.size() + " old player names to UUID. This may take a while."); - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); - try { - Map response = fetcher.call(); - for (String s : list) { - // Are we missing any responses? - if (!response.containsKey(s)) { - // They don't have a UUID so they should just be removed - invalidList.add(s); - } - } - for (String value : response.keySet()) { - // For all the valid responses, let's replace their old - // named entry with a UUID key - String id = response.get(value).toString(); + // Start fetching those UUIDs + Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + list.size() + " old player names to UUID. This may take a while."); + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); + try { + Map response = fetcher.call(); + for (String s : list) { + // Are we missing any responses? + if (!response.containsKey(s)) { + // They don't have a UUID so they should just be removed + invalidList.add(s); + } + } + for (String value : response.keySet()) { + // For all the valid responses, let's replace their old + // named entry with a UUID key + String id = response.get(value).toString(); - JSONFPlayer player = data.get(value); + JSONFPlayer player = data.get(value); - if (player == null) { - // The player never existed here, and shouldn't persist - invalidList.add(value); - continue; - } + if (player == null) { + // The player never existed here, and shouldn't persist + invalidList.add(value); + continue; + } - player.setId(id); // Update the object so it knows + player.setId(id); // Update the object so it knows - data.remove(value); // Out with the old... - data.put(id, player); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - if (invalidList.size() > 0) { - for (String name : invalidList) { - // Remove all the invalid names we collected - data.remove(name); - } - Bukkit.getLogger().log(Level.INFO, "While converting we found names that either don't have a UUID or aren't players and removed them from storage."); - Bukkit.getLogger().log(Level.INFO, "The following names were detected as being invalid: " + StringUtils.join(invalidList, ", ")); - } - saveCore(this.file, data, true); // Update the - // flatfile - Bukkit.getLogger().log(Level.INFO, "Done converting players.json to UUID."); - } - return data; - } + data.remove(value); // Out with the old... + data.put(id, player); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + if (invalidList.size() > 0) { + for (String name : invalidList) { + // Remove all the invalid names we collected + data.remove(name); + } + Bukkit.getLogger().log(Level.INFO, "While converting we found names that either don't have a UUID or aren't players and removed them from storage."); + Bukkit.getLogger().log(Level.INFO, "The following names were detected as being invalid: " + StringUtils.join(invalidList, ", ")); + } + saveCore(this.file, data, true); // Update the + // flatfile + Bukkit.getLogger().log(Level.INFO, "Done converting players.json to UUID."); + } + return data; + } - private boolean doesKeyNeedMigration(String key) { - if (!key.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { - // Not a valid UUID.. - // Valid playername, we'll mark this as one for conversion - // to UUID - return key.matches("[a-zA-Z0-9_]{2,16}"); - } - return false; - } + private boolean doesKeyNeedMigration(String key) { + if (!key.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { + // Not a valid UUID.. + // Valid playername, we'll mark this as one for conversion + // to UUID + return key.matches("[a-zA-Z0-9_]{2,16}"); + } + return false; + } - private boolean isKeyInvalid(String key) { - return !key.matches("[a-zA-Z0-9_]{2,16}"); - } + private boolean isKeyInvalid(String key) { + return !key.matches("[a-zA-Z0-9_]{2,16}"); + } - @Override - public FPlayer generateFPlayer(String id) { - FPlayer player = new JSONFPlayer(id); - this.fPlayers.put(player.getId(), player); - return player; - } + @Override + public FPlayer generateFPlayer(String id) { + FPlayer player = new JSONFPlayer(id); + this.fPlayers.put(player.getId(), player); + return player; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java index af1b4e81..c96e85c9 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java @@ -4,14 +4,14 @@ import com.massivecraft.factions.zcore.persist.MemoryFaction; public class JSONFaction extends MemoryFaction { - public JSONFaction(MemoryFaction arg0) { - super(arg0); - } + public JSONFaction(MemoryFaction arg0) { + super(arg0); + } - public JSONFaction() { - } + public JSONFaction() { + } - public JSONFaction(String id) { - super(id); - } + public JSONFaction(String id) { + super(id); + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java index 89ecac94..9d79dfb8 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java @@ -1,253 +1,253 @@ -package com.massivecraft.factions.zcore.persist.json; - -import com.google.common.base.Function; -import com.google.common.collect.Maps; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.massivecraft.factions.FLocation; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.Factions; -import com.massivecraft.factions.SavageFactions; -import com.massivecraft.factions.zcore.persist.MemoryFaction; -import com.massivecraft.factions.zcore.persist.MemoryFactions; -import com.massivecraft.factions.zcore.util.DiscUtil; -import com.massivecraft.factions.zcore.util.UUIDFetcher; -import org.bukkit.Bukkit; - -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.Map.Entry; -import java.util.logging.Level; - -public class JSONFactions extends MemoryFactions { - // Info on how to persist - private final Gson gson; - private final File file; - - public JSONFactions() { - this.file = new File(SavageFactions.plugin.getDataFolder(), "factions.json"); - this.gson = SavageFactions.plugin.gson; - this.nextId = 1; - } - - public Gson getGson() { - return gson; - } - - // -------------------------------------------- // - // CONSTRUCTORS - // -------------------------------------------- // - - public File getFile() { - return file; - } - - public void forceSave() { - forceSave(true); - } - - public void forceSave(boolean sync) { - final Map entitiesThatShouldBeSaved = new HashMap<>(); - for (Faction entity : this.factions.values()) { - entitiesThatShouldBeSaved.put(entity.getId(), (JSONFaction) entity); - } - - saveCore(file, entitiesThatShouldBeSaved, sync); - } - - private boolean saveCore(File target, Map entities, boolean sync) { - return DiscUtil.writeCatch(target, this.gson.toJson(entities), sync); - } - - public void load() { - Map factions = this.loadCore(); - if (factions == null) { - return; - } - this.factions.putAll(factions); - - super.load(); - SavageFactions.plugin.log("Loaded " + factions.size() + " Factions"); - } - - private Map loadCore() { - if (!this.file.exists()) { - return new HashMap<>(); - } - - String content = DiscUtil.readCatch(this.file); - if (content == null) { - return null; - } - - Map data = this.gson.fromJson(content, new TypeToken>() { - }.getType()); - - this.nextId = 1; - // Do we have any names that need updating in claims or invites? - - int needsUpdate = 0; - for (Entry entry : data.entrySet()) { - String id = entry.getKey(); - Faction f = entry.getValue(); - f.setId(id); - this.updateNextIdForId(id); - needsUpdate += whichKeysNeedMigration(f.getInvites()).size(); - for (Set keys : f.getClaimOwnership().values()) { - needsUpdate += whichKeysNeedMigration(keys).size(); - } - } - - if (needsUpdate > 0) { - // We've got some converting to do! - Bukkit.getLogger().log(Level.INFO, "Factions is now updating factions.json"); - - // First we'll make a backup, because god forbid anybody heed a - // warning - File file = new File(this.file.getParentFile(), "factions.json.old"); - try { - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - saveCore(file, data, true); - Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); - - Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + needsUpdate + " old player names to UUID. This may take a while."); - - // Update claim ownership - - for (String string : data.keySet()) { - Faction f = data.get(string); - Map> claims = f.getClaimOwnership(); - for (FLocation key : claims.keySet()) { - Set set = claims.get(key); - - Set list = whichKeysNeedMigration(set); - - if (list.size() > 0) { - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); - try { - Map response = fetcher.call(); - for (String value : response.keySet()) { - // Let's replace their old named entry with a - // UUID key - String id = response.get(value).toString(); - set.remove(value.toLowerCase()); // Out with the - // old... - set.add(id); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - claims.put(key, set); // Update - } - } - } - - // Update invites - - for (String string : data.keySet()) { - Faction f = data.get(string); - Set invites = f.getInvites(); - Set list = whichKeysNeedMigration(invites); - - if (list.size() > 0) { - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); - try { - Map response = fetcher.call(); - for (String value : response.keySet()) { - // Let's replace their old named entry with a UUID - // key - String id = response.get(value).toString(); - invites.remove(value.toLowerCase()); // Out with the - // old... - invites.add(id); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - saveCore(this.file, data, true); // Update the flatfile - Bukkit.getLogger().log(Level.INFO, "Done converting factions.json to UUID."); - } - return data; - } - - private Set whichKeysNeedMigration(Set keys) { - HashSet list = new HashSet<>(); - for (String value : keys) { - if (!value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { - // Not a valid UUID.. - if (value.matches("[a-zA-Z0-9_]{2,16}")) { - // Valid playername, we'll mark this as one for conversion - // to UUID - list.add(value); - } - } - } - return list; - } - - // -------------------------------------------- // - // ID MANAGEMENT - // -------------------------------------------- // - - public String getNextId() { - while (!isIdFree(this.nextId)) { - this.nextId += 1; - } - return Integer.toString(this.nextId); - } - - public boolean isIdFree(String id) { - return !this.factions.containsKey(id); - } - - public boolean isIdFree(int id) { - return this.isIdFree(Integer.toString(id)); - } - - protected synchronized void updateNextIdForId(int id) { - if (this.nextId < id) { - this.nextId = id + 1; - } - } - - protected void updateNextIdForId(String id) { - try { - int idAsInt = Integer.parseInt(id); - this.updateNextIdForId(idAsInt); - } catch (Exception ignored) { - } - } - - @Override - public Faction generateFactionObject() { - String id = getNextId(); - Faction faction = new JSONFaction(id); - updateNextIdForId(id); - return faction; - } - - @Override - public Faction generateFactionObject(String id) { - return new JSONFaction(id); - } - - @Override - public void convertFrom(MemoryFactions old) { - this.factions.putAll(Maps.transformValues(old.factions, new Function() { - @Override - public JSONFaction apply(Faction arg0) { - return new JSONFaction((MemoryFaction) arg0); - } - })); - this.nextId = old.nextId; - forceSave(); - Factions.instance = this; - } -} +package com.massivecraft.factions.zcore.persist.json; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.SavageFactions; +import com.massivecraft.factions.zcore.persist.MemoryFaction; +import com.massivecraft.factions.zcore.persist.MemoryFactions; +import com.massivecraft.factions.zcore.util.DiscUtil; +import com.massivecraft.factions.zcore.util.UUIDFetcher; +import org.bukkit.Bukkit; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; +import java.util.logging.Level; + +public class JSONFactions extends MemoryFactions { + // Info on how to persist + private final Gson gson; + private final File file; + + public JSONFactions() { + this.file = new File(SavageFactions.plugin.getDataFolder(), "factions.json"); + this.gson = SavageFactions.plugin.gson; + this.nextId = 1; + } + + public Gson getGson() { + return gson; + } + + // -------------------------------------------- // + // CONSTRUCTORS + // -------------------------------------------- // + + public File getFile() { + return file; + } + + public void forceSave() { + forceSave(true); + } + + public void forceSave(boolean sync) { + final Map entitiesThatShouldBeSaved = new HashMap<>(); + for (Faction entity : this.factions.values()) { + entitiesThatShouldBeSaved.put(entity.getId(), (JSONFaction) entity); + } + + saveCore(file, entitiesThatShouldBeSaved, sync); + } + + private boolean saveCore(File target, Map entities, boolean sync) { + return DiscUtil.writeCatch(target, this.gson.toJson(entities), sync); + } + + public void load() { + Map factions = this.loadCore(); + if (factions == null) { + return; + } + this.factions.putAll(factions); + + super.load(); + SavageFactions.plugin.log("Loaded " + factions.size() + " Factions"); + } + + private Map loadCore() { + if (!this.file.exists()) { + return new HashMap<>(); + } + + String content = DiscUtil.readCatch(this.file); + if (content == null) { + return null; + } + + Map data = this.gson.fromJson(content, new TypeToken>() { + }.getType()); + + this.nextId = 1; + // Do we have any names that need updating in claims or invites? + + int needsUpdate = 0; + for (Entry entry : data.entrySet()) { + String id = entry.getKey(); + Faction f = entry.getValue(); + f.setId(id); + this.updateNextIdForId(id); + needsUpdate += whichKeysNeedMigration(f.getInvites()).size(); + for (Set keys : f.getClaimOwnership().values()) { + needsUpdate += whichKeysNeedMigration(keys).size(); + } + } + + if (needsUpdate > 0) { + // We've got some converting to do! + Bukkit.getLogger().log(Level.INFO, "Factions is now updating factions.json"); + + // First we'll make a backup, because god forbid anybody heed a + // warning + File file = new File(this.file.getParentFile(), "factions.json.old"); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + saveCore(file, data, true); + Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); + + Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + needsUpdate + " old player names to UUID. This may take a while."); + + // Update claim ownership + + for (String string : data.keySet()) { + Faction f = data.get(string); + Map> claims = f.getClaimOwnership(); + for (FLocation key : claims.keySet()) { + Set set = claims.get(key); + + Set list = whichKeysNeedMigration(set); + + if (list.size() > 0) { + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); + try { + Map response = fetcher.call(); + for (String value : response.keySet()) { + // Let's replace their old named entry with a + // UUID key + String id = response.get(value).toString(); + set.remove(value.toLowerCase()); // Out with the + // old... + set.add(id); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + claims.put(key, set); // Update + } + } + } + + // Update invites + + for (String string : data.keySet()) { + Faction f = data.get(string); + Set invites = f.getInvites(); + Set list = whichKeysNeedMigration(invites); + + if (list.size() > 0) { + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList<>(list)); + try { + Map response = fetcher.call(); + for (String value : response.keySet()) { + // Let's replace their old named entry with a UUID + // key + String id = response.get(value).toString(); + invites.remove(value.toLowerCase()); // Out with the + // old... + invites.add(id); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + saveCore(this.file, data, true); // Update the flatfile + Bukkit.getLogger().log(Level.INFO, "Done converting factions.json to UUID."); + } + return data; + } + + private Set whichKeysNeedMigration(Set keys) { + HashSet list = new HashSet<>(); + for (String value : keys) { + if (!value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { + // Not a valid UUID.. + if (value.matches("[a-zA-Z0-9_]{2,16}")) { + // Valid playername, we'll mark this as one for conversion + // to UUID + list.add(value); + } + } + } + return list; + } + + // -------------------------------------------- // + // ID MANAGEMENT + // -------------------------------------------- // + + public String getNextId() { + while (!isIdFree(this.nextId)) { + this.nextId += 1; + } + return Integer.toString(this.nextId); + } + + public boolean isIdFree(String id) { + return !this.factions.containsKey(id); + } + + public boolean isIdFree(int id) { + return this.isIdFree(Integer.toString(id)); + } + + protected synchronized void updateNextIdForId(int id) { + if (this.nextId < id) { + this.nextId = id + 1; + } + } + + protected void updateNextIdForId(String id) { + try { + int idAsInt = Integer.parseInt(id); + this.updateNextIdForId(idAsInt); + } catch (Exception ignored) { + } + } + + @Override + public Faction generateFactionObject() { + String id = getNextId(); + Faction faction = new JSONFaction(id); + updateNextIdForId(id); + return faction; + } + + @Override + public Faction generateFactionObject(String id) { + return new JSONFaction(id); + } + + @Override + public void convertFrom(MemoryFactions old) { + this.factions.putAll(Maps.transformValues(old.factions, new Function() { + @Override + public JSONFaction apply(Faction arg0) { + return new JSONFaction((MemoryFaction) arg0); + } + })); + this.nextId = old.nextId; + forceSave(); + Factions.instance = this; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java index eaf37257..fcf2e7ca 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/DiscUtil.java @@ -1,121 +1,121 @@ -package com.massivecraft.factions.zcore.util; - -import com.massivecraft.factions.SavageFactions; -import org.bukkit.Bukkit; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -public class DiscUtil { - - // -------------------------------------------- // - // CONSTANTS - // -------------------------------------------- // - - private final static String UTF8 = "UTF-8"; - - // -------------------------------------------- // - // BYTE - // -------------------------------------------- // - private static HashMap locks = new HashMap<>(); - - public static byte[] readBytes(File file) throws IOException { - int length = (int) file.length(); - byte[] output = new byte[length]; - InputStream in = new FileInputStream(file); - int offset = 0; - while (offset < length) { - offset += in.read(output, offset, (length - offset)); - } - in.close(); - return output; - } - - // -------------------------------------------- // - // STRING - // -------------------------------------------- // - - public static void writeBytes(File file, byte[] bytes) throws IOException { - FileOutputStream out = new FileOutputStream(file); - out.write(bytes); - out.close(); - } - - public static void write(File file, String content) throws IOException { - writeBytes(file, utf8(content)); - } - - // -------------------------------------------- // - // CATCH - // -------------------------------------------- // - - public static String read(File file) throws IOException { - return utf8(readBytes(file)); - } - - public static boolean writeCatch(final File file, final String content, boolean sync) { - String name = file.getName(); - final Lock lock; - - // Create lock for each file if there isn't already one. - if (locks.containsKey(name)) { - lock = locks.get(name); - } else { - ReadWriteLock rwl = new ReentrantReadWriteLock(); - lock = rwl.writeLock(); - locks.put(name, lock); - } - - if (sync) { - lock.lock(); - try { - write(file, content); - } catch (IOException e) { - e.printStackTrace(); - } finally { - lock.unlock(); - } - } else { - Bukkit.getScheduler().runTaskAsynchronously(SavageFactions.plugin, new Runnable() { - @Override - public void run() { - lock.lock(); - try { - write(file, content); - } catch (IOException e) { - e.printStackTrace(); - } finally { - lock.unlock(); - } - } - }); - } - - return true; // don't really care but for some reason this is a boolean. - } - - public static String readCatch(File file) { - try { - return read(file); - } catch (IOException e) { - return null; - } - } - - // -------------------------------------------- // - // UTF8 ENCODE AND DECODE - // -------------------------------------------- // - - public static byte[] utf8(String string) { - return string.getBytes(StandardCharsets.UTF_8); - } - - public static String utf8(byte[] bytes) { - return new String(bytes, StandardCharsets.UTF_8); - } - +package com.massivecraft.factions.zcore.util; + +import com.massivecraft.factions.SavageFactions; +import org.bukkit.Bukkit; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class DiscUtil { + + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private final static String UTF8 = "UTF-8"; + + // -------------------------------------------- // + // BYTE + // -------------------------------------------- // + private static HashMap locks = new HashMap<>(); + + public static byte[] readBytes(File file) throws IOException { + int length = (int) file.length(); + byte[] output = new byte[length]; + InputStream in = new FileInputStream(file); + int offset = 0; + while (offset < length) { + offset += in.read(output, offset, (length - offset)); + } + in.close(); + return output; + } + + // -------------------------------------------- // + // STRING + // -------------------------------------------- // + + public static void writeBytes(File file, byte[] bytes) throws IOException { + FileOutputStream out = new FileOutputStream(file); + out.write(bytes); + out.close(); + } + + public static void write(File file, String content) throws IOException { + writeBytes(file, utf8(content)); + } + + // -------------------------------------------- // + // CATCH + // -------------------------------------------- // + + public static String read(File file) throws IOException { + return utf8(readBytes(file)); + } + + public static boolean writeCatch(final File file, final String content, boolean sync) { + String name = file.getName(); + final Lock lock; + + // Create lock for each file if there isn't already one. + if (locks.containsKey(name)) { + lock = locks.get(name); + } else { + ReadWriteLock rwl = new ReentrantReadWriteLock(); + lock = rwl.writeLock(); + locks.put(name, lock); + } + + if (sync) { + lock.lock(); + try { + write(file, content); + } catch (IOException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } else { + Bukkit.getScheduler().runTaskAsynchronously(SavageFactions.plugin, new Runnable() { + @Override + public void run() { + lock.lock(); + try { + write(file, content); + } catch (IOException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } + }); + } + + return true; // don't really care but for some reason this is a boolean. + } + + public static String readCatch(File file) { + try { + return read(file); + } catch (IOException e) { + return null; + } + } + + // -------------------------------------------- // + // UTF8 ENCODE AND DECODE + // -------------------------------------------- // + + public static byte[] utf8(String string) { + return string.getBytes(StandardCharsets.UTF_8); + } + + public static String utf8(byte[] bytes) { + return new String(bytes, StandardCharsets.UTF_8); + } + } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java index 3d8a8933..5d457631 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/PermUtil.java @@ -10,65 +10,65 @@ import java.util.Map.Entry; public class PermUtil { - public Map permissionDescriptions = new HashMap<>(); + public Map permissionDescriptions = new HashMap<>(); - protected MPlugin p; + protected MPlugin p; - public PermUtil(MPlugin p) { - this.p = p; - this.setup(); - } + public PermUtil(MPlugin p) { + this.p = p; + this.setup(); + } - public String getForbiddenMessage(String perm) { - return p.txt.parse(TL.GENERIC_NOPERMISSION.toString(), getPermissionDescription(perm)); - } + public String getForbiddenMessage(String perm) { + return p.txt.parse(TL.GENERIC_NOPERMISSION.toString(), getPermissionDescription(perm)); + } - /** - * This method hooks into all permission plugins we are supporting - */ - public final void setup() { - for (Permission permission : p.getDescription().getPermissions()) { - //plugin.log("\""+permission.getName()+"\" = \""+permission.getDescription()+"\""); - this.permissionDescriptions.put(permission.getName(), permission.getDescription()); - } - } + /** + * This method hooks into all permission plugins we are supporting + */ + public final void setup() { + for (Permission permission : p.getDescription().getPermissions()) { + //plugin.log("\""+permission.getName()+"\" = \""+permission.getDescription()+"\""); + this.permissionDescriptions.put(permission.getName(), permission.getDescription()); + } + } - public String getPermissionDescription(String perm) { - String desc = permissionDescriptions.get(perm); + public String getPermissionDescription(String perm) { + String desc = permissionDescriptions.get(perm); - return desc != null ? desc : TL.GENERIC_DOTHAT.toString(); - } + return desc != null ? desc : TL.GENERIC_DOTHAT.toString(); + } - /** - * This method tests if me has a certain permission and returns true if me has. Otherwise false - */ - public boolean has(CommandSender me, String perm) { - return me != null && me.hasPermission(perm); - } + /** + * This method tests if me has a certain permission and returns true if me has. Otherwise false + */ + public boolean has(CommandSender me, String perm) { + return me != null && me.hasPermission(perm); + } - public boolean has(CommandSender me, String perm, boolean informSenderIfNot) { - if (has(me, perm)) { - return true; - } else if (informSenderIfNot && me != null) { - me.sendMessage(this.getForbiddenMessage(perm)); - } - return false; - } + public boolean has(CommandSender me, String perm, boolean informSenderIfNot) { + if (has(me, perm)) { + return true; + } else if (informSenderIfNot && me != null) { + me.sendMessage(this.getForbiddenMessage(perm)); + } + return false; + } - public T pickFirstVal(CommandSender me, Map perm2val) { - if (perm2val == null) { - return null; - } - T ret = null; + public T pickFirstVal(CommandSender me, Map perm2val) { + if (perm2val == null) { + return null; + } + T ret = null; - for (Entry entry : perm2val.entrySet()) { - ret = entry.getValue(); - if (has(me, entry.getKey())) { - break; - } - } + for (Entry entry : perm2val.entrySet()) { + ret = entry.getValue(); + if (has(me, entry.getKey())) { + break; + } + } - return ret; - } + return ret; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/Persist.java b/src/main/java/com/massivecraft/factions/zcore/util/Persist.java index 65042cb2..21d3027a 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/Persist.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/Persist.java @@ -10,144 +10,144 @@ import java.util.logging.Level; public class Persist { - private MPlugin p; + private MPlugin p; - public Persist(MPlugin p) { - this.p = p; - } + public Persist(MPlugin p) { + this.p = p; + } - // ------------------------------------------------------------ // - // GET NAME - What should we call this type of object? - // ------------------------------------------------------------ // + // ------------------------------------------------------------ // + // GET NAME - What should we call this type of object? + // ------------------------------------------------------------ // - public static String getName(Class clazz) { - return clazz.getSimpleName().toLowerCase(); - } + public static String getName(Class clazz) { + return clazz.getSimpleName().toLowerCase(); + } - public static String getName(Object o) { - return getName(o.getClass()); - } + public static String getName(Object o) { + return getName(o.getClass()); + } - public static String getName(Type type) { - return getName(type.getClass()); - } + public static String getName(Type type) { + return getName(type.getClass()); + } - // ------------------------------------------------------------ // - // GET FILE - In which file would we like to store this object? - // ------------------------------------------------------------ // + // ------------------------------------------------------------ // + // GET FILE - In which file would we like to store this object? + // ------------------------------------------------------------ // - public File getFile(String name) { - return new File(p.getDataFolder(), name + ".json"); - } + public File getFile(String name) { + return new File(p.getDataFolder(), name + ".json"); + } - public File getFile(Class clazz) { - return getFile(getName(clazz)); - } + public File getFile(Class clazz) { + return getFile(getName(clazz)); + } - public File getFile(Object obj) { - return getFile(getName(obj)); - } + public File getFile(Object obj) { + return getFile(getName(obj)); + } - public File getFile(Type type) { - return getFile(getName(type)); - } + public File getFile(Type type) { + return getFile(getName(type)); + } - // NICE WRAPPERS + // NICE WRAPPERS - public T loadOrSaveDefault(T def, Class clazz) { - return loadOrSaveDefault(def, clazz, getFile(clazz)); - } + public T loadOrSaveDefault(T def, Class clazz) { + return loadOrSaveDefault(def, clazz, getFile(clazz)); + } - public T loadOrSaveDefault(T def, Class clazz, String name) { - return loadOrSaveDefault(def, clazz, getFile(name)); - } + public T loadOrSaveDefault(T def, Class clazz, String name) { + return loadOrSaveDefault(def, clazz, getFile(name)); + } - public T loadOrSaveDefault(T def, Class clazz, File file) { - if (!file.exists()) { - p.log("Creating default: " + file); - this.save(def, file); - return def; - } + public T loadOrSaveDefault(T def, Class clazz, File file) { + if (!file.exists()) { + p.log("Creating default: " + file); + this.save(def, file); + return def; + } - T loaded = this.load(clazz, file); + T loaded = this.load(clazz, file); - if (loaded == null) { - p.log(Level.WARNING, "Using default as I failed to load: " + file); + if (loaded == null) { + p.log(Level.WARNING, "Using default as I failed to load: " + file); - // backup bad file, so user can attempt to recover their changes from it - File backup = new File(file.getPath() + "_bad"); - if (backup.exists()) { - backup.delete(); - } - p.log(Level.WARNING, "Backing up copy of bad file to: " + backup); - file.renameTo(backup); + // backup bad file, so user can attempt to recover their changes from it + File backup = new File(file.getPath() + "_bad"); + if (backup.exists()) { + backup.delete(); + } + p.log(Level.WARNING, "Backing up copy of bad file to: " + backup); + file.renameTo(backup); - return def; - } + return def; + } - return loaded; - } + return loaded; + } - // SAVE + // SAVE - public boolean save(Object instance) { - return save(instance, getFile(instance)); - } + public boolean save(Object instance) { + return save(instance, getFile(instance)); + } - public boolean save(Object instance, String name) { - return save(instance, getFile(name)); - } + public boolean save(Object instance, String name) { + return save(instance, getFile(name)); + } - public boolean save(Object instance, File file) { - return DiscUtil.writeCatch(file, p.gson.toJson(instance), true); - } + public boolean save(Object instance, File file) { + return DiscUtil.writeCatch(file, p.gson.toJson(instance), true); + } - // LOAD BY CLASS + // LOAD BY CLASS - public T load(Class clazz) { - return load(clazz, getFile(clazz)); - } + public T load(Class clazz) { + return load(clazz, getFile(clazz)); + } - public T load(Class clazz, String name) { - return load(clazz, getFile(name)); - } + public T load(Class clazz, String name) { + return load(clazz, getFile(name)); + } - public T load(Class clazz, File file) { - String content = DiscUtil.readCatch(file); - if (content == null) { - return null; - } + public T load(Class clazz, File file) { + String content = DiscUtil.readCatch(file); + if (content == null) { + return null; + } - try { - return p.gson.fromJson(content, clazz); - } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely - p.log(Level.WARNING, ex.getMessage()); - } + try { + return p.gson.fromJson(content, clazz); + } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely + p.log(Level.WARNING, ex.getMessage()); + } - return null; - } + return null; + } - // LOAD BY TYPE - @SuppressWarnings("unchecked") - public T load(Type typeOfT, String name) { - return (T) load(typeOfT, getFile(name)); - } + // LOAD BY TYPE + @SuppressWarnings("unchecked") + public T load(Type typeOfT, String name) { + return (T) load(typeOfT, getFile(name)); + } - @SuppressWarnings("unchecked") - public T load(Type typeOfT, File file) { - String content = DiscUtil.readCatch(file); - if (content == null) { - return null; - } + @SuppressWarnings("unchecked") + public T load(Type typeOfT, File file) { + String content = DiscUtil.readCatch(file); + if (content == null) { + return null; + } - try { - return (T) p.gson.fromJson(content, typeOfT); - } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely - p.log(Level.WARNING, ex.getMessage()); - } + try { + return (T) p.gson.fromJson(content, typeOfT); + } catch (Exception ex) { // output the error message rather than full stack trace; error parsing the file, most likely + p.log(Level.WARNING, ex.getMessage()); + } - return null; - } + return null; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java index 1f9ffe84..cacba74b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/SmokeUtil.java @@ -1,82 +1,82 @@ -package com.massivecraft.factions.zcore.util; - -import org.bukkit.Effect; -import org.bukkit.Location; - -import java.util.Collection; -import java.util.Random; - -// http://mc.kev009.com/Protocol -// ----------------------------- -// Smoke Directions -// ----------------------------- -// Direction ID Direction -// 0 South - East -// 1 South -// 2 South - West -// 3 East -// 4 (Up or middle ?) -// 5 West -// 6 North - East -// 7 North -// 8 North - West -//----------------------------- - -public class SmokeUtil { - - public static Random random = new Random(); - - // -------------------------------------------- // - // Spawn once - // -------------------------------------------- // - - // Single ======== - public static void spawnSingle(Location location, int direction) { - if (location == null) { - return; - } - location.getWorld().playEffect(location.clone(), Effect.SMOKE, direction); - } - - public static void spawnSingle(Location location) { - spawnSingle(location, 4); - } - - public static void spawnSingleRandom(Location location) { - spawnSingle(location, random.nextInt(9)); - } - - // Simple Cloud ======== - public static void spawnCloudSimple(Location location) { - for (int i = 0; i <= 8; i++) { - spawnSingle(location, i); - } - } - - public static void spawnCloudSimple(Collection locations) { - for (Location location : locations) { - spawnCloudSimple(location); - } - } - - // Random Cloud ======== - public static void spawnCloudRandom(Location location, float thickness) { - int singles = (int) Math.floor(thickness * 9); - for (int i = 0; i < singles; i++) { - spawnSingleRandom(location.clone()); - } - } - - public static void spawnCloudRandom(Collection locations, float thickness) { - for (Location location : locations) { - spawnCloudRandom(location, thickness); - } - } - - // -------------------------------------------- // - // Attach continuous effects to or locations - // -------------------------------------------- // - - // TODO - -} +package com.massivecraft.factions.zcore.util; + +import org.bukkit.Effect; +import org.bukkit.Location; + +import java.util.Collection; +import java.util.Random; + +// http://mc.kev009.com/Protocol +// ----------------------------- +// Smoke Directions +// ----------------------------- +// Direction ID Direction +// 0 South - East +// 1 South +// 2 South - West +// 3 East +// 4 (Up or middle ?) +// 5 West +// 6 North - East +// 7 North +// 8 North - West +//----------------------------- + +public class SmokeUtil { + + public static Random random = new Random(); + + // -------------------------------------------- // + // Spawn once + // -------------------------------------------- // + + // Single ======== + public static void spawnSingle(Location location, int direction) { + if (location == null) { + return; + } + location.getWorld().playEffect(location.clone(), Effect.SMOKE, direction); + } + + public static void spawnSingle(Location location) { + spawnSingle(location, 4); + } + + public static void spawnSingleRandom(Location location) { + spawnSingle(location, random.nextInt(9)); + } + + // Simple Cloud ======== + public static void spawnCloudSimple(Location location) { + for (int i = 0; i <= 8; i++) { + spawnSingle(location, i); + } + } + + public static void spawnCloudSimple(Collection locations) { + for (Location location : locations) { + spawnCloudSimple(location); + } + } + + // Random Cloud ======== + public static void spawnCloudRandom(Location location, float thickness) { + int singles = (int) Math.floor(thickness * 9); + for (int i = 0; i < singles; i++) { + spawnSingleRandom(location.clone()); + } + } + + public static void spawnCloudRandom(Collection locations, float thickness) { + for (Location location : locations) { + spawnCloudRandom(location, thickness); + } + } + + // -------------------------------------------- // + // Attach continuous effects to or locations + // -------------------------------------------- // + + // TODO + +} diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TL.java b/src/main/java/com/massivecraft/factions/zcore/util/TL.java index 8edff483..202c3e83 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TL.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TL.java @@ -26,1018 +26,1018 @@ import java.text.SimpleDateFormat; * changes. */ public enum TL { - /** - * Translation meta - */ - _AUTHOR("misc"), - _RESPONSIBLE("misc"), - _LANGUAGE("English"), - _ENCODING("UTF-8"), - _LOCALE("en_US"), - _REQUIRESUNICODE("false"), - _DEFAULT("true"), - _STATE("complete"), //incomplete, limited, partial, majority, complete - - /** - * Localised translation meta - */ - _LOCAL_AUTHOR("misc"), - _LOCAL_RESPONSIBLE("misc"), - _LOCAL_LANGUAGE("English"), - _LOCAL_REGION("US"), - _LOCAL_STATE("complete"), //And this is the English version. It's not ever going to be not complete. - - /** - * Command translations - */ - - /** - * Messsges for /f help - */ - COMMAND_HELP_NEXTCREATE("Learn how to create a faction on the next page."), - COMMAND_HELP_INVITATIONS("command.help.invitations", "You might want to close it and use invitations:"), - COMMAND_HELP_HOME("And don't forget to set your home:"), - COMMAND_HELP_404("&c&l» &7This page does &cnot &7exist"), - COMMAND_HELP_BANK_1("Your faction has a bank which is used to pay for certain"), //Move to last /f help page - COMMAND_HELP_BANK_2("things, so it will need to have money deposited into it."), //Move to last /f help page - COMMAND_HELP_BANK_3("To learn more, use the money command."), //Move to last /f help page - COMMAND_HELP_PLAYERTITLES("Player titles are just for fun. No rules connected to them."), //Move to last /f help page - COMMAND_HELP_OWNERSHIP_1("Claimed land with ownership set is further protected so"), //Move to last /f help page - COMMAND_HELP_OWNERSHIP_2("that only the owner(s), faction admin, and possibly the"), //Move to last /f help page - COMMAND_HELP_OWNERSHIP_3("faction moderators have full access."), //Move to last /f help page - COMMAND_HELP_RELATIONS_1("Set the relation you WISH to have with another faction."), //Move to last /f help page - COMMAND_HELP_RELATIONS_2("Your default relation with other factions will be neutral."), //Move to last /f help page - COMMAND_HELP_RELATIONS_3("If BOTH factions choose \"ally\" you will be allies."), //Move to last /f help page - COMMAND_HELP_RELATIONS_4("If ONE faction chooses \"enemy\" you will be enemies."), //Move to last /f help page - COMMAND_HELP_RELATIONS_5("You can never hurt members or allies."), //Move to last /f help page - COMMAND_HELP_RELATIONS_6("You can not hurt neutrals in their own territory."), //Move to last /f help page - COMMAND_HELP_RELATIONS_7("You can always hurt enemies and players without faction."), //Move to last /f help page - COMMAND_HELP_RELATIONS_8(""), - COMMAND_HELP_RELATIONS_9("Damage from enemies is reduced in your own territory."), //Move to last /f help page - COMMAND_HELP_RELATIONS_10("When you die you lose power. It is restored over time."), //Move to last /f help page - COMMAND_HELP_RELATIONS_11("The power of a faction is the sum of all member power."), //Move to last /f help page - COMMAND_HELP_RELATIONS_12("The power of a faction determines how much land it can hold."), //Move to last /f help page - COMMAND_HELP_RELATIONS_13("You can claim land from factions with too little power."), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_1("Only faction members can build and destroy in their own"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_2("territory. Usage of the following items is also restricted:"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_3("Door, Chest, Furnace, Dispenser, Diode."), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_4(""), - COMMAND_HELP_PERMISSIONS_5("Make sure to put pressure plates in front of doors for your"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_6("guest visitors. Otherwise they can't get through. You can"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_7("also use this to create member only areas."), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_8("As dispensers are protected, you can create traps without"), //Move to last /f help page - COMMAND_HELP_PERMISSIONS_9("worrying about those arrows getting stolen."), //Move to last /f help page - COMMAND_HELP_ADMIN_1("&a&l» &a/f claim safezone \n &7claim land for the Safe Zone"), - COMMAND_HELP_ADMIN_2("&a&l» &a/f claim warzone \n &7claim land for the War Zone"), - COMMAND_HELP_ADMIN_3("&a&l» &a/f autoclaim [safezone|warzone] \n &7take a guess"), - COMMAND_HELP_MOAR_1("Finally some commands for the server admins:"), - COMMAND_HELP_MOAR_2("More commands for server admins:"), - COMMAND_HELP_MOAR_3("Even more commands for server admins:"), - COMMAND_HELP_DESCRIPTION("\n &a&l» &7Display a &ahelp &7page"), - - COMMAND_NEAR_DESCRIPTION("Get nearby faction players in a radius."), - COMMAND_NEAR_DISABLED_MSG("&cThis command is disabled!"), - COMMAND_NEAR_FORMAT("{playername} &c({distance}m)"), - COMMAND_NEAR_USE_MSG("&cFaction members nearby"), - - /** - * Messsges for Faction Admins/Mods - */ - - COMMAND_UPGRADES_DESCRIPTION("&cOpen the Upgrades Menu"), - - COMMAND_ADMIN_NOTMEMBER("&c&l[!] &7%1$s &cis not a member in your faction."), - COMMAND_ADMIN_NOTADMIN("&c&l[!] &cYou are not the faction admin."), - COMMAND_ADMIN_TARGETSELF("'&c&l[!] &cThe target player musn''t be yourself."), - COMMAND_ADMIN_DEMOTES("&c&l[!] &cYou have demoted &7%1$s &cfrom the position of faction admin."), - COMMAND_ADMIN_DEMOTED("&c&l[!] &cYou have been demoted from the position of faction admin by &7%1$s&c"), - COMMAND_ADMIN_PROMOTES("&e&l[!] &eYou have promoted &6%1$s &eto the position of faction admin."), - COMMAND_ADMIN_PROMOTED("&e&l[!] &6%1$s &egave &6%2$s ðe leadership of &6%3$s&e."), - COMMAND_ADMIN_DESCRIPTION("Hand over your admin rights"), - COMMAND_ADMIN_NOMEMBERS("&e&l[!] &cNo one else to promote, please disband faction."), - - COMMAND_AHOME_DESCRIPTION("Send a player to their f home no matter what."), - COMMAND_AHOME_NOHOME("%1$s doesn't have an f home."), - COMMAND_AHOME_SUCCESS("$1%s was sent to their f home."), - COMMAND_AHOME_OFFLINE("%1$s is offline."), - COMMAND_AHOME_TARGET("You were sent to your f home."), - - COMMAND_ANNOUNCE_DESCRIPTION("Announce a message to players in faction."), - - COMMAND_FREECAM_ENEMYINRADIUS("Freecam disabled, An enemy is closeby!"), - COMMAND_FREECAM_OUTSIDEFLIGHT("Please dont leave the flight radius!"), - COMMAND_FREECAM_ENABLED("Freecam is now enabled!"), - COMMAND_FREECAM_DISABLED("Freecam is now disabled"), - COMMAND_FREECAM_DESCRIPTION("Go into spectator mode"), - - - COMMAND_AUTOCLAIM_ENABLED("&c&l[!] &7Now &cauto-claiming&7 land for %1$s."), - COMMAND_AUTOCLAIM_DISABLED("&c&l[!] Auto-claiming&7 of land is now &cdisabled."), - COMMAND_AUTOCLAIM_REQUIREDRANK("&c&l[!] &7You must be &c%1$s&7 to claim land."), - COMMAND_AUTOCLAIM_OTHERFACTION("&c&l[!]&7 You &ccan't &7claim land for &c%1$s&7."), - COMMAND_AUTOCLAIM_DESCRIPTION("Auto-claim land as you walk around"), - - COMMAND_AUTOHELP_HELPFOR("Help for command \""), - - COMMAND_BAN_DESCRIPTION("Ban players from joining your Faction."), - COMMAND_BAN_TARGET("&c&l[!] &7You were &cbanned &7from &c%1$s"), // banned player perspective - COMMAND_BAN_BANNED("&c&l[!] &7%1$s &cbanned &7%2$s"), - COMMAND_BAN_SELF("&c&l[!] &7You may &cnot &7ban &cyourself&7."), - COMMAND_BAN_INSUFFICIENTRANK("&c&l[!] &7Your &crank &7is too low to&c ban &7%1$s"), - COMMAND_BAN_ALREADYBANNED("&c&l[!] &7This player is &calready banned&7!"), - - COMMAND_BANLIST_DESCRIPTION("View a Faction's ban list"), - COMMAND_BANLIST_HEADER("&c&l[!] &7There are &c%d&7 bans for &c%s"), - COMMAND_BANLIST_ENTRY("&7%d. &c%s &r&7// &c%s &r&7// &c%s"), - COMMAND_BANLIST_NOFACTION("&c&l[!] &7You are &cnot &7in a Faction."), - COMMAND_BANLIST_INVALID("&c&l[!] &7The faction &c%s &7does not exist"), - - COMMAND_BOOM_PEACEFULONLY("&c&l[!] &7This command is &conly &7usable by factions which are &cspecifically &7designated as &cpeaceful&7."), - COMMAND_BOOM_TOTOGGLE("to toggle explosions"), - COMMAND_BOOM_FORTOGGLE("for toggling explosions"), - COMMAND_BOOM_ENABLED("&c&l[!] &c%1$s&7 has&c %2$s&7 explosions in your faction's territory."), - COMMAND_BOOM_DESCRIPTION("Toggle explosions (peaceful factions only)"), - - - COMMAND_BYPASS_ENABLE("&e&l[!] &eYou have enabled admin bypass mode. You will be able to build or destroy anywhere."), - COMMAND_BYPASS_ENABLELOG(" has ENABLED admin bypass mode."), - COMMAND_BYPASS_DISABLE("&c&l[!] &cYou have disabled admin bypass mode."), - COMMAND_BYPASS_DISABLELOG(" has DISABLED admin bypass mode."), - COMMAND_BYPASS_DESCRIPTION("Enable admin bypass mode"), - - COMMAND_BANNER_DESCRIPTION("Turn a held banner into a war banner"), - COMMAND_BANNER_NOTENOUGHMONEY("&c&l[!] &7You do&c not&7 have enough money"), - COMMAND_BANNER_MONEYTAKE("&c&l[!] $&c{amount} &7has been taken from your account."), - COMMAND_BANNER_SUCCESS("&c&l[!] &7You have created a &c&lWarBanner!"), - COMMAND_BANNER_DISABLED("&c&l[!] &7Buying&c warbanners&7 is &cdisabled!"), - - COMMAND_TPBANNER_NOTSET("&c&l[!] &7Your faction &cdoes not &7have a &c&lWarBanner &7placed!"), - COMMAND_TPBANNER_SUCCESS("&c&l[!] &cTeleporting &7to your factions's &c&lWarBanner"), - COMMAND_TPBANNER_DESCRIPTION("Teleport to your faction banner"), - - - COMMAND_CHAT_DISABLED("&c&l[!] &7The built in chat channels are &cdisabled &7on this server."), - COMMAND_CHAT_INVALIDMODE("&c&l[!] &cUnrecognised &7chat mode. Please enter either '&da&7','&af&7','&6m&7' or '&fp&7'"), - COMMAND_CHAT_DESCRIPTION("Change chat mode"), - - COMMAND_CHAT_MODE_PUBLIC("&c&l[!] &fPublic &7chat mode."), - COMMAND_CHAT_MODE_ALLIANCE("&c&l[!] &dAlliance &7only chat mode."), - COMMAND_CHAT_MODE_TRUCE("&c&l[!] &5Truce &7only chat mode."), - COMMAND_CHAT_MODE_FACTION("&c&l[!] &aFaction&7 only chat mode."), - COMMAND_CHAT_MODE_MOD("&c&l[!] &dMod &7only chat mode."), - COMMAND_CHAT_MOD_ONLY("&c&l[!] &7Only Mods can talk through this chat mode."), - - COMMAND_CHATSPY_ENABLE("&c&l[!] &7You have &cenabled &7chat spying mode."), - COMMAND_CHATSPY_ENABLELOG(" has ENABLED chat spying mode."), - COMMAND_CHATSPY_DISABLE("&c&l[!] &7You have &cdisabled &7chat spying mode."), - COMMAND_CHATSPY_DISABLELOG(" has DISABLED chat spying mode."), - COMMAND_CHATSPY_DESCRIPTION("Enable admin chat spy mode"), - - COMMAND_CLAIM_INVALIDRADIUS("&c&l[!]&7 If you specify a &cradius&7, it must be at least &c1&7."), - COMMAND_CLAIM_DENIED("&c&l[!]&7 You &cdo not &7have &cpermission&7 to &cclaim&7 in a radius."), - COMMAND_CLAIM_DESCRIPTION("Claim land from where you are standing"), - - COMMAND_CLAIMLINE_INVALIDRADIUS("&c&l[!]&7 If you &cspecify&7 a distance, it must be at least &c1&7."), - COMMAND_CLAIMLINE_DENIED("&c&l[!]&7 You &cdo not &7have&c permission&7 to claim in a line."), - COMMAND_CLAIMLINE_DESCRIPTION("Claim land in a straight line."), - COMMAND_CLAIMLINE_ABOVEMAX("&c&l[!]&7 The &cmaximum&7 limit for claim line is &c%s&7."), - COMMAND_CLAIMLINE_NOTVALID("&c&l[!]&7 &c%s&7 is not a &ccardinal &7direction. You may use &cnorth&7, &ceast&7, &csouth &7or &cwest&7."), - - COMMAND_CONFIG_NOEXIST("&c&l[!]&7 No configuration setting \"&c%1$s&7\" exists."), - COMMAND_CONFIG_SET_TRUE("\" option set to true (enabled)."), - COMMAND_CONFIG_SET_FALSE("\" option set to false (disabled)."), - COMMAND_CONFIG_OPTIONSET("\" option set to "), - COMMAND_CONFIG_COLOURSET("\" color option set to \""), - COMMAND_CONFIG_INTREQUIRED("Cannot set \"%1$s\": An integer (whole number) value required."), - COMMAND_CONFIG_LONGREQUIRED("Cannot set \"%1$s\": A long integer (whole number) value required."), - COMMAND_CONFIG_DOUBLEREQUIRED("Cannot set \"%1$s\": A double (numeric) value required."), - COMMAND_CONFIG_FLOATREQUIRED("Cannot set \"%1$s\": A float (numeric) value required."), - COMMAND_CONFIG_INVALID_COLOUR("Cannot set \"%1$s\": \"%2$s\" is not a valid color."), - COMMAND_CONFIG_INVALID_COLLECTION("\"%1$s\" is not a data collection type which can be modified with this command."), - COMMAND_CONFIG_INVALID_MATERIAL("Cannot change \"%1$s\" set: \"%2$s\" is not a valid material."), - COMMAND_CONFIG_INVALID_TYPESET("\"%1$s\" is not a data type set which can be modified with this command."), - COMMAND_CONFIG_MATERIAL_ADDED("\"%1$s\" set: Material \"%2$s\" added."), - COMMAND_CONFIG_MATERIAL_REMOVED("\"%1$s\" set: Material \"%2$s\" removed."), - COMMAND_CONFIG_SET_ADDED("\"%1$s\" set: \"%2$s\" added."), - COMMAND_CONFIG_SET_REMOVED("\"%1$s\" set: \"%2$s\" removed."), - COMMAND_CONFIG_LOG(" (Command was run by %1$s.)"), - COMMAND_CONFIG_ERROR_SETTING("Error setting configuration setting \"%1$s\" to \"%2$s\"."), - COMMAND_CONFIG_ERROR_MATCHING("Configuration setting \"%1$s\" couldn't be matched, though it should be... please report this error."), - COMMAND_CONFIG_ERROR_TYPE("'%1$s' is of type '%2$s', which cannot be modified with this command."), - COMMAND_CONFIG_DESCRIPTION("Change a conf.json setting"), - - COMMAND_CONVERT_BACKEND_RUNNING("&c&l[!]&7 Already running that backend."), - COMMAND_CONVERT_BACKEND_INVALID("&c&l[!]&7 Invalid backend"), - COMMAND_CONVERT_DESCRIPTION("Convert the plugin backend"), - - COMMAND_COORDS_MESSAGE("&c&l[!] &7{player}&7's coords are &c{x}&7,&c{y}&7,&c{z}&7 in &c{world}"), - COMMAND_COORDS_DESCRIPTION("broadcast your coords to your faction"), - - COMMAND_CHECKPOINT_DISABLED("&c&l[!]&7 You &ccannot&7 use checkpoint while its&c disabled&7!"), - COMMAND_CHECKPOINT_SET("&c&l[!]&7 You have &cset&7 the &cfaction checkpoint&7 at your &cLocation&7."), - COMMAND_CHECKPOINT_GO("&c&l[!]&7 &cTeleporting&7 to &cfaction checkpoint"), - COMMAND_CHECKPOINT_INVALIDLOCATION("&c&l[!]&7 &cInvalid Location!&7 You can &cset&7 checkpoints in &cyour claims&7 or &2wilderness&7."), - COMMAND_CHECKPOINT_NOT_SET("&c&l[!]&7 You have to &cset &7the &cfaction checkpoint&7 first."), - COMMAND_CHECKPOINT_CLAIMED("&c&l[!]&7 Your current &cfaction checkpoint&7 is claimed, set a &cnew &7one!"), - COMMAND_CHECKPOINT_DESCRIPTION("Set or go to your faction checkpoint!"), - - COMMAND_CREATE_MUSTLEAVE("&c&l[!]&7 You must &cleave &7your &ccurrent faction &7first."), - COMMAND_CREATE_INUSE("&c&l[!]&7 That tag is &calready &7in use."), - COMMAND_CREATE_TOCREATE("to create a new faction"), - COMMAND_CREATE_FORCREATE("for creating a new faction"), - COMMAND_CREATE_ERROR("&c&l[!]&7 There was an &cinternal error&7 while trying to create your faction. &cPlease try again&7."), - COMMAND_CREATE_CREATED("&c&l[!]&7 &c%1$s &7created a new faction &c&l%2$s"), - COMMAND_CREATE_YOUSHOULD("&c&l[!]&7 You should now: &c%1$s"), - COMMAND_CREATE_CREATEDLOG(" created a new faction: "), - COMMAND_CREATE_DESCRIPTION("Create a new faction"), - - COMMAND_DEINVITE_CANDEINVITE("&c&l[!]&7 Players you can &cdeinvite: "), - COMMAND_DEINVITE_CLICKTODEINVITE("&c&l[!]&7 Click to &crevoke&7 invite for &c%1$s"), - COMMAND_DEINVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of &c%2$s"), - COMMAND_DEINVITE_MIGHTWANT("&c&l[!]&7 You might want to: &c%1$s"), - COMMAND_DEINVITE_REVOKED("&c&l[!]&7 &7%1$s &crevoked&7 your invitation to &c%2$s&7."), - COMMAND_DEINVITE_REVOKES("&c&l[!]&7 %1$s&c revoked &7%2$s's&c invitation."), - COMMAND_DEINVITE_DESCRIPTION("Remove a pending invitation"), - - COMMAND_DELFWARP_DELETED("&c&l[!]&7 Deleted warp &c%1$s"), - COMMAND_DELFWARP_INVALID("&c&l[!]&7 Couldn't &cfind&7 warp &c%1$s"), - COMMAND_DELFWARP_TODELETE("to delete warp"), - COMMAND_DELFWARP_FORDELETE("for deleting warp"), - COMMAND_DELFWARP_DESCRIPTION("Delete a faction warp"), - - COMMAND_DESCRIPTION_CHANGES("&c&l[!]&7 You have &cchanged&7 the &cdescription&7 for &c%1$s&7 to:"), - COMMAND_DESCRIPTION_CHANGED("&c&l[!]&7 The faction&c %1$s&7 changed their &cdescription &7to:"), - COMMAND_DESCRIPTION_TOCHANGE("to change faction description"), - COMMAND_DESCRIPTION_FORCHANGE("for changing faction description"), - COMMAND_DESCRIPTION_DESCRIPTION("Change the faction description"), - - COMMAND_DISBAND_IMMUTABLE("&c&l[!]&7 &7You &ccannot&7 disband &2Wilderness&7,&e SafeZone&7, or &4WarZone."), - COMMAND_DISBAND_MARKEDPERMANENT("&c&l[!]&7 This faction is designated as&c permanent&7, so you cannot disband it."), - COMMAND_DISBAND_BROADCAST_YOURS("&c&l[!]&7 &c%1$s&7 disbanded your &cfaction."), - COMMAND_DISBAND_BROADCAST_NOTYOURS("&c&l[!]&7 &c%1$s &7disbanded the faction &c%2$s."), - COMMAND_DISBAND_HOLDINGS("&c&l[!]&7 &7You have been given the disbanded &cfaction's bank&7, totaling &c%1$s."), - COMMAND_DISBAND_PLAYER("&c&l[!] &7You have disbanded your &cfaction"), - COMMAND_DISBAND_CONFIRM("&c&l[!]&7 Your Faction has&c {tnt} &7tnt left in the bank, it will be &clost&7 if the faction is &cdisbanded&7. Type&c /f disband &7again within &c10&7 seconds to&c disband&7."), - COMMAND_DISBAND_DESCRIPTION("Disband a faction"), - - COMMAND_FLY_DISABLED("&c&l[!]&7 Sorry, Faction flight is &cdisabled &7on this server"), - COMMAND_FLY_DESCRIPTION("Enter or leave Faction flight mode"), - COMMAND_FLY_CHANGE("&c&l[!]&7 Faction flight &c%1$s"), - COMMAND_FLY_COOLDOWN("&c&l[!]&7 You will &cnot&7 take fall damage for &c{amount}&7 seconds"), - COMMAND_FLY_DAMAGE("&c&l[!]&7 Faction flight &cdisabled&7 due to entering combat"), - COMMAND_FLY_NO_ACCESS("&c&l[!]&7 &cCannot fly &7in territory of %1$s"), - COMMAND_FLY_ENEMY_NEAR("&c&l[!]&7 Flight has been&c disabled&7 an enemy is nearby"), - COMMAND_FLY_CHECK_ENEMY("&c&l[!]&7 Cannot fly here, an enemy is &cnearby"), - COMMAND_FLY_NO_EPEARL("&c&l[!] &7You &ccannot&7 throw enderpearls while flying!"), - - COMMAND_FOCUS_SAMEFACTION("&c[!] You may not focus players in your faction!"), - COMMAND_FOCUS_FOCUSING("&c&l[!] &7Your faction is now focusing &c%s"), - COMMAND_FOCUS_NO_LONGER("&c&l[!] &7Your faction is no longer focusing &c%s"), - COMMAND_FOCUS_DESCRIPTION("Focus a Specific Player"), - - - COMMAND_FWARP_CLICKTOWARP("&c&l[!]&7 Click to &cwarp!"), - COMMAND_FWARP_COMMANDFORMAT("&c&l[!]&7 /f warp &c[password]"), - COMMAND_FWARP_WARPED("&c&l[!]&7 Warped to &c%1$s"), - COMMAND_FWARP_INVALID_WARP("&c&l[!]&7 Couldn't find warp &c%1$s"), - COMMAND_FWARP_TOWARP("to warp"), - COMMAND_FWARP_FORWARPING("for warping"), - COMMAND_FWARP_WARPS("Warps: "), - COMMAND_FWARP_DESCRIPTION("Teleport to a faction warp"), - COMMAND_FWARP_INVALID_PASSWORD("&c&l[!]&7 &cInvalid password!"), - COMMAND_FWARP_PASSWORD_REQUIRED("&c&l[!]&c Warp Password:"), - COMMAND_FWARP_PASSWORD_TIMEOUT("&c&l[!]&7 Warp password &ccanceled"), - - COMMAND_HINT_PERMISSION("&aYou can manage your factions permissions using &7/f perms"), - - COMMAND_HOME_DISABLED("&c&l[!]&7 Sorry, Faction homes are &cdisabled on this server."), - COMMAND_HOME_TELEPORTDISABLED("&c&l[!]&7 Sorry, the ability to &cteleport &7to Faction homes is &cdisabled &7on this server."), - COMMAND_HOME_NOHOME("&c&l[!]&7 Your faction does &cnot &7have a home. "), - COMMAND_HOME_INENEMY("&c&l[!]&7 You &ccannot teleport &7to your &cfaction home&7 while in the territory of an &cenemy faction&7."), - COMMAND_HOME_WRONGWORLD("&c&l[!]&7 You &ccannot &7teleport to your &cfaction home&7 while in a different world."), - COMMAND_HOME_ENEMYNEAR("&c&l[!]&7 You &ccannot teleport&7 to your faction home while an enemy is within &c%s&7 blocks of you."), - COMMAND_HOME_TOTELEPORT("to teleport to your faction home"), - COMMAND_HOME_FORTELEPORT("for teleporting to your faction home"), - COMMAND_HOME_DESCRIPTION("Teleport to the faction home"), - COMMAND_HOME_BLOCKED("&c&l[!] You may not teleport to a home that is claimed by &b%1$s"), - - COMMAND_INSPECT_DISABLED_MSG("&c&l[!]&7 Inspect mode is now &cdisabled."), - COMMAND_INSPECT_DISABLED_NOFAC("&c&l[!]&7 Inspect mode is now &cdisabled,&7 because you &cdo not have a faction!"), - COMMAND_INSPECT_ENABLED("&c&l[!]&7 Inspect mode is now &aEnabled."), - COMMAND_INSPECT_HEADER("&c&m---&7Inspect Data&c&m---&c//&7x:{x},y:{y},z:{z}"), - COMMAND_INSPECT_ROW("&c{time} &7// &c{action} &7// &c{player} &7// &c{block-type}"), - COMMAND_INSPECT_NODATA("&c&l[!]&7 &7No Data was found!"), - COMMAND_INSPECT_NOTINCLAIM("&c&l[!]&7 &7You can &conly&7 inspect in &cyour &7claims!"), - COMMAND_INSPECT_BYPASS("&c&l[!]&7 Inspecting in &cbypass&7 mode"), - COMMAND_INSPECT_DESCRIPTION("Inspect blocks!"), - - COMMAND_INVITE_TOINVITE("to invite someone"), - COMMAND_INVITE_FORINVITE("for inviting someone"), - COMMAND_INVITE_CLICKTOJOIN("Click to join!"), - COMMAND_INVITE_INVITEDYOU(" &chas invited you to join "), - COMMAND_INVITE_INVITED("&c&l[!]&7 &c%1$s&7 invited &c%2$s&7 to your faction."), - COMMAND_INVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of&c %2$s"), - COMMAND_INVITE_ALREADYINVITED("&c&l[!]&7 &c%1$s&7 has already been invited"), - COMMAND_INVITE_DESCRIPTION("Invite a player to your faction"), - COMMAND_INVITE_BANNED("&c&l[!]&7 &7%1$s &cis banned &7from your Faction. &cNot &7sending an invite."), - - COMMAND_JOIN_CANNOTFORCE("&c&l[!]&7 You&c do not&7 have permission to &cmove other players&7 into a faction."), - COMMAND_JOIN_SYSTEMFACTION("&c&l[!]&7 Players may only join &cnormal factions&7. This is a &c&lsystem faction&7."), - COMMAND_JOIN_ALREADYMEMBER("&c&l[!]&7 &c%1$s %2$s already a member of&c %3$s"), - COMMAND_JOIN_ATLIMIT(" &c&l[!]&7 The faction &c%1$s &7is at the limit of&c %2$d&7 members, so&c %3$s&7 cannot currently join."), - COMMAND_JOIN_INOTHERFACTION("&c&l[!]&7 &c%1$s &7must leave&c %2$s &7current faction first."), - COMMAND_JOIN_NEGATIVEPOWER("&c&l[!]&7 &c%1$s &7cannot join a faction with a &cnegative power&7 level."), - COMMAND_JOIN_REQUIRESINVITATION("&c&l[!]&7 This faction &crequires&7 an invitation."), - COMMAND_JOIN_ATTEMPTEDJOIN("&c&l[!]&7 &c%1$s&7 tried to join your faction."), - COMMAND_JOIN_TOJOIN("to join a faction"), - COMMAND_JOIN_FORJOIN("for joining a faction"), - COMMAND_JOIN_SUCCESS("&c&l[!]&7 &c%1$s &7successfully joined &c%2$s."), - COMMAND_JOIN_MOVED("&c&l[!]&7 &c%1$s &7moved you into the faction&c %2$s."), - COMMAND_JOIN_JOINED("&c&l[!]&7 &c%1$s &7joined your faction."), - COMMAND_JOIN_JOINEDLOG("&c&l[!]&7 &c%1$s&7 joined the faction&c %2$s."), - COMMAND_JOIN_MOVEDLOG("&c&l[!]&7 &c%1$s &7moved the player&c %2$s &7into the faction&c %3$s&7."), - COMMAND_JOIN_DESCRIPTION("&a&l» &7Join a faction"), - COMMAND_JOIN_BANNED("&c&l[!]&7 You are &cbanned &7from &c%1$s."), - - COMMAND_KICK_CANDIDATES("&c&l[!]&7 Players you can kick: "), - COMMAND_KICK_CLICKTOKICK("Click to kick "), - COMMAND_KICK_SELF("&c&l[!]&7 You &ccannot &7kick&c yourself&7."), - COMMAND_KICK_NONE("&c&l[!]&7 That player&c is not&7 in a faction."), - COMMAND_KICK_NOTMEMBER("&c&l[!]&7 &c%1$s is not a member of %2$s"), - COMMAND_KICK_INSUFFICIENTRANK("&c&l[!]&7 Your rank is &ctoo low &7to kick this player."), - COMMAND_KICK_NEGATIVEPOWER("&c&l[!]&7 You &ccannot &7kick that member until their power is &apositive&7."), - COMMAND_KICK_TOKICK("to kick someone from the faction"), - COMMAND_KICK_FORKICK("for kicking someone from the faction"), - COMMAND_KICK_FACTION("&c&l[!]&7 %1$s&7 kicked %2$s&c from the faction!"), //message given to faction members - COMMAND_KICK_KICKS("&c&l[!]&7 You kicked &c%1$s&7 from the faction&c %2$s&7!"), //kicker perspective - COMMAND_KICK_KICKED("&c&l[!]&7 &c%1$s &7kicked you from&c %2$s&7!"), //kicked player perspective - COMMAND_KICK_DESCRIPTION("Kick a player from the faction"), - - COMMAND_LIST_FACTIONLIST("&c&l[!]&7 Faction List "), - COMMAND_LIST_TOLIST("to list the factions"), - COMMAND_LIST_FORLIST("for listing the factions"), - COMMAND_LIST_ONLINEFACTIONLESS("Online factionless: "), - COMMAND_LIST_DESCRIPTION("&a&l» &7See a list of the factions"), - - COMMAND_LOCK_LOCKED("&c&l[!]&7 Factions is now&c locked"), - COMMAND_LOCK_UNLOCKED("&c&l[!]&7 Factions in now&a unlocked"), - COMMAND_LOCK_DESCRIPTION("Lock all write stuff. Apparently."), - - COMMAND_LOGINS_TOGGLE("&c&l[!]&7 Set login / logout notifications for Faction members to: &c%s"), - COMMAND_LOGINS_DESCRIPTION("Toggle(?) login / logout notifications for Faction members"), - - COMMAND_LOWPOWER_HEADER("&8&m--------&8&8&m---------"), - COMMAND_LOWPOWER_FORMAT("&c{player} &8(&c{player_power}&8/&c{maxpower}&8)"), - COMMAND_LOWPOWER_DESCRIPTION("Shows a list of players in your faction with lower power levels"), - - COMMAND_MAP_TOSHOW("to show the map"), - COMMAND_MAP_FORSHOW("for showing the map"), - COMMAND_MAP_UPDATE_ENABLED("&c&l[!]&7 Map auto update &aENABLED."), - COMMAND_MAP_UPDATE_DISABLED("&c&l[!]&7 Map auto update &cDISABLED."), - COMMAND_MAP_DESCRIPTION("Show the territory map, and set optional auto update"), - - COMMAND_MAPHEIGHT_DESCRIPTION("&eUpdate the lines that /f map sends"), - COMMAND_MAPHEIGHT_SET("&c&l[!]&7 Set /f map lines to &c&a%1$d"), - COMMAND_MAPHEIGHT_CURRENT("&c&l[!]&7 Current &cmapheight: &a%1$d"), - - COMMAND_MOD_CANDIDATES("&c&l[!]&7 Players you can promote: "), - COMMAND_MOD_CLICKTOPROMOTE("Click to promote "), - COMMAND_MOD_NOTMEMBER("&c&l[!]&7 &c%1$s7 is not a member in your faction."), - COMMAND_MOD_NOTADMIN("&c&l[!]&7 You &care not&7 the faction admin."), - COMMAND_MOD_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), - COMMAND_MOD_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin.&7 Demote them first."), - COMMAND_MOD_REVOKES("&c&l[!]&7 &7You have &cremoved&7 moderator status from &c%1$s."), - COMMAND_MOD_REVOKED("&c&l[!]&7 &c%1$s&7 is &cno longer&7 moderator in your faction."), - COMMAND_MOD_PROMOTES("&c&l[!]&7 &c%1$s&7 was &cpromoted&7 to moderator in your faction."), - COMMAND_MOD_PROMOTED("&c&l[!]&7 You have promoted&c %1$s&7 to moderator."), - COMMAND_MOD_DESCRIPTION("Give or revoke moderator rights"), - - COMMAND_COLEADER_CANDIDATES("&c&l[!]&7 Players you can promote: "), - COMMAND_COLEADER_CLICKTOPROMOTE("Click to promote "), - COMMAND_COLEADER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member&7 in your faction."), - COMMAND_COLEADER_NOTADMIN("&c&l[!]&7 You are&c not&7 the faction admin."), - COMMAND_COLEADER_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), - COMMAND_COLEADER_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin&7. Demote them first."), - COMMAND_COLEADER_REVOKES("&c&l[!]&7 You have removed &ccoleader &7status from&c %1$s&7."), - COMMAND_COLEADER_REVOKED("&c&l[!]&7 &c%1$s&7 is no longer&c coleader &7in your faction."), - COMMAND_COLEADER_PROMOTES("&c&l[!]&7 &c%1$s&7 was promoted to &ccoleader &7in your faction."), - COMMAND_COLEADER_PROMOTED("&c&l[!]&7 You have &cpromoted &7%1$s to &ccoleader."), - COMMAND_COLEADER_DESCRIPTION("Give or revoke coleader rights"), - - COMMAND_MODIFYPOWER_ADDED("&c&l[!]&7 Added &c%1$f &7power to &c%2$s. &7New total rounded power: &c%3$d"), - COMMAND_MODIFYPOWER_DESCRIPTION("Modify the power of a faction/player"), - - COMMAND_MONEY_LONG("&c&l[!]&7 The faction money commands."), - COMMAND_MONEY_DESCRIPTION("Faction money commands"), - - COMMAND_MONEYBALANCE_SHORT("show faction balance"), - COMMAND_MONEYBALANCE_DESCRIPTION("Show your factions current money balance"), - - COMMAND_MONEYDEPOSIT_DESCRIPTION("Deposit money"), - COMMAND_MONEYDEPOSIT_DEPOSITED("&c&l[!]&7 &c%1$s &7deposited&c %2$s&7 in the faction bank:&c %3$s"), - - COMMAND_MONEYTRANSFERFF_DESCRIPTION("Transfer f -> f"), - COMMAND_MONEYTRANSFERFF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred&c %2$s &7from the faction &c\"%3$s\"&7 to the faction&c \"%4$s\"&7"), - - COMMAND_MONEYTRANSFERFP_DESCRIPTION("Transfer f -> plugin"), - COMMAND_MONEYTRANSFERFP_TRANSFER("&c&l[!]&7 &c%1$s &7transferred&c %2$s &7from the faction&c \"%3$s\" &7to the player &c\"%4$s\""), - - COMMAND_MONEYTRANSFERPF_DESCRIPTION("Transfer plugin -> f"), - COMMAND_MONEYTRANSFERPF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred &c%2$s&7 from the player &c\"%3$s\" &7to the faction&c \"%4$s\""), - - COMMAND_MONEYWITHDRAW_DESCRIPTION("Withdraw money"), - COMMAND_MONEYWITHDRAW_WITHDRAW("&c&l[!]&7 &c%1$s&7 withdrew&c %2$s &7from the faction bank:&c %3$s"), - - COMMAND_OPEN_TOOPEN("to open or close the faction"), - COMMAND_OPEN_FOROPEN("for opening or closing the faction"), - COMMAND_OPEN_OPEN("open"), - COMMAND_OPEN_CLOSED("closed"), - COMMAND_OPEN_CHANGES("&c&l[!]&7 &c%1$s&7 changed the faction to &c%2$s&7."), - COMMAND_OPEN_CHANGED("&c&l[!]&7 The faction &c%1$s&7 is now &c%2$s"), - COMMAND_OPEN_DESCRIPTION("Switch if invitation is required to join"), - - COMMAND_OWNER_DISABLED("&c&l[!]&7 Sorry, but &cowned areas &7are &cdisabled &7on this server."), - COMMAND_OWNER_LIMIT("&c&l[!]&7 Sorry, but you have reached the server's &climit&7 of &c%1$d&7 owned areas per faction."), - COMMAND_OWNER_WRONGFACTION("&c&l[!]&7 &7This land is &cnot claimed &7by your faction, so you &ccan't set&7 ownership of it."), - COMMAND_OWNER_NOTCLAIMED("&c&l[!]&7 This land&c is not &7claimed by a faction. Ownership &cis not &7possible."), - COMMAND_OWNER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member &7of this faction."), - COMMAND_OWNER_CLEARED("&c&l[!]&7 You have &ccleared &7ownership for this claimed area."), - COMMAND_OWNER_REMOVED("&c&l[!]&7 You have&c removed ownership &7of this &cclaimed land&7 from &c%1$s&7."), - COMMAND_OWNER_TOSET("to set ownership of claimed land"), - COMMAND_OWNER_FORSET("for setting ownership of claimed land"), - COMMAND_OWNER_ADDED("&c&l[!]&7 You have added &c%1$s&7 to the &cowner list&7 for this claimed land."), - COMMAND_OWNER_DESCRIPTION("Set ownership of claimed land"), - - COMMAND_KILLHOLOGRAMS_DESCRIPTION("Kill holograms in a radius, admin command"), - - COMMAND_OWNERLIST_DISABLED("&c&l[!]&7 &cSorry, &7but owned areas are &cdisabled&7 on this server."),//dup-> - COMMAND_OWNERLIST_WRONGFACTION("&c&l[!]&7 This land &cis not&7 claimed by your faction."),//eq - COMMAND_OWNERLIST_NOTCLAIMED("&c&l[!]&7 This land is not claimed by any faction, thus no owners."),//eq - COMMAND_OWNERLIST_NONE("&c&l[!]&7 No owners are set here; everyone in the faction has access."), - COMMAND_OWNERLIST_OWNERS("&c&l[!]&7 Current owner(s) of this land: %1$s"), - COMMAND_OWNERLIST_DESCRIPTION("List owner(s) of this claimed land"), - - COMMAND_PAYPALSET_DESCRIPTION("&c&l[!] &7Set the email of your faction to claim rewards."), - COMMAND_PAYPALSEE_DESCRIPTION("&c&l[!] &7View a specific factions paypal email with &b/f &b."), - COMMAND_PAYPALSET_CREATED("&c&l[!] &7Make sure to type &b/f &7!"), - COMMAND_PAYPALSET_SUCCESSFUL("&c&l[!] &7Successfully set your factions email - &b%1$s&7."), - COMMAND_PAYPALSEE_FACTION_PAYPAL("&c&l[!] &b%1$s's &7faction has their paypal set to &b%2$s&7."), - COMMAND_PAYPALSEE_FACTION_NOTSET("&c&l[!] &b%1$s's &7paypal has not yet been set!"), - COMMAND_PAYPALSEE_FACTION_NOFACTION("&c&l[!] &b%1$s &7does not have a faction!"), - - COMMAND_PEACEFUL_DESCRIPTION("&c&l[!]&7Set a faction to peaceful"), - COMMAND_PEACEFUL_YOURS("&c&l[!]&7%1$s has %2$s your faction"), - COMMAND_PEACEFUL_OTHER("&c&l[!]&7%s has %s the faction '%s'."), - COMMAND_PEACEFUL_GRANT("&c&l[!]&7 granted peaceful status to"), - COMMAND_PEACEFUL_REVOKE("removed peaceful status from"), - - COMMAND_PERM_DESCRIPTION("&c&l[!]&7&6Edit or list your Faction's permissions."), - COMMAND_PERM_INVALID_RELATION("&c&l[!]&7Invalid relation defined. Try something like&c 'ally'"), - COMMAND_PERM_INVALID_ACCESS("&c&l[!]&7 Invalid access defined. Try something like &c'allow'"), - COMMAND_PERM_INVALID_ACTION("&c&l[!]&7 Invalid action defined. Try something like &c'build'"), - COMMAND_PERM_SET("&c&l[!]&7 Set permission&c %1$s &7to &c%2$s &7for relation&c %3$s"), - COMMAND_PERM_TOP("RCT MEM OFF ALLY TRUCE NEUT ENEMY"), - - COMMAND_PERMANENT_DESCRIPTION("Toggles a permanent faction option"), - COMMAND_PERMANENT_GRANT("&c&l[!]&7 added permanent status to"), - COMMAND_PERMANENT_REVOKE("&c&l[!]&7 removed permanent status from"), - COMMAND_PERMANENT_YOURS("&c&l[!]&7 &c%1$s&7 has &c%2$s&7 your faction"), - COMMAND_PERMANENT_OTHER("&c&l[!]&7 &c%s &7has &c%s &7the faction &c'%s'."), - COMMAND_PROMOTE_TARGET("&c&l[!]&7 You've been &c%1$s&7 to &c%2$s"), - COMMAND_PROMOTE_SUCCESS("&c&l[!]&7 You successfully&c %1$s %2$s &cto&7 %3$s"), - COMMAND_PROMOTE_PROMOTED("promoted"), - COMMAND_PROMOTE_DEMOTED("demoted"), - COMMAND_PROMOTE_COLEADER_ADMIN("&c&l[!]&7 &cColeaders cant promote players to Admin!"), - - COMMAND_PERMANENTPOWER_DESCRIPTION("Toggle permanent faction power option"), - COMMAND_PERMANENTPOWER_GRANT("added permanentpower status to"), - COMMAND_PERMANENTPOWER_REVOKE("removed permanentpower status from"), - COMMAND_PERMANENTPOWER_SUCCESS("&c&l[!]&7 You&c %s &7%s."), - COMMAND_PERMANENTPOWER_FACTION("&c&l[!]&7 &c%s %s &7your faction"), - - COMMAND_PROMOTE_DESCRIPTION("/f promote "), - COMMAND_PROMOTE_WRONGFACTION("&c&l[!]&7 &c%1$s&7 is &cnot&7 part of your faction."), - COMMAND_NOACCESS("&c&l[!]&7 You don't have access to that."), - COMMAND_PROMOTE_NOTTHATPLAYER("&c&l[!]&7 That player &ccannot&7 be promoted."), - COMMAND_PROMOTE_NOT_ALLOWED("&c&l[!]&7 You cannot promote to the same rank as yourself!"), - COMMAND_PROMOTE_NOTSELF("&c&l[!]&7 You cannot manage your own rank."), - COMMAND_PROMOTE_NOT_SAME("&c&l[!]&7 You cannot promote to the same rank as yourself!"), - - - COMMAND_POWER_TOSHOW("to show player power info"), - COMMAND_POWER_FORSHOW("for showing player power info"), - COMMAND_POWER_POWER("&c&l[!]&7 &c%1$s » &cPower &7/ &cMaxpower&a » &c%2$d &7/&c%3$d %4$s"), - COMMAND_POWER_BONUS(" (bonus: "), - COMMAND_POWER_PENALTY(" (penalty: "), - COMMAND_POWER_DESCRIPTION("&a&l» &7Show player &apower &7info"), - - COMMAND_POWERBOOST_HELP_1("&c&l[!]&7 You must specify \"plugin\" or \"player\" to target a player or \"f\" or \"faction\" to target a faction."), - COMMAND_POWERBOOST_HELP_2("&c&l[!]&7 ex. /f powerboost plugin SomePlayer 0.5 -or- /f powerboost f SomeFaction -5"), - COMMAND_POWERBOOST_INVALIDNUM("You must specify a valid numeric value for the power bonus/penalty amount."), - COMMAND_POWERBOOST_PLAYER("Player \"%1$s\""), - COMMAND_POWERBOOST_FACTION("Faction \"%1$s\""), - COMMAND_POWERBOOST_BOOST("%1$s now has a power bonus/penalty of %2$d to min and max power levels."), - COMMAND_POWERBOOST_BOOSTLOG("%1$s has set the power bonus/penalty for %2$s to %3$d."), - COMMAND_POWERBOOST_DESCRIPTION("Apply permanent power bonus/penalty to specified player or faction"), - - COMMAND_RELATIONS_ALLTHENOPE("&c&l[!]&7 &cNope!You can't."), - COMMAND_RELATIONS_MORENOPE("&c&l[!]&7 &cNope!&7You can't declare a relation to &cyourself"), - COMMAND_RELATIONS_ALREADYINRELATIONSHIP("&c&l[!]&7 You &calready&7 have that relation wish set with&c %1$s."), - COMMAND_RELATIONS_TOMARRY("to change a relation wish"), - COMMAND_RELATIONS_FORMARRY("for changing a relation wish"), - COMMAND_RELATIONS_MUTUAL("&c&l[!]&7 Your faction is now %1$s to %2$s"), - COMMAND_RELATIONS_PEACEFUL("&c&l[!]&7 This will have no effect while your faction is peaceful."), - COMMAND_RELATIONS_PEACEFULOTHER("&c&l[!]&7 This will have &cno effect&7 while their faction is peaceful."), - COMMAND_RELATIONS_DESCRIPTION("Set relation wish to another faction"), - COMMAND_RELATIONS_EXCEEDS_ME("&c&l[!]&7 Failed to set relation wish. You can only have %1$s %2$s."), - COMMAND_RELATIONS_EXCEEDS_THEY("&c&l[!]&7 Failed to set relation wish. They can only have %1$s %2$s."), - - COMMAND_RELATIONS_PROPOSAL_1("&c&l[!]&7&c %1$s &7wishes to be your&c %2$s"), - COMMAND_RELATIONS_PROPOSAL_2("&c&l[!]&7 Type &c/%1$s %2$s %3$s&7 to accept."), - COMMAND_RELATIONS_PROPOSAL_SENT("&c&l[!]&7 &c%1$s&7 were informed that you wish to be &c%2$s"), - - COMMAND_RELOAD_TIME("&c&l[!]&7 Reloaded &call &7configuration files from disk, took &c%1$d ms."), - COMMAND_RELOAD_DESCRIPTION("Reload data file(s) from disk"), - - COMMAND_SAFEUNCLAIMALL_DESCRIPTION("Unclaim all safezone land"), - COMMAND_SAFEUNCLAIMALL_UNCLAIMED("&c&l[!]&7 You unclaimed&c ALL&7 safe zone land."), - COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG("&c&l[!]&7 &c%1$s&7 unclaimed all safe zones."), - - COMMAND_SAVEALL_SUCCESS("&c&l[!]&7 &cFactions saved to disk!"), - COMMAND_SAVEALL_DESCRIPTION("Save all data to disk"), - - COMMAND_SCOREBOARD_DESCRIPTION("Scoreboardy things"), - - COMMAND_SETBANNER_SUCCESS("&c&l[!] &7Banner Pattern Set!"), - COMMAND_SETBANNER_NOTBANNER("&c&l[!] &7The item is &cnot&7 a banner!"), - COMMAND_SETBANNER_DESCRIPTION("set banner pattern for your faction"), - - - COMMAND_SETDEFAULTROLE_DESCRIPTION("/f defaultrole - set your Faction's default role."), - COMMAND_SETDEFAULTROLE_NOTTHATROLE("&c&l[!]&7 You cannot set the default to admin."), - COMMAND_SETDEFAULTROLE_SUCCESS("Set default role of your faction to %1$s"), - COMMAND_SETDEFAULTROLE_INVALIDROLE("Couldn't find matching role for %1$s"), - - COMMAND_SETFWARP_NOTCLAIMED("&c&l[!]&7 You can &conly&7 set warps in your faction territory."), - COMMAND_SETFWARP_LIMIT("&c&l[!]&7 Your Faction already has the &cmax amount&7 of warps set &c(%1$d)."), - COMMAND_SETFWARP_SET("&c&l[!]&7 Set warp &c%1$s&7 and password &c'%2$s' &7to your location."), - COMMAND_SETFWARP_TOSET("to set warp"), - COMMAND_SETFWARP_FORSET("for setting warp"), - COMMAND_SETFWARP_DESCRIPTION("Set a faction warp"), - - COMMAND_SETHOME_DISABLED("&c&l[!]&7 &cSorry&7, Faction homes are disabled on this server."), - COMMAND_SETHOME_NOTCLAIMED("&c&l[!]&c Sorry&7, your faction home can only be set inside your &cown &7claimed territory."), - COMMAND_SETHOME_TOSET("to set the faction home"), - COMMAND_SETHOME_FORSET("for setting the faction home"), - COMMAND_SETHOME_SET("&c&l[!]&c %1$s&7 set the home for your faction. You can now use:"), - COMMAND_SETHOME_SETOTHER("&c&l[!]&7 You have set the home for the &c%1$s&7 faction."), - COMMAND_SETHOME_DESCRIPTION("Set the faction home"), - - COMMAND_SETMAXVAULTS_DESCRIPTION("Set max vaults for a Faction."), - COMMAND_SETMAXVAULTS_SUCCESS("&aSet max vaults for &e%s &ato &b%d"), - - COMMAND_VAULT_DESCRIPTION("Open your placed faction vault!"), - COMMAND_VAULT_INVALID("&c&l[!]&7 Your vault was either&c claimed&7, &cbroken&7, or has&c not been&7 placed yet."), - COMMAND_VAULT_OPENING("&c&l[!]&7 Opening faction vault."), - COMMAND_VAULT_NO_HOPPER("&c&l[!] &7You cannot place a hopper near a vault!"), - - COMMAND_GETVAULT_ALREADYSET("&c&l[!]&7 Vault has already been set!"), - COMMAND_GETVAULT_ALREADYHAVE("&c&l[!]&7 You already have a vault in your inventory!"), - COMMAND_GETVAULT_CHESTNEAR("&c&l[!]&7 &7There is a chest or hopper &cnearby"), - COMMAND_GETVAULT_SUCCESS("&cSucessfully set vault."), - COMMAND_GETVAULT_INVALIDLOCATION("&cVault can only be placed in faction land!"), - COMMAND_GETVAULT_DESCRIPTION("Get the faction vault item!"), - COMMAND_GETVAULT_RECEIVE("&cYou have recieved a faction vault!"), - COMMAND_GETVAULT_NOMONEY("&cYou do not have enough money"), - COMMAND_GETVAULT_MONEYTAKE("&c{amount} has been taken from your account"), - - COMMAND_SHOW_NOFACTION_SELF("You are not in a faction"), - COMMAND_SHOW_NOFACTION_OTHER("That's not a faction"), - COMMAND_SHOW_TOSHOW("to show faction information"), - COMMAND_SHOW_FORSHOW("for showing faction information"), - COMMAND_SHOW_DESCRIPTION("Description: %1$s"), - COMMAND_SHOW_PEACEFUL("This faction is Peaceful"), - COMMAND_SHOW_PERMANENT("This faction is permanent, remaining even with no members."), - COMMAND_SHOW_JOINING("Joining: %1$s "), - COMMAND_SHOW_INVITATION("invitation is required"), - COMMAND_SHOW_UNINVITED("no invitation is needed"), - COMMAND_SHOW_NOHOME("n/a"), - COMMAND_SHOW_POWER("Land / Power / Maxpower: %1$d/%2$d/%3$d %4$s."), - COMMAND_SHOW_BONUS(" (bonus: "), - COMMAND_SHOW_PENALTY(" (penalty: "), - COMMAND_SHOW_DEPRECIATED("(%1$s depreciated)"), //This is spelled correctly. - COMMAND_SHOW_LANDVALUE("Total land value: %1$s %2$s"), - COMMAND_SHOW_BANKCONTAINS("Bank contains: %1$s"), - COMMAND_SHOW_ALLIES("Allies: "), - COMMAND_SHOW_ENEMIES("Enemies: "), - COMMAND_SHOW_MEMBERSONLINE("Members online: "), - COMMAND_SHOW_MEMBERSOFFLINE("Members offline: "), - COMMAND_SHOW_COMMANDDESCRIPTION("Show faction information"), - COMMAND_SHOW_DEATHS_TIL_RAIDABLE("DTR: %1$d"), - COMMAND_SHOW_EXEMPT("This faction is exempt and cannot be seen."), - COMMAND_SHOW_NEEDFACTION("&cYou need to join a faction to view your own!"), - - COMMAND_SHOWCLAIMS_HEADER("&8&m-------------&8<{faction}'s claims&8>&8&m-------------"), - COMMAND_SHOWCLAIMS_FORMAT("&8[{world}]:"), - COMMAND_SHOWCLAIMS_CHUNKSFORMAT("&8(&c{x}&8,&c{z}&8)"), - COMMAND_SHOWCLAIMS_DESCRIPTION("show your factions claims!"), - - COMMAND_SHOWINVITES_PENDING("Players with pending invites: "), - COMMAND_SHOWINVITES_CLICKTOREVOKE("Click to revoke invite for %1$s"), - COMMAND_SHOWINVITES_DESCRIPTION("Show pending faction invites"), - - COMMAND_STATUS_FORMAT("%1$s Power: %2$s Last Seen: %3$s"), - COMMAND_STATUS_ONLINE("Online"), - COMMAND_STATUS_AGOSUFFIX(" ago."), - COMMAND_STATUS_DESCRIPTION("Show the status of a player"), - - COMMAND_STEALTH_DESCRIPTION("Enable and Disable Stealth Mode"), - COMMAND_STEALTH_ENABLE("&cStealth &7» &7You will no longer disable nearby players in /f fly."), - COMMAND_STEALTH_DISABLE("&cStealth &8» &7You will now disable other nearby players in /f fly."), - COMMAND_STEALTH_MUSTBEMEMBER("&cStealth &8» &4You must be in a faction to use this command"), - - COMMAND_STUCK_TIMEFORMAT("m 'minutes', s 'seconds.'"), - COMMAND_STUCK_CANCELLED("Teleport cancelled because you were damaged"), - COMMAND_STUCK_OUTSIDE("Teleport cancelled because you left %1$d block radius"), - COMMAND_STUCK_EXISTS("You are already teleporting, you must wait %1$s"), - COMMAND_STUCK_START("Teleport will commence in %s. Don't take or deal damage. "), - COMMAND_STUCK_TELEPORT("Teleported safely to %1$d, %2$d, %3$d."), - COMMAND_STUCK_TOSTUCK("to safely teleport %1$s out"), - COMMAND_STUCK_FORSTUCK("for %1$s initiating a safe teleport out"), - COMMAND_STUCK_DESCRIPTION("Safely teleports you out of enemy faction"), - - COMMAND_SEECHUNK_ENABLED("&cSeechunk enabled!"), - COMMAND_SEECHUNK_DISABLED("&cSeechunk disabled!"), - - - COMMAND_TAG_TAKEN("That tag is already taken"), - COMMAND_TAG_TOCHANGE("to change the faction tag"), - COMMAND_TAG_FORCHANGE("for changing the faction tag"), - COMMAND_TAG_FACTION("%1$s changed your faction tag to %2$s"), - COMMAND_TAG_CHANGED("The faction %1$s changed their name to %2$s."), - COMMAND_TAG_DESCRIPTION("Change the faction tag"), - - COMMAND_TITLE_TOCHANGE("to change a players title"), - COMMAND_TITLE_FORCHANGE("for changing a players title"), - COMMAND_TITLE_CHANGED("%1$s changed a title: %2$s"), - COMMAND_TITLE_DESCRIPTION("Set or remove a players title"), - - COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION("Toggles whether or not you will see alliance chat"), - COMMAND_TOGGLEALLIANCECHAT_IGNORE("Alliance chat is now ignored"), - COMMAND_TOGGLEALLIANCECHAT_UNIGNORE("Alliance chat is no longer ignored"), - - COMMAND_TOGGLESB_DISABLED("You can't toggle scoreboards while they are disabled."), - - COMMAND_TOP_DESCRIPTION("Sort Factions to see the top of some criteria."), - COMMAND_TOP_TOP("Top Factions by %s. Page %d/%d"), - COMMAND_TOP_LINE("%d. &6%s: &c%s"), // Rank. Faction: Value - COMMAND_TOP_INVALID("Could not sort by %s. Try balance, online, members, power or land."), - - COMMAND_TNT_DISABLED_MSG("&cThis command is disabled!"), - COMMAND_TNT_INVALID_NUM("The amount needs to be a number!"), - COMMAND_TNT_DEPOSIT_SUCCESS("&cSuccessfully deposited tnt."), - COMMAND_TNT_EXCEEDLIMIT("&cThis exceeds the bank limit!"), - COMMAND_TNT_WIDTHDRAW_SUCCESS("&cSuccessfully withdrew tnt."), - COMMAND_TNT_WIDTHDRAW_NOTENOUGH("&cNot enough tnt in bank."), - COMMAND_TNT_DEPOSIT_NOTENOUGH("&cNot enough tnt in tnt inventory."), - COMMAND_TNT_AMOUNT("&cYour faction has {amount} tnt in the tnt bank."), - COMMAND_TNT_POSITIVE("&cPlease use positive numbers!"), - COMMAND_TNT_DESCRIPTION("add/widthraw from faction's tnt bank"), - COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE("&cNot enough space in your inventory."), - COMMAND_TNT_ADD_DESCRIPTION("&b/f tnt add&3 "), - COMMAND_TNT_TAKE_DESCRIPTION("&b/f tnt take&3 "), - - COMMAND_TNTFILL_HEADER("&c&l[!] &7Filling tnt in dispensers..."), - COMMAND_TNTFILL_SUCCESS("&c&l[!] &7Filled &c{amount}&7 Tnt in &c{dispensers} &7dispensers"), - COMMAND_TNTFILL_NOTENOUGH("&c&l[!] &7Not enough tnt in inventory."), - COMMAND_TNTFILL_RADIUSMAX("&c&l[!] &7The max radius is {max}"), - COMMAND_TNTFILL_AMOUNTMAX("&c&l[!] &7The max amount is {max}"), - COMMAND_TNTFILL_MOD("&c&l[!] &7Tnt will be used from the faction bank because you dont have the specified amount in your inventory and you are a {role}"), - COMMAND_TNTFILL_DESCRIPTION("Fill tnt into dispensers around you"), - - COMMAND_UNBAN_DESCRIPTION("Unban someone from your Faction"), - COMMAND_UNBAN_NOTBANNED("&7%s &cisn't banned. Not doing anything."), - COMMAND_UNBAN_UNBANNED("&e%1$s &cunbanned &7%2$s"), - COMMAND_UNBAN_TARGET("&aYou were unbanned from &r%s"), - - COMMAND_UNCLAIM_SAFEZONE_SUCCESS("Safe zone was unclaimed."), - COMMAND_UNCLAIM_SAFEZONE_NOPERM("This is a safe zone. You lack permissions to unclaim."), - COMMAND_UNCLAIM_WARZONE_SUCCESS("War zone was unclaimed."), - COMMAND_UNCLAIM_WARZONE_NOPERM("This is a war zone. You lack permissions to unclaim."), - COMMAND_UNCLAIM_UNCLAIMED("%1$s unclaimed some of your land."), - COMMAND_UNCLAIM_UNCLAIMS("You unclaimed this land."), - COMMAND_UNCLAIM_LOG("%1$s unclaimed land at (%2$s) from the faction: %3$s"), - COMMAND_UNCLAIM_WRONGFACTION("You don't own this land."), - COMMAND_UNCLAIM_TOUNCLAIM("to unclaim this land"), - COMMAND_UNCLAIM_FORUNCLAIM("for unclaiming this land"), - COMMAND_UNCLAIM_FACTIONUNCLAIMED("%1$s unclaimed some land."), - COMMAND_UNCLAIM_DESCRIPTION("Unclaim the land where you are standing"), - - COMMAND_UNCLAIMALL_TOUNCLAIM("to unclaim all faction land"), - COMMAND_UNCLAIMALL_FORUNCLAIM("for unclaiming all faction land"), - COMMAND_UNCLAIMALL_UNCLAIMED("%1$s unclaimed ALL of your faction's land."), - COMMAND_UNCLAIMALL_LOG("%1$s unclaimed everything for the faction: %2$s"), - COMMAND_UNCLAIMALL_DESCRIPTION("Unclaim all of your factions land"), - COMMAND_UNCLAIM_CLICKTOUNCLAIM("Click to unclaim &2(%1$d, %2$d)"), - - COMMAND_VERSION_NAME("&c&l[!]&7 &c&k||| &r&4SavageFactions&7 &c&k|||&r &c» &7By ProSavage"), - COMMAND_VERSION_VERSION("&7Version &c» &7%1$s"), - COMMAND_VERSION_DESCRIPTION("Show plugin and translation version information"), - - COMMAND_WARUNCLAIMALL_DESCRIPTION("Unclaim all warzone land"), - COMMAND_WARUNCLAIMALL_SUCCESS("You unclaimed ALL war zone land."), - COMMAND_WARUNCLAIMALL_LOG("%1$s unclaimed all war zones."), - - COMMAND_RULES_DISABLED_MSG("&cThis command is disabled!"), - COMMAND_RULES_DESCRIPTION("set/remove/add rules!"), - COMMAND_RULES_ADD_INVALIDARGS("Please include a rule!"), - COMMAND_RULES_SET_INVALIDARGS("Please include a line number & rule!"), - COMMAND_RULES_REMOVE_INVALIDARGS("Please include a line number!"), - COMMAND_RULES_ADD_SUCCESS("&cRule added successfully!"), - COMMAND_RULES_REMOVE_SUCCESS("&cRule removed successfully!"), - COMMAND_RULES_SET_SUCCESS("&cRule set successfully!"), - COMMAND_RULES_CLEAR_SUCCESS("&cRule cleared successfully!"), - - /** - * Leaving - This is accessed through a command, and so it MAY need a COMMAND_* slug :s - */ - LEAVE_PASSADMIN("You must give the admin role to someone else first."), - LEAVE_NEGATIVEPOWER("You cannot leave until your power is positive."), - LEAVE_TOLEAVE("to leave your faction."), - LEAVE_FORLEAVE("for leaving your faction."), - LEAVE_LEFT("%s left faction %s."), - LEAVE_DISBANDED("%s was disbanded."), - LEAVE_DISBANDEDLOG("The faction %s (%s) was disbanded due to the last player (%s) leaving."), - LEAVE_DESCRIPTION("\\n &a&l» &7Leave your faction"), - - /** - * Claiming - Same as above basically. No COMMAND_* because it's not in a command class, but... - */ - CLAIM_PROTECTED("This land is protected"), - CLAIM_DISABLED("Sorry, this world has land claiming disabled."), - CLAIM_CANTCLAIM("You can't claim land for %s."), - CLAIM_ALREADYOWN("%s already own this land."), - CLAIM_MUSTBE("You must be %s to claim land."), - CLAIM_MEMBERS("Factions must have at least %s members to claim land."), - CLAIM_SAFEZONE("You can not claim a Safe Zone."), - CLAIM_WARZONE("You can not claim a War Zone."), - CLAIM_POWER("You can't claim more land!You need more power!"), - CLAIM_LIMIT("Limit reached. You can't claim more land!"), - CLAIM_ALLY("You can't claim the land of your allies."), - CLAIM_CONTIGIOUS("You can only claim additional land which is connected to your first claim or controlled by another faction!"), - CLAIM_FACTIONCONTIGUOUS("You can only claim additional land which is connected to your first claim!"), - CLAIM_PEACEFUL("%s owns this land. Your faction is peaceful, so you cannot claim land from other factions."), - CLAIM_PEACEFULTARGET("%s owns this land, and is a peaceful faction. You cannot claim land from them."), - CLAIM_THISISSPARTA("%s owns this land and is strong enough to keep it."), - CLAIM_BORDER("You must start claiming land at the border of the territory."), - CLAIM_TOCLAIM("to claim this land"), - CLAIM_FORCLAIM("for claiming this land"), - CLAIM_TOOVERCLAIM("to overclaim this land"), - CLAIM_FOROVERCLAIM("for over claiming this land"), - CLAIM_CLAIMED("%s claimed land for %s from %s."), - CLAIM_CLAIMEDLOG("%s claimed land at (%s) for the faction: %s"), - CLAIM_OVERCLAIM_DISABLED("Over claiming is disabled on this server."), - CLAIM_TOOCLOSETOOTHERFACTION("Your claim is too close to another Faction. Buffer required is %d"), - CLAIM_OUTSIDEWORLDBORDER("Your claim is outside the border."), - CLAIM_OUTSIDEBORDERBUFFER("Your claim is outside the border. %d chunks away world edge required."), - CLAIM_CLICK_TO_CLAIM("Click to try to claim &2(%1$d, %2$d)"), - CLAIM_MAP_OUTSIDEBORDER("&cThis claim is outside the worldborder!"), - CLAIM_YOUAREHERE("You are here"), - CLAIM_NO_TERRITORY_PERM("You do not have permission from your faction leader to do this!"), - - /** - * More generic, or less easily categorisable translations, which may apply to more than one class - */ - GENERIC_YOU("you"), - GENERIC_YOURFACTION("your faction"), - GENERIC_NOPERMISSION("You don't have permission to %1$s."), - GENERIC_FPERM_NOPERMISSION("&7The faction leader does not allow you to &c%1$s."), - GENERIC_DOTHAT("do that"), //Ugh nuke this from high orbit - GENERIC_NOPLAYERMATCH("No player match found for \"%1$s\"."), - GENERIC_NOPLAYERFOUND("No player \"%1$s\" could not be found."), - GENERIC_ARGS_TOOFEW("Too few arguments. Use like this:"), - GENERIC_ARGS_TOOMANY("Strange argument \"%1$s\". Use the command like this:"), - GENERIC_DEFAULTDESCRIPTION("Default faction description :("), - GENERIC_OWNERS("Owner(s): %1$s"), - GENERIC_PUBLICLAND("Public faction land."), - GENERIC_FACTIONLESS("factionless"), - GENERIC_SERVERADMIN("A server admin"), - GENERIC_DISABLED("disabled"), - GENERIC_ENABLED("enabled"), - GENERIC_INFINITY("∞"), - GENERIC_CONSOLEONLY("This command cannot be run as a player."), - GENERIC_PLAYERONLY("This command can only be used by ingame players."), - GENERIC_ASKYOURLEADER(" Ask your leader to:"), - GENERIC_YOUSHOULD("You should:"), - GENERIC_YOUMAYWANT("You may want to: "), - GENERIC_TRANSLATION_VERSION("Translation: %1$s(%2$s,%3$s) State: %4$s"), - GENERIC_TRANSLATION_CONTRIBUTORS("Translation contributors: %1$s"), - GENERIC_TRANSLATION_RESPONSIBLE("Responsible for translation: %1$s"), - GENERIC_FACTIONTAG_TOOSHORT("The faction tag can't be shorter than %1$s chars."), - GENERIC_FACTIONTAG_TOOLONG("The faction tag can't be longer than %s chars."), - GENERIC_FACTIONTAG_ALPHANUMERIC("Faction tag must be alphanumeric. \"%s\" is not allowed."), - GENERIC_PLACEHOLDER(""), - GENERIC_NOTENOUGHMONEY("&cYou dont have enough money!"), - GENERIC_MONEYTAKE("&c{amount} has been taken from your account."), - - - WARBANNER_NOFACTION("&cYou need a faction to use a warbanner!"), - WARBANNER_COOLDOWN("&cThe warbanner is on cooldown for your faction!"), - WARBANNER_INVALIDLOC("&cYou can only use warbanners in enemy land or the warzone"), - - /** - * ASCII compass (for chat map) - */ - COMPASS_SHORT_NORTH("N"), - COMPASS_SHORT_EAST("E"), - COMPASS_SHORT_SOUTH("S"), - COMPASS_SHORT_WEST("W"), - - /** - * Chat modes - */ - CHAT_MOD("mod chat"), - CHAT_FACTION("faction chat"), - CHAT_ALLIANCE("alliance chat"), - CHAT_TRUCE("truce chat"), - CHAT_PUBLIC("public chat"), - - /** - * Economy stuff - */ - - ECON_OFF("no %s"), // no balance, no value, no refund, etc - ECON_FORMAT("###,###.###"), - - /** - * Relations - */ - RELATION_MEMBER_SINGULAR("member"), - RELATION_MEMBER_PLURAL("members"), - RELATION_ALLY_SINGULAR("ally"), - RELATION_ALLY_PLURAL("allies"), - RELATION_TRUCE_SINGULAR("truce"), - RELATION_TRUCE_PLURAL("truces"), - RELATION_NEUTRAL_SINGULAR("neutral"), - RELATION_NEUTRAL_PLURAL("neutrals"), - RELATION_ENEMY_SINGULAR("enemy"), - RELATION_ENEMY_PLURAL("enemies"), - - /** - * Roles - */ - ROLE_LEADER("leader"), - ROLE_COLEADER("coleader"), - ROLE_MODERATOR("moderator"), - ROLE_NORMAL("normal member"), - ROLE_RECRUIT("recruit"), - - /** - * Region types. - */ - REGION_SAFEZONE("safezone"), - REGION_WARZONE("warzone"), - REGION_WILDERNESS("wilderness"), - - REGION_PEACEFUL("peaceful territory"), - /** - * In the player and entity listeners - */ - PLAYER_CANTHURT("You may not harm other players in %s"), - PLAYER_SAFEAUTO("This land is now a safe zone."), - PLAYER_WARAUTO("This land is now a war zone."), - PLAYER_OUCH("Ouch, that is starting to hurt. You should give it a rest."), - PLAYER_USE_WILDERNESS("You can't use %s in the wilderness."), - PLAYER_USE_SAFEZONE("You can't use %s in a safe zone."), - PLAYER_USE_WARZONE("You can't use %s in a war zone."), - PLAYER_USE_TERRITORY("You can't %s in the territory of %s."), - PLAYER_USE_OWNED("You can't use %s in this territory, it is owned by: %s."), - PLAYER_COMMAND_WARZONE("You can't use the command '%s' in warzone."), - PLAYER_COMMAND_NEUTRAL("You can't use the command '%s' in neutral territory."), - PLAYER_COMMAND_ENEMY("You can't use the command '%s' in enemy territory."), - PLAYER_COMMAND_PERMANENT("You can't use the command '%s' because you are in a permanent faction."), - PLAYER_COMMAND_ALLY("You can't use the command '%s' in ally territory."), - PLAYER_COMMAND_WILDERNESS("You can't use the command '%s' in the wilderness."), - - PLAYER_POWER_NOLOSS_PEACEFUL("You didn't lose any power since you are in a peaceful faction."), - PLAYER_POWER_NOLOSS_WORLD("You didn't lose any power due to the world you died in."), - PLAYER_POWER_NOLOSS_WILDERNESS("You didn't lose any power since you were in the wilderness."), - PLAYER_POWER_NOLOSS_WARZONE("You didn't lose any power since you were in a war zone."), - PLAYER_POWER_LOSS_WARZONE("The world you are in has power loss normally disabled, but you still lost power since you were in a war zone.\nYour power is now %d / %d"), - PLAYER_POWER_NOW("Your power is now %d / %d"), - - PLAYER_PVP_LOGIN("You can't hurt other players for %d seconds after logging in."), - PLAYER_PVP_REQUIREFACTION("You can't hurt other players until you join a faction."), - PLAYER_PVP_FACTIONLESS("You can't hurt players who are not currently in a faction."), - PLAYER_PVP_PEACEFUL("Peaceful players cannot participate in combat."), - PLAYER_PVP_NEUTRAL("You can't hurt neutral factions. Declare them as an enemy."), - PLAYER_PVP_CANTHURT("You can't hurt %s."), - - PLAYER_PVP_NEUTRALFAIL("You can't hurt %s in their own territory unless you declare them as an enemy."), - PLAYER_PVP_TRIED("%s tried to hurt you."), - - /** - * Strings lying around in other bits of the plugins - */ - NOPAGES("Sorry. No Pages available."), - INVALIDPAGE("Invalid page. Must be between 1 and %1$d"), - - /** - * The ones here before I started messing around with this - */ - TITLE("title", "&bFactions &0|&r"), - WILDERNESS("wilderness", "&2Wilderness"), - WILDERNESS_DESCRIPTION("wilderness-description", ""), - WARZONE("warzone", "&4Warzone"), - WARZONE_DESCRIPTION("warzone-description", "Not the safest place to be."), - SAFEZONE("safezone", "&6Safezone"), - SAFEZONE_DESCRIPTION("safezone-description", "Free from pvp and monsters."), - TOGGLE_SB("toggle-sb", "You now have scoreboards set to {value}"), - FACTION_LEAVE("faction-leave", "Leaving %1$s, Entering %2$s"), - FACTIONS_ANNOUNCEMENT_TOP("faction-announcement-top", "&d--Unread Faction Announcements--"), - FACTIONS_ANNOUNCEMENT_BOTTOM("faction-announcement-bottom", "&d--Unread Faction Announcements--"), - DEFAULT_PREFIX("default-prefix", "{relationcolor}[{faction}]"), - FACTION_LOGIN("faction-login", "&e%1$s &9logged in."), - FACTION_LOGOUT("faction-logout", "&e%1$s &9logged out.."), - NOFACTION_PREFIX("nofactions-prefix", "&6[&a4-&6]&r"), - DATE_FORMAT("date-format", "MM/d/yy h:ma"), // 3/31/15 07:49AM - - /** - * Raidable is used in multiple places. Allow more than just true/false. - */ - RAIDABLE_TRUE("raidable-true", "true"), - RAIDABLE_FALSE("raidable-false", "false"), - /** - * Warmups - */ - WARMUPS_NOTIFY_FLIGHT("&eFlight will enable in &d%2$d &eseconds."), - WARMUPS_NOTIFY_TELEPORT("&eYou will teleport to &d%1$s &ein &d%2$d &eseconds."), - WARMUPS_ALREADY("&cYou are already warming up."), - WARMUPS_CANCELLED("&cYou have cancelled your warmup."); - - public static SimpleDateFormat sdf; - private static YamlConfiguration LANG; - private String path; - private String def; - - /** - * Lang enum constructor. - * - * @param path The string path. - * @param start The default string. - */ - TL(String path, String start) { - this.path = path; - this.def = start; - } - - /** - * Lang enum constructor. Use this when your desired path simply exchanges '_' for '.' - * - * @param start The default string. - */ - TL(String start) { - this.path = this.name().replace('_', '.'); - if (this.path.startsWith(".")) { - path = "root" + path; - } - this.def = start; - } - - /** - * Set the {@code YamlConfiguration} to use. - * - * @param config The config to set. - */ - public static void setFile(YamlConfiguration config) { - LANG = config; - sdf = new SimpleDateFormat(DATE_FORMAT.toString()); - } - - @Override - public String toString() { - return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def)) + (this == TITLE ? " " : ""); - } - - public String format(Object... args) { - return String.format(toString(), args); - } - - /** - * Get the default value of the path. - * - * @return The default value of the path. - */ - public String getDefault() { - return this.def; - } - - /** - * Get the path to the string. - * - * @return The path to the string. - */ - public String getPath() { - return this.path; - } + /** + * Translation meta + */ + _AUTHOR("misc"), + _RESPONSIBLE("misc"), + _LANGUAGE("English"), + _ENCODING("UTF-8"), + _LOCALE("en_US"), + _REQUIRESUNICODE("false"), + _DEFAULT("true"), + _STATE("complete"), //incomplete, limited, partial, majority, complete + + /** + * Localised translation meta + */ + _LOCAL_AUTHOR("misc"), + _LOCAL_RESPONSIBLE("misc"), + _LOCAL_LANGUAGE("English"), + _LOCAL_REGION("US"), + _LOCAL_STATE("complete"), //And this is the English version. It's not ever going to be not complete. + + /** + * Command translations + */ + + /** + * Messsges for /f help + */ + COMMAND_HELP_NEXTCREATE("Learn how to create a faction on the next page."), + COMMAND_HELP_INVITATIONS("command.help.invitations", "You might want to close it and use invitations:"), + COMMAND_HELP_HOME("And don't forget to set your home:"), + COMMAND_HELP_404("&c&l» &7This page does &cnot &7exist"), + COMMAND_HELP_BANK_1("Your faction has a bank which is used to pay for certain"), //Move to last /f help page + COMMAND_HELP_BANK_2("things, so it will need to have money deposited into it."), //Move to last /f help page + COMMAND_HELP_BANK_3("To learn more, use the money command."), //Move to last /f help page + COMMAND_HELP_PLAYERTITLES("Player titles are just for fun. No rules connected to them."), //Move to last /f help page + COMMAND_HELP_OWNERSHIP_1("Claimed land with ownership set is further protected so"), //Move to last /f help page + COMMAND_HELP_OWNERSHIP_2("that only the owner(s), faction admin, and possibly the"), //Move to last /f help page + COMMAND_HELP_OWNERSHIP_3("faction moderators have full access."), //Move to last /f help page + COMMAND_HELP_RELATIONS_1("Set the relation you WISH to have with another faction."), //Move to last /f help page + COMMAND_HELP_RELATIONS_2("Your default relation with other factions will be neutral."), //Move to last /f help page + COMMAND_HELP_RELATIONS_3("If BOTH factions choose \"ally\" you will be allies."), //Move to last /f help page + COMMAND_HELP_RELATIONS_4("If ONE faction chooses \"enemy\" you will be enemies."), //Move to last /f help page + COMMAND_HELP_RELATIONS_5("You can never hurt members or allies."), //Move to last /f help page + COMMAND_HELP_RELATIONS_6("You can not hurt neutrals in their own territory."), //Move to last /f help page + COMMAND_HELP_RELATIONS_7("You can always hurt enemies and players without faction."), //Move to last /f help page + COMMAND_HELP_RELATIONS_8(""), + COMMAND_HELP_RELATIONS_9("Damage from enemies is reduced in your own territory."), //Move to last /f help page + COMMAND_HELP_RELATIONS_10("When you die you lose power. It is restored over time."), //Move to last /f help page + COMMAND_HELP_RELATIONS_11("The power of a faction is the sum of all member power."), //Move to last /f help page + COMMAND_HELP_RELATIONS_12("The power of a faction determines how much land it can hold."), //Move to last /f help page + COMMAND_HELP_RELATIONS_13("You can claim land from factions with too little power."), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_1("Only faction members can build and destroy in their own"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_2("territory. Usage of the following items is also restricted:"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_3("Door, Chest, Furnace, Dispenser, Diode."), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_4(""), + COMMAND_HELP_PERMISSIONS_5("Make sure to put pressure plates in front of doors for your"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_6("guest visitors. Otherwise they can't get through. You can"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_7("also use this to create member only areas."), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_8("As dispensers are protected, you can create traps without"), //Move to last /f help page + COMMAND_HELP_PERMISSIONS_9("worrying about those arrows getting stolen."), //Move to last /f help page + COMMAND_HELP_ADMIN_1("&a&l» &a/f claim safezone \n &7claim land for the Safe Zone"), + COMMAND_HELP_ADMIN_2("&a&l» &a/f claim warzone \n &7claim land for the War Zone"), + COMMAND_HELP_ADMIN_3("&a&l» &a/f autoclaim [safezone|warzone] \n &7take a guess"), + COMMAND_HELP_MOAR_1("Finally some commands for the server admins:"), + COMMAND_HELP_MOAR_2("More commands for server admins:"), + COMMAND_HELP_MOAR_3("Even more commands for server admins:"), + COMMAND_HELP_DESCRIPTION("\n &a&l» &7Display a &ahelp &7page"), + + COMMAND_NEAR_DESCRIPTION("Get nearby faction players in a radius."), + COMMAND_NEAR_DISABLED_MSG("&cThis command is disabled!"), + COMMAND_NEAR_FORMAT("{playername} &c({distance}m)"), + COMMAND_NEAR_USE_MSG("&cFaction members nearby"), + + /** + * Messsges for Faction Admins/Mods + */ + + COMMAND_UPGRADES_DESCRIPTION("&cOpen the Upgrades Menu"), + + COMMAND_ADMIN_NOTMEMBER("&c&l[!] &7%1$s &cis not a member in your faction."), + COMMAND_ADMIN_NOTADMIN("&c&l[!] &cYou are not the faction admin."), + COMMAND_ADMIN_TARGETSELF("'&c&l[!] &cThe target player musn''t be yourself."), + COMMAND_ADMIN_DEMOTES("&c&l[!] &cYou have demoted &7%1$s &cfrom the position of faction admin."), + COMMAND_ADMIN_DEMOTED("&c&l[!] &cYou have been demoted from the position of faction admin by &7%1$s&c"), + COMMAND_ADMIN_PROMOTES("&e&l[!] &eYou have promoted &6%1$s &eto the position of faction admin."), + COMMAND_ADMIN_PROMOTED("&e&l[!] &6%1$s &egave &6%2$s ðe leadership of &6%3$s&e."), + COMMAND_ADMIN_DESCRIPTION("Hand over your admin rights"), + COMMAND_ADMIN_NOMEMBERS("&e&l[!] &cNo one else to promote, please disband faction."), + + COMMAND_AHOME_DESCRIPTION("Send a player to their f home no matter what."), + COMMAND_AHOME_NOHOME("%1$s doesn't have an f home."), + COMMAND_AHOME_SUCCESS("$1%s was sent to their f home."), + COMMAND_AHOME_OFFLINE("%1$s is offline."), + COMMAND_AHOME_TARGET("You were sent to your f home."), + + COMMAND_ANNOUNCE_DESCRIPTION("Announce a message to players in faction."), + + COMMAND_FREECAM_ENEMYINRADIUS("Freecam disabled, An enemy is closeby!"), + COMMAND_FREECAM_OUTSIDEFLIGHT("Please dont leave the flight radius!"), + COMMAND_FREECAM_ENABLED("Freecam is now enabled!"), + COMMAND_FREECAM_DISABLED("Freecam is now disabled"), + COMMAND_FREECAM_DESCRIPTION("Go into spectator mode"), + + + COMMAND_AUTOCLAIM_ENABLED("&c&l[!] &7Now &cauto-claiming&7 land for %1$s."), + COMMAND_AUTOCLAIM_DISABLED("&c&l[!] Auto-claiming&7 of land is now &cdisabled."), + COMMAND_AUTOCLAIM_REQUIREDRANK("&c&l[!] &7You must be &c%1$s&7 to claim land."), + COMMAND_AUTOCLAIM_OTHERFACTION("&c&l[!]&7 You &ccan't &7claim land for &c%1$s&7."), + COMMAND_AUTOCLAIM_DESCRIPTION("Auto-claim land as you walk around"), + + COMMAND_AUTOHELP_HELPFOR("Help for command \""), + + COMMAND_BAN_DESCRIPTION("Ban players from joining your Faction."), + COMMAND_BAN_TARGET("&c&l[!] &7You were &cbanned &7from &c%1$s"), // banned player perspective + COMMAND_BAN_BANNED("&c&l[!] &7%1$s &cbanned &7%2$s"), + COMMAND_BAN_SELF("&c&l[!] &7You may &cnot &7ban &cyourself&7."), + COMMAND_BAN_INSUFFICIENTRANK("&c&l[!] &7Your &crank &7is too low to&c ban &7%1$s"), + COMMAND_BAN_ALREADYBANNED("&c&l[!] &7This player is &calready banned&7!"), + + COMMAND_BANLIST_DESCRIPTION("View a Faction's ban list"), + COMMAND_BANLIST_HEADER("&c&l[!] &7There are &c%d&7 bans for &c%s"), + COMMAND_BANLIST_ENTRY("&7%d. &c%s &r&7// &c%s &r&7// &c%s"), + COMMAND_BANLIST_NOFACTION("&c&l[!] &7You are &cnot &7in a Faction."), + COMMAND_BANLIST_INVALID("&c&l[!] &7The faction &c%s &7does not exist"), + + COMMAND_BOOM_PEACEFULONLY("&c&l[!] &7This command is &conly &7usable by factions which are &cspecifically &7designated as &cpeaceful&7."), + COMMAND_BOOM_TOTOGGLE("to toggle explosions"), + COMMAND_BOOM_FORTOGGLE("for toggling explosions"), + COMMAND_BOOM_ENABLED("&c&l[!] &c%1$s&7 has&c %2$s&7 explosions in your faction's territory."), + COMMAND_BOOM_DESCRIPTION("Toggle explosions (peaceful factions only)"), + + + COMMAND_BYPASS_ENABLE("&e&l[!] &eYou have enabled admin bypass mode. You will be able to build or destroy anywhere."), + COMMAND_BYPASS_ENABLELOG(" has ENABLED admin bypass mode."), + COMMAND_BYPASS_DISABLE("&c&l[!] &cYou have disabled admin bypass mode."), + COMMAND_BYPASS_DISABLELOG(" has DISABLED admin bypass mode."), + COMMAND_BYPASS_DESCRIPTION("Enable admin bypass mode"), + + COMMAND_BANNER_DESCRIPTION("Turn a held banner into a war banner"), + COMMAND_BANNER_NOTENOUGHMONEY("&c&l[!] &7You do&c not&7 have enough money"), + COMMAND_BANNER_MONEYTAKE("&c&l[!] $&c{amount} &7has been taken from your account."), + COMMAND_BANNER_SUCCESS("&c&l[!] &7You have created a &c&lWarBanner!"), + COMMAND_BANNER_DISABLED("&c&l[!] &7Buying&c warbanners&7 is &cdisabled!"), + + COMMAND_TPBANNER_NOTSET("&c&l[!] &7Your faction &cdoes not &7have a &c&lWarBanner &7placed!"), + COMMAND_TPBANNER_SUCCESS("&c&l[!] &cTeleporting &7to your factions's &c&lWarBanner"), + COMMAND_TPBANNER_DESCRIPTION("Teleport to your faction banner"), + + + COMMAND_CHAT_DISABLED("&c&l[!] &7The built in chat channels are &cdisabled &7on this server."), + COMMAND_CHAT_INVALIDMODE("&c&l[!] &cUnrecognised &7chat mode. Please enter either '&da&7','&af&7','&6m&7' or '&fp&7'"), + COMMAND_CHAT_DESCRIPTION("Change chat mode"), + + COMMAND_CHAT_MODE_PUBLIC("&c&l[!] &fPublic &7chat mode."), + COMMAND_CHAT_MODE_ALLIANCE("&c&l[!] &dAlliance &7only chat mode."), + COMMAND_CHAT_MODE_TRUCE("&c&l[!] &5Truce &7only chat mode."), + COMMAND_CHAT_MODE_FACTION("&c&l[!] &aFaction&7 only chat mode."), + COMMAND_CHAT_MODE_MOD("&c&l[!] &dMod &7only chat mode."), + COMMAND_CHAT_MOD_ONLY("&c&l[!] &7Only Mods can talk through this chat mode."), + + COMMAND_CHATSPY_ENABLE("&c&l[!] &7You have &cenabled &7chat spying mode."), + COMMAND_CHATSPY_ENABLELOG(" has ENABLED chat spying mode."), + COMMAND_CHATSPY_DISABLE("&c&l[!] &7You have &cdisabled &7chat spying mode."), + COMMAND_CHATSPY_DISABLELOG(" has DISABLED chat spying mode."), + COMMAND_CHATSPY_DESCRIPTION("Enable admin chat spy mode"), + + COMMAND_CLAIM_INVALIDRADIUS("&c&l[!]&7 If you specify a &cradius&7, it must be at least &c1&7."), + COMMAND_CLAIM_DENIED("&c&l[!]&7 You &cdo not &7have &cpermission&7 to &cclaim&7 in a radius."), + COMMAND_CLAIM_DESCRIPTION("Claim land from where you are standing"), + + COMMAND_CLAIMLINE_INVALIDRADIUS("&c&l[!]&7 If you &cspecify&7 a distance, it must be at least &c1&7."), + COMMAND_CLAIMLINE_DENIED("&c&l[!]&7 You &cdo not &7have&c permission&7 to claim in a line."), + COMMAND_CLAIMLINE_DESCRIPTION("Claim land in a straight line."), + COMMAND_CLAIMLINE_ABOVEMAX("&c&l[!]&7 The &cmaximum&7 limit for claim line is &c%s&7."), + COMMAND_CLAIMLINE_NOTVALID("&c&l[!]&7 &c%s&7 is not a &ccardinal &7direction. You may use &cnorth&7, &ceast&7, &csouth &7or &cwest&7."), + + COMMAND_CONFIG_NOEXIST("&c&l[!]&7 No configuration setting \"&c%1$s&7\" exists."), + COMMAND_CONFIG_SET_TRUE("\" option set to true (enabled)."), + COMMAND_CONFIG_SET_FALSE("\" option set to false (disabled)."), + COMMAND_CONFIG_OPTIONSET("\" option set to "), + COMMAND_CONFIG_COLOURSET("\" color option set to \""), + COMMAND_CONFIG_INTREQUIRED("Cannot set \"%1$s\": An integer (whole number) value required."), + COMMAND_CONFIG_LONGREQUIRED("Cannot set \"%1$s\": A long integer (whole number) value required."), + COMMAND_CONFIG_DOUBLEREQUIRED("Cannot set \"%1$s\": A double (numeric) value required."), + COMMAND_CONFIG_FLOATREQUIRED("Cannot set \"%1$s\": A float (numeric) value required."), + COMMAND_CONFIG_INVALID_COLOUR("Cannot set \"%1$s\": \"%2$s\" is not a valid color."), + COMMAND_CONFIG_INVALID_COLLECTION("\"%1$s\" is not a data collection type which can be modified with this command."), + COMMAND_CONFIG_INVALID_MATERIAL("Cannot change \"%1$s\" set: \"%2$s\" is not a valid material."), + COMMAND_CONFIG_INVALID_TYPESET("\"%1$s\" is not a data type set which can be modified with this command."), + COMMAND_CONFIG_MATERIAL_ADDED("\"%1$s\" set: Material \"%2$s\" added."), + COMMAND_CONFIG_MATERIAL_REMOVED("\"%1$s\" set: Material \"%2$s\" removed."), + COMMAND_CONFIG_SET_ADDED("\"%1$s\" set: \"%2$s\" added."), + COMMAND_CONFIG_SET_REMOVED("\"%1$s\" set: \"%2$s\" removed."), + COMMAND_CONFIG_LOG(" (Command was run by %1$s.)"), + COMMAND_CONFIG_ERROR_SETTING("Error setting configuration setting \"%1$s\" to \"%2$s\"."), + COMMAND_CONFIG_ERROR_MATCHING("Configuration setting \"%1$s\" couldn't be matched, though it should be... please report this error."), + COMMAND_CONFIG_ERROR_TYPE("'%1$s' is of type '%2$s', which cannot be modified with this command."), + COMMAND_CONFIG_DESCRIPTION("Change a conf.json setting"), + + COMMAND_CONVERT_BACKEND_RUNNING("&c&l[!]&7 Already running that backend."), + COMMAND_CONVERT_BACKEND_INVALID("&c&l[!]&7 Invalid backend"), + COMMAND_CONVERT_DESCRIPTION("Convert the plugin backend"), + + COMMAND_COORDS_MESSAGE("&c&l[!] &7{player}&7's coords are &c{x}&7,&c{y}&7,&c{z}&7 in &c{world}"), + COMMAND_COORDS_DESCRIPTION("broadcast your coords to your faction"), + + COMMAND_CHECKPOINT_DISABLED("&c&l[!]&7 You &ccannot&7 use checkpoint while its&c disabled&7!"), + COMMAND_CHECKPOINT_SET("&c&l[!]&7 You have &cset&7 the &cfaction checkpoint&7 at your &cLocation&7."), + COMMAND_CHECKPOINT_GO("&c&l[!]&7 &cTeleporting&7 to &cfaction checkpoint"), + COMMAND_CHECKPOINT_INVALIDLOCATION("&c&l[!]&7 &cInvalid Location!&7 You can &cset&7 checkpoints in &cyour claims&7 or &2wilderness&7."), + COMMAND_CHECKPOINT_NOT_SET("&c&l[!]&7 You have to &cset &7the &cfaction checkpoint&7 first."), + COMMAND_CHECKPOINT_CLAIMED("&c&l[!]&7 Your current &cfaction checkpoint&7 is claimed, set a &cnew &7one!"), + COMMAND_CHECKPOINT_DESCRIPTION("Set or go to your faction checkpoint!"), + + COMMAND_CREATE_MUSTLEAVE("&c&l[!]&7 You must &cleave &7your &ccurrent faction &7first."), + COMMAND_CREATE_INUSE("&c&l[!]&7 That tag is &calready &7in use."), + COMMAND_CREATE_TOCREATE("to create a new faction"), + COMMAND_CREATE_FORCREATE("for creating a new faction"), + COMMAND_CREATE_ERROR("&c&l[!]&7 There was an &cinternal error&7 while trying to create your faction. &cPlease try again&7."), + COMMAND_CREATE_CREATED("&c&l[!]&7 &c%1$s &7created a new faction &c&l%2$s"), + COMMAND_CREATE_YOUSHOULD("&c&l[!]&7 You should now: &c%1$s"), + COMMAND_CREATE_CREATEDLOG(" created a new faction: "), + COMMAND_CREATE_DESCRIPTION("Create a new faction"), + + COMMAND_DEINVITE_CANDEINVITE("&c&l[!]&7 Players you can &cdeinvite: "), + COMMAND_DEINVITE_CLICKTODEINVITE("&c&l[!]&7 Click to &crevoke&7 invite for &c%1$s"), + COMMAND_DEINVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of &c%2$s"), + COMMAND_DEINVITE_MIGHTWANT("&c&l[!]&7 You might want to: &c%1$s"), + COMMAND_DEINVITE_REVOKED("&c&l[!]&7 &7%1$s &crevoked&7 your invitation to &c%2$s&7."), + COMMAND_DEINVITE_REVOKES("&c&l[!]&7 %1$s&c revoked &7%2$s's&c invitation."), + COMMAND_DEINVITE_DESCRIPTION("Remove a pending invitation"), + + COMMAND_DELFWARP_DELETED("&c&l[!]&7 Deleted warp &c%1$s"), + COMMAND_DELFWARP_INVALID("&c&l[!]&7 Couldn't &cfind&7 warp &c%1$s"), + COMMAND_DELFWARP_TODELETE("to delete warp"), + COMMAND_DELFWARP_FORDELETE("for deleting warp"), + COMMAND_DELFWARP_DESCRIPTION("Delete a faction warp"), + + COMMAND_DESCRIPTION_CHANGES("&c&l[!]&7 You have &cchanged&7 the &cdescription&7 for &c%1$s&7 to:"), + COMMAND_DESCRIPTION_CHANGED("&c&l[!]&7 The faction&c %1$s&7 changed their &cdescription &7to:"), + COMMAND_DESCRIPTION_TOCHANGE("to change faction description"), + COMMAND_DESCRIPTION_FORCHANGE("for changing faction description"), + COMMAND_DESCRIPTION_DESCRIPTION("Change the faction description"), + + COMMAND_DISBAND_IMMUTABLE("&c&l[!]&7 &7You &ccannot&7 disband &2Wilderness&7,&e SafeZone&7, or &4WarZone."), + COMMAND_DISBAND_MARKEDPERMANENT("&c&l[!]&7 This faction is designated as&c permanent&7, so you cannot disband it."), + COMMAND_DISBAND_BROADCAST_YOURS("&c&l[!]&7 &c%1$s&7 disbanded your &cfaction."), + COMMAND_DISBAND_BROADCAST_NOTYOURS("&c&l[!]&7 &c%1$s &7disbanded the faction &c%2$s."), + COMMAND_DISBAND_HOLDINGS("&c&l[!]&7 &7You have been given the disbanded &cfaction's bank&7, totaling &c%1$s."), + COMMAND_DISBAND_PLAYER("&c&l[!] &7You have disbanded your &cfaction"), + COMMAND_DISBAND_CONFIRM("&c&l[!]&7 Your Faction has&c {tnt} &7tnt left in the bank, it will be &clost&7 if the faction is &cdisbanded&7. Type&c /f disband &7again within &c10&7 seconds to&c disband&7."), + COMMAND_DISBAND_DESCRIPTION("Disband a faction"), + + COMMAND_FLY_DISABLED("&c&l[!]&7 Sorry, Faction flight is &cdisabled &7on this server"), + COMMAND_FLY_DESCRIPTION("Enter or leave Faction flight mode"), + COMMAND_FLY_CHANGE("&c&l[!]&7 Faction flight &c%1$s"), + COMMAND_FLY_COOLDOWN("&c&l[!]&7 You will &cnot&7 take fall damage for &c{amount}&7 seconds"), + COMMAND_FLY_DAMAGE("&c&l[!]&7 Faction flight &cdisabled&7 due to entering combat"), + COMMAND_FLY_NO_ACCESS("&c&l[!]&7 &cCannot fly &7in territory of %1$s"), + COMMAND_FLY_ENEMY_NEAR("&c&l[!]&7 Flight has been&c disabled&7 an enemy is nearby"), + COMMAND_FLY_CHECK_ENEMY("&c&l[!]&7 Cannot fly here, an enemy is &cnearby"), + COMMAND_FLY_NO_EPEARL("&c&l[!] &7You &ccannot&7 throw enderpearls while flying!"), + + COMMAND_FOCUS_SAMEFACTION("&c[!] You may not focus players in your faction!"), + COMMAND_FOCUS_FOCUSING("&c&l[!] &7Your faction is now focusing &c%s"), + COMMAND_FOCUS_NO_LONGER("&c&l[!] &7Your faction is no longer focusing &c%s"), + COMMAND_FOCUS_DESCRIPTION("Focus a Specific Player"), + + + COMMAND_FWARP_CLICKTOWARP("&c&l[!]&7 Click to &cwarp!"), + COMMAND_FWARP_COMMANDFORMAT("&c&l[!]&7 /f warp &c[password]"), + COMMAND_FWARP_WARPED("&c&l[!]&7 Warped to &c%1$s"), + COMMAND_FWARP_INVALID_WARP("&c&l[!]&7 Couldn't find warp &c%1$s"), + COMMAND_FWARP_TOWARP("to warp"), + COMMAND_FWARP_FORWARPING("for warping"), + COMMAND_FWARP_WARPS("Warps: "), + COMMAND_FWARP_DESCRIPTION("Teleport to a faction warp"), + COMMAND_FWARP_INVALID_PASSWORD("&c&l[!]&7 &cInvalid password!"), + COMMAND_FWARP_PASSWORD_REQUIRED("&c&l[!]&c Warp Password:"), + COMMAND_FWARP_PASSWORD_TIMEOUT("&c&l[!]&7 Warp password &ccanceled"), + + COMMAND_HINT_PERMISSION("&aYou can manage your factions permissions using &7/f perms"), + + COMMAND_HOME_DISABLED("&c&l[!]&7 Sorry, Faction homes are &cdisabled on this server."), + COMMAND_HOME_TELEPORTDISABLED("&c&l[!]&7 Sorry, the ability to &cteleport &7to Faction homes is &cdisabled &7on this server."), + COMMAND_HOME_NOHOME("&c&l[!]&7 Your faction does &cnot &7have a home. "), + COMMAND_HOME_INENEMY("&c&l[!]&7 You &ccannot teleport &7to your &cfaction home&7 while in the territory of an &cenemy faction&7."), + COMMAND_HOME_WRONGWORLD("&c&l[!]&7 You &ccannot &7teleport to your &cfaction home&7 while in a different world."), + COMMAND_HOME_ENEMYNEAR("&c&l[!]&7 You &ccannot teleport&7 to your faction home while an enemy is within &c%s&7 blocks of you."), + COMMAND_HOME_TOTELEPORT("to teleport to your faction home"), + COMMAND_HOME_FORTELEPORT("for teleporting to your faction home"), + COMMAND_HOME_DESCRIPTION("Teleport to the faction home"), + COMMAND_HOME_BLOCKED("&c&l[!] You may not teleport to a home that is claimed by &b%1$s"), + + COMMAND_INSPECT_DISABLED_MSG("&c&l[!]&7 Inspect mode is now &cdisabled."), + COMMAND_INSPECT_DISABLED_NOFAC("&c&l[!]&7 Inspect mode is now &cdisabled,&7 because you &cdo not have a faction!"), + COMMAND_INSPECT_ENABLED("&c&l[!]&7 Inspect mode is now &aEnabled."), + COMMAND_INSPECT_HEADER("&c&m---&7Inspect Data&c&m---&c//&7x:{x},y:{y},z:{z}"), + COMMAND_INSPECT_ROW("&c{time} &7// &c{action} &7// &c{player} &7// &c{block-type}"), + COMMAND_INSPECT_NODATA("&c&l[!]&7 &7No Data was found!"), + COMMAND_INSPECT_NOTINCLAIM("&c&l[!]&7 &7You can &conly&7 inspect in &cyour &7claims!"), + COMMAND_INSPECT_BYPASS("&c&l[!]&7 Inspecting in &cbypass&7 mode"), + COMMAND_INSPECT_DESCRIPTION("Inspect blocks!"), + + COMMAND_INVITE_TOINVITE("to invite someone"), + COMMAND_INVITE_FORINVITE("for inviting someone"), + COMMAND_INVITE_CLICKTOJOIN("Click to join!"), + COMMAND_INVITE_INVITEDYOU(" &chas invited you to join "), + COMMAND_INVITE_INVITED("&c&l[!]&7 &c%1$s&7 invited &c%2$s&7 to your faction."), + COMMAND_INVITE_ALREADYMEMBER("&c&l[!]&7 &c%1$s&7 is already a member of&c %2$s"), + COMMAND_INVITE_ALREADYINVITED("&c&l[!]&7 &c%1$s&7 has already been invited"), + COMMAND_INVITE_DESCRIPTION("Invite a player to your faction"), + COMMAND_INVITE_BANNED("&c&l[!]&7 &7%1$s &cis banned &7from your Faction. &cNot &7sending an invite."), + + COMMAND_JOIN_CANNOTFORCE("&c&l[!]&7 You&c do not&7 have permission to &cmove other players&7 into a faction."), + COMMAND_JOIN_SYSTEMFACTION("&c&l[!]&7 Players may only join &cnormal factions&7. This is a &c&lsystem faction&7."), + COMMAND_JOIN_ALREADYMEMBER("&c&l[!]&7 &c%1$s %2$s already a member of&c %3$s"), + COMMAND_JOIN_ATLIMIT(" &c&l[!]&7 The faction &c%1$s &7is at the limit of&c %2$d&7 members, so&c %3$s&7 cannot currently join."), + COMMAND_JOIN_INOTHERFACTION("&c&l[!]&7 &c%1$s &7must leave&c %2$s &7current faction first."), + COMMAND_JOIN_NEGATIVEPOWER("&c&l[!]&7 &c%1$s &7cannot join a faction with a &cnegative power&7 level."), + COMMAND_JOIN_REQUIRESINVITATION("&c&l[!]&7 This faction &crequires&7 an invitation."), + COMMAND_JOIN_ATTEMPTEDJOIN("&c&l[!]&7 &c%1$s&7 tried to join your faction."), + COMMAND_JOIN_TOJOIN("to join a faction"), + COMMAND_JOIN_FORJOIN("for joining a faction"), + COMMAND_JOIN_SUCCESS("&c&l[!]&7 &c%1$s &7successfully joined &c%2$s."), + COMMAND_JOIN_MOVED("&c&l[!]&7 &c%1$s &7moved you into the faction&c %2$s."), + COMMAND_JOIN_JOINED("&c&l[!]&7 &c%1$s &7joined your faction."), + COMMAND_JOIN_JOINEDLOG("&c&l[!]&7 &c%1$s&7 joined the faction&c %2$s."), + COMMAND_JOIN_MOVEDLOG("&c&l[!]&7 &c%1$s &7moved the player&c %2$s &7into the faction&c %3$s&7."), + COMMAND_JOIN_DESCRIPTION("&a&l» &7Join a faction"), + COMMAND_JOIN_BANNED("&c&l[!]&7 You are &cbanned &7from &c%1$s."), + + COMMAND_KICK_CANDIDATES("&c&l[!]&7 Players you can kick: "), + COMMAND_KICK_CLICKTOKICK("Click to kick "), + COMMAND_KICK_SELF("&c&l[!]&7 You &ccannot &7kick&c yourself&7."), + COMMAND_KICK_NONE("&c&l[!]&7 That player&c is not&7 in a faction."), + COMMAND_KICK_NOTMEMBER("&c&l[!]&7 &c%1$s is not a member of %2$s"), + COMMAND_KICK_INSUFFICIENTRANK("&c&l[!]&7 Your rank is &ctoo low &7to kick this player."), + COMMAND_KICK_NEGATIVEPOWER("&c&l[!]&7 You &ccannot &7kick that member until their power is &apositive&7."), + COMMAND_KICK_TOKICK("to kick someone from the faction"), + COMMAND_KICK_FORKICK("for kicking someone from the faction"), + COMMAND_KICK_FACTION("&c&l[!]&7 %1$s&7 kicked %2$s&c from the faction!"), //message given to faction members + COMMAND_KICK_KICKS("&c&l[!]&7 You kicked &c%1$s&7 from the faction&c %2$s&7!"), //kicker perspective + COMMAND_KICK_KICKED("&c&l[!]&7 &c%1$s &7kicked you from&c %2$s&7!"), //kicked player perspective + COMMAND_KICK_DESCRIPTION("Kick a player from the faction"), + + COMMAND_LIST_FACTIONLIST("&c&l[!]&7 Faction List "), + COMMAND_LIST_TOLIST("to list the factions"), + COMMAND_LIST_FORLIST("for listing the factions"), + COMMAND_LIST_ONLINEFACTIONLESS("Online factionless: "), + COMMAND_LIST_DESCRIPTION("&a&l» &7See a list of the factions"), + + COMMAND_LOCK_LOCKED("&c&l[!]&7 Factions is now&c locked"), + COMMAND_LOCK_UNLOCKED("&c&l[!]&7 Factions in now&a unlocked"), + COMMAND_LOCK_DESCRIPTION("Lock all write stuff. Apparently."), + + COMMAND_LOGINS_TOGGLE("&c&l[!]&7 Set login / logout notifications for Faction members to: &c%s"), + COMMAND_LOGINS_DESCRIPTION("Toggle(?) login / logout notifications for Faction members"), + + COMMAND_LOWPOWER_HEADER("&8&m--------&8&8&m---------"), + COMMAND_LOWPOWER_FORMAT("&c{player} &8(&c{player_power}&8/&c{maxpower}&8)"), + COMMAND_LOWPOWER_DESCRIPTION("Shows a list of players in your faction with lower power levels"), + + COMMAND_MAP_TOSHOW("to show the map"), + COMMAND_MAP_FORSHOW("for showing the map"), + COMMAND_MAP_UPDATE_ENABLED("&c&l[!]&7 Map auto update &aENABLED."), + COMMAND_MAP_UPDATE_DISABLED("&c&l[!]&7 Map auto update &cDISABLED."), + COMMAND_MAP_DESCRIPTION("Show the territory map, and set optional auto update"), + + COMMAND_MAPHEIGHT_DESCRIPTION("&eUpdate the lines that /f map sends"), + COMMAND_MAPHEIGHT_SET("&c&l[!]&7 Set /f map lines to &c&a%1$d"), + COMMAND_MAPHEIGHT_CURRENT("&c&l[!]&7 Current &cmapheight: &a%1$d"), + + COMMAND_MOD_CANDIDATES("&c&l[!]&7 Players you can promote: "), + COMMAND_MOD_CLICKTOPROMOTE("Click to promote "), + COMMAND_MOD_NOTMEMBER("&c&l[!]&7 &c%1$s7 is not a member in your faction."), + COMMAND_MOD_NOTADMIN("&c&l[!]&7 You &care not&7 the faction admin."), + COMMAND_MOD_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), + COMMAND_MOD_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin.&7 Demote them first."), + COMMAND_MOD_REVOKES("&c&l[!]&7 &7You have &cremoved&7 moderator status from &c%1$s."), + COMMAND_MOD_REVOKED("&c&l[!]&7 &c%1$s&7 is &cno longer&7 moderator in your faction."), + COMMAND_MOD_PROMOTES("&c&l[!]&7 &c%1$s&7 was &cpromoted&7 to moderator in your faction."), + COMMAND_MOD_PROMOTED("&c&l[!]&7 You have promoted&c %1$s&7 to moderator."), + COMMAND_MOD_DESCRIPTION("Give or revoke moderator rights"), + + COMMAND_COLEADER_CANDIDATES("&c&l[!]&7 Players you can promote: "), + COMMAND_COLEADER_CLICKTOPROMOTE("Click to promote "), + COMMAND_COLEADER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member&7 in your faction."), + COMMAND_COLEADER_NOTADMIN("&c&l[!]&7 You are&c not&7 the faction admin."), + COMMAND_COLEADER_SELF("&c&l[!]&7 The target player&c musn't&7 be yourself."), + COMMAND_COLEADER_TARGETISADMIN("&c&l[!]&7 The target player is a &cfaction admin&7. Demote them first."), + COMMAND_COLEADER_REVOKES("&c&l[!]&7 You have removed &ccoleader &7status from&c %1$s&7."), + COMMAND_COLEADER_REVOKED("&c&l[!]&7 &c%1$s&7 is no longer&c coleader &7in your faction."), + COMMAND_COLEADER_PROMOTES("&c&l[!]&7 &c%1$s&7 was promoted to &ccoleader &7in your faction."), + COMMAND_COLEADER_PROMOTED("&c&l[!]&7 You have &cpromoted &7%1$s to &ccoleader."), + COMMAND_COLEADER_DESCRIPTION("Give or revoke coleader rights"), + + COMMAND_MODIFYPOWER_ADDED("&c&l[!]&7 Added &c%1$f &7power to &c%2$s. &7New total rounded power: &c%3$d"), + COMMAND_MODIFYPOWER_DESCRIPTION("Modify the power of a faction/player"), + + COMMAND_MONEY_LONG("&c&l[!]&7 The faction money commands."), + COMMAND_MONEY_DESCRIPTION("Faction money commands"), + + COMMAND_MONEYBALANCE_SHORT("show faction balance"), + COMMAND_MONEYBALANCE_DESCRIPTION("Show your factions current money balance"), + + COMMAND_MONEYDEPOSIT_DESCRIPTION("Deposit money"), + COMMAND_MONEYDEPOSIT_DEPOSITED("&c&l[!]&7 &c%1$s &7deposited&c %2$s&7 in the faction bank:&c %3$s"), + + COMMAND_MONEYTRANSFERFF_DESCRIPTION("Transfer f -> f"), + COMMAND_MONEYTRANSFERFF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred&c %2$s &7from the faction &c\"%3$s\"&7 to the faction&c \"%4$s\"&7"), + + COMMAND_MONEYTRANSFERFP_DESCRIPTION("Transfer f -> plugin"), + COMMAND_MONEYTRANSFERFP_TRANSFER("&c&l[!]&7 &c%1$s &7transferred&c %2$s &7from the faction&c \"%3$s\" &7to the player &c\"%4$s\""), + + COMMAND_MONEYTRANSFERPF_DESCRIPTION("Transfer plugin -> f"), + COMMAND_MONEYTRANSFERPF_TRANSFER("&c&l[!]&7 &c%1$s&7 transferred &c%2$s&7 from the player &c\"%3$s\" &7to the faction&c \"%4$s\""), + + COMMAND_MONEYWITHDRAW_DESCRIPTION("Withdraw money"), + COMMAND_MONEYWITHDRAW_WITHDRAW("&c&l[!]&7 &c%1$s&7 withdrew&c %2$s &7from the faction bank:&c %3$s"), + + COMMAND_OPEN_TOOPEN("to open or close the faction"), + COMMAND_OPEN_FOROPEN("for opening or closing the faction"), + COMMAND_OPEN_OPEN("open"), + COMMAND_OPEN_CLOSED("closed"), + COMMAND_OPEN_CHANGES("&c&l[!]&7 &c%1$s&7 changed the faction to &c%2$s&7."), + COMMAND_OPEN_CHANGED("&c&l[!]&7 The faction &c%1$s&7 is now &c%2$s"), + COMMAND_OPEN_DESCRIPTION("Switch if invitation is required to join"), + + COMMAND_OWNER_DISABLED("&c&l[!]&7 Sorry, but &cowned areas &7are &cdisabled &7on this server."), + COMMAND_OWNER_LIMIT("&c&l[!]&7 Sorry, but you have reached the server's &climit&7 of &c%1$d&7 owned areas per faction."), + COMMAND_OWNER_WRONGFACTION("&c&l[!]&7 &7This land is &cnot claimed &7by your faction, so you &ccan't set&7 ownership of it."), + COMMAND_OWNER_NOTCLAIMED("&c&l[!]&7 This land&c is not &7claimed by a faction. Ownership &cis not &7possible."), + COMMAND_OWNER_NOTMEMBER("&c&l[!]&7 &c%1$s&7 is &cnot a member &7of this faction."), + COMMAND_OWNER_CLEARED("&c&l[!]&7 You have &ccleared &7ownership for this claimed area."), + COMMAND_OWNER_REMOVED("&c&l[!]&7 You have&c removed ownership &7of this &cclaimed land&7 from &c%1$s&7."), + COMMAND_OWNER_TOSET("to set ownership of claimed land"), + COMMAND_OWNER_FORSET("for setting ownership of claimed land"), + COMMAND_OWNER_ADDED("&c&l[!]&7 You have added &c%1$s&7 to the &cowner list&7 for this claimed land."), + COMMAND_OWNER_DESCRIPTION("Set ownership of claimed land"), + + COMMAND_KILLHOLOGRAMS_DESCRIPTION("Kill holograms in a radius, admin command"), + + COMMAND_OWNERLIST_DISABLED("&c&l[!]&7 &cSorry, &7but owned areas are &cdisabled&7 on this server."),//dup-> + COMMAND_OWNERLIST_WRONGFACTION("&c&l[!]&7 This land &cis not&7 claimed by your faction."),//eq + COMMAND_OWNERLIST_NOTCLAIMED("&c&l[!]&7 This land is not claimed by any faction, thus no owners."),//eq + COMMAND_OWNERLIST_NONE("&c&l[!]&7 No owners are set here; everyone in the faction has access."), + COMMAND_OWNERLIST_OWNERS("&c&l[!]&7 Current owner(s) of this land: %1$s"), + COMMAND_OWNERLIST_DESCRIPTION("List owner(s) of this claimed land"), + + COMMAND_PAYPALSET_DESCRIPTION("&c&l[!] &7Set the email of your faction to claim rewards."), + COMMAND_PAYPALSEE_DESCRIPTION("&c&l[!] &7View a specific factions paypal email with &b/f &b."), + COMMAND_PAYPALSET_CREATED("&c&l[!] &7Make sure to type &b/f &7!"), + COMMAND_PAYPALSET_SUCCESSFUL("&c&l[!] &7Successfully set your factions email - &b%1$s&7."), + COMMAND_PAYPALSEE_FACTION_PAYPAL("&c&l[!] &b%1$s's &7faction has their paypal set to &b%2$s&7."), + COMMAND_PAYPALSEE_FACTION_NOTSET("&c&l[!] &b%1$s's &7paypal has not yet been set!"), + COMMAND_PAYPALSEE_FACTION_NOFACTION("&c&l[!] &b%1$s &7does not have a faction!"), + + COMMAND_PEACEFUL_DESCRIPTION("&c&l[!]&7Set a faction to peaceful"), + COMMAND_PEACEFUL_YOURS("&c&l[!]&7%1$s has %2$s your faction"), + COMMAND_PEACEFUL_OTHER("&c&l[!]&7%s has %s the faction '%s'."), + COMMAND_PEACEFUL_GRANT("&c&l[!]&7 granted peaceful status to"), + COMMAND_PEACEFUL_REVOKE("removed peaceful status from"), + + COMMAND_PERM_DESCRIPTION("&c&l[!]&7&6Edit or list your Faction's permissions."), + COMMAND_PERM_INVALID_RELATION("&c&l[!]&7Invalid relation defined. Try something like&c 'ally'"), + COMMAND_PERM_INVALID_ACCESS("&c&l[!]&7 Invalid access defined. Try something like &c'allow'"), + COMMAND_PERM_INVALID_ACTION("&c&l[!]&7 Invalid action defined. Try something like &c'build'"), + COMMAND_PERM_SET("&c&l[!]&7 Set permission&c %1$s &7to &c%2$s &7for relation&c %3$s"), + COMMAND_PERM_TOP("RCT MEM OFF ALLY TRUCE NEUT ENEMY"), + + COMMAND_PERMANENT_DESCRIPTION("Toggles a permanent faction option"), + COMMAND_PERMANENT_GRANT("&c&l[!]&7 added permanent status to"), + COMMAND_PERMANENT_REVOKE("&c&l[!]&7 removed permanent status from"), + COMMAND_PERMANENT_YOURS("&c&l[!]&7 &c%1$s&7 has &c%2$s&7 your faction"), + COMMAND_PERMANENT_OTHER("&c&l[!]&7 &c%s &7has &c%s &7the faction &c'%s'."), + COMMAND_PROMOTE_TARGET("&c&l[!]&7 You've been &c%1$s&7 to &c%2$s"), + COMMAND_PROMOTE_SUCCESS("&c&l[!]&7 You successfully&c %1$s %2$s &cto&7 %3$s"), + COMMAND_PROMOTE_PROMOTED("promoted"), + COMMAND_PROMOTE_DEMOTED("demoted"), + COMMAND_PROMOTE_COLEADER_ADMIN("&c&l[!]&7 &cColeaders cant promote players to Admin!"), + + COMMAND_PERMANENTPOWER_DESCRIPTION("Toggle permanent faction power option"), + COMMAND_PERMANENTPOWER_GRANT("added permanentpower status to"), + COMMAND_PERMANENTPOWER_REVOKE("removed permanentpower status from"), + COMMAND_PERMANENTPOWER_SUCCESS("&c&l[!]&7 You&c %s &7%s."), + COMMAND_PERMANENTPOWER_FACTION("&c&l[!]&7 &c%s %s &7your faction"), + + COMMAND_PROMOTE_DESCRIPTION("/f promote "), + COMMAND_PROMOTE_WRONGFACTION("&c&l[!]&7 &c%1$s&7 is &cnot&7 part of your faction."), + COMMAND_NOACCESS("&c&l[!]&7 You don't have access to that."), + COMMAND_PROMOTE_NOTTHATPLAYER("&c&l[!]&7 That player &ccannot&7 be promoted."), + COMMAND_PROMOTE_NOT_ALLOWED("&c&l[!]&7 You cannot promote to the same rank as yourself!"), + COMMAND_PROMOTE_NOTSELF("&c&l[!]&7 You cannot manage your own rank."), + COMMAND_PROMOTE_NOT_SAME("&c&l[!]&7 You cannot promote to the same rank as yourself!"), + + + COMMAND_POWER_TOSHOW("to show player power info"), + COMMAND_POWER_FORSHOW("for showing player power info"), + COMMAND_POWER_POWER("&c&l[!]&7 &c%1$s » &cPower &7/ &cMaxpower&a » &c%2$d &7/&c%3$d %4$s"), + COMMAND_POWER_BONUS(" (bonus: "), + COMMAND_POWER_PENALTY(" (penalty: "), + COMMAND_POWER_DESCRIPTION("&a&l» &7Show player &apower &7info"), + + COMMAND_POWERBOOST_HELP_1("&c&l[!]&7 You must specify \"plugin\" or \"player\" to target a player or \"f\" or \"faction\" to target a faction."), + COMMAND_POWERBOOST_HELP_2("&c&l[!]&7 ex. /f powerboost plugin SomePlayer 0.5 -or- /f powerboost f SomeFaction -5"), + COMMAND_POWERBOOST_INVALIDNUM("You must specify a valid numeric value for the power bonus/penalty amount."), + COMMAND_POWERBOOST_PLAYER("Player \"%1$s\""), + COMMAND_POWERBOOST_FACTION("Faction \"%1$s\""), + COMMAND_POWERBOOST_BOOST("%1$s now has a power bonus/penalty of %2$d to min and max power levels."), + COMMAND_POWERBOOST_BOOSTLOG("%1$s has set the power bonus/penalty for %2$s to %3$d."), + COMMAND_POWERBOOST_DESCRIPTION("Apply permanent power bonus/penalty to specified player or faction"), + + COMMAND_RELATIONS_ALLTHENOPE("&c&l[!]&7 &cNope!You can't."), + COMMAND_RELATIONS_MORENOPE("&c&l[!]&7 &cNope!&7You can't declare a relation to &cyourself"), + COMMAND_RELATIONS_ALREADYINRELATIONSHIP("&c&l[!]&7 You &calready&7 have that relation wish set with&c %1$s."), + COMMAND_RELATIONS_TOMARRY("to change a relation wish"), + COMMAND_RELATIONS_FORMARRY("for changing a relation wish"), + COMMAND_RELATIONS_MUTUAL("&c&l[!]&7 Your faction is now %1$s to %2$s"), + COMMAND_RELATIONS_PEACEFUL("&c&l[!]&7 This will have no effect while your faction is peaceful."), + COMMAND_RELATIONS_PEACEFULOTHER("&c&l[!]&7 This will have &cno effect&7 while their faction is peaceful."), + COMMAND_RELATIONS_DESCRIPTION("Set relation wish to another faction"), + COMMAND_RELATIONS_EXCEEDS_ME("&c&l[!]&7 Failed to set relation wish. You can only have %1$s %2$s."), + COMMAND_RELATIONS_EXCEEDS_THEY("&c&l[!]&7 Failed to set relation wish. They can only have %1$s %2$s."), + + COMMAND_RELATIONS_PROPOSAL_1("&c&l[!]&7&c %1$s &7wishes to be your&c %2$s"), + COMMAND_RELATIONS_PROPOSAL_2("&c&l[!]&7 Type &c/%1$s %2$s %3$s&7 to accept."), + COMMAND_RELATIONS_PROPOSAL_SENT("&c&l[!]&7 &c%1$s&7 were informed that you wish to be &c%2$s"), + + COMMAND_RELOAD_TIME("&c&l[!]&7 Reloaded &call &7configuration files from disk, took &c%1$d ms."), + COMMAND_RELOAD_DESCRIPTION("Reload data file(s) from disk"), + + COMMAND_SAFEUNCLAIMALL_DESCRIPTION("Unclaim all safezone land"), + COMMAND_SAFEUNCLAIMALL_UNCLAIMED("&c&l[!]&7 You unclaimed&c ALL&7 safe zone land."), + COMMAND_SAFEUNCLAIMALL_UNCLAIMEDLOG("&c&l[!]&7 &c%1$s&7 unclaimed all safe zones."), + + COMMAND_SAVEALL_SUCCESS("&c&l[!]&7 &cFactions saved to disk!"), + COMMAND_SAVEALL_DESCRIPTION("Save all data to disk"), + + COMMAND_SCOREBOARD_DESCRIPTION("Scoreboardy things"), + + COMMAND_SETBANNER_SUCCESS("&c&l[!] &7Banner Pattern Set!"), + COMMAND_SETBANNER_NOTBANNER("&c&l[!] &7The item is &cnot&7 a banner!"), + COMMAND_SETBANNER_DESCRIPTION("set banner pattern for your faction"), + + + COMMAND_SETDEFAULTROLE_DESCRIPTION("/f defaultrole - set your Faction's default role."), + COMMAND_SETDEFAULTROLE_NOTTHATROLE("&c&l[!]&7 You cannot set the default to admin."), + COMMAND_SETDEFAULTROLE_SUCCESS("Set default role of your faction to %1$s"), + COMMAND_SETDEFAULTROLE_INVALIDROLE("Couldn't find matching role for %1$s"), + + COMMAND_SETFWARP_NOTCLAIMED("&c&l[!]&7 You can &conly&7 set warps in your faction territory."), + COMMAND_SETFWARP_LIMIT("&c&l[!]&7 Your Faction already has the &cmax amount&7 of warps set &c(%1$d)."), + COMMAND_SETFWARP_SET("&c&l[!]&7 Set warp &c%1$s&7 and password &c'%2$s' &7to your location."), + COMMAND_SETFWARP_TOSET("to set warp"), + COMMAND_SETFWARP_FORSET("for setting warp"), + COMMAND_SETFWARP_DESCRIPTION("Set a faction warp"), + + COMMAND_SETHOME_DISABLED("&c&l[!]&7 &cSorry&7, Faction homes are disabled on this server."), + COMMAND_SETHOME_NOTCLAIMED("&c&l[!]&c Sorry&7, your faction home can only be set inside your &cown &7claimed territory."), + COMMAND_SETHOME_TOSET("to set the faction home"), + COMMAND_SETHOME_FORSET("for setting the faction home"), + COMMAND_SETHOME_SET("&c&l[!]&c %1$s&7 set the home for your faction. You can now use:"), + COMMAND_SETHOME_SETOTHER("&c&l[!]&7 You have set the home for the &c%1$s&7 faction."), + COMMAND_SETHOME_DESCRIPTION("Set the faction home"), + + COMMAND_SETMAXVAULTS_DESCRIPTION("Set max vaults for a Faction."), + COMMAND_SETMAXVAULTS_SUCCESS("&aSet max vaults for &e%s &ato &b%d"), + + COMMAND_VAULT_DESCRIPTION("Open your placed faction vault!"), + COMMAND_VAULT_INVALID("&c&l[!]&7 Your vault was either&c claimed&7, &cbroken&7, or has&c not been&7 placed yet."), + COMMAND_VAULT_OPENING("&c&l[!]&7 Opening faction vault."), + COMMAND_VAULT_NO_HOPPER("&c&l[!] &7You cannot place a hopper near a vault!"), + + COMMAND_GETVAULT_ALREADYSET("&c&l[!]&7 Vault has already been set!"), + COMMAND_GETVAULT_ALREADYHAVE("&c&l[!]&7 You already have a vault in your inventory!"), + COMMAND_GETVAULT_CHESTNEAR("&c&l[!]&7 &7There is a chest or hopper &cnearby"), + COMMAND_GETVAULT_SUCCESS("&cSucessfully set vault."), + COMMAND_GETVAULT_INVALIDLOCATION("&cVault can only be placed in faction land!"), + COMMAND_GETVAULT_DESCRIPTION("Get the faction vault item!"), + COMMAND_GETVAULT_RECEIVE("&cYou have recieved a faction vault!"), + COMMAND_GETVAULT_NOMONEY("&cYou do not have enough money"), + COMMAND_GETVAULT_MONEYTAKE("&c{amount} has been taken from your account"), + + COMMAND_SHOW_NOFACTION_SELF("You are not in a faction"), + COMMAND_SHOW_NOFACTION_OTHER("That's not a faction"), + COMMAND_SHOW_TOSHOW("to show faction information"), + COMMAND_SHOW_FORSHOW("for showing faction information"), + COMMAND_SHOW_DESCRIPTION("Description: %1$s"), + COMMAND_SHOW_PEACEFUL("This faction is Peaceful"), + COMMAND_SHOW_PERMANENT("This faction is permanent, remaining even with no members."), + COMMAND_SHOW_JOINING("Joining: %1$s "), + COMMAND_SHOW_INVITATION("invitation is required"), + COMMAND_SHOW_UNINVITED("no invitation is needed"), + COMMAND_SHOW_NOHOME("n/a"), + COMMAND_SHOW_POWER("Land / Power / Maxpower: %1$d/%2$d/%3$d %4$s."), + COMMAND_SHOW_BONUS(" (bonus: "), + COMMAND_SHOW_PENALTY(" (penalty: "), + COMMAND_SHOW_DEPRECIATED("(%1$s depreciated)"), //This is spelled correctly. + COMMAND_SHOW_LANDVALUE("Total land value: %1$s %2$s"), + COMMAND_SHOW_BANKCONTAINS("Bank contains: %1$s"), + COMMAND_SHOW_ALLIES("Allies: "), + COMMAND_SHOW_ENEMIES("Enemies: "), + COMMAND_SHOW_MEMBERSONLINE("Members online: "), + COMMAND_SHOW_MEMBERSOFFLINE("Members offline: "), + COMMAND_SHOW_COMMANDDESCRIPTION("Show faction information"), + COMMAND_SHOW_DEATHS_TIL_RAIDABLE("DTR: %1$d"), + COMMAND_SHOW_EXEMPT("This faction is exempt and cannot be seen."), + COMMAND_SHOW_NEEDFACTION("&cYou need to join a faction to view your own!"), + + COMMAND_SHOWCLAIMS_HEADER("&8&m-------------&8<{faction}'s claims&8>&8&m-------------"), + COMMAND_SHOWCLAIMS_FORMAT("&8[{world}]:"), + COMMAND_SHOWCLAIMS_CHUNKSFORMAT("&8(&c{x}&8,&c{z}&8)"), + COMMAND_SHOWCLAIMS_DESCRIPTION("show your factions claims!"), + + COMMAND_SHOWINVITES_PENDING("Players with pending invites: "), + COMMAND_SHOWINVITES_CLICKTOREVOKE("Click to revoke invite for %1$s"), + COMMAND_SHOWINVITES_DESCRIPTION("Show pending faction invites"), + + COMMAND_STATUS_FORMAT("%1$s Power: %2$s Last Seen: %3$s"), + COMMAND_STATUS_ONLINE("Online"), + COMMAND_STATUS_AGOSUFFIX(" ago."), + COMMAND_STATUS_DESCRIPTION("Show the status of a player"), + + COMMAND_STEALTH_DESCRIPTION("Enable and Disable Stealth Mode"), + COMMAND_STEALTH_ENABLE("&cStealth &7» &7You will no longer disable nearby players in /f fly."), + COMMAND_STEALTH_DISABLE("&cStealth &8» &7You will now disable other nearby players in /f fly."), + COMMAND_STEALTH_MUSTBEMEMBER("&cStealth &8» &4You must be in a faction to use this command"), + + COMMAND_STUCK_TIMEFORMAT("m 'minutes', s 'seconds.'"), + COMMAND_STUCK_CANCELLED("Teleport cancelled because you were damaged"), + COMMAND_STUCK_OUTSIDE("Teleport cancelled because you left %1$d block radius"), + COMMAND_STUCK_EXISTS("You are already teleporting, you must wait %1$s"), + COMMAND_STUCK_START("Teleport will commence in %s. Don't take or deal damage. "), + COMMAND_STUCK_TELEPORT("Teleported safely to %1$d, %2$d, %3$d."), + COMMAND_STUCK_TOSTUCK("to safely teleport %1$s out"), + COMMAND_STUCK_FORSTUCK("for %1$s initiating a safe teleport out"), + COMMAND_STUCK_DESCRIPTION("Safely teleports you out of enemy faction"), + + COMMAND_SEECHUNK_ENABLED("&cSeechunk enabled!"), + COMMAND_SEECHUNK_DISABLED("&cSeechunk disabled!"), + + + COMMAND_TAG_TAKEN("That tag is already taken"), + COMMAND_TAG_TOCHANGE("to change the faction tag"), + COMMAND_TAG_FORCHANGE("for changing the faction tag"), + COMMAND_TAG_FACTION("%1$s changed your faction tag to %2$s"), + COMMAND_TAG_CHANGED("The faction %1$s changed their name to %2$s."), + COMMAND_TAG_DESCRIPTION("Change the faction tag"), + + COMMAND_TITLE_TOCHANGE("to change a players title"), + COMMAND_TITLE_FORCHANGE("for changing a players title"), + COMMAND_TITLE_CHANGED("%1$s changed a title: %2$s"), + COMMAND_TITLE_DESCRIPTION("Set or remove a players title"), + + COMMAND_TOGGLEALLIANCECHAT_DESCRIPTION("Toggles whether or not you will see alliance chat"), + COMMAND_TOGGLEALLIANCECHAT_IGNORE("Alliance chat is now ignored"), + COMMAND_TOGGLEALLIANCECHAT_UNIGNORE("Alliance chat is no longer ignored"), + + COMMAND_TOGGLESB_DISABLED("You can't toggle scoreboards while they are disabled."), + + COMMAND_TOP_DESCRIPTION("Sort Factions to see the top of some criteria."), + COMMAND_TOP_TOP("Top Factions by %s. Page %d/%d"), + COMMAND_TOP_LINE("%d. &6%s: &c%s"), // Rank. Faction: Value + COMMAND_TOP_INVALID("Could not sort by %s. Try balance, online, members, power or land."), + + COMMAND_TNT_DISABLED_MSG("&cThis command is disabled!"), + COMMAND_TNT_INVALID_NUM("The amount needs to be a number!"), + COMMAND_TNT_DEPOSIT_SUCCESS("&cSuccessfully deposited tnt."), + COMMAND_TNT_EXCEEDLIMIT("&cThis exceeds the bank limit!"), + COMMAND_TNT_WIDTHDRAW_SUCCESS("&cSuccessfully withdrew tnt."), + COMMAND_TNT_WIDTHDRAW_NOTENOUGH("&cNot enough tnt in bank."), + COMMAND_TNT_DEPOSIT_NOTENOUGH("&cNot enough tnt in tnt inventory."), + COMMAND_TNT_AMOUNT("&cYour faction has {amount} tnt in the tnt bank."), + COMMAND_TNT_POSITIVE("&cPlease use positive numbers!"), + COMMAND_TNT_DESCRIPTION("add/widthraw from faction's tnt bank"), + COMMAND_TNT_WIDTHDRAW_NOTENOUGH_SPACE("&cNot enough space in your inventory."), + COMMAND_TNT_ADD_DESCRIPTION("&b/f tnt add&3 "), + COMMAND_TNT_TAKE_DESCRIPTION("&b/f tnt take&3 "), + + COMMAND_TNTFILL_HEADER("&c&l[!] &7Filling tnt in dispensers..."), + COMMAND_TNTFILL_SUCCESS("&c&l[!] &7Filled &c{amount}&7 Tnt in &c{dispensers} &7dispensers"), + COMMAND_TNTFILL_NOTENOUGH("&c&l[!] &7Not enough tnt in inventory."), + COMMAND_TNTFILL_RADIUSMAX("&c&l[!] &7The max radius is {max}"), + COMMAND_TNTFILL_AMOUNTMAX("&c&l[!] &7The max amount is {max}"), + COMMAND_TNTFILL_MOD("&c&l[!] &7Tnt will be used from the faction bank because you dont have the specified amount in your inventory and you are a {role}"), + COMMAND_TNTFILL_DESCRIPTION("Fill tnt into dispensers around you"), + + COMMAND_UNBAN_DESCRIPTION("Unban someone from your Faction"), + COMMAND_UNBAN_NOTBANNED("&7%s &cisn't banned. Not doing anything."), + COMMAND_UNBAN_UNBANNED("&e%1$s &cunbanned &7%2$s"), + COMMAND_UNBAN_TARGET("&aYou were unbanned from &r%s"), + + COMMAND_UNCLAIM_SAFEZONE_SUCCESS("Safe zone was unclaimed."), + COMMAND_UNCLAIM_SAFEZONE_NOPERM("This is a safe zone. You lack permissions to unclaim."), + COMMAND_UNCLAIM_WARZONE_SUCCESS("War zone was unclaimed."), + COMMAND_UNCLAIM_WARZONE_NOPERM("This is a war zone. You lack permissions to unclaim."), + COMMAND_UNCLAIM_UNCLAIMED("%1$s unclaimed some of your land."), + COMMAND_UNCLAIM_UNCLAIMS("You unclaimed this land."), + COMMAND_UNCLAIM_LOG("%1$s unclaimed land at (%2$s) from the faction: %3$s"), + COMMAND_UNCLAIM_WRONGFACTION("You don't own this land."), + COMMAND_UNCLAIM_TOUNCLAIM("to unclaim this land"), + COMMAND_UNCLAIM_FORUNCLAIM("for unclaiming this land"), + COMMAND_UNCLAIM_FACTIONUNCLAIMED("%1$s unclaimed some land."), + COMMAND_UNCLAIM_DESCRIPTION("Unclaim the land where you are standing"), + + COMMAND_UNCLAIMALL_TOUNCLAIM("to unclaim all faction land"), + COMMAND_UNCLAIMALL_FORUNCLAIM("for unclaiming all faction land"), + COMMAND_UNCLAIMALL_UNCLAIMED("%1$s unclaimed ALL of your faction's land."), + COMMAND_UNCLAIMALL_LOG("%1$s unclaimed everything for the faction: %2$s"), + COMMAND_UNCLAIMALL_DESCRIPTION("Unclaim all of your factions land"), + COMMAND_UNCLAIM_CLICKTOUNCLAIM("Click to unclaim &2(%1$d, %2$d)"), + + COMMAND_VERSION_NAME("&c&l[!]&7 &c&k||| &r&4SavageFactions&7 &c&k|||&r &c» &7By ProSavage"), + COMMAND_VERSION_VERSION("&7Version &c» &7%1$s"), + COMMAND_VERSION_DESCRIPTION("Show plugin and translation version information"), + + COMMAND_WARUNCLAIMALL_DESCRIPTION("Unclaim all warzone land"), + COMMAND_WARUNCLAIMALL_SUCCESS("You unclaimed ALL war zone land."), + COMMAND_WARUNCLAIMALL_LOG("%1$s unclaimed all war zones."), + + COMMAND_RULES_DISABLED_MSG("&cThis command is disabled!"), + COMMAND_RULES_DESCRIPTION("set/remove/add rules!"), + COMMAND_RULES_ADD_INVALIDARGS("Please include a rule!"), + COMMAND_RULES_SET_INVALIDARGS("Please include a line number & rule!"), + COMMAND_RULES_REMOVE_INVALIDARGS("Please include a line number!"), + COMMAND_RULES_ADD_SUCCESS("&cRule added successfully!"), + COMMAND_RULES_REMOVE_SUCCESS("&cRule removed successfully!"), + COMMAND_RULES_SET_SUCCESS("&cRule set successfully!"), + COMMAND_RULES_CLEAR_SUCCESS("&cRule cleared successfully!"), + + /** + * Leaving - This is accessed through a command, and so it MAY need a COMMAND_* slug :s + */ + LEAVE_PASSADMIN("You must give the admin role to someone else first."), + LEAVE_NEGATIVEPOWER("You cannot leave until your power is positive."), + LEAVE_TOLEAVE("to leave your faction."), + LEAVE_FORLEAVE("for leaving your faction."), + LEAVE_LEFT("%s left faction %s."), + LEAVE_DISBANDED("%s was disbanded."), + LEAVE_DISBANDEDLOG("The faction %s (%s) was disbanded due to the last player (%s) leaving."), + LEAVE_DESCRIPTION("\\n &a&l» &7Leave your faction"), + + /** + * Claiming - Same as above basically. No COMMAND_* because it's not in a command class, but... + */ + CLAIM_PROTECTED("This land is protected"), + CLAIM_DISABLED("Sorry, this world has land claiming disabled."), + CLAIM_CANTCLAIM("You can't claim land for %s."), + CLAIM_ALREADYOWN("%s already own this land."), + CLAIM_MUSTBE("You must be %s to claim land."), + CLAIM_MEMBERS("Factions must have at least %s members to claim land."), + CLAIM_SAFEZONE("You can not claim a Safe Zone."), + CLAIM_WARZONE("You can not claim a War Zone."), + CLAIM_POWER("You can't claim more land!You need more power!"), + CLAIM_LIMIT("Limit reached. You can't claim more land!"), + CLAIM_ALLY("You can't claim the land of your allies."), + CLAIM_CONTIGIOUS("You can only claim additional land which is connected to your first claim or controlled by another faction!"), + CLAIM_FACTIONCONTIGUOUS("You can only claim additional land which is connected to your first claim!"), + CLAIM_PEACEFUL("%s owns this land. Your faction is peaceful, so you cannot claim land from other factions."), + CLAIM_PEACEFULTARGET("%s owns this land, and is a peaceful faction. You cannot claim land from them."), + CLAIM_THISISSPARTA("%s owns this land and is strong enough to keep it."), + CLAIM_BORDER("You must start claiming land at the border of the territory."), + CLAIM_TOCLAIM("to claim this land"), + CLAIM_FORCLAIM("for claiming this land"), + CLAIM_TOOVERCLAIM("to overclaim this land"), + CLAIM_FOROVERCLAIM("for over claiming this land"), + CLAIM_CLAIMED("%s claimed land for %s from %s."), + CLAIM_CLAIMEDLOG("%s claimed land at (%s) for the faction: %s"), + CLAIM_OVERCLAIM_DISABLED("Over claiming is disabled on this server."), + CLAIM_TOOCLOSETOOTHERFACTION("Your claim is too close to another Faction. Buffer required is %d"), + CLAIM_OUTSIDEWORLDBORDER("Your claim is outside the border."), + CLAIM_OUTSIDEBORDERBUFFER("Your claim is outside the border. %d chunks away world edge required."), + CLAIM_CLICK_TO_CLAIM("Click to try to claim &2(%1$d, %2$d)"), + CLAIM_MAP_OUTSIDEBORDER("&cThis claim is outside the worldborder!"), + CLAIM_YOUAREHERE("You are here"), + CLAIM_NO_TERRITORY_PERM("You do not have permission from your faction leader to do this!"), + + /** + * More generic, or less easily categorisable translations, which may apply to more than one class + */ + GENERIC_YOU("you"), + GENERIC_YOURFACTION("your faction"), + GENERIC_NOPERMISSION("You don't have permission to %1$s."), + GENERIC_FPERM_NOPERMISSION("&7The faction leader does not allow you to &c%1$s."), + GENERIC_DOTHAT("do that"), //Ugh nuke this from high orbit + GENERIC_NOPLAYERMATCH("No player match found for \"%1$s\"."), + GENERIC_NOPLAYERFOUND("No player \"%1$s\" could not be found."), + GENERIC_ARGS_TOOFEW("Too few arguments. Use like this:"), + GENERIC_ARGS_TOOMANY("Strange argument \"%1$s\". Use the command like this:"), + GENERIC_DEFAULTDESCRIPTION("Default faction description :("), + GENERIC_OWNERS("Owner(s): %1$s"), + GENERIC_PUBLICLAND("Public faction land."), + GENERIC_FACTIONLESS("factionless"), + GENERIC_SERVERADMIN("A server admin"), + GENERIC_DISABLED("disabled"), + GENERIC_ENABLED("enabled"), + GENERIC_INFINITY("∞"), + GENERIC_CONSOLEONLY("This command cannot be run as a player."), + GENERIC_PLAYERONLY("This command can only be used by ingame players."), + GENERIC_ASKYOURLEADER(" Ask your leader to:"), + GENERIC_YOUSHOULD("You should:"), + GENERIC_YOUMAYWANT("You may want to: "), + GENERIC_TRANSLATION_VERSION("Translation: %1$s(%2$s,%3$s) State: %4$s"), + GENERIC_TRANSLATION_CONTRIBUTORS("Translation contributors: %1$s"), + GENERIC_TRANSLATION_RESPONSIBLE("Responsible for translation: %1$s"), + GENERIC_FACTIONTAG_TOOSHORT("The faction tag can't be shorter than %1$s chars."), + GENERIC_FACTIONTAG_TOOLONG("The faction tag can't be longer than %s chars."), + GENERIC_FACTIONTAG_ALPHANUMERIC("Faction tag must be alphanumeric. \"%s\" is not allowed."), + GENERIC_PLACEHOLDER(""), + GENERIC_NOTENOUGHMONEY("&cYou dont have enough money!"), + GENERIC_MONEYTAKE("&c{amount} has been taken from your account."), + + + WARBANNER_NOFACTION("&cYou need a faction to use a warbanner!"), + WARBANNER_COOLDOWN("&cThe warbanner is on cooldown for your faction!"), + WARBANNER_INVALIDLOC("&cYou can only use warbanners in enemy land or the warzone"), + + /** + * ASCII compass (for chat map) + */ + COMPASS_SHORT_NORTH("N"), + COMPASS_SHORT_EAST("E"), + COMPASS_SHORT_SOUTH("S"), + COMPASS_SHORT_WEST("W"), + + /** + * Chat modes + */ + CHAT_MOD("mod chat"), + CHAT_FACTION("faction chat"), + CHAT_ALLIANCE("alliance chat"), + CHAT_TRUCE("truce chat"), + CHAT_PUBLIC("public chat"), + + /** + * Economy stuff + */ + + ECON_OFF("no %s"), // no balance, no value, no refund, etc + ECON_FORMAT("###,###.###"), + + /** + * Relations + */ + RELATION_MEMBER_SINGULAR("member"), + RELATION_MEMBER_PLURAL("members"), + RELATION_ALLY_SINGULAR("ally"), + RELATION_ALLY_PLURAL("allies"), + RELATION_TRUCE_SINGULAR("truce"), + RELATION_TRUCE_PLURAL("truces"), + RELATION_NEUTRAL_SINGULAR("neutral"), + RELATION_NEUTRAL_PLURAL("neutrals"), + RELATION_ENEMY_SINGULAR("enemy"), + RELATION_ENEMY_PLURAL("enemies"), + + /** + * Roles + */ + ROLE_LEADER("leader"), + ROLE_COLEADER("coleader"), + ROLE_MODERATOR("moderator"), + ROLE_NORMAL("normal member"), + ROLE_RECRUIT("recruit"), + + /** + * Region types. + */ + REGION_SAFEZONE("safezone"), + REGION_WARZONE("warzone"), + REGION_WILDERNESS("wilderness"), + + REGION_PEACEFUL("peaceful territory"), + /** + * In the player and entity listeners + */ + PLAYER_CANTHURT("You may not harm other players in %s"), + PLAYER_SAFEAUTO("This land is now a safe zone."), + PLAYER_WARAUTO("This land is now a war zone."), + PLAYER_OUCH("Ouch, that is starting to hurt. You should give it a rest."), + PLAYER_USE_WILDERNESS("You can't use %s in the wilderness."), + PLAYER_USE_SAFEZONE("You can't use %s in a safe zone."), + PLAYER_USE_WARZONE("You can't use %s in a war zone."), + PLAYER_USE_TERRITORY("You can't %s in the territory of %s."), + PLAYER_USE_OWNED("You can't use %s in this territory, it is owned by: %s."), + PLAYER_COMMAND_WARZONE("You can't use the command '%s' in warzone."), + PLAYER_COMMAND_NEUTRAL("You can't use the command '%s' in neutral territory."), + PLAYER_COMMAND_ENEMY("You can't use the command '%s' in enemy territory."), + PLAYER_COMMAND_PERMANENT("You can't use the command '%s' because you are in a permanent faction."), + PLAYER_COMMAND_ALLY("You can't use the command '%s' in ally territory."), + PLAYER_COMMAND_WILDERNESS("You can't use the command '%s' in the wilderness."), + + PLAYER_POWER_NOLOSS_PEACEFUL("You didn't lose any power since you are in a peaceful faction."), + PLAYER_POWER_NOLOSS_WORLD("You didn't lose any power due to the world you died in."), + PLAYER_POWER_NOLOSS_WILDERNESS("You didn't lose any power since you were in the wilderness."), + PLAYER_POWER_NOLOSS_WARZONE("You didn't lose any power since you were in a war zone."), + PLAYER_POWER_LOSS_WARZONE("The world you are in has power loss normally disabled, but you still lost power since you were in a war zone.\nYour power is now %d / %d"), + PLAYER_POWER_NOW("Your power is now %d / %d"), + + PLAYER_PVP_LOGIN("You can't hurt other players for %d seconds after logging in."), + PLAYER_PVP_REQUIREFACTION("You can't hurt other players until you join a faction."), + PLAYER_PVP_FACTIONLESS("You can't hurt players who are not currently in a faction."), + PLAYER_PVP_PEACEFUL("Peaceful players cannot participate in combat."), + PLAYER_PVP_NEUTRAL("You can't hurt neutral factions. Declare them as an enemy."), + PLAYER_PVP_CANTHURT("You can't hurt %s."), + + PLAYER_PVP_NEUTRALFAIL("You can't hurt %s in their own territory unless you declare them as an enemy."), + PLAYER_PVP_TRIED("%s tried to hurt you."), + + /** + * Strings lying around in other bits of the plugins + */ + NOPAGES("Sorry. No Pages available."), + INVALIDPAGE("Invalid page. Must be between 1 and %1$d"), + + /** + * The ones here before I started messing around with this + */ + TITLE("title", "&bFactions &0|&r"), + WILDERNESS("wilderness", "&2Wilderness"), + WILDERNESS_DESCRIPTION("wilderness-description", ""), + WARZONE("warzone", "&4Warzone"), + WARZONE_DESCRIPTION("warzone-description", "Not the safest place to be."), + SAFEZONE("safezone", "&6Safezone"), + SAFEZONE_DESCRIPTION("safezone-description", "Free from pvp and monsters."), + TOGGLE_SB("toggle-sb", "You now have scoreboards set to {value}"), + FACTION_LEAVE("faction-leave", "Leaving %1$s, Entering %2$s"), + FACTIONS_ANNOUNCEMENT_TOP("faction-announcement-top", "&d--Unread Faction Announcements--"), + FACTIONS_ANNOUNCEMENT_BOTTOM("faction-announcement-bottom", "&d--Unread Faction Announcements--"), + DEFAULT_PREFIX("default-prefix", "{relationcolor}[{faction}]"), + FACTION_LOGIN("faction-login", "&e%1$s &9logged in."), + FACTION_LOGOUT("faction-logout", "&e%1$s &9logged out.."), + NOFACTION_PREFIX("nofactions-prefix", "&6[&a4-&6]&r"), + DATE_FORMAT("date-format", "MM/d/yy h:ma"), // 3/31/15 07:49AM + + /** + * Raidable is used in multiple places. Allow more than just true/false. + */ + RAIDABLE_TRUE("raidable-true", "true"), + RAIDABLE_FALSE("raidable-false", "false"), + /** + * Warmups + */ + WARMUPS_NOTIFY_FLIGHT("&eFlight will enable in &d%2$d &eseconds."), + WARMUPS_NOTIFY_TELEPORT("&eYou will teleport to &d%1$s &ein &d%2$d &eseconds."), + WARMUPS_ALREADY("&cYou are already warming up."), + WARMUPS_CANCELLED("&cYou have cancelled your warmup."); + + public static SimpleDateFormat sdf; + private static YamlConfiguration LANG; + private String path; + private String def; + + /** + * Lang enum constructor. + * + * @param path The string path. + * @param start The default string. + */ + TL(String path, String start) { + this.path = path; + this.def = start; + } + + /** + * Lang enum constructor. Use this when your desired path simply exchanges '_' for '.' + * + * @param start The default string. + */ + TL(String start) { + this.path = this.name().replace('_', '.'); + if (this.path.startsWith(".")) { + path = "root" + path; + } + this.def = start; + } + + /** + * Set the {@code YamlConfiguration} to use. + * + * @param config The config to set. + */ + public static void setFile(YamlConfiguration config) { + LANG = config; + sdf = new SimpleDateFormat(DATE_FORMAT.toString()); + } + + @Override + public String toString() { + return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def)) + (this == TITLE ? " " : ""); + } + + public String format(Object... args) { + return String.format(toString(), args); + } + + /** + * Get the default value of the path. + * + * @return The default value of the path. + */ + public String getDefault() { + return this.def; + } + + /** + * Get the path to the string. + * + * @return The path to the string. + */ + public String getPath() { + return this.path; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java b/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java index 6d726ab6..3392ec7d 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java @@ -17,284 +17,284 @@ import java.util.UUID; */ public enum TagReplacer { - /** - * Fancy variables, used by f show - */ - ALLIES_LIST(TagType.FANCY, "{allies-list}"), - ONLINE_LIST(TagType.FANCY, "{online-list}"), - ENEMIES_LIST(TagType.FANCY, "{enemies-list}"), - TRUCES_LIST(TagType.FANCY, "{truces-list}"), - OFFLINE_LIST(TagType.FANCY, "{offline-list}"), + /** + * Fancy variables, used by f show + */ + ALLIES_LIST(TagType.FANCY, "{allies-list}"), + ONLINE_LIST(TagType.FANCY, "{online-list}"), + ENEMIES_LIST(TagType.FANCY, "{enemies-list}"), + TRUCES_LIST(TagType.FANCY, "{truces-list}"), + OFFLINE_LIST(TagType.FANCY, "{offline-list}"), - /** - * Player variables, require a player - */ - PLAYER_GROUP(TagType.PLAYER, "{group}"), - LAST_SEEN(TagType.PLAYER, "{lastSeen}"), - PLAYER_BALANCE(TagType.PLAYER, "{balance}"), - PLAYER_POWER(TagType.PLAYER, "{player-power}"), - PLAYER_MAXPOWER(TagType.PLAYER, "{player-maxpower}"), - PLAYER_KILLS(TagType.PLAYER, "{player-kills}"), - PLAYER_DEATHS(TagType.PLAYER, "{player-deaths}"), + /** + * Player variables, require a player + */ + PLAYER_GROUP(TagType.PLAYER, "{group}"), + LAST_SEEN(TagType.PLAYER, "{lastSeen}"), + PLAYER_BALANCE(TagType.PLAYER, "{balance}"), + PLAYER_POWER(TagType.PLAYER, "{player-power}"), + PLAYER_MAXPOWER(TagType.PLAYER, "{player-maxpower}"), + PLAYER_KILLS(TagType.PLAYER, "{player-kills}"), + PLAYER_DEATHS(TagType.PLAYER, "{player-deaths}"), - /** - * Faction variables, require at least a player - */ - HOME_X(TagType.FACTION, "{x}"), - HOME_Y(TagType.FACTION, "{y}"), - HOME_Z(TagType.FACTION, "{z}"), - CHUNKS(TagType.FACTION, "{chunks}"), - WARPS(TagType.FACTION, "{warps}"), - HEADER(TagType.FACTION, "{header}"), - POWER(TagType.FACTION, "{power}"), - MAX_POWER(TagType.FACTION, "{maxPower}"), - POWER_BOOST(TagType.FACTION, "{power-boost}"), - LEADER(TagType.FACTION, "{leader}"), - JOINING(TagType.FACTION, "{joining}"), - FACTION(TagType.FACTION, "{faction}"), - PLAYER_NAME(TagType.FACTION, "{name}"), - HOME_WORLD(TagType.FACTION, "{world}"), - RAIDABLE(TagType.FACTION, "{raidable}"), - PEACEFUL(TagType.FACTION, "{peaceful}"), - PERMANENT(TagType.FACTION, "permanent"), // no braces needed - TIME_LEFT(TagType.FACTION, "{time-left}"), - LAND_VALUE(TagType.FACTION, "{land-value}"), - DESCRIPTION(TagType.FACTION, "{description}"), - CREATE_DATE(TagType.FACTION, "{create-date}"), - LAND_REFUND(TagType.FACTION, "{land-refund}"), - BANK_BALANCE(TagType.FACTION, "{faction-balance}"), - ALLIES_COUNT(TagType.FACTION, "{allies}"), - ENEMIES_COUNT(TagType.FACTION, "{enemies}"), - TRUCES_COUNT(TagType.FACTION, "{truces}"), - ONLINE_COUNT(TagType.FACTION, "{online}"), - OFFLINE_COUNT(TagType.FACTION, "{offline}"), - FACTION_SIZE(TagType.FACTION, "{members}"), - FACTION_KILLS(TagType.FACTION, "{faction-kills}"), - FACTION_DEATHS(TagType.FACTION, "{faction-deaths}"), - FACTION_BANCOUNT(TagType.FACTION, "{faction-bancount}"), + /** + * Faction variables, require at least a player + */ + HOME_X(TagType.FACTION, "{x}"), + HOME_Y(TagType.FACTION, "{y}"), + HOME_Z(TagType.FACTION, "{z}"), + CHUNKS(TagType.FACTION, "{chunks}"), + WARPS(TagType.FACTION, "{warps}"), + HEADER(TagType.FACTION, "{header}"), + POWER(TagType.FACTION, "{power}"), + MAX_POWER(TagType.FACTION, "{maxPower}"), + POWER_BOOST(TagType.FACTION, "{power-boost}"), + LEADER(TagType.FACTION, "{leader}"), + JOINING(TagType.FACTION, "{joining}"), + FACTION(TagType.FACTION, "{faction}"), + PLAYER_NAME(TagType.FACTION, "{name}"), + HOME_WORLD(TagType.FACTION, "{world}"), + RAIDABLE(TagType.FACTION, "{raidable}"), + PEACEFUL(TagType.FACTION, "{peaceful}"), + PERMANENT(TagType.FACTION, "permanent"), // no braces needed + TIME_LEFT(TagType.FACTION, "{time-left}"), + LAND_VALUE(TagType.FACTION, "{land-value}"), + DESCRIPTION(TagType.FACTION, "{description}"), + CREATE_DATE(TagType.FACTION, "{create-date}"), + LAND_REFUND(TagType.FACTION, "{land-refund}"), + BANK_BALANCE(TagType.FACTION, "{faction-balance}"), + ALLIES_COUNT(TagType.FACTION, "{allies}"), + ENEMIES_COUNT(TagType.FACTION, "{enemies}"), + TRUCES_COUNT(TagType.FACTION, "{truces}"), + ONLINE_COUNT(TagType.FACTION, "{online}"), + OFFLINE_COUNT(TagType.FACTION, "{offline}"), + FACTION_SIZE(TagType.FACTION, "{members}"), + FACTION_KILLS(TagType.FACTION, "{faction-kills}"), + FACTION_DEATHS(TagType.FACTION, "{faction-deaths}"), + FACTION_BANCOUNT(TagType.FACTION, "{faction-bancount}"), - /** - * General variables, require no faction or player - */ - MAX_WARPS(TagType.GENERAL, "{max-warps}"), - MAX_ALLIES(TagType.GENERAL, "{max-allies}"), - MAX_ENEMIES(TagType.GENERAL, "{max-enemies}"), - MAX_TRUCES(TagType.GENERAL, "{max-truces}"), - FACTIONLESS(TagType.GENERAL, "{factionless}"), - TOTAL_ONLINE(TagType.GENERAL, "{total-online}"); + /** + * General variables, require no faction or player + */ + MAX_WARPS(TagType.GENERAL, "{max-warps}"), + MAX_ALLIES(TagType.GENERAL, "{max-allies}"), + MAX_ENEMIES(TagType.GENERAL, "{max-enemies}"), + MAX_TRUCES(TagType.GENERAL, "{max-truces}"), + FACTIONLESS(TagType.GENERAL, "{factionless}"), + TOTAL_ONLINE(TagType.GENERAL, "{total-online}"); - private TagType type; - private String tag; + private TagType type; + private String tag; - TagReplacer(TagType type, String tag) { - this.type = type; - this.tag = tag; - } + TagReplacer(TagType type, String tag) { + this.type = type; + this.tag = tag; + } - /** - * Returns a list of all the variables we can use for this type
    - * - * @param type the type we want - * @return a list of all the variables with this type - */ - protected static List getByType(TagType type) { - List tagReplacers = new ArrayList<>(); - for (TagReplacer tagReplacer : TagReplacer.values()) { - if (type == TagType.FANCY) { - if (tagReplacer.type == TagType.FANCY) { - tagReplacers.add(tagReplacer); - } - } else if (tagReplacer.type.id >= type.id) { - tagReplacers.add(tagReplacer); - } - } - return tagReplacers; - } + /** + * Returns a list of all the variables we can use for this type
    + * + * @param type the type we want + * @return a list of all the variables with this type + */ + protected static List getByType(TagType type) { + List tagReplacers = new ArrayList<>(); + for (TagReplacer tagReplacer : TagReplacer.values()) { + if (type == TagType.FANCY) { + if (tagReplacer.type == TagType.FANCY) { + tagReplacers.add(tagReplacer); + } + } else if (tagReplacer.type.id >= type.id) { + tagReplacers.add(tagReplacer); + } + } + return tagReplacers; + } - /** - * Protected access to this generic server related variable - * - * @return value for this generic server related variable
    - */ - protected String getValue() { - switch (this) { - case TOTAL_ONLINE: - return String.valueOf(Bukkit.getOnlinePlayers().size()); - case FACTIONLESS: - return String.valueOf(Factions.getInstance().getWilderness().getFPlayersWhereOnline(true).size()); - case MAX_ALLIES: - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.ally", 10)); - } - return TL.GENERIC_INFINITY.toString(); - case MAX_ENEMIES: - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.enemy", 10)); - } - return TL.GENERIC_INFINITY.toString(); - case MAX_TRUCES: - if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.truce", 10)); - } - return TL.GENERIC_INFINITY.toString(); - case MAX_WARPS: - return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-warps", 5)); - default: - } - return null; - } + /** + * Protected access to this generic server related variable + * + * @return value for this generic server related variable
    + */ + protected String getValue() { + switch (this) { + case TOTAL_ONLINE: + return String.valueOf(Bukkit.getOnlinePlayers().size()); + case FACTIONLESS: + return String.valueOf(Factions.getInstance().getWilderness().getFPlayersWhereOnline(true).size()); + case MAX_ALLIES: + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.ally", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_ENEMIES: + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.enemy", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_TRUCES: + if (SavageFactions.plugin.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-relations.truce", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_WARPS: + return String.valueOf(SavageFactions.plugin.getConfig().getInt("max-warps", 5)); + default: + } + return null; + } - /** - * Gets the value for this (as in the instance this is called from) variable! - * - * @param fac Target faction - * @param fp Target player (can be null) - * @return the value for this enum! - */ - protected String getValue(Faction fac, FPlayer fp) { - if (this.type == TagType.GENERAL) { - return getValue(); - } + /** + * Gets the value for this (as in the instance this is called from) variable! + * + * @param fac Target faction + * @param fp Target player (can be null) + * @return the value for this enum! + */ + protected String getValue(Faction fac, FPlayer fp) { + if (this.type == TagType.GENERAL) { + return getValue(); + } - boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); + boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); - if (fp != null) { - switch (this) { - case HEADER: - return SavageFactions.plugin.txt.titleize(fac.getTag(fp)); - case PLAYER_NAME: - return fp.getName(); - case FACTION: - return !fac.isWilderness() ? fac.getTag(fp) : TL.GENERIC_FACTIONLESS.toString(); - case LAST_SEEN: - String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; - return fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); - case PLAYER_GROUP: - return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fp.getId()))); - case PLAYER_BALANCE: - return Econ.isSetup() ? Econ.getFriendlyBalance(fp) : TL.ECON_OFF.format("balance"); - case PLAYER_POWER: - return String.valueOf(fp.getPowerRounded()); - case PLAYER_MAXPOWER: - return String.valueOf(fp.getPowerMaxRounded()); - case PLAYER_KILLS: - return String.valueOf(fp.getKills()); - case PLAYER_DEATHS: - return String.valueOf(fp.getDeaths()); - default: - } - } + if (fp != null) { + switch (this) { + case HEADER: + return SavageFactions.plugin.txt.titleize(fac.getTag(fp)); + case PLAYER_NAME: + return fp.getName(); + case FACTION: + return !fac.isWilderness() ? fac.getTag(fp) : TL.GENERIC_FACTIONLESS.toString(); + case LAST_SEEN: + String humanized = DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - fp.getLastLoginTime(), true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + return fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : (System.currentTimeMillis() - fp.getLastLoginTime() < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + case PLAYER_GROUP: + return SavageFactions.plugin.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fp.getId()))); + case PLAYER_BALANCE: + return Econ.isSetup() ? Econ.getFriendlyBalance(fp) : TL.ECON_OFF.format("balance"); + case PLAYER_POWER: + return String.valueOf(fp.getPowerRounded()); + case PLAYER_MAXPOWER: + return String.valueOf(fp.getPowerMaxRounded()); + case PLAYER_KILLS: + return String.valueOf(fp.getKills()); + case PLAYER_DEATHS: + return String.valueOf(fp.getDeaths()); + default: + } + } - switch (this) { - case DESCRIPTION: - return fac.getDescription(); - case FACTION: - return fac.getTag(); - case JOINING: - return (fac.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); - case PEACEFUL: - return fac.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; - case PERMANENT: - return fac.isPermanent() ? "permanent" : "{notPermanent}"; - case CHUNKS: - return String.valueOf(fac.getLandRounded()); - case POWER: - return String.valueOf(fac.getPowerRounded()); - case MAX_POWER: - return String.valueOf(fac.getPowerMaxRounded()); - case POWER_BOOST: - double powerBoost = fac.getPowerBoost(); - return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); - case LEADER: - FPlayer fAdmin = fac.getFPlayerAdmin(); - return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); - case WARPS: - return String.valueOf(fac.getWarps().size()); - case CREATE_DATE: - return TL.sdf.format(fac.getFoundedDate()); - case RAIDABLE: - boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && fac.getLandRounded() >= fac.getPowerRounded(); - return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); - case HOME_WORLD: - return fac.hasHome() ? fac.getHome().getWorld().getName() : minimal ? null : "{ig}"; - case HOME_X: - return fac.hasHome() ? String.valueOf(fac.getHome().getBlockX()) : minimal ? null : "{ig}"; - case HOME_Y: - return fac.hasHome() ? String.valueOf(fac.getHome().getBlockY()) : minimal ? null : "{ig}"; - case HOME_Z: - return fac.hasHome() ? String.valueOf(fac.getHome().getBlockZ()) : minimal ? null : "{ig}"; - case LAND_VALUE: - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("value"); - case LAND_REFUND: - return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("refund"); - case BANK_BALANCE: - if (Econ.shouldBeUsed()) { - return Conf.bankEnabled ? Econ.moneyString(Econ.getBalance(fac.getAccountId())) : minimal ? null : TL.ECON_OFF.format("balance"); - } - return minimal ? null : TL.ECON_OFF.format("balance"); - case ALLIES_COUNT: - return String.valueOf(fac.getRelationCount(Relation.ALLY)); - case ENEMIES_COUNT: - return String.valueOf(fac.getRelationCount(Relation.ENEMY)); - case TRUCES_COUNT: - return String.valueOf(fac.getRelationCount(Relation.TRUCE)); - case ONLINE_COUNT: - if (fp != null && fp.isOnline()) { - return String.valueOf(fac.getFPlayersWhereOnline(true, fp).size()); - } else { - // Only console should ever get here. - return String.valueOf(fac.getFPlayersWhereOnline(true).size()); - } - case OFFLINE_COUNT: - return String.valueOf(fac.getFPlayers().size() - fac.getOnlinePlayers().size()); - case FACTION_SIZE: - return String.valueOf(fac.getFPlayers().size()); - case FACTION_KILLS: - return String.valueOf(fac.getKills()); - case FACTION_DEATHS: - return String.valueOf(fac.getDeaths()); - case FACTION_BANCOUNT: - return String.valueOf(fac.getBannedPlayers().size()); - default: - } - return null; - } + switch (this) { + case DESCRIPTION: + return fac.getDescription(); + case FACTION: + return fac.getTag(); + case JOINING: + return (fac.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); + case PEACEFUL: + return fac.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; + case PERMANENT: + return fac.isPermanent() ? "permanent" : "{notPermanent}"; + case CHUNKS: + return String.valueOf(fac.getLandRounded()); + case POWER: + return String.valueOf(fac.getPowerRounded()); + case MAX_POWER: + return String.valueOf(fac.getPowerMaxRounded()); + case POWER_BOOST: + double powerBoost = fac.getPowerBoost(); + return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); + case LEADER: + FPlayer fAdmin = fac.getFPlayerAdmin(); + return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); + case WARPS: + return String.valueOf(fac.getWarps().size()); + case CREATE_DATE: + return TL.sdf.format(fac.getFoundedDate()); + case RAIDABLE: + boolean raid = SavageFactions.plugin.getConfig().getBoolean("hcf.raidable", false) && fac.getLandRounded() >= fac.getPowerRounded(); + return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); + case HOME_WORLD: + return fac.hasHome() ? fac.getHome().getWorld().getName() : minimal ? null : "{ig}"; + case HOME_X: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockX()) : minimal ? null : "{ig}"; + case HOME_Y: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockY()) : minimal ? null : "{ig}"; + case HOME_Z: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockZ()) : minimal ? null : "{ig}"; + case LAND_VALUE: + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("value"); + case LAND_REFUND: + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(fac.getLandRounded())) : minimal ? null : TL.ECON_OFF.format("refund"); + case BANK_BALANCE: + if (Econ.shouldBeUsed()) { + return Conf.bankEnabled ? Econ.moneyString(Econ.getBalance(fac.getAccountId())) : minimal ? null : TL.ECON_OFF.format("balance"); + } + return minimal ? null : TL.ECON_OFF.format("balance"); + case ALLIES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.ALLY)); + case ENEMIES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.ENEMY)); + case TRUCES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.TRUCE)); + case ONLINE_COUNT: + if (fp != null && fp.isOnline()) { + return String.valueOf(fac.getFPlayersWhereOnline(true, fp).size()); + } else { + // Only console should ever get here. + return String.valueOf(fac.getFPlayersWhereOnline(true).size()); + } + case OFFLINE_COUNT: + return String.valueOf(fac.getFPlayers().size() - fac.getOnlinePlayers().size()); + case FACTION_SIZE: + return String.valueOf(fac.getFPlayers().size()); + case FACTION_KILLS: + return String.valueOf(fac.getKills()); + case FACTION_DEATHS: + return String.valueOf(fac.getDeaths()); + case FACTION_BANCOUNT: + return String.valueOf(fac.getBannedPlayers().size()); + default: + } + return null; + } - /** - * @param original raw line with variables - * @param value what to replace var in raw line with - * @return the string with the new value - */ - public String replace(String original, String value) { - return original.replace(tag, value); - } + /** + * @param original raw line with variables + * @param value what to replace var in raw line with + * @return the string with the new value + */ + public String replace(String original, String value) { + return original.replace(tag, value); + } - /** - * @param toSearch raw line with variables - * @return if the raw line contains this enums variable - */ - public boolean contains(String toSearch) { - if (tag == null) { - return false; - } - return toSearch.contains(tag); - } + /** + * @param toSearch raw line with variables + * @return if the raw line contains this enums variable + */ + public boolean contains(String toSearch) { + if (tag == null) { + return false; + } + return toSearch.contains(tag); + } - /** - * Gets the tag associated with this enum that we should replace - * - * @return the {....} variable that is located in config - */ - public String getTag() { - return this.tag; - } + /** + * Gets the tag associated with this enum that we should replace + * + * @return the {....} variable that is located in config + */ + public String getTag() { + return this.tag; + } - protected enum TagType { - FANCY(0), PLAYER(1), FACTION(2), GENERAL(3); - public int id; + protected enum TagType { + FANCY(0), PLAYER(1), FACTION(2), GENERAL(3); + public int id; - TagType(int id) { - this.id = id; - } - } + TagType(int id) { + this.id = id; + } + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java index da621d69..e0639037 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java @@ -19,250 +19,250 @@ import static com.massivecraft.factions.zcore.util.TagReplacer.TagType; public class TagUtil { - private static final int ARBITRARY_LIMIT = 25000; + private static final int ARBITRARY_LIMIT = 25000; - /** - * Replaces all variables in a plain raw line for a faction - * - * @param faction for faction - * @param line raw line from config with variables to replace for - * @return clean line - */ - public static String parsePlain(Faction faction, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FACTION)) { - if (tagReplacer.contains(line)) { - line = tagReplacer.replace(line, tagReplacer.getValue(faction, null)); - } - } - return line; - } + /** + * Replaces all variables in a plain raw line for a faction + * + * @param faction for faction + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(Faction faction, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FACTION)) { + if (tagReplacer.contains(line)) { + line = tagReplacer.replace(line, tagReplacer.getValue(faction, null)); + } + } + return line; + } - /** - * Replaces all variables in a plain raw line for a player - * - * @param fplayer for player - * @param line raw line from config with variables to replace for - * @return clean line - */ - public static String parsePlain(FPlayer fplayer, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { - if (tagReplacer.contains(line)) { - String rep = tagReplacer.getValue(fplayer.getFaction(), fplayer); - if (rep == null) { - rep = ""; // this should work, but it's not a good way to handle whatever is going wrong - } - line = tagReplacer.replace(line, rep); - } - } - return line; - } + /** + * Replaces all variables in a plain raw line for a player + * + * @param fplayer for player + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(FPlayer fplayer, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { + if (tagReplacer.contains(line)) { + String rep = tagReplacer.getValue(fplayer.getFaction(), fplayer); + if (rep == null) { + rep = ""; // this should work, but it's not a good way to handle whatever is going wrong + } + line = tagReplacer.replace(line, rep); + } + } + return line; + } - /** - * Replaces all variables in a plain raw line for a faction, using relations from fplayer - * - * @param faction for faction - * @param fplayer from player - * @param line raw line from config with variables to replace for - * @return clean line - */ - public static String parsePlain(Faction faction, FPlayer fplayer, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { - if (tagReplacer.contains(line)) { - String value = tagReplacer.getValue(faction, fplayer); - if (value != null) { - line = tagReplacer.replace(line, value); - } else { - return null; // minimal show, entire line to be ignored - } - } - } - return line; - } + /** + * Replaces all variables in a plain raw line for a faction, using relations from fplayer + * + * @param faction for faction + * @param fplayer from player + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(Faction faction, FPlayer fplayer, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { + if (tagReplacer.contains(line)) { + String value = tagReplacer.getValue(faction, fplayer); + if (value != null) { + line = tagReplacer.replace(line, value); + } else { + return null; // minimal show, entire line to be ignored + } + } + } + return line; + } - /** - * Scan a line and parse the fancy variable into a fancy list - * - * @param faction for faction (viewers faction) - * @param fme for player (viewer) - * @param line fancy message prefix - * @return list of fancy msgs - */ - public static List parseFancy(Faction faction, FPlayer fme, String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { - if (tagReplacer.contains(line)) { - String clean = line.replace(tagReplacer.getTag(), ""); // remove tag - return getFancy(faction, fme, tagReplacer, clean); - } - } - return null; - } + /** + * Scan a line and parse the fancy variable into a fancy list + * + * @param faction for faction (viewers faction) + * @param fme for player (viewer) + * @param line fancy message prefix + * @return list of fancy msgs + */ + public static List parseFancy(Faction faction, FPlayer fme, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { + if (tagReplacer.contains(line)) { + String clean = line.replace(tagReplacer.getTag(), ""); // remove tag + return getFancy(faction, fme, tagReplacer, clean); + } + } + return null; + } - public static String parsePlaceholders(Player player, String line) { - if (SavageFactions.plugin.isClipPlaceholderAPIHooked() && player.isOnline()) { - line = PlaceholderAPI.setPlaceholders(player, line); - } + public static String parsePlaceholders(Player player, String line) { + if (SavageFactions.plugin.isClipPlaceholderAPIHooked() && player.isOnline()) { + line = PlaceholderAPI.setPlaceholders(player, line); + } - if (SavageFactions.plugin.isMVdWPlaceholderAPIHooked() && player.isOnline()) { - line = be.maximvdw.placeholderapi.PlaceholderAPI.replacePlaceholders(player, line); - } + if (SavageFactions.plugin.isMVdWPlaceholderAPIHooked() && player.isOnline()) { + line = be.maximvdw.placeholderapi.PlaceholderAPI.replacePlaceholders(player, line); + } - return line; - } + return line; + } - /** - * Checks if a line has fancy variables - * - * @param line raw line from config with variables - * @return if the line has fancy variables - */ - public static boolean hasFancy(String line) { - for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { - if (tagReplacer.contains(line)) { - return true; - } - } - return false; - } + /** + * Checks if a line has fancy variables + * + * @param line raw line from config with variables + * @return if the line has fancy variables + */ + public static boolean hasFancy(String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { + if (tagReplacer.contains(line)) { + return true; + } + } + return false; + } - /** - * Lets get fancy. - * - * @param target Faction to get relate from - * @param fme Player to relate to - * @param prefix First part of the fancy message - * @return list of fancy messages to send - */ - protected static List getFancy(Faction target, FPlayer fme, TagReplacer type, String prefix) { - List fancyMessages = new ArrayList<>(); - boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); + /** + * Lets get fancy. + * + * @param target Faction to get relate from + * @param fme Player to relate to + * @param prefix First part of the fancy message + * @return list of fancy messages to send + */ + protected static List getFancy(Faction target, FPlayer fme, TagReplacer type, String prefix) { + List fancyMessages = new ArrayList<>(); + boolean minimal = SavageFactions.plugin.getConfig().getBoolean("minimal-show", false); - switch (type) { - case ALLIES_LIST: - FancyMessage currentAllies = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstAlly = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == target) { - continue; - } - String s = otherFaction.getTag(fme); - if (otherFaction.getRelationTo(target).isAlly()) { - currentAllies.then(firstAlly ? s : ", " + s); - currentAllies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); - firstAlly = false; - if (currentAllies.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentAllies); - currentAllies = new FancyMessage(""); - } - } - } - fancyMessages.add(currentAllies); - return firstAlly && minimal ? null : fancyMessages; // we must return here and not outside the switch - case ENEMIES_LIST: - FancyMessage currentEnemies = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstEnemy = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == target) { - continue; - } - String s = otherFaction.getTag(fme); - if (otherFaction.getRelationTo(target).isEnemy()) { - currentEnemies.then(firstEnemy ? s : ", " + s); - currentEnemies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); - firstEnemy = false; - if (currentEnemies.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentEnemies); - currentEnemies = new FancyMessage(""); - } - } - } - fancyMessages.add(currentEnemies); - return firstEnemy && minimal ? null : fancyMessages; // we must return here and not outside the switch - case TRUCES_LIST: - FancyMessage currentTruces = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstTruce = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == target) { - continue; - } - String s = otherFaction.getTag(fme); - if (otherFaction.getRelationTo(target).isTruce()) { - currentTruces.then(firstTruce ? s : ", " + s); - currentTruces.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); - firstTruce = false; - if (currentTruces.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentTruces); - currentTruces = new FancyMessage(""); - } - } - } - fancyMessages.add(currentTruces); - return firstTruce && minimal ? null : fancyMessages; // we must return here and not outside the switch - case ONLINE_LIST: - FancyMessage currentOnline = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstOnline = true; - for (FPlayer p : MiscUtil.rankOrder(target.getFPlayersWhereOnline(true, fme))) { - if (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer())) { - continue; // skip - } - String name = p.getNameAndTitle(); - currentOnline.then(firstOnline ? name : ", " + name); - currentOnline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); - firstOnline = false; - if (currentOnline.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentOnline); - currentOnline = new FancyMessage(""); - } - } - fancyMessages.add(currentOnline); - return firstOnline && minimal ? null : fancyMessages; // we must return here and not outside the switch - case OFFLINE_LIST: - FancyMessage currentOffline = SavageFactions.plugin.txt.parseFancy(prefix); - boolean firstOffline = true; - for (FPlayer p : MiscUtil.rankOrder(target.getFPlayers())) { - String name = p.getNameAndTitle(); - // Also make sure to add players that are online BUT can't be seen. - if (!p.isOnline() || (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer()))) { - currentOffline.then(firstOffline ? name : ", " + name); - currentOffline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); - firstOffline = false; - if (currentOffline.toJSONString().length() > ARBITRARY_LIMIT) { - fancyMessages.add(currentOffline); - currentOffline = new FancyMessage(""); - } - } - } - fancyMessages.add(currentOffline); - return firstOffline && minimal ? null : fancyMessages; // we must return here and not outside the switch - default: - } - return null; - } + switch (type) { + case ALLIES_LIST: + FancyMessage currentAllies = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstAlly = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isAlly()) { + currentAllies.then(firstAlly ? s : ", " + s); + currentAllies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); + firstAlly = false; + if (currentAllies.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentAllies); + currentAllies = new FancyMessage(""); + } + } + } + fancyMessages.add(currentAllies); + return firstAlly && minimal ? null : fancyMessages; // we must return here and not outside the switch + case ENEMIES_LIST: + FancyMessage currentEnemies = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstEnemy = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isEnemy()) { + currentEnemies.then(firstEnemy ? s : ", " + s); + currentEnemies.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); + firstEnemy = false; + if (currentEnemies.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentEnemies); + currentEnemies = new FancyMessage(""); + } + } + } + fancyMessages.add(currentEnemies); + return firstEnemy && minimal ? null : fancyMessages; // we must return here and not outside the switch + case TRUCES_LIST: + FancyMessage currentTruces = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstTruce = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isTruce()) { + currentTruces.then(firstTruce ? s : ", " + s); + currentTruces.tooltip(tipFaction(otherFaction)).color(fme != null ? fme.getColorTo(otherFaction) : Relation.NEUTRAL.getColor()); + firstTruce = false; + if (currentTruces.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentTruces); + currentTruces = new FancyMessage(""); + } + } + } + fancyMessages.add(currentTruces); + return firstTruce && minimal ? null : fancyMessages; // we must return here and not outside the switch + case ONLINE_LIST: + FancyMessage currentOnline = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstOnline = true; + for (FPlayer p : MiscUtil.rankOrder(target.getFPlayersWhereOnline(true, fme))) { + if (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer())) { + continue; // skip + } + String name = p.getNameAndTitle(); + currentOnline.then(firstOnline ? name : ", " + name); + currentOnline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); + firstOnline = false; + if (currentOnline.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentOnline); + currentOnline = new FancyMessage(""); + } + } + fancyMessages.add(currentOnline); + return firstOnline && minimal ? null : fancyMessages; // we must return here and not outside the switch + case OFFLINE_LIST: + FancyMessage currentOffline = SavageFactions.plugin.txt.parseFancy(prefix); + boolean firstOffline = true; + for (FPlayer p : MiscUtil.rankOrder(target.getFPlayers())) { + String name = p.getNameAndTitle(); + // Also make sure to add players that are online BUT can't be seen. + if (!p.isOnline() || (fme != null && fme.getPlayer() != null && !fme.getPlayer().canSee(p.getPlayer()))) { + currentOffline.then(firstOffline ? name : ", " + name); + currentOffline.tooltip(tipPlayer(p)).color(fme != null ? fme.getColorTo(p) : Relation.NEUTRAL.getColor()); + firstOffline = false; + if (currentOffline.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentOffline); + currentOffline = new FancyMessage(""); + } + } + } + fancyMessages.add(currentOffline); + return firstOffline && minimal ? null : fancyMessages; // we must return here and not outside the switch + default: + } + return null; + } - /** - * Parses tooltip variables from config
    Supports variables for factions only (type 2) - * - * @param faction faction to tooltip for - * @return list of tooltips for a fancy message - */ - private static List tipFaction(Faction faction) { - List lines = new ArrayList<>(); - for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.list")) { - lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(faction, line))); - } - return lines; - } + /** + * Parses tooltip variables from config
    Supports variables for factions only (type 2) + * + * @param faction faction to tooltip for + * @return list of tooltips for a fancy message + */ + private static List tipFaction(Faction faction) { + List lines = new ArrayList<>(); + for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.list")) { + lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(faction, line))); + } + return lines; + } - /** - * Parses tooltip variables from config
    Supports variables for players and factions (types 1 and 2) - * - * @param fplayer player to tooltip for - * @return list of tooltips for a fancy message - */ - private static List tipPlayer(FPlayer fplayer) { - List lines = new ArrayList<>(); - for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.show")) { - lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(fplayer, line))); - } - return lines; - } + /** + * Parses tooltip variables from config
    Supports variables for players and factions (types 1 and 2) + * + * @param fplayer player to tooltip for + * @return list of tooltips for a fancy message + */ + private static List tipPlayer(FPlayer fplayer) { + List lines = new ArrayList<>(); + for (String line : SavageFactions.plugin.getConfig().getStringList("tooltips.show")) { + lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(fplayer, line))); + } + return lines; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java index 6b58ff69..1c6a4045 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java @@ -10,223 +10,223 @@ import java.util.regex.Pattern; public class TextUtil { - public static final transient Pattern patternTag = Pattern.compile("<([a-zA-Z0-9_]*)>"); - private final static String titleizeLine = repeat("-", 52); + public static final transient Pattern patternTag = Pattern.compile("<([a-zA-Z0-9_]*)>"); + private final static String titleizeLine = repeat("-", 52); - // -------------------------------------------- // - // Top-level parsing functions. - // -------------------------------------------- // - private final static int titleizeBalance = -1; - public Map tags; + // -------------------------------------------- // + // Top-level parsing functions. + // -------------------------------------------- // + private final static int titleizeBalance = -1; + public Map tags; - // -------------------------------------------- // - // Tag parsing - // -------------------------------------------- // + // -------------------------------------------- // + // Tag parsing + // -------------------------------------------- // - public TextUtil() { - this.tags = new HashMap<>(); - } + public TextUtil() { + this.tags = new HashMap<>(); + } - public static String replaceTags(String str, Map tags) { - StringBuffer ret = new StringBuffer(); - Matcher matcher = patternTag.matcher(str); - while (matcher.find()) { - String tag = matcher.group(1); - String repl = tags.get(tag); - if (repl == null) { - matcher.appendReplacement(ret, "<" + tag + ">"); - } else { - matcher.appendReplacement(ret, repl); - } - } - matcher.appendTail(ret); - return ret.toString(); - } + public static String replaceTags(String str, Map tags) { + StringBuffer ret = new StringBuffer(); + Matcher matcher = patternTag.matcher(str); + while (matcher.find()) { + String tag = matcher.group(1); + String repl = tags.get(tag); + if (repl == null) { + matcher.appendReplacement(ret, "<" + tag + ">"); + } else { + matcher.appendReplacement(ret, repl); + } + } + matcher.appendTail(ret); + return ret.toString(); + } - public static FancyMessage toFancy(String first) { - String text = ""; - FancyMessage message = new FancyMessage(text); - ChatColor color = null; - char[] chars = first.toCharArray(); + public static FancyMessage toFancy(String first) { + String text = ""; + FancyMessage message = new FancyMessage(text); + ChatColor color = null; + char[] chars = first.toCharArray(); - for (int i = 0; i < chars.length; i++) { - // changed this so javadocs wont throw an error - String compareChar = chars[i] + ""; - if (compareChar.equals("§")) { - if (color != null) { - if (color.isColor()) { - message.then(text).color(color); - } else { - message.then(text).style(color); - } - text = ""; - color = ChatColor.getByChar(chars[i + 1]); - } else { - color = ChatColor.getByChar(chars[i + 1]); - } - i++; // skip color char - } else { - text += chars[i]; - } - } - if (text.length() > 0) { - if (color != null) { - if (color.isColor()) { - message.then(text).color(color); - } else { - message.then(text).style(color); - } - } else { - message.text(text); - } - } - return message; - } + for (int i = 0; i < chars.length; i++) { + // changed this so javadocs wont throw an error + String compareChar = chars[i] + ""; + if (compareChar.equals("§")) { + if (color != null) { + if (color.isColor()) { + message.then(text).color(color); + } else { + message.then(text).style(color); + } + text = ""; + color = ChatColor.getByChar(chars[i + 1]); + } else { + color = ChatColor.getByChar(chars[i + 1]); + } + i++; // skip color char + } else { + text += chars[i]; + } + } + if (text.length() > 0) { + if (color != null) { + if (color.isColor()) { + message.then(text).color(color); + } else { + message.then(text).style(color); + } + } else { + message.text(text); + } + } + return message; + } - // -------------------------------------------- // - // Fancy parsing - // -------------------------------------------- // + // -------------------------------------------- // + // Fancy parsing + // -------------------------------------------- // - public static String parseColor(String string) { - string = parseColorAmp(string); - string = parseColorAcc(string); - string = parseColorTags(string); - return ChatColor.translateAlternateColorCodes('&', string); - } + public static String parseColor(String string) { + string = parseColorAmp(string); + string = parseColorAcc(string); + string = parseColorTags(string); + return ChatColor.translateAlternateColorCodes('&', string); + } - public static String parseColorAmp(String string) { - string = string.replaceAll("(§([a-z0-9]))", "\u00A7$2"); - string = string.replaceAll("(&([a-z0-9]))", "\u00A7$2"); - string = string.replace("&&", "&"); - return string; - } + public static String parseColorAmp(String string) { + string = string.replaceAll("(§([a-z0-9]))", "\u00A7$2"); + string = string.replaceAll("(&([a-z0-9]))", "\u00A7$2"); + string = string.replace("&&", "&"); + return string; + } - // -------------------------------------------- // - // Color parsing - // -------------------------------------------- // + // -------------------------------------------- // + // Color parsing + // -------------------------------------------- // - public static String parseColorAcc(String string) { - return string.replace("`e", "").replace("`r", ChatColor.RED.toString()).replace("`R", ChatColor.DARK_RED.toString()).replace("`y", ChatColor.YELLOW.toString()).replace("`Y", ChatColor.GOLD.toString()).replace("`g", ChatColor.GREEN.toString()).replace("`G", ChatColor.DARK_GREEN.toString()).replace("`a", ChatColor.AQUA.toString()).replace("`A", ChatColor.DARK_AQUA.toString()).replace("`b", ChatColor.BLUE.toString()).replace("`B", ChatColor.DARK_BLUE.toString()).replace("`plugin", ChatColor.LIGHT_PURPLE.toString()).replace("`SavageFactions", ChatColor.DARK_PURPLE.toString()).replace("`k", ChatColor.BLACK.toString()).replace("`s", ChatColor.GRAY.toString()).replace("`S", ChatColor.DARK_GRAY.toString()).replace("`w", ChatColor.WHITE.toString()); - } + public static String parseColorAcc(String string) { + return string.replace("`e", "").replace("`r", ChatColor.RED.toString()).replace("`R", ChatColor.DARK_RED.toString()).replace("`y", ChatColor.YELLOW.toString()).replace("`Y", ChatColor.GOLD.toString()).replace("`g", ChatColor.GREEN.toString()).replace("`G", ChatColor.DARK_GREEN.toString()).replace("`a", ChatColor.AQUA.toString()).replace("`A", ChatColor.DARK_AQUA.toString()).replace("`b", ChatColor.BLUE.toString()).replace("`B", ChatColor.DARK_BLUE.toString()).replace("`plugin", ChatColor.LIGHT_PURPLE.toString()).replace("`SavageFactions", ChatColor.DARK_PURPLE.toString()).replace("`k", ChatColor.BLACK.toString()).replace("`s", ChatColor.GRAY.toString()).replace("`S", ChatColor.DARK_GRAY.toString()).replace("`w", ChatColor.WHITE.toString()); + } - public static String parseColorTags(String string) { - return string.replace("", "").replace("", "\u00A70").replace("", "\u00A71").replace("", "\u00A72").replace("", "\u00A73").replace("", "\u00A74").replace("", "\u00A75").replace("", "\u00A76").replace("", "\u00A77").replace("", "\u00A78").replace("", "\u00A79").replace("", "\u00A7a").replace("", "\u00A7b").replace("", "\u00A7c").replace("", "\u00A7d").replace("", "\u00A7e").replace("", "\u00A7f"); - } + public static String parseColorTags(String string) { + return string.replace("", "").replace("", "\u00A70").replace("", "\u00A71").replace("", "\u00A72").replace("", "\u00A73").replace("", "\u00A74").replace("", "\u00A75").replace("", "\u00A76").replace("", "\u00A77").replace("", "\u00A78").replace("", "\u00A79").replace("", "\u00A7a").replace("", "\u00A7b").replace("", "\u00A7c").replace("", "\u00A7d").replace("", "\u00A7e").replace("", "\u00A7f"); + } - public static String upperCaseFirst(String string) { - return string.substring(0, 1).toUpperCase() + string.substring(1); - } + public static String upperCaseFirst(String string) { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } - public static String implode(List list, String glue) { - StringBuilder ret = new StringBuilder(); - for (int i = 0; i < list.size(); i++) - ret.append(glue).append(list.get(i)); + public static String implode(List list, String glue) { + StringBuilder ret = new StringBuilder(); + for (int i = 0; i < list.size(); i++) + ret.append(glue).append(list.get(i)); - return ret.length() > 0 ? ret.toString().substring(glue.length()) : ""; - } + return ret.length() > 0 ? ret.toString().substring(glue.length()) : ""; + } - // -------------------------------------------- // - // Standard utils like UCFirst, implode and repeat. - // -------------------------------------------- // + // -------------------------------------------- // + // Standard utils like UCFirst, implode and repeat. + // -------------------------------------------- // - public static String repeat(String s, int times) { - return times > 0 ? s + repeat(s, times - 1) : ""; - } + public static String repeat(String s, int times) { + return times > 0 ? s + repeat(s, times - 1) : ""; + } - public static String getMaterialName(Material material) { - return material.toString().replace('_', ' ').toLowerCase(); - } + public static String getMaterialName(Material material) { + return material.toString().replace('_', ' ').toLowerCase(); + } - // -------------------------------------------- // - // Material name tools - // -------------------------------------------- // + // -------------------------------------------- // + // Material name tools + // -------------------------------------------- // - public static String getBestStartWithCI(Collection candidates, String start) { - String ret = null; - int best = 0; + public static String getBestStartWithCI(Collection candidates, String start) { + String ret = null; + int best = 0; - start = start.toLowerCase(); - int minlength = start.length(); - for (String candidate : candidates) { - if (candidate.length() < minlength) { - continue; - } - if (!candidate.toLowerCase().startsWith(start)) { - continue; - } + start = start.toLowerCase(); + int minlength = start.length(); + for (String candidate : candidates) { + if (candidate.length() < minlength) { + continue; + } + if (!candidate.toLowerCase().startsWith(start)) { + continue; + } - // The closer to zero the better - int lendiff = candidate.length() - minlength; - if (lendiff == 0) { - return candidate; - } - if (lendiff < best || best == 0) { - best = lendiff; - ret = candidate; - } - } - return ret; - } + // The closer to zero the better + int lendiff = candidate.length() - minlength; + if (lendiff == 0) { + return candidate; + } + if (lendiff < best || best == 0) { + best = lendiff; + ret = candidate; + } + } + return ret; + } - public String parse(String str, Object... args) { - return String.format(this.parse(str), args); - } + public String parse(String str, Object... args) { + return String.format(this.parse(str), args); + } - // -------------------------------------------- // - // Paging and chrome-tools like titleize - // -------------------------------------------- // + // -------------------------------------------- // + // Paging and chrome-tools like titleize + // -------------------------------------------- // - public String parse(String str) { - return this.parseTags(parseColor(str)); - } + public String parse(String str) { + return this.parseTags(parseColor(str)); + } - public String parseTags(String str) { - return replaceTags(str, this.tags); - } + public String parseTags(String str) { + return replaceTags(str, this.tags); + } - public FancyMessage parseFancy(String prefix) { - return toFancy(parse(prefix)); - } + public FancyMessage parseFancy(String prefix) { + return toFancy(parse(prefix)); + } - public String titleize(String str) { - String center = ChatColor.DARK_GRAY + "< " + parseTags("") + str + parseTags("
    ") + ChatColor.DARK_GRAY + " >"; - int centerlen = ChatColor.stripColor(center).length(); - int pivot = titleizeLine.length() / 2; - int eatLeft = (centerlen / 2) - titleizeBalance; - int eatRight = (centerlen - eatLeft) + titleizeBalance; + public String titleize(String str) { + String center = ChatColor.DARK_GRAY + "< " + parseTags("") + str + parseTags("") + ChatColor.DARK_GRAY + " >"; + int centerlen = ChatColor.stripColor(center).length(); + int pivot = titleizeLine.length() / 2; + int eatLeft = (centerlen / 2) - titleizeBalance; + int eatRight = (centerlen - eatLeft) + titleizeBalance; - if (eatLeft < pivot) { - return parseTags("") + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(0, pivot - eatLeft) + center + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(pivot + eatRight); - } else { - return parseTags("") + center; - } - } + if (eatLeft < pivot) { + return parseTags("") + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(0, pivot - eatLeft) + center + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + titleizeLine.substring(pivot + eatRight); + } else { + return parseTags("") + center; + } + } - public ArrayList getPage(List lines, int pageHumanBased, String title) { - ArrayList ret = new ArrayList<>(); - int pageZeroBased = pageHumanBased - 1; - int pageheight = 9; - int pagecount = (lines.size() / pageheight) + 1; + public ArrayList getPage(List lines, int pageHumanBased, String title) { + ArrayList ret = new ArrayList<>(); + int pageZeroBased = pageHumanBased - 1; + int pageheight = 9; + int pagecount = (lines.size() / pageheight) + 1; - ret.add(this.titleize(title + " " + pageHumanBased + "/" + pagecount)); + ret.add(this.titleize(title + " " + pageHumanBased + "/" + pagecount)); - if (pagecount == 0) { - ret.add(this.parseTags(TL.NOPAGES.toString())); - return ret; - } else if (pageZeroBased < 0 || pageHumanBased > pagecount) { - ret.add(this.parseTags(TL.INVALIDPAGE.format(pagecount))); - return ret; - } + if (pagecount == 0) { + ret.add(this.parseTags(TL.NOPAGES.toString())); + return ret; + } else if (pageZeroBased < 0 || pageHumanBased > pagecount) { + ret.add(this.parseTags(TL.INVALIDPAGE.format(pagecount))); + return ret; + } - int from = pageZeroBased * pageheight; - int to = from + pageheight; - if (to > lines.size()) { - to = lines.size(); - } + int from = pageZeroBased * pageheight; + int to = from + pageheight; + if (to > lines.size()) { + to = lines.size(); + } - ret.addAll(lines.subList(from, to)); + ret.addAll(lines.subList(from, to)); - return ret; - } + return ret; + } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java b/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java index adf3e3a2..667d58b8 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/UUIDFetcher.java @@ -18,83 +18,83 @@ import java.util.concurrent.Callable; */ public class UUIDFetcher implements Callable> { - private static final double PROFILES_PER_REQUEST = 100; - private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; - private final JSONParser jsonParser = new JSONParser(); - private final List names; - private final boolean rateLimiting; + private static final double PROFILES_PER_REQUEST = 100; + private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; + private final JSONParser jsonParser = new JSONParser(); + private final List names; + private final boolean rateLimiting; - public UUIDFetcher(List names, boolean rateLimiting) { - this.names = ImmutableList.copyOf(names); - this.rateLimiting = rateLimiting; - } + public UUIDFetcher(List names, boolean rateLimiting) { + this.names = ImmutableList.copyOf(names); + this.rateLimiting = rateLimiting; + } - public UUIDFetcher(List names) { - this(names, true); - } + public UUIDFetcher(List names) { + this(names, true); + } - private static void writeBody(HttpURLConnection connection, String body) throws Exception { - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - } + private static void writeBody(HttpURLConnection connection, String body) throws Exception { + OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + } - private static HttpURLConnection createConnection() throws Exception { - URL url = new URL(PROFILE_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - return connection; - } + private static HttpURLConnection createConnection() throws Exception { + URL url = new URL(PROFILE_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + return connection; + } - private static UUID getUUID(String id) { - return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); - } + private static UUID getUUID(String id) { + return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); + } - public static byte[] toBytes(UUID uuid) { - ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); - byteBuffer.putLong(uuid.getMostSignificantBits()); - byteBuffer.putLong(uuid.getLeastSignificantBits()); - return byteBuffer.array(); - } + public static byte[] toBytes(UUID uuid) { + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } - public static UUID fromBytes(byte[] array) { - if (array.length != 16) { - throw new IllegalArgumentException("Illegal byte array length: " + array.length); - } - ByteBuffer byteBuffer = ByteBuffer.wrap(array); - long mostSignificant = byteBuffer.getLong(); - long leastSignificant = byteBuffer.getLong(); - return new UUID(mostSignificant, leastSignificant); - } + public static UUID fromBytes(byte[] array) { + if (array.length != 16) { + throw new IllegalArgumentException("Illegal byte array length: " + array.length); + } + ByteBuffer byteBuffer = ByteBuffer.wrap(array); + long mostSignificant = byteBuffer.getLong(); + long leastSignificant = byteBuffer.getLong(); + return new UUID(mostSignificant, leastSignificant); + } - public static UUID getUUIDOf(String name) throws Exception { - return new UUIDFetcher(Collections.singletonList(name)).call().get(name); - } + public static UUID getUUIDOf(String name) throws Exception { + return new UUIDFetcher(Collections.singletonList(name)).call().get(name); + } - public Map call() throws Exception { - Map uuidMap = new HashMap<>(); - int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); - for (int i = 0; i < requests; i++) { - HttpURLConnection connection = createConnection(); - String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); - writeBody(connection, body); - JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); - for (Object profile : array) { - JSONObject jsonProfile = (JSONObject) profile; - String id = (String) jsonProfile.get("id"); - String name = (String) jsonProfile.get("name"); - UUID uuid = UUIDFetcher.getUUID(id); - uuidMap.put(name, uuid); - } - if (rateLimiting && i != requests - 1) { - Thread.sleep(100L); - } - } - return uuidMap; - } + public Map call() throws Exception { + Map uuidMap = new HashMap<>(); + int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); + for (int i = 0; i < requests; i++) { + HttpURLConnection connection = createConnection(); + String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); + writeBody(connection, body); + JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); + for (Object profile : array) { + JSONObject jsonProfile = (JSONObject) profile; + String id = (String) jsonProfile.get("id"); + String name = (String) jsonProfile.get("name"); + UUID uuid = UUIDFetcher.getUUID(id); + uuidMap.put(name, uuid); + } + if (rateLimiting && i != requests - 1) { + Thread.sleep(100L); + } + } + return uuidMap; + } } From 19b556a8c4d3a51c4a273b7973b267a6240234af Mon Sep 17 00:00:00 2001 From: Liz3 Date: Sun, 3 Mar 2019 04:52:32 +0100 Subject: [PATCH 4/5] added ident message to Contributing.m --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ebd382ea..6d81a1ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,6 +12,8 @@ * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. +* Please use tabs as ident with a size of 3 spaces. + #### **Did you fix whitespace, format code, or make a purely cosmetic patch?** Please specify what changes you made to the formatting etc., as it allows us to get an idea of how this will change our files overall. From b10d0caafa67fdada7496d08e70377a102b923e2 Mon Sep 17 00:00:00 2001 From: Liz3 Date: Sun, 3 Mar 2019 05:10:25 +0100 Subject: [PATCH 5/5] Ident correction. Last branch had a bad intend due to some misconfiguration on my side. --- .../java/com/massivecraft/factions/Board.java | 104 +- .../java/com/massivecraft/factions/Conf.java | 851 +++-- .../com/massivecraft/factions/FLocation.java | 386 +- .../com/massivecraft/factions/FPlayer.java | 410 +-- .../com/massivecraft/factions/FPlayers.java | 82 +- .../com/massivecraft/factions/Faction.java | 351 +- .../com/massivecraft/factions/Factions.java | 110 +- .../massivecraft/factions/MassiveStats.java | 750 ++-- .../massivecraft/factions/SavageFactions.java | 1402 ++++---- .../massivecraft/factions/cmd/CmdAHome.java | 70 +- .../massivecraft/factions/cmd/CmdAdmin.java | 138 +- .../factions/cmd/CmdAnnounce.java | 58 +- .../factions/cmd/CmdAutoClaim.java | 72 +- .../factions/cmd/CmdAutoHelp.java | 96 +- .../com/massivecraft/factions/cmd/CmdBan.java | 132 +- .../massivecraft/factions/cmd/CmdBanlist.java | 90 +- .../massivecraft/factions/cmd/CmdBanner.java | 200 +- .../massivecraft/factions/cmd/CmdBoom.java | 68 +- .../massivecraft/factions/cmd/CmdBypass.java | 58 +- .../massivecraft/factions/cmd/CmdChat.java | 132 +- .../massivecraft/factions/cmd/CmdChatSpy.java | 54 +- .../factions/cmd/CmdCheckpoint.java | 108 +- .../massivecraft/factions/cmd/CmdChest.java | 62 +- .../massivecraft/factions/cmd/CmdClaim.java | 130 +- .../massivecraft/factions/cmd/CmdClaimAt.java | 50 +- .../factions/cmd/CmdClaimLine.java | 106 +- .../factions/cmd/CmdColeader.java | 130 +- .../massivecraft/factions/cmd/CmdConfig.java | 396 +-- .../massivecraft/factions/cmd/CmdConvert.java | 58 +- .../massivecraft/factions/cmd/CmdCoords.java | 50 +- .../massivecraft/factions/cmd/CmdCreate.java | 166 +- .../factions/cmd/CmdDeinvite.java | 94 +- .../factions/cmd/CmdDelFWarp.java | 62 +- .../massivecraft/factions/cmd/CmdDemote.java | 8 +- .../factions/cmd/CmdDescription.java | 78 +- .../massivecraft/factions/cmd/CmdDisband.java | 156 +- .../massivecraft/factions/cmd/CmdFWarp.java | 126 +- .../com/massivecraft/factions/cmd/CmdFly.java | 402 +-- .../massivecraft/factions/cmd/CmdFocus.java | 74 +- .../factions/cmd/CmdGetVault.java | 102 +- .../massivecraft/factions/cmd/CmdHelp.java | 360 +- .../massivecraft/factions/cmd/CmdHome.java | 206 +- .../massivecraft/factions/cmd/CmdInspect.java | 52 +- .../massivecraft/factions/cmd/CmdInvite.java | 130 +- .../massivecraft/factions/cmd/CmdJoin.java | 188 +- .../massivecraft/factions/cmd/CmdKick.java | 208 +- .../factions/cmd/CmdKillHolograms.java | 42 +- .../massivecraft/factions/cmd/CmdLeave.java | 42 +- .../massivecraft/factions/cmd/CmdList.java | 194 +- .../massivecraft/factions/cmd/CmdLock.java | 46 +- .../massivecraft/factions/cmd/CmdLogins.java | 40 +- .../factions/cmd/CmdLowPower.java | 50 +- .../com/massivecraft/factions/cmd/CmdMap.java | 92 +- .../factions/cmd/CmdMapHeight.java | 44 +- .../com/massivecraft/factions/cmd/CmdMod.java | 124 +- .../factions/cmd/CmdModifyPower.java | 66 +- .../massivecraft/factions/cmd/CmdMoney.java | 68 +- .../factions/cmd/CmdMoneyBalance.java | 66 +- .../factions/cmd/CmdMoneyDeposit.java | 58 +- .../factions/cmd/CmdMoneyTransferFf.java | 68 +- .../factions/cmd/CmdMoneyTransferFp.java | 66 +- .../factions/cmd/CmdMoneyTransferPf.java | 66 +- .../factions/cmd/CmdMoneyWithdraw.java | 66 +- .../massivecraft/factions/cmd/CmdNear.java | 70 +- .../massivecraft/factions/cmd/CmdOpen.java | 68 +- .../massivecraft/factions/cmd/CmdOwner.java | 148 +- .../factions/cmd/CmdOwnerList.java | 94 +- .../factions/cmd/CmdPaypalSee.java | 66 +- .../factions/cmd/CmdPaypalSet.java | 52 +- .../factions/cmd/CmdPeaceful.java | 82 +- .../massivecraft/factions/cmd/CmdPerm.java | 168 +- .../factions/cmd/CmdPermanent.java | 126 +- .../factions/cmd/CmdPermanentPower.java | 118 +- .../massivecraft/factions/cmd/CmdPower.java | 70 +- .../factions/cmd/CmdPowerBoost.java | 176 +- .../massivecraft/factions/cmd/CmdPromote.java | 10 +- .../factions/cmd/CmdRelationAlly.java | 8 +- .../factions/cmd/CmdRelationEnemy.java | 8 +- .../factions/cmd/CmdRelationNeutral.java | 8 +- .../factions/cmd/CmdRelationTruce.java | 8 +- .../massivecraft/factions/cmd/CmdReload.java | 60 +- .../massivecraft/factions/cmd/CmdRules.java | 138 +- .../com/massivecraft/factions/cmd/CmdSB.java | 44 +- .../factions/cmd/CmdSafeunclaimall.java | 70 +- .../massivecraft/factions/cmd/CmdSaveAll.java | 86 +- .../factions/cmd/CmdSeeChunk.java | 214 +- .../factions/cmd/CmdSetBanner.java | 42 +- .../factions/cmd/CmdSetDefaultRole.java | 60 +- .../factions/cmd/CmdSetFWarp.java | 106 +- .../factions/cmd/CmdSetMaxVaults.java | 64 +- .../massivecraft/factions/cmd/CmdSethome.java | 102 +- .../massivecraft/factions/cmd/CmdShow.java | 168 +- .../factions/cmd/CmdShowClaims.java | 70 +- .../factions/cmd/CmdShowInvites.java | 42 +- .../massivecraft/factions/cmd/CmdStatus.java | 50 +- .../massivecraft/factions/cmd/CmdStealth.java | 46 +- .../massivecraft/factions/cmd/CmdStuck.java | 160 +- .../com/massivecraft/factions/cmd/CmdTag.java | 118 +- .../massivecraft/factions/cmd/CmdTitle.java | 68 +- .../com/massivecraft/factions/cmd/CmdTnt.java | 306 +- .../massivecraft/factions/cmd/CmdTntFill.java | 432 +-- .../factions/cmd/CmdToggleAllianceChat.java | 54 +- .../com/massivecraft/factions/cmd/CmdTop.java | 296 +- .../factions/cmd/CmdTpBanner.java | 66 +- .../massivecraft/factions/cmd/CmdUnban.java | 74 +- .../massivecraft/factions/cmd/CmdUnclaim.java | 268 +- .../factions/cmd/CmdUnclaimall.java | 82 +- .../factions/cmd/CmdUpgrades.java | 52 +- .../massivecraft/factions/cmd/CmdVault.java | 102 +- .../massivecraft/factions/cmd/CmdVersion.java | 42 +- .../factions/cmd/CmdWarunclaimall.java | 68 +- .../massivecraft/factions/cmd/FCmdRoot.java | 458 +-- .../massivecraft/factions/cmd/FCommand.java | 652 ++-- .../factions/cmd/FPromoteCommand.java | 134 +- .../factions/cmd/FRelationCommand.java | 184 +- .../event/FPlayerEnteredFactionEvent.java | 52 +- .../factions/event/FPlayerJoinEvent.java | 50 +- .../factions/event/FPlayerLeaveEvent.java | 52 +- .../factions/event/FPlayerStoppedFlying.java | 32 +- .../factions/event/FactionCreateEvent.java | 58 +- .../factions/event/FactionDisbandEvent.java | 62 +- .../factions/event/FactionEvent.java | 40 +- .../factions/event/FactionPlayerEvent.java | 16 +- .../factions/event/FactionRelationEvent.java | 58 +- .../event/FactionRelationWishEvent.java | 54 +- .../factions/event/FactionRenameEvent.java | 84 +- .../factions/event/LandClaimEvent.java | 106 +- .../factions/event/LandUnclaimAllEvent.java | 84 +- .../factions/event/LandUnclaimEvent.java | 96 +- .../factions/event/PowerLossEvent.java | 118 +- .../factions/event/PowerRegenEvent.java | 24 +- .../factions/iface/EconomyParticipator.java | 6 +- .../factions/iface/RelationParticipator.java | 10 +- .../factions/integration/Econ.java | 686 ++-- .../factions/integration/Essentials.java | 48 +- .../factions/integration/Worldguard.java | 172 +- .../integration/dynmap/DynmapStyle.java | 164 +- .../integration/dynmap/EngineDynmap.java | 1492 ++++---- .../integration/dynmap/TempAreaMarker.java | 170 +- .../integration/dynmap/TempMarker.java | 100 +- .../integration/dynmap/TempMarkerSet.java | 72 +- .../listeners/FactionsBlockListener.java | 970 ++--- .../listeners/FactionsChatListener.java | 316 +- .../listeners/FactionsEntityListener.java | 1396 ++++---- .../listeners/FactionsExploitListener.java | 82 +- .../listeners/FactionsPlayerListener.java | 1960 +++++------ .../scoreboards/BufferedObjective.java | 242 +- .../factions/scoreboards/FScoreboard.java | 216 +- .../scoreboards/FSidebarProvider.java | 44 +- .../factions/scoreboards/FTeamWrapper.java | 350 +- .../scoreboards/sidebar/FDefaultSidebar.java | 48 +- .../scoreboards/sidebar/FInfoSidebar.java | 34 +- .../player/PlayerFactionExpression.java | 120 +- .../player/PlayerPowerExpression.java | 116 +- .../player/PlayerRoleExpression.java | 112 +- .../massivecraft/factions/struct/BanInfo.java | 66 +- .../factions/struct/ChatMode.java | 60 +- .../factions/struct/Permission.java | 250 +- .../factions/struct/Relation.java | 370 +- .../massivecraft/factions/struct/Role.java | 216 +- .../factions/util/AsciiCompass.java | 172 +- .../factions/util/AutoLeaveProcessTask.java | 132 +- .../factions/util/AutoLeaveTask.java | 32 +- .../util/ClipPlaceholderAPIManager.java | 272 +- .../factions/util/EnumTypeAdapter.java | 86 +- .../factions/util/FactionGUI.java | 4 +- .../factions/util/InventoryTypeAdapter.java | 22 +- .../factions/util/InventoryUtil.java | 130 +- .../factions/util/LazyLocation.java | 140 +- .../factions/util/LocationTypeAdapter.java | 60 +- .../util/MapFLocToStringSetTypeAdapter.java | 142 +- .../massivecraft/factions/util/MiscUtil.java | 176 +- .../factions/util/MultiversionMaterials.java | 1898 +++++----- .../factions/util/MyLocationTypeAdapter.java | 80 +- .../util/Particles/ParticleEffect.java | 3110 ++++++++--------- .../util/Particles/ReflectionUtils.java | 1078 +++--- .../util/PermissionsMapTypeAdapter.java | 138 +- .../factions/util/RelationUtil.java | 152 +- .../factions/util/SpiralTask.java | 296 +- .../massivecraft/factions/util/UtilFly.java | 168 +- .../factions/util/VisualizeUtil.java | 102 +- .../factions/util/WarmUpUtil.java | 62 +- .../massivecraft/factions/util/WarpGUI.java | 388 +- .../factions/zcore/CommandVisibility.java | 14 +- .../massivecraft/factions/zcore/MCommand.java | 918 ++--- .../massivecraft/factions/zcore/MPlugin.java | 516 +-- .../zcore/MPluginSecretPlayerListener.java | 52 +- .../factions/zcore/fperms/Access.java | 62 +- .../zcore/fperms/DefaultPermissions.java | 291 +- .../factions/zcore/fperms/Permissable.java | 6 +- .../zcore/fperms/PermissableAction.java | 276 +- .../fperms/gui/PermissableActionGUI.java | 472 +-- .../fperms/gui/PermissableRelationGUI.java | 286 +- .../zcore/fupgrades/CropUpgrades.java | 96 +- .../factions/zcore/fupgrades/EXPUpgrade.java | 62 +- .../zcore/fupgrades/FUpgradesGUI.java | 464 +-- .../zcore/fupgrades/SpawnerUpgrades.java | 50 +- .../factions/zcore/fupgrades/Upgrade.java | 18 +- .../factions/zcore/nbtapi/NBTCompound.java | 290 +- .../factions/zcore/nbtapi/NBTContainer.java | 42 +- .../factions/zcore/nbtapi/NBTEntity.java | 20 +- .../factions/zcore/nbtapi/NBTFile.java | 58 +- .../factions/zcore/nbtapi/NBTItem.java | 44 +- .../factions/zcore/nbtapi/NBTList.java | 210 +- .../zcore/nbtapi/NBTListCompound.java | 164 +- .../zcore/nbtapi/NBTReflectionUtil.java | 1798 +++++----- .../factions/zcore/nbtapi/NBTTileEntity.java | 20 +- .../factions/zcore/nbtapi/NBTType.java | 50 +- .../zcore/nbtapi/utils/GsonWrapper.java | 32 +- .../zcore/nbtapi/utils/MethodNames.java | 32 +- .../zcore/nbtapi/utils/MinecraftVersion.java | 90 +- .../factions/zcore/persist/MemoryBoard.java | 624 ++-- .../factions/zcore/persist/MemoryFPlayer.java | 2366 ++++++------- .../zcore/persist/MemoryFPlayers.java | 82 +- .../factions/zcore/persist/MemoryFaction.java | 2414 ++++++------- .../zcore/persist/MemoryFactions.java | 278 +- .../factions/zcore/persist/SaveTask.java | 34 +- .../zcore/persist/json/FactionsJSON.java | 64 +- .../zcore/persist/json/JSONBoard.java | 136 +- .../zcore/persist/json/JSONFPlayer.java | 26 +- .../zcore/persist/json/JSONFPlayers.java | 288 +- .../zcore/persist/json/JSONFaction.java | 16 +- .../zcore/persist/json/JSONFactions.java | 506 +-- .../factions/zcore/util/DiscUtil.java | 240 +- .../factions/zcore/util/PermUtil.java | 98 +- .../factions/zcore/util/Persist.java | 210 +- .../factions/zcore/util/SmokeUtil.java | 164 +- .../massivecraft/factions/zcore/util/TL.java | 2028 +++++------ .../factions/zcore/util/TagReplacer.java | 528 +-- .../factions/zcore/util/TagUtil.java | 468 +-- .../factions/zcore/util/TextUtil.java | 366 +- .../factions/zcore/util/UUIDFetcher.java | 140 +- 232 files changed, 26900 insertions(+), 26895 deletions(-) diff --git a/src/main/java/com/massivecraft/factions/Board.java b/src/main/java/com/massivecraft/factions/Board.java index 1857fab2..dbd7d8f4 100644 --- a/src/main/java/com/massivecraft/factions/Board.java +++ b/src/main/java/com/massivecraft/factions/Board.java @@ -9,82 +9,82 @@ import java.util.Set; public abstract class Board { - protected static Board instance = getBoardImpl(); + protected static Board instance = getBoardImpl(); - private static Board getBoardImpl() { - switch (Conf.backEnd) { - case JSON: - return new JSONBoard(); - } - return null; - } + private static Board getBoardImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONBoard(); + } + return null; + } - public static Board getInstance() { - return instance; - } + public static Board getInstance() { + return instance; + } - //----------------------------------------------// - // Get and Set - //----------------------------------------------// - public abstract String getIdAt(FLocation flocation); + //----------------------------------------------// + // Get and Set + //----------------------------------------------// + public abstract String getIdAt(FLocation flocation); - public abstract Faction getFactionAt(FLocation flocation); + public abstract Faction getFactionAt(FLocation flocation); - public abstract void setIdAt(String id, FLocation flocation); + public abstract void setIdAt(String id, FLocation flocation); - public abstract void setFactionAt(Faction faction, FLocation flocation); + public abstract void setFactionAt(Faction faction, FLocation flocation); - public abstract void removeAt(FLocation flocation); + public abstract void removeAt(FLocation flocation); - public abstract Set getAllClaims(String factionId); + public abstract Set getAllClaims(String factionId); - public abstract Set getAllClaims(Faction faction); + public abstract Set getAllClaims(Faction faction); - // not to be confused with claims, ownership referring to further member-specific ownership of a claim - public abstract void clearOwnershipAt(FLocation flocation); + // not to be confused with claims, ownership referring to further member-specific ownership of a claim + public abstract void clearOwnershipAt(FLocation flocation); - public abstract void unclaimAll(String factionId); + public abstract void unclaimAll(String factionId); - public abstract void unclaimAllInWorld(String factionId, World world); + public abstract void unclaimAllInWorld(String factionId, World world); - // Is this coord NOT completely surrounded by coords claimed by the same faction? - // Simpler: Is there any nearby coord with a faction other than the faction here? - public abstract boolean isBorderLocation(FLocation flocation); + // Is this coord NOT completely surrounded by coords claimed by the same faction? + // Simpler: Is there any nearby coord with a faction other than the faction here? + public abstract boolean isBorderLocation(FLocation flocation); - // Is this coord connected to any coord claimed by the specified faction? - public abstract boolean isConnectedLocation(FLocation flocation, Faction faction); + // Is this coord connected to any coord claimed by the specified faction? + public abstract boolean isConnectedLocation(FLocation flocation, Faction faction); - public abstract boolean hasFactionWithin(FLocation flocation, Faction faction, int radius); + public abstract boolean hasFactionWithin(FLocation flocation, Faction faction, int radius); - //----------------------------------------------// - // Cleaner. Remove orphaned foreign keys - //----------------------------------------------// + //----------------------------------------------// + // Cleaner. Remove orphaned foreign keys + //----------------------------------------------// - public abstract void clean(); + public abstract void clean(); - //----------------------------------------------// - // Coord count - //----------------------------------------------// + //----------------------------------------------// + // Coord count + //----------------------------------------------// - public abstract int getFactionCoordCount(String factionId); + public abstract int getFactionCoordCount(String factionId); - public abstract int getFactionCoordCount(Faction faction); + public abstract int getFactionCoordCount(Faction faction); - public abstract int getFactionCoordCountInWorld(Faction faction, String worldName); + public abstract int getFactionCoordCountInWorld(Faction faction, String worldName); - //----------------------------------------------// - // Map generation - //----------------------------------------------// + //----------------------------------------------// + // Map generation + //----------------------------------------------// - /* - * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction - * of decreasing z - */ - public abstract ArrayList getMap(FPlayer fPlayer, FLocation flocation, double inDegrees); + /* + * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction + * of decreasing z + */ + public abstract ArrayList getMap(FPlayer fPlayer, FLocation flocation, double inDegrees); - public abstract void forceSave(); + public abstract void forceSave(); - public abstract void forceSave(boolean sync); + public abstract void forceSave(boolean sync); - public abstract boolean load(); + public abstract boolean load(); } diff --git a/src/main/java/com/massivecraft/factions/Conf.java b/src/main/java/com/massivecraft/factions/Conf.java index 45082931..9a4989eb 100644 --- a/src/main/java/com/massivecraft/factions/Conf.java +++ b/src/main/java/com/massivecraft/factions/Conf.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap; import com.massivecraft.factions.integration.dynmap.DynmapStyle; import com.massivecraft.factions.util.MultiversionMaterials; import com.massivecraft.factions.zcore.fperms.DefaultPermissions; -import com.massivecraft.factions.zcore.fperms.PermissableAction; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.EntityType; @@ -13,454 +12,454 @@ import java.util.*; public class Conf { - // Region Style - public static final transient String DYNMAP_STYLE_LINE_COLOR = "#00FF00"; - public static final transient double DYNMAP_STYLE_LINE_OPACITY = 0.8D; - public static final transient int DYNMAP_STYLE_LINE_WEIGHT = 3; - public static final transient String DYNMAP_STYLE_FILL_COLOR = "#00FF00"; - public static final transient double DYNMAP_STYLE_FILL_OPACITY = 0.35D; - public static final transient String DYNMAP_STYLE_HOME_MARKER = "greenflag"; - public static final transient boolean DYNMAP_STYLE_BOOST = false; - public static List baseCommandAliases = new ArrayList<>(); - public static boolean allowNoSlashCommand = true; - public static Set allowedStealthFactions = new LinkedHashSet<>(); + // Region Style + public static final transient String DYNMAP_STYLE_LINE_COLOR = "#00FF00"; + public static final transient double DYNMAP_STYLE_LINE_OPACITY = 0.8D; + public static final transient int DYNMAP_STYLE_LINE_WEIGHT = 3; + public static final transient String DYNMAP_STYLE_FILL_COLOR = "#00FF00"; + public static final transient double DYNMAP_STYLE_FILL_OPACITY = 0.35D; + public static final transient String DYNMAP_STYLE_HOME_MARKER = "greenflag"; + public static final transient boolean DYNMAP_STYLE_BOOST = false; + public static List baseCommandAliases = new ArrayList<>(); + public static boolean allowNoSlashCommand = true; + public static Set allowedStealthFactions = new LinkedHashSet<>(); - // Colors - public static ChatColor colorMember = ChatColor.GREEN; - public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE; - public static ChatColor colorTruce = ChatColor.DARK_PURPLE; - public static ChatColor colorNeutral = ChatColor.WHITE; - public static ChatColor colorEnemy = ChatColor.RED; - public static ChatColor colorPeaceful = ChatColor.GOLD; - public static ChatColor colorWilderness = ChatColor.GRAY; - public static ChatColor colorSafezone = ChatColor.GOLD; - public static ChatColor colorWar = ChatColor.DARK_RED; - // Power - public static double powerPlayerMax = 10.0; - public static double powerPlayerMin = -10.0; - public static double powerPlayerStarting = 0.0; - public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power - public static double powerPerDeath = 4.0; // A death makes you lose 4 power - public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline? - public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline - public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less - public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts) - public static String prefixLeader = "***"; - public static String prefixCoLeader = "**"; - public static String prefixMod = "*"; - public static String prefixRecruit = "-"; - public static String prefixNormal = "+"; - public static int factionTagLengthMin = 3; - public static int factionTagLengthMax = 10; - public static boolean factionTagForceUpperCase = false; - public static boolean newFactionsDefaultOpen = false; - // when faction membership hits this limit, players will no longer be able to join using /f join; default is 0, no limit - public static int factionMemberLimit = 0; - // what faction ID to start new players in when they first join the server; default is 0, "no faction" - public static String newPlayerStartingFactionID = "0"; - public static boolean showMapFactionKey = true; - public static boolean showNeutralFactionsOnMap = true; - public static boolean showEnemyFactionsOnMap = true; - public static boolean showTrucesFactionsOnMap = true; - // Disallow joining/leaving/kicking while power is negative - public static boolean canLeaveWithNegativePower = true; - // Configuration for faction-only chat - public static boolean factionOnlyChat = true; - // Configuration on the Faction tag in chat messages. - public static boolean chatTagEnabled = true; - public static transient boolean chatTagHandledByAnotherPlugin = false; - public static boolean chatTagRelationColored = true; - public static String chatTagReplaceString = "[FACTION]"; - public static String chatTagInsertAfterString = ""; - public static String chatTagInsertBeforeString = ""; - public static int chatTagInsertIndex = 0; - public static boolean chatTagPadBefore = false; - public static boolean chatTagPadAfter = true; - public static String chatTagFormat = "%s" + ChatColor.WHITE; - public static String factionChatFormat = "%s:" + ChatColor.WHITE + " %s"; - public static String allianceChatFormat = ChatColor.LIGHT_PURPLE + "%s:" + ChatColor.WHITE + " %s"; - public static String truceChatFormat = ChatColor.DARK_PURPLE + "%s:" + ChatColor.WHITE + " %s"; - public static String modChatFormat = ChatColor.RED + "%s:" + ChatColor.WHITE + " %s"; - public static int stealthFlyCheckRadius = 32; - public static boolean noEnderpearlsInFly = false; - public static boolean broadcastDescriptionChanges = false; - public static boolean broadcastTagChanges = false; - public static double saveToFileEveryXMinutes = 30.0; - public static double autoLeaveAfterDaysOfInactivity = 10.0; - public static double autoLeaveRoutineRunsEveryXMinutes = 5.0; - public static int autoLeaveRoutineMaxMillisecondsPerTick = 5; // 1 server tick is roughly 50ms, so default max 10% of a tick - public static boolean removePlayerDataWhenBanned = true; - public static boolean autoLeaveDeleteFPlayerData = true; // Let them just remove player from Faction. - public static boolean worldGuardChecking = false; - public static boolean worldGuardBuildPriority = false; - // server logging options - public static boolean logFactionCreate = true; - public static boolean logFactionDisband = true; - public static boolean logFactionJoin = true; - public static boolean logFactionKick = true; - public static boolean logFactionLeave = true; - public static boolean logLandClaims = true; - public static boolean logLandUnclaims = true; - public static boolean logMoneyTransactions = true; - public static boolean logPlayerCommands = true; - // prevent some potential exploits - public static boolean handleExploitObsidianGenerators = true; - public static boolean handleExploitEnderPearlClipping = true; - public static boolean handleExploitInteractionSpam = true; - public static boolean handleExploitTNTWaterlog = false; - public static boolean handleExploitLiquidFlow = false; - public static boolean homesEnabled = true; - public static boolean homesMustBeInClaimedTerritory = true; - public static boolean homesTeleportToOnDeath = true; - public static boolean homesRespawnFromNoPowerLossWorlds = true; - public static boolean homesTeleportCommandEnabled = true; - public static boolean homesTeleportCommandEssentialsIntegration = true; - public static boolean homesTeleportCommandSmokeEffectEnabled = true; - public static float homesTeleportCommandSmokeEffectThickness = 3f; - public static boolean homesTeleportAllowedFromEnemyTerritory = true; - public static boolean homesTeleportAllowedFromDifferentWorld = true; - public static double homesTeleportAllowedEnemyDistance = 32.0; - public static boolean homesTeleportIgnoreEnemiesIfInOwnTerritory = true; - public static boolean disablePVPBetweenNeutralFactions = false; - public static boolean disablePVPForFactionlessPlayers = false; - public static boolean enablePVPAgainstFactionlessInAttackersLand = false; - public static int noPVPDamageToOthersForXSecondsAfterLogin = 3; - public static boolean peacefulTerritoryDisablePVP = true; - public static boolean peacefulTerritoryDisableMonsters = false; - public static boolean peacefulTerritoryDisableBoom = false; - public static boolean peacefulMembersDisablePowerLoss = true; - public static boolean permanentFactionsDisableLeaderPromotion = false; - public static boolean claimsMustBeConnected = false; - public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true; - public static int claimsRequireMinFactionMembers = 1; - public static int claimedLandsMax = 0; - public static int lineClaimLimit = 5; - // if someone is doing a radius claim and the process fails to claim land this many times in a row, it will exit - public static int radiusClaimFailureLimit = 9; - public static double considerFactionsReallyOfflineAfterXMinutes = 0.0; - public static int actionDeniedPainAmount = 1; - // commands which will be prevented if the player is a member of a permanent faction - public static Set permanentFactionMemberDenyCommands = new LinkedHashSet<>(); - // commands which will be prevented when in claimed territory of another faction - public static Set territoryNeutralDenyCommands = new LinkedHashSet<>(); - public static Set territoryEnemyDenyCommands = new LinkedHashSet<>(); - public static Set territoryAllyDenyCommands = new LinkedHashSet<>(); - public static Set warzoneDenyCommands = new LinkedHashSet<>(); - public static Set wildernessDenyCommands = new LinkedHashSet<>(); - public static boolean territoryDenyBuild = true; - public static boolean territoryDenyBuildWhenOffline = true; - public static boolean territoryPainBuild = false; - public static boolean territoryPainBuildWhenOffline = false; - public static boolean territoryDenyUseage = true; - public static boolean territoryEnemyDenyBuild = true; - public static boolean territoryEnemyDenyBuildWhenOffline = true; - public static boolean territoryEnemyPainBuild = false; - public static boolean territoryEnemyPainBuildWhenOffline = false; - public static boolean territoryEnemyDenyUseage = true; - public static boolean territoryEnemyProtectMaterials = true; - public static boolean territoryAllyDenyBuild = true; - public static boolean territoryAllyDenyBuildWhenOffline = true; - public static boolean territoryAllyPainBuild = false; - public static boolean territoryAllyPainBuildWhenOffline = false; - public static boolean territoryAllyDenyUseage = true; - public static boolean territoryAllyProtectMaterials = true; - public static boolean territoryTruceDenyBuild = true; - public static boolean territoryTruceDenyBuildWhenOffline = true; - public static boolean territoryTrucePainBuild = false; - public static boolean territoryTrucePainBuildWhenOffline = false; - public static boolean territoryTruceDenyUseage = true; - public static boolean territoryTruceProtectMaterials = true; - public static boolean territoryBlockCreepers = false; - public static boolean territoryBlockCreepersWhenOffline = false; - public static boolean territoryBlockFireballs = false; - public static boolean territoryBlockFireballsWhenOffline = false; - public static boolean territoryBlockTNT = false; - public static boolean territoryBlockTNTWhenOffline = false; - public static boolean territoryDenyEndermanBlocks = true; - public static boolean territoryDenyEndermanBlocksWhenOffline = true; - public static boolean safeZoneDenyBuild = true; - public static boolean safeZoneDenyUseage = true; - public static boolean safeZoneBlockTNT = true; - public static boolean safeZonePreventAllDamageToPlayers = false; - public static boolean safeZoneDenyEndermanBlocks = true; - public static boolean warZoneDenyBuild = true; - public static boolean warZoneDenyUseage = true; - public static boolean warZoneBlockCreepers = false; - public static boolean warZoneBlockFireballs = false; - public static boolean warZoneBlockTNT = true; - public static boolean warZonePowerLoss = true; - public static boolean warZoneFriendlyFire = false; - public static boolean warZoneDenyEndermanBlocks = true; - public static boolean wildernessDenyBuild = false; - public static boolean wildernessDenyUseage = false; - public static boolean wildernessBlockCreepers = false; - public static boolean wildernessBlockFireballs = false; - public static boolean wildernessBlockTNT = false; - public static boolean wildernessPowerLoss = true; - public static boolean wildernessDenyEndermanBlocks = false; - // for claimed areas where further faction-member ownership can be defined - public static boolean ownedAreasEnabled = true; - public static int ownedAreasLimitPerFaction = 0; - public static boolean ownedAreasModeratorsCanSet = false; - public static boolean ownedAreaModeratorsBypass = true; - public static boolean ownedAreaDenyBuild = true; - public static boolean ownedAreaPainBuild = false; - public static boolean ownedAreaProtectMaterials = true; - public static boolean ownedAreaDenyUseage = true; - public static boolean ownedMessageOnBorder = true; - public static boolean ownedMessageInsideTerritory = true; - public static boolean ownedMessageByChunk = false; - public static boolean pistonProtectionThroughDenyBuild = true; - public static Set territoryProtectedMaterials = EnumSet.noneOf(Material.class); - public static Set territoryDenyUseageMaterials = EnumSet.noneOf(Material.class); - public static Set territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class); - public static Set territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class); - public static transient Set safeZoneNerfedCreatureTypes = EnumSet.noneOf(EntityType.class); + // Colors + public static ChatColor colorMember = ChatColor.GREEN; + public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE; + public static ChatColor colorTruce = ChatColor.DARK_PURPLE; + public static ChatColor colorNeutral = ChatColor.WHITE; + public static ChatColor colorEnemy = ChatColor.RED; + public static ChatColor colorPeaceful = ChatColor.GOLD; + public static ChatColor colorWilderness = ChatColor.GRAY; + public static ChatColor colorSafezone = ChatColor.GOLD; + public static ChatColor colorWar = ChatColor.DARK_RED; + // Power + public static double powerPlayerMax = 10.0; + public static double powerPlayerMin = -10.0; + public static double powerPlayerStarting = 0.0; + public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power + public static double powerPerDeath = 4.0; // A death makes you lose 4 power + public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline? + public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline + public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less + public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts) + public static String prefixLeader = "***"; + public static String prefixCoLeader = "**"; + public static String prefixMod = "*"; + public static String prefixRecruit = "-"; + public static String prefixNormal = "+"; + public static int factionTagLengthMin = 3; + public static int factionTagLengthMax = 10; + public static boolean factionTagForceUpperCase = false; + public static boolean newFactionsDefaultOpen = false; + // when faction membership hits this limit, players will no longer be able to join using /f join; default is 0, no limit + public static int factionMemberLimit = 0; + // what faction ID to start new players in when they first join the server; default is 0, "no faction" + public static String newPlayerStartingFactionID = "0"; + public static boolean showMapFactionKey = true; + public static boolean showNeutralFactionsOnMap = true; + public static boolean showEnemyFactionsOnMap = true; + public static boolean showTrucesFactionsOnMap = true; + // Disallow joining/leaving/kicking while power is negative + public static boolean canLeaveWithNegativePower = true; + // Configuration for faction-only chat + public static boolean factionOnlyChat = true; + // Configuration on the Faction tag in chat messages. + public static boolean chatTagEnabled = true; + public static transient boolean chatTagHandledByAnotherPlugin = false; + public static boolean chatTagRelationColored = true; + public static String chatTagReplaceString = "[FACTION]"; + public static String chatTagInsertAfterString = ""; + public static String chatTagInsertBeforeString = ""; + public static int chatTagInsertIndex = 0; + public static boolean chatTagPadBefore = false; + public static boolean chatTagPadAfter = true; + public static String chatTagFormat = "%s" + ChatColor.WHITE; + public static String factionChatFormat = "%s:" + ChatColor.WHITE + " %s"; + public static String allianceChatFormat = ChatColor.LIGHT_PURPLE + "%s:" + ChatColor.WHITE + " %s"; + public static String truceChatFormat = ChatColor.DARK_PURPLE + "%s:" + ChatColor.WHITE + " %s"; + public static String modChatFormat = ChatColor.RED + "%s:" + ChatColor.WHITE + " %s"; + public static int stealthFlyCheckRadius = 32; + public static boolean noEnderpearlsInFly = false; + public static boolean broadcastDescriptionChanges = false; + public static boolean broadcastTagChanges = false; + public static double saveToFileEveryXMinutes = 30.0; + public static double autoLeaveAfterDaysOfInactivity = 10.0; + public static double autoLeaveRoutineRunsEveryXMinutes = 5.0; + public static int autoLeaveRoutineMaxMillisecondsPerTick = 5; // 1 server tick is roughly 50ms, so default max 10% of a tick + public static boolean removePlayerDataWhenBanned = true; + public static boolean autoLeaveDeleteFPlayerData = true; // Let them just remove player from Faction. + public static boolean worldGuardChecking = false; + public static boolean worldGuardBuildPriority = false; + // server logging options + public static boolean logFactionCreate = true; + public static boolean logFactionDisband = true; + public static boolean logFactionJoin = true; + public static boolean logFactionKick = true; + public static boolean logFactionLeave = true; + public static boolean logLandClaims = true; + public static boolean logLandUnclaims = true; + public static boolean logMoneyTransactions = true; + public static boolean logPlayerCommands = true; + // prevent some potential exploits + public static boolean handleExploitObsidianGenerators = true; + public static boolean handleExploitEnderPearlClipping = true; + public static boolean handleExploitInteractionSpam = true; + public static boolean handleExploitTNTWaterlog = false; + public static boolean handleExploitLiquidFlow = false; + public static boolean homesEnabled = true; + public static boolean homesMustBeInClaimedTerritory = true; + public static boolean homesTeleportToOnDeath = true; + public static boolean homesRespawnFromNoPowerLossWorlds = true; + public static boolean homesTeleportCommandEnabled = true; + public static boolean homesTeleportCommandEssentialsIntegration = true; + public static boolean homesTeleportCommandSmokeEffectEnabled = true; + public static float homesTeleportCommandSmokeEffectThickness = 3f; + public static boolean homesTeleportAllowedFromEnemyTerritory = true; + public static boolean homesTeleportAllowedFromDifferentWorld = true; + public static double homesTeleportAllowedEnemyDistance = 32.0; + public static boolean homesTeleportIgnoreEnemiesIfInOwnTerritory = true; + public static boolean disablePVPBetweenNeutralFactions = false; + public static boolean disablePVPForFactionlessPlayers = false; + public static boolean enablePVPAgainstFactionlessInAttackersLand = false; + public static int noPVPDamageToOthersForXSecondsAfterLogin = 3; + public static boolean peacefulTerritoryDisablePVP = true; + public static boolean peacefulTerritoryDisableMonsters = false; + public static boolean peacefulTerritoryDisableBoom = false; + public static boolean peacefulMembersDisablePowerLoss = true; + public static boolean permanentFactionsDisableLeaderPromotion = false; + public static boolean claimsMustBeConnected = false; + public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true; + public static int claimsRequireMinFactionMembers = 1; + public static int claimedLandsMax = 0; + public static int lineClaimLimit = 5; + // if someone is doing a radius claim and the process fails to claim land this many times in a row, it will exit + public static int radiusClaimFailureLimit = 9; + public static double considerFactionsReallyOfflineAfterXMinutes = 0.0; + public static int actionDeniedPainAmount = 1; + // commands which will be prevented if the player is a member of a permanent faction + public static Set permanentFactionMemberDenyCommands = new LinkedHashSet<>(); + // commands which will be prevented when in claimed territory of another faction + public static Set territoryNeutralDenyCommands = new LinkedHashSet<>(); + public static Set territoryEnemyDenyCommands = new LinkedHashSet<>(); + public static Set territoryAllyDenyCommands = new LinkedHashSet<>(); + public static Set warzoneDenyCommands = new LinkedHashSet<>(); + public static Set wildernessDenyCommands = new LinkedHashSet<>(); + public static boolean territoryDenyBuild = true; + public static boolean territoryDenyBuildWhenOffline = true; + public static boolean territoryPainBuild = false; + public static boolean territoryPainBuildWhenOffline = false; + public static boolean territoryDenyUseage = true; + public static boolean territoryEnemyDenyBuild = true; + public static boolean territoryEnemyDenyBuildWhenOffline = true; + public static boolean territoryEnemyPainBuild = false; + public static boolean territoryEnemyPainBuildWhenOffline = false; + public static boolean territoryEnemyDenyUseage = true; + public static boolean territoryEnemyProtectMaterials = true; + public static boolean territoryAllyDenyBuild = true; + public static boolean territoryAllyDenyBuildWhenOffline = true; + public static boolean territoryAllyPainBuild = false; + public static boolean territoryAllyPainBuildWhenOffline = false; + public static boolean territoryAllyDenyUseage = true; + public static boolean territoryAllyProtectMaterials = true; + public static boolean territoryTruceDenyBuild = true; + public static boolean territoryTruceDenyBuildWhenOffline = true; + public static boolean territoryTrucePainBuild = false; + public static boolean territoryTrucePainBuildWhenOffline = false; + public static boolean territoryTruceDenyUseage = true; + public static boolean territoryTruceProtectMaterials = true; + public static boolean territoryBlockCreepers = false; + public static boolean territoryBlockCreepersWhenOffline = false; + public static boolean territoryBlockFireballs = false; + public static boolean territoryBlockFireballsWhenOffline = false; + public static boolean territoryBlockTNT = false; + public static boolean territoryBlockTNTWhenOffline = false; + public static boolean territoryDenyEndermanBlocks = true; + public static boolean territoryDenyEndermanBlocksWhenOffline = true; + public static boolean safeZoneDenyBuild = true; + public static boolean safeZoneDenyUseage = true; + public static boolean safeZoneBlockTNT = true; + public static boolean safeZonePreventAllDamageToPlayers = false; + public static boolean safeZoneDenyEndermanBlocks = true; + public static boolean warZoneDenyBuild = true; + public static boolean warZoneDenyUseage = true; + public static boolean warZoneBlockCreepers = false; + public static boolean warZoneBlockFireballs = false; + public static boolean warZoneBlockTNT = true; + public static boolean warZonePowerLoss = true; + public static boolean warZoneFriendlyFire = false; + public static boolean warZoneDenyEndermanBlocks = true; + public static boolean wildernessDenyBuild = false; + public static boolean wildernessDenyUseage = false; + public static boolean wildernessBlockCreepers = false; + public static boolean wildernessBlockFireballs = false; + public static boolean wildernessBlockTNT = false; + public static boolean wildernessPowerLoss = true; + public static boolean wildernessDenyEndermanBlocks = false; + // for claimed areas where further faction-member ownership can be defined + public static boolean ownedAreasEnabled = true; + public static int ownedAreasLimitPerFaction = 0; + public static boolean ownedAreasModeratorsCanSet = false; + public static boolean ownedAreaModeratorsBypass = true; + public static boolean ownedAreaDenyBuild = true; + public static boolean ownedAreaPainBuild = false; + public static boolean ownedAreaProtectMaterials = true; + public static boolean ownedAreaDenyUseage = true; + public static boolean ownedMessageOnBorder = true; + public static boolean ownedMessageInsideTerritory = true; + public static boolean ownedMessageByChunk = false; + public static boolean pistonProtectionThroughDenyBuild = true; + public static Set territoryProtectedMaterials = EnumSet.noneOf(Material.class); + public static Set territoryDenyUseageMaterials = EnumSet.noneOf(Material.class); + public static Set territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class); + public static Set territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class); + public static transient Set safeZoneNerfedCreatureTypes = EnumSet.noneOf(EntityType.class); - // Economy settings - public static boolean econEnabled = false; - public static String econUniverseAccount = ""; - public static double econCostClaimWilderness = 30.0; - public static double econCostClaimFromFactionBonus = 30.0; - public static double econOverclaimRewardMultiplier = 0.0; - public static double econClaimAdditionalMultiplier = 0.5; - public static double econClaimRefundMultiplier = 0.7; - public static double econClaimUnconnectedFee = 0.0; - public static double econCostCreate = 100.0; - public static double econCostOwner = 15.0; - public static double econCostSethome = 30.0; - public static double econCostJoin = 0.0; - public static double econCostLeave = 0.0; - public static double econCostKick = 0.0; - public static double econCostInvite = 0.0; - public static double econCostHome = 0.0; - public static double econCostTag = 0.0; - public static double econCostDesc = 0.0; - public static double econCostTitle = 0.0; - public static double econCostList = 0.0; - public static double econCostMap = 0.0; - public static double econCostPower = 0.0; - public static double econCostShow = 0.0; + // Economy settings + public static boolean econEnabled = false; + public static String econUniverseAccount = ""; + public static double econCostClaimWilderness = 30.0; + public static double econCostClaimFromFactionBonus = 30.0; + public static double econOverclaimRewardMultiplier = 0.0; + public static double econClaimAdditionalMultiplier = 0.5; + public static double econClaimRefundMultiplier = 0.7; + public static double econClaimUnconnectedFee = 0.0; + public static double econCostCreate = 100.0; + public static double econCostOwner = 15.0; + public static double econCostSethome = 30.0; + public static double econCostJoin = 0.0; + public static double econCostLeave = 0.0; + public static double econCostKick = 0.0; + public static double econCostInvite = 0.0; + public static double econCostHome = 0.0; + public static double econCostTag = 0.0; + public static double econCostDesc = 0.0; + public static double econCostTitle = 0.0; + public static double econCostList = 0.0; + public static double econCostMap = 0.0; + public static double econCostPower = 0.0; + public static double econCostShow = 0.0; - // -------------------------------------------- // - // INTEGRATION: DYNMAP - // -------------------------------------------- // - public static double econCostStuck = 0.0; - public static double econCostOpen = 0.0; - public static double econCostAlly = 0.0; - public static double econCostTruce = 0.0; - public static double econCostEnemy = 0.0; - public static double econCostNeutral = 0.0; - public static double econCostNoBoom = 0.0; - // Should the dynmap intagration be used? - public static boolean dynmapUse = false; - // Name of the Factions layer - public static String dynmapLayerName = "Factions"; - // Should the layer be visible per default - public static boolean dynmapLayerVisible = true; - // Ordering priority in layer menu (low goes before high - default is 0) - public static int dynmapLayerPriority = 2; - // (optional) set minimum zoom level before layer is visible (0 = default, always visible) - public static int dynmapLayerMinimumZoom = 0; - // Format for popup - substitute values for macros - public static String dynmapDescription = - "