From 8f13e018eea9fb6bb2b3ca241392f1ae9a7f183b Mon Sep 17 00:00:00 2001 From: TheTrouper <93684527+thetrouper@users.noreply.github.com> Date: Tue, 16 Jan 2024 20:56:35 -0600 Subject: [PATCH] Converting to PDK --- build.gradle | 11 +- libs/PDK-1.3.3.jar | Bin 0 -> 89914 bytes .../github/thetrouper/sentinel/Sentinel.java | 50 +++--- .../{commands => cmds}/ChatClickCallback.java | 34 ++-- .../sentinel/cmds/MessageCommand.java | 45 +++++ .../{commands => cmds}/ReopCommand.java | 18 +- .../{commands => cmds}/ReplyCommand.java | 27 ++- .../sentinel/cmds/SentinelCommand.java | 75 ++++++++ .../{commands => cmds}/SocialSpyCommand.java | 19 +- .../sentinel/commands/CustomCommand.java | 166 ------------------ .../sentinel/commands/MessageCommand.java | 55 ------ .../sentinel/commands/SentinelCommand.java | 102 ----------- .../thetrouper/sentinel/data/ActionType.java | 4 +- .../github/thetrouper/sentinel/data/FAT.java | 2 + .../sentinel/discord/DiscordWebhook.java | 11 +- .../sentinel/events/CMDBlockExecute.java | 12 +- .../sentinel/events/CMDBlockPlace.java | 8 +- .../sentinel/events/CMDBlockUse.java | 8 +- .../sentinel/events/CMDMinecartPlace.java | 8 +- .../sentinel/events/CMDMinecartUse.java | 8 +- .../thetrouper/sentinel/events/ChatEvent.java | 10 +- .../sentinel/events/CommandEvent.java | 9 +- .../thetrouper/sentinel/events/NBTEvents.java | 8 +- .../sentinel/{data => server}/Action.java | 38 +--- .../{data => server}/FilterAction.java | 8 +- .../server/config/AdvancedConfig.java | 38 ++++ .../{data => server/config}/Config.java | 6 +- .../sentinel/server/config/FPConfig.java | 16 ++ .../sentinel/server/config/Lang.java | 15 ++ .../{data => server/config}/LanguageFile.java | 2 +- .../sentinel/server/config/MainConfig.java | 77 ++++++++ .../sentinel/server/config/NBTConfig.java | 59 +++++++ .../sentinel/server/config/StrictConfig.java | 15 ++ .../sentinel/server/config/SwearsConfig.java | 15 ++ .../sentinel/server/functions/AntiSpam.java | 5 +- .../sentinel/server/functions/Message.java | 14 +- .../server/functions/ProfanityFilter.java | 9 +- .../functions/ReportFalsePositives.java | 3 +- .../sentinel/server/util/ArgBuilder.java | 90 ---------- .../sentinel/server/util/ArrayUtils.java | 41 ----- .../sentinel/server/util/Cooldown.java | 38 ---- .../sentinel/server/util/FileUtils.java | 26 +-- .../sentinel/server/util/Randomizer.java | 4 +- .../sentinel/server/util/ServerUtils.java | 16 +- .../thetrouper/sentinel/server/util/Text.java | 2 +- src/main/resources/config.yml | 2 +- 46 files changed, 516 insertions(+), 713 deletions(-) create mode 100644 libs/PDK-1.3.3.jar rename src/main/java/io/github/thetrouper/sentinel/{commands => cmds}/ChatClickCallback.java (50%) create mode 100644 src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java rename src/main/java/io/github/thetrouper/sentinel/{commands => cmds}/ReopCommand.java (67%) rename src/main/java/io/github/thetrouper/sentinel/{commands => cmds}/ReplyCommand.java (61%) create mode 100644 src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java rename src/main/java/io/github/thetrouper/sentinel/{commands => cmds}/SocialSpyCommand.java (67%) delete mode 100644 src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java delete mode 100644 src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java delete mode 100644 src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java rename src/main/java/io/github/thetrouper/sentinel/{data => server}/Action.java (88%) rename src/main/java/io/github/thetrouper/sentinel/{data => server}/FilterAction.java (97%) create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/AdvancedConfig.java rename src/main/java/io/github/thetrouper/sentinel/{data => server/config}/Config.java (98%) create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/FPConfig.java create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/Lang.java rename src/main/java/io/github/thetrouper/sentinel/{data => server/config}/LanguageFile.java (93%) create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/MainConfig.java create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/NBTConfig.java create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/StrictConfig.java create mode 100644 src/main/java/io/github/thetrouper/sentinel/server/config/SwearsConfig.java delete mode 100644 src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java delete mode 100644 src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java delete mode 100644 src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java diff --git a/build.gradle b/build.gradle index 662ca37..15e82c0 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,15 @@ plugins { group = project.group version = project.version +jar { + from { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + configurations.runtimeClasspath.collect { + it.isDirectory() ? it : zipTree(it) + } + } +} + repositories { mavenCentral() maven { @@ -20,6 +29,7 @@ repositories { dependencies { compileOnly "org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT" implementation 'com.google.code.gson:gson:2.10.1' + implementation files("libs/PDK-1.3.3.jar") } def targetJavaVersion = 16 @@ -52,4 +62,3 @@ compileJava.options.encoding("UTF-8") tasks.withType(JavaCompile) { options.encoding = "UTF-8" } - diff --git a/libs/PDK-1.3.3.jar b/libs/PDK-1.3.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..e949bf16cf74b392688d46b6fee0165700ddacd0 GIT binary patch literal 89914 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 $$NX$*d| zL0(xL$otNd0;W+x2PHMMR80-A!KI~0ajXyLw=%^YQ!YBFYMjxjia+JJzNZGuMp#+y zfd8V;Eh69jf;134JfLm{GNaDf`2D<(2cYb~=rElQZdwwxUyd1!A=JUPBq zFa?EFuV{v97*e=aA6+Tjt#8SSOIyZimQh4}fkScKr3D&Xz%!0lH}y1_1nZt!FBrg9 zjvKIH4N{>!HPP9gDPq#HC5CZXYs$iUGr~Aiti>}t0|_3{nHoWH9p1HsO0O{Dg3}Y| z{A$FE@|@4on?=y)yo3CRhVGiteQ4)f(6_+)MHpOBkCiV zM|T5}rDKIE{qA0M7makG$$r$dSI2h@TD6`M$tgkNY9XGdkh3=0qpVw~Kx@{GLXat_ z@C{|3*$-YcD<%by-((xJZ_o&Cr#l5)OSUFM1+g;WmV2n9w?WfD+nbw(D$uGjo7pXVOsG{&d|`{&Z;%ZEC_VrGJ}s(N{4C)mg- zTJ0XF(6)Y5c;c*BgRVCMsa3;2c)#_4w`bSJznUG*aIJ81JHRb3+s$uq&Tt(MXVD)2 zBI|-$3&U&6iGM*TMMe7<=6!2`ulBfttxf2-)Cs7pGAJ)!p{&g=a>DZQ&#sc~g)72; zm_! zkGCw@0oSuU^9lo{&{QeX)PXman%m72V1&c$<-x65xNN+&`P<(^4+r97nvODM- zef*Bl-)uT!jxdT)U#?s`db;4YQ+#aQ)9Dm$Rrd!Fv~uHe{6qa){1I|zG{1l_7zUUq z%3aJG+UzGn8A`WH`7xW@C<|(i17EkZ?qNbj?{CC6=f{`tA3wK#NZ-{@Z5e=_6mUXLh&7umI$eQmwv}@bej9~RENvgG)vYV-|nM&6U;-=L_0dlK}NLo zBHNG{7}&D}5Nf(AidauNhmK{Ii^C8WDKlX6zAVUR0IsYHA0qw={m)y=#F)~B{W|T4 zul4iaytV&w;tt08PXBV`UkqD*m~;FK;Hr_u1aO{X{v+D!pJH-|d10g*rYUWx$#7{W zvD>nH+wfl`6jKHtt@GS!bDh_hmycR+kY8BGg)?$?(kdy$bOg)9)%&U$7@VEyGApIsDm2b=E?2ks}#CtOT-ns$7HIfeOK4VSCQ(Z|K*)P|?&QME7L8=M}94H!Kf zFJBq6Qocw|mndJ6s6ty(A{!3sqBonF zOj&PM)0q@AiR3DC%!yTU=1z>Hs8%VX7A#XEbABo>agVAKViw>jGIK|j0{g66NTyxu z_$|pPR&c{P8B1<3SWBj*Rq1~>fdYMTns*omTZ+bDgzz(E=8jMY-VLzJnD()iqY*c7~upApq8VE)@0FBq8jFR(G zE2dWmm6&N*M0oDe%fa9^XUNm1NS-xdHRh_4QOTiInc21)v2f}E?CZfn+^p%o5h~yCkEeg()u8qg2M5@8XdRr;cM`DGR!Zu3d zNSb08TnaQ0ysc_=kb-Hu2Z9UZqJ#^U1iQU?$$pVfTSAf?8&#U7;M|>hv(m=^Gd@vM4hdEb?8INf(!Nb-?&OliNF9>yx^Id)sGQP-!ju zi%;U4WNH~Jm;Oki$%5#^~Q4ncmIML+kc(OESz!|^0_0ho46jL=ie9D^SV?D1}Dl^ZZaXQ@m- z?v{2;#NAH3f9jvg7-)jRloPt@sk=u#NVR}FYw{Iie{BpPDcW>UPq1pZVJjEN6&8PO zJfJg{i%igr7{Pu&8fu_+{+bLT{~(l=Q#V8Q8gml8W{8JL2tCFoVsu+|+!bXJ5tQ}h z;EdD_x$ZxjQfhbLZxNqD&QC5+Xw>E{F-Z}=g5~hwE84W}5gk2 zcs1C3l;8EyxTbT!LKX!i#YIzgmj%#F5y@m)q4xY~y90-9(T2Sk1N&ejaOnfDsG3l@ ztK`-AC^Q{6+}$-bwvrE55$Wv)`lT7Y3hxg?R_tS=7jH`Un518*aSoU=ru#h2Vpx6; z--4$@n~+f`^5r8mrvY5UQQKFUevb^w#va062pa?a)u5;>vsY$n{(~s_&#pLZ@5Z|e83F%*GE%9sd z{I3(5xQ)v{v0AMR@RwjL!VNrB!qV6EdEV%gyh-Pp?p$n*@2~ce=IOwE!l6M zo!vI&(Qk@TCk9G3S+N1^J9MMU969ZQV%JO%nix$CEJ{+({qw?7;e?=aT#85Ks^so> ztIoJpx^yEuwOm6=|8S1Ud0G4iK1GA z;Mx!p*k>c$YR>QNk!wRts$=#FUjL=QRpoB+JMzny-U8>_H>UsXdH;=w2h}09ke4w& z`A}U}Hi1wFK=?^Q+o+E%qR7OMkvB*50}WUv8L0ai>&~oPOr^!w?^0M70S~+luJa4H z=H;X%W*I|GYpjir#+Ou`m+g~_K9`dw};-Jmmgb?L!#NdpY*?ID(1qt zSBUq=$$w?_ddqPXJPAm!AD{l=D)|oc-7^7oDbnP7Msd}$p8z{CyKxIXQ^kUlt{l_% zJ#XI07Rd-5hTwRYUK$%S z0^JZq^Zo5XMhW)130E7kfmlYwJvs^FM18mbN442L(l65MLndg+eF%J7f&a1=#w~re z8(3bMLCIc@G>3mvksR~}6b7`s_}X^?4{D(GR4S`@wH(^`T69TtD40ozQW)cNab0ID zc^Yiw^{NEvvLJbulEKL1&;(Q-#y{JIgEfkxzLs}A6u@;$%-g|EH<+vh1 zMmX9Eyci4|f)CQJ;Kli8eVI$q`i4Bq=#Oja+ARCo`kfg`-^#^8pY8Mu!g{J5#k zbPuwA2L+BGPH3Fp%f|z#Zp3n!3sT(~npWkJ)@D2WIU%r6t1C9nf%-P6Op7?%ug&8t zeyogS;zNb$an~(auA^6bA`;p>nN^hi8nT{Wbkbz&qvZ3{T6qcyFq)J?$syd0L<;Eh z5&mR*?)aefLQN5PfV8oh7|zLI5d}_+JOW&U5KtTZbX<+@5YR>@YL0)83{W*?KTMK& z;vprx119Ep3HBD@p2~&@Mv)L9fx}XK!#l`zjhKjT1`9zK)C)1F(Om$Utb=ViFSdLh z6vefriba|gCLL?W*kD$G?g!GYJ<^Z zVO!3Udo_-<8SThEB$B)&dL6bis|-qZK?%4^sT#{})d>)DH)nBJTBny(FT)s`H zw^962l!bJn&5EQ2`SLpHq0~=&%(pCXm6iyqpQ5sw%|uCU0qZ;*oHewjA?yBcB3i_E zq?YQ}dkr>b>6qhI&hEJMcScp(8R<-}a*&T93!RV`ODK6iS?Hw79XrLvp6u6-KouJ* zA_v~}ieM0zLE4(LlD~8q{Kc zw)M`i5&@XVN3l6OA*~+v(bG;aj4{d2e{RNe8At%+12c3^QM1X;fXW4}$1qsj*>A64 zDf+$NC9Exk7OG6t7$$ib4@H%R_oe{5!*0|>RkoJxjrw(zKG_bA8!L%zh}T0?5MEScgi`|{pm_l?jjp#m6k zz$R+#!HU^c1(ZezX)rEf9pQ^jr!R8cbE$=tQUc^2J?fpz>N3)rY}eN1h)~X!!E47N znqgTe?D8XLj9>N>ttWVnMy{Huq7TXJsSz3uq~jH#D2nxHM4yTx^a~zu^CVK*)fufA zOP(fiR&On_?>jY^*02<{=yXfbi6Uw;vI43az#Iv2RJG4A<0kuZVahY!hJPv(We-iX zLIn0_ty_LTKd11um3$ed-&~Q8J*BJ<+@c+~5+6K6@ucX(O^!b`%QMgl6{4dVhM`;5 zBn~O$QS_jN9ZKFgB@GE+Vs)7Ic6{lYV>?j5^2u+iu!Gh$_3?yTn*}fjfoP6?tA6rcJ0P;LmC>U`m^Gy`s|#F~%gfeR&s24i;(4LyB0au;CqP4D zqE!c^+T&Om3^h)oF;$uRrP@!P84NimTsfyt*OO}-C0xI&nsu9}*v1C_9%v4QUv7%1 z;TU$fG)@GFR6fF}xDCtM_VZqj2C57S_-hDgiriHEm>Va>>7ps|sZ@Q#7#j=`cSHE8H_RukE+;0q{nA*{mdhjnKU<~ZzN zfsgrmLtaW@c1x9<64h6c_AbTtSO%38@h9(qKjlIc2q))Ohm$=JTadhkf<8goj1l%+ zn1dcqAnWn?+28}Q#(&FT0)09`2Bv?5A(H}1O^9V*(!Ufeu_<%nA{?HPb~J}^BEkhB zId|tqbDHe*h5_+9(8GP-#j73Gvzrx}+J4q73%z0|UWeR2VpGMT7>>AeY%!gU>yd9Z ztO-*_G+5-oKFO)=(1)p>0+|fQe8}#{ddM2qYC-eKy}xfLPh<9$8o03;tIyUXuwMy(2Hqed%tEkc@$u80>nbN~vXbqc zUQu~y8IkcNWW1=yo>%n!e#sk6i@D{B(f&jq3{RgqBzieas?aA*>mgP`G&^4F_|$UH zRn|bVGbrz9I~Q{+QJHtA}hocGHtO48} zdJepM8#+oRdu1Q4+R1z&+3P}5qfKaVEOhkQsSorrz;wOa#g+DpasK3|gaxV^JxsTR zkr8EWqPUkOssR(1ue4?ND3n4XytMs%NP^?_qwuc@HYnNYk#TT0QIoX z!1nqds(i8h*i!;$J=xc25iJ^Sp>+?ywC8*g()*)ud5tU+=2@Rexj9L>^^7JqEq+fXU|CEnO z{|#_!{-xph?~yG~f*0o-oP`C>$fv#i!_#Dyna^G>qs4bthDbC^=; zi8kUHMXy~S1n)PEotKj%n39Y-T_1Xr6JLgcJg(lhZ#TYGo!|8EK2`%UL6H|67IFc( z%QcIMJ5q;xWjmQ{4ru}k(`9MTH43m0j1^;= z$;nFz>qv;U?cd=2^VRvGMXA;fDFC6_i%4(?GAA+%3l1E>5J83{K&@gAoaisfhaq|# zgqzc-{%TPyP@Eh#eUmViU&8T8qsJWM)#yX?rokE}CH?hjkqjhdNevMG4S!9PiUT*; zB?c?aSkonm(85mor7<%PIA{)+s8v9!5%bmGfc?K zT{GUbH_RwJi1>ffI+9{PgsiDjWKY#kCQbb6gY*TDgY$Om!I~KwQjDT4T1WM1=EYF3 z4?}ZIt5EB~!n@(43Pu)Gtd3f6DCKdPsry%_XAme8pkg9|TLSXoxzPO+Yum|Di&SDy zGzt{@lPbFvN5ToRPuKRQel2r5dGe?jgHTXH-=@%=G!XVL%hihOp|f&^aTb0}{N z@q;V4Qn_BembeDaUdSE|fulIhJu7qr`=*%8BBO{lUuI79iW5wfBiJrd-cNOGh$)JceQMv+(4aE9M(8iq zT0%nLzTFz(L=A~SY8^`Mfm<-{5qQKpKGO%Hy0x4=F5j+orIZ`zVDmPdk!fE{FRTo8ei zckGxQkg7TU>WB96!~$shc^Rov@CY8I0C;;Zbi7=C15M!=blN~v)@F!9gDTZBI&5Xz zB_86wd;4hF?SuutG;V|qMdJc$`;msddF*V2*6IX75vk4T@Y2^7t4n*R-IBOEX0q%; zi*|b77r5lhkN}=>KG`!owJ^B;PH4yL;Jz_C%X}9FwDmasli}Nw766Xp<8E|n*35)` zlt&1lb5O%{E+_a*vx~-JjB>r2%R}VQW$?k>QRB=Frg&`m!?x?T;gFd0$Ytg@kL&Aq z1`3kT(5%nEj~Kypr;2ed$uKKV6Z;-fUtJf|;;1@;P3d;j)4w?7O*P`GCxM1h`7M9b z&BuJ!=y9yPKCgdh$f!u<`|!hsHh(;omOW7a-6^h{_VniFvsh!63khI3qA{0PJ@%`= zOw$xYz!vr(J}HszVZSlzw~3{3Xjgzx)ZRY*U~E2TlSHlJMZfbZXTj9y#9eCrAVZbm zi4m>L#Yo3M_+bk#?s_DFe1goDO5eF>XSXnAiu8gYI8fJ!e6tQF>aZPa%~eond|bm| zPUcv7@5T|TyNv?Yz5j&bBmL?)ierJ`DWPgOXKByPA;?fSh-@M8nyqu45>&j8$xb<+ zx{h6cUg}jO;Y(9MF5zQLr=7sI1gqK=Wl_W-v4dmQZ;Qsh9i!ObL+7%=XZHrdXVagJ z?m~AT&`P-KHBxu1N1`D!P4Pt4pG*QK-~0On+tX0qf?l-+(1m{DhD~&K?>*cP5Wd-uzZ2*$bk6Cta*{NA~coo1>4SqsTQ8uSKaLfPOy9>XU zkewcs_Y=D|!4Yb*Y>)K%4sPqz7sfdP z?A{2@>qXgbm)&Y%B4j9tH6WWS;-=F+cLr=c=V`ZfSd~r^-U2V{vaCYKRpS1Bs+X!5j%2!n*k|mdJd(0RbH7rC~CRP3B%QE#C2pd+I*BVCkU%v zcwwA(f zrk)qC)~0panQIL z8bWAL!<~hDL^u0~#Lrp2i9QzYN@3_i@UHfctV--!J|wK}0y+~32S>SurA9-_B7}>3 z#Xc+Ya%yplvG8&?p+HN47HXfR(pDor_ze^?KUex#T@IgMgw1l_VgJ7#?9soB9>x2= z;X`L9bF2RjFLje4%n`p@xTRn2NOb@6-}%4v^zO=k?ezEkG^(BaH8$n5(`KI3P;qV( z3fYQ5k|Y#gfKszSK}xfs5QXv&b6V59jA@^d0yS;Pw*M>b#Y!tT&=iQ|*+XwI!vd?2K+&wU+5OZEwuC=&El0jJk%>e0P z@_ypz40DB9xO-|YFERjiW@5$$@<2*B3Wo{CoTk)B`isp8K3b$37z!>XEm61+b3!I4 zt_p}4ir6}G)EHB8qG8>I+10OJ46HJCq^d)BB>Ke)q$vbCJN3h9Cpx{3V6v1kfW8`w ztYCpq(6^+h_R5Kg6C?d{gPnfC_b3<}RIoV|_l}WSA}z9QsD@`BvgF%x2roCWUU{hX z%G3{)yA^)}+QUPGaCh-hlcl*jgz6tUA>Ex=} zxq~}_anWkwUoo0m#+$yYTd{=J8jS3uqq87m5dBZ~b?hJkdpWf=!3|FpTByx2i} zWoANat~KebDk}k1<<)pnGk=2WF_GjyEuC|{%yiB9gwZ?fiw2}6$Tep7i`cX>{o)Kl(3~~m(VLbwZ1)u# z%W5jQWni=me=L6md?)T!aIwf|kWL3%!8K&S4drP5_3ifABxjaMjs`#Kr5BxrVsb4}zamRcN|>jHO{yX@Wm5nk zsVj|EK=hZnYZm7g!y1oMS>f{G480^sup&#To0&u782&md779%Qk=XDh5iiP+$OVcz zi(sV;5$0%i`zxz=I!e~yQj(vn%4#T>yoGDy(rro6Mbg%0ltV1PvPPPuBuG%dryl&l z-qr;>?ty4>TAyc@Xwoz3eP&#|DDsv(u#M>Yq;V-8&a!g?DWg)GBa_bd5vw`6^jkmB+ z*=vlf`XWI0Pv=1HbZM-vmRGR8I1*Fc=c})YkXJO_KfOgO>wp_+EPt1Z+?=$0d=~d3 zRBz$%2(Cw7VhFVfPS2sF&)$0FfEhBgl$qDX$rW0uOhG-R!F5O@{J5g(Z(7S+pt90$ z`*SZ}_N2?Sxpl$@EwVVqPe?hedlG=gc(R=~}6tvu+ zv>h(a*T2d_nA+wVQ!^rO;?r!1SmFeK

_0Yn78MiFdUhx34p<+m;((GND%4bo{E{ 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�NsLQ0 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 F{|^dpV>18% literal 0 HcmV?d00001 diff --git a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java index e91b660..fe7e38e 100644 --- a/src/main/java/io/github/thetrouper/sentinel/Sentinel.java +++ b/src/main/java/io/github/thetrouper/sentinel/Sentinel.java @@ -1,10 +1,12 @@ package io.github.thetrouper.sentinel; +import io.github.itzispyder.pdk.PDK; import io.github.thetrouper.sentinel.auth.Auth; -import io.github.thetrouper.sentinel.commands.*; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.LanguageFile; +import io.github.thetrouper.sentinel.cmds.*; import io.github.thetrouper.sentinel.events.*; +import io.github.thetrouper.sentinel.server.config.Config; +import io.github.thetrouper.sentinel.server.config.LanguageFile; +import io.github.thetrouper.sentinel.server.config.MainConfig; import io.github.thetrouper.sentinel.server.functions.AntiSpam; import io.github.thetrouper.sentinel.server.functions.Authenticator; import io.github.thetrouper.sentinel.server.functions.ProfanityFilter; @@ -15,11 +17,14 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import java.io.File; import java.util.logging.Logger; public final class Sentinel extends JavaPlugin { private static Sentinel instance; public static LanguageFile dict; + private static File cfgfile = new File("plugins/Sentinel/main-config.json"); + public static MainConfig mainConfig = JsonSerializable.load(cfgfile, MainConfig.class, new MainConfig()); public static final PluginManager manager = Bukkit.getPluginManager(); public static String prefix = ""; public static String key = ""; @@ -33,6 +38,7 @@ public final class Sentinel extends JavaPlugin { @Override public void onEnable() { log.info("\n]======------ Pre-load started! ------======["); + PDK.init(this); instance = this; log.info("Loading Config..."); loadConfig(); @@ -49,7 +55,7 @@ public final class Sentinel extends JavaPlugin { } catch (Exception e) { e.printStackTrace(); log.info("WTFFFF ARE YOU DOING MAN??????"); - getServer().getPluginManager().disablePlugin(this); + manager.disablePlugin(this); } switch (authStatus) { case "AUTHORIZED" -> { @@ -67,21 +73,21 @@ public final class Sentinel extends JavaPlugin { } case "FAILURE" -> { log.info("Dynamic IP Failure. Webhook Error possible? Please contact obvWolf to fix this."); - getServer().getPluginManager().disablePlugin(this); + manager.disablePlugin(this); } } } case "INVALID-ID" -> { log.info("Authentication Failure, You have not whitelisted this server ID yet."); - getServer().getPluginManager().disablePlugin(this); + manager.disablePlugin(this); } case "UNREGISTERED" -> { log.warning("Authentication Failure, YOU SHALL NOT PASS! License: " + key + " Server ID: " + serverID); - getServer().getPluginManager().disablePlugin(this); + manager.disablePlugin(this); } case "ERROR" -> { log.warning("Hmmmmmm thats not right... License: " + key + " Server ID: " + serverID + "\nPlease report the above stacktrace."); - getServer().getPluginManager().disablePlugin(this); + manager.disablePlugin(this); } } } @@ -96,7 +102,7 @@ public final class Sentinel extends JavaPlugin { AntiSpam.enableAntiSpam(); ProfanityFilter.enableAntiSwear(); - prefix = Config.Plugin.getPrefix(); + prefix = MainConfig.Plugin.prefix; // Commands -> BE SURE TO REGISTER ANY NEW COMMANDS IN PLUGIN.YML (src/main/java/resources/plugin.yml)! new SentinelCommand().register(); @@ -107,14 +113,15 @@ public final class Sentinel extends JavaPlugin { new ChatClickCallback().register(); // Events - manager.registerEvents(new CommandEvent(),this); - manager.registerEvents(new CMDBlockExecute(), this); - manager.registerEvents(new CMDBlockPlace(), this); - manager.registerEvents(new CMDBlockUse(), this); - manager.registerEvents(new CMDMinecartPlace(), this); - manager.registerEvents(new CMDMinecartUse(), this); - manager.registerEvents(new NBTEvents(), this); - manager.registerEvents(new ChatEvent(),this); + new ChatEvent().register(); + new CommandEvent().register(); + new CMDBlockExecute().register(); + new CMDBlockPlace().register(); + new CMDBlockUse().register(); + new CMDMinecartPlace().register(); + new CMDMinecartUse().register(); + new NBTEvents().register(); + // Scheduled timers Bukkit.getScheduler().runTaskTimer(this, AntiSpam::decayHeat,0, 20); @@ -132,9 +139,8 @@ public final class Sentinel extends JavaPlugin { public void loadConfig() { // Init - Config.loadConfiguration(); - log.info("Loading Dictionary (" + Config.lang + ")..."); + log.info("Loading Dictionary (" + MainConfig.Plugin.lang + ")..."); dict = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile()); log.info("Verifying Config..."); @@ -160,7 +166,7 @@ public final class Sentinel extends JavaPlugin { * @return true if the player is trusted, false otherwise */ public static boolean isTrusted(Player player) { - return Config.trustedPlayers.contains(player.getUniqueId().toString()); + return MainConfig.Plugin.trustedPlayers.contains(player.getUniqueId().toString()); } /** @@ -169,7 +175,7 @@ public final class Sentinel extends JavaPlugin { * @return true if the command is logged, false otherwise */ public static boolean isLoggedCommand(String command) { - return Config.logged.contains(command); + return MainConfig.Plugin.logged.contains(command); } /** @@ -178,7 +184,7 @@ public final class Sentinel extends JavaPlugin { * @return true if the command is dangerous, false otherwise */ public static boolean isDangerousCommand(String command) { - return Config.dangerous.contains(command); + return MainConfig.Plugin.dangerous.contains(command); } /** * Returns an instance of this plugin diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/ChatClickCallback.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java similarity index 50% rename from src/main/java/io/github/thetrouper/sentinel/commands/ChatClickCallback.java rename to src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java index 272fb9a..e6e5c74 100644 --- a/src/main/java/io/github/thetrouper/sentinel/commands/ChatClickCallback.java +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ChatClickCallback.java @@ -1,38 +1,28 @@ -/** - * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :) - */ - -package io.github.thetrouper.sentinel.commands; +package io.github.thetrouper.sentinel.cmds; +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import io.github.itzispyder.pdk.utils.misc.Cooldown; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives; -import io.github.thetrouper.sentinel.server.util.Cooldown; import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.UUID; -/** - * Example command - */ -public class ChatClickCallback extends CustomCommand { - public static Cooldown fpReportCooldown = new Cooldown<>(); - public ChatClickCallback() { - super("sentinelcallback"); - this.setPrintStacktrace(true); - } - +public class ChatClickCallback implements CustomCommand { + Cooldown fpReportCooldown = new Cooldown<>(); @Override - public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) { + public void dispatchCommand(CommandSender sender, Args args) { Player p = (Player) sender; - switch (args[0]) { + switch (args.get(0).toString()) { case "fpreport" -> { if (fpReportCooldown.isOnCooldown(p.getUniqueId()) && !p.isOp()) { p.sendMessage(Text.prefix(Sentinel.dict.get("cooldown") + fpReportCooldown.getCooldown(p.getUniqueId()))); } else { - ReportFalsePositives.sendFalsePositiveReport(args[1]); + ReportFalsePositives.sendFalsePositiveReport(args.get(1).toString()); p.sendMessage(Text.prefix(Sentinel.dict.get("false-positive-report-success"))); } } @@ -40,7 +30,7 @@ public class ChatClickCallback extends CustomCommand { } @Override - public void registerCompletions(CompletionBuilder builder) { - builder.addCompletion(1,"a_you","b_must","c_be","d_called","e_before","f_running","g_a","h_callback"); + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg("a_you","b_must","c_be","d_called","e_before","f_running","g_a","h_callback")); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java new file mode 100644 index 0000000..ab63368 --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/MessageCommand.java @@ -0,0 +1,45 @@ +package io.github.thetrouper.sentinel.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.Permission; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import io.github.thetrouper.sentinel.Sentinel; +import io.github.thetrouper.sentinel.server.functions.Message; +import io.github.thetrouper.sentinel.server.util.ServerUtils; +import io.github.thetrouper.sentinel.server.util.Text; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@CommandRegistry(value = "sentinelmessage",permission = @Permission("sentinel.message")) +public class MessageCommand implements CustomCommand { + @Override + public void dispatchCommand(CommandSender sender, Args args) { + Player p = (Player) sender; + Player r = null; + if (args.getSize() == 0) { + p.sendMessage(Text.prefix(Sentinel.dict.get("no-online-player"))); + return; + } + if (args.getSize() == 1) { + p.sendMessage(Text.prefix(Sentinel.dict.get("no-message-provided"))); + return; + } + r = Bukkit.getPlayer(args.get(0).toString()); + + String msg = args.getAll(1).toString().trim(); + + if (p.hasPermission("sentinel.message") && r != null) { + Message.messagePlayer(p,r,msg); + } else if (r == null) p.sendMessage(Text.prefix((Sentinel.dict.get("no-online-player")))); + else sender.sendMessage(Text.prefix(Sentinel.dict.get("no-permission"))); + } + + @Override + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg(ServerUtils.unVanishedPlayers()) + .then(b.arg("[]"))); + } +} diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/ReopCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ReopCommand.java similarity index 67% rename from src/main/java/io/github/thetrouper/sentinel/commands/ReopCommand.java rename to src/main/java/io/github/thetrouper/sentinel/cmds/ReopCommand.java index a01d44e..fd1f698 100644 --- a/src/main/java/io/github/thetrouper/sentinel/commands/ReopCommand.java +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ReopCommand.java @@ -1,19 +1,16 @@ -package io.github.thetrouper.sentinel.commands; +package io.github.thetrouper.sentinel.cmds; +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class ReopCommand extends CustomCommand { - public ReopCommand() { - super("reop"); - this.setPrintStacktrace(true); - } - +public class ReopCommand implements CustomCommand { @Override - public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) { + public void dispatchCommand(CommandSender sender, Args args) { Player p = (Player) sender; if (Sentinel.isTrusted(p)) { if (!p.isOp()) { @@ -31,8 +28,7 @@ public class ReopCommand extends CustomCommand { } @Override - public void registerCompletions(CompletionBuilder builder) { + public void dispatchCompletions(CompletionBuilder completionBuilder) { } - } diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/ReplyCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/ReplyCommand.java similarity index 61% rename from src/main/java/io/github/thetrouper/sentinel/commands/ReplyCommand.java rename to src/main/java/io/github/thetrouper/sentinel/cmds/ReplyCommand.java index d504ec8..76be823 100644 --- a/src/main/java/io/github/thetrouper/sentinel/commands/ReplyCommand.java +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/ReplyCommand.java @@ -1,26 +1,21 @@ -package io.github.thetrouper.sentinel.commands; +package io.github.thetrouper.sentinel.cmds; +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.server.functions.Message; import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import java.util.Arrays; import java.util.Map; import java.util.UUID; -public class ReplyCommand extends CustomCommand { - public static Map replyMap = MessageCommand.replyMap; - - public ReplyCommand() { - super("reply"); - this.setPrintStacktrace(true); - } - +public class ReplyCommand implements CustomCommand { + public static Map replyMap = Message.replyMap; @Override - public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) { + public void dispatchCommand(CommandSender sender, Args args) { String name = sender.getName(); Player p = sender.getServer().getPlayer(name); UUID senderID = p.getUniqueId(); @@ -29,10 +24,10 @@ public class ReplyCommand extends CustomCommand { } Player r = sender.getServer().getPlayer(replyMap.get(senderID)); UUID reciverID = r.getUniqueId(); - if (args[0] == null) { + if (args.get(0).toString() == null) { p.sendMessage(Text.prefix(Sentinel.dict.get("no-message-provided"))); } - String msg = String.join(" ", Arrays.asList(args)); + String msg = args.getAll().toString(); if (p.hasPermission("sentinel.message")) { Message.messagePlayer(p,r,msg); replyMap.put(senderID,reciverID); @@ -42,7 +37,7 @@ public class ReplyCommand extends CustomCommand { } @Override - public void registerCompletions(CompletionBuilder builder) { - builder.addCompletion(1,builder.args.length >= 2, "[]"); + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg("[]")); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java new file mode 100644 index 0000000..769e02e --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/SentinelCommand.java @@ -0,0 +1,75 @@ +package io.github.thetrouper.sentinel.cmds; + +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CommandRegistry; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.Permission; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; +import io.github.thetrouper.sentinel.Sentinel; +import io.github.thetrouper.sentinel.server.config.Config; +import io.github.thetrouper.sentinel.server.functions.AntiSpam; +import io.github.thetrouper.sentinel.server.functions.ProfanityFilter; +import io.github.thetrouper.sentinel.server.util.Text; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +import java.util.HashSet; +@CommandRegistry(value = "sentinel",permission = @Permission("sentinel.debug")) +public class SentinelCommand implements CustomCommand { + public static boolean debugMode; + @Override + public void dispatchCommand(CommandSender commandSender, Args args) { + Player p = (Player) commandSender; + Sentinel instance = Sentinel.getInstance(); + switch (args.get(0).toString()) { + case "reload" -> { + if (!Sentinel.isTrusted(p)) return; + p.sendMessage(Text.prefix("Reloading Sentinel!")); + Sentinel.log.info("[Sentinel] Re-Initializing Sentinel!"); + instance.loadConfig(); + } + case "debug" -> { + switch (args.get(1).toString()) { + case "antiswear" -> { + HashSet players = new HashSet<>(); + players.add(p); + String msg = args.getAll(1).toString().trim(); + AsyncPlayerChatEvent e = new AsyncPlayerChatEvent(true, p, msg, players); + ProfanityFilter.handleProfanityFilter(e); + } + case "antispam" -> { + HashSet players = new HashSet<>(); + players.add(p); + String msg = args.getAll(1).toString().trim(); + AsyncPlayerChatEvent e = new AsyncPlayerChatEvent(true, p, msg, players); + AntiSpam.handleAntiSpam(e); + } + case "lang" -> { + p.sendMessage(Sentinel.dict.get("exmaple-message")); + } + case "toggle" -> { + debugMode = !debugMode; + p.sendMessage(Text.prefix((debugMode ? "Enabled" : "Disabled") + " debug mode.")); + } + } + } + case "getHeat" -> { + Player target = Bukkit.getPlayer(args.get(1).toString()); + if (target == null) { + p.sendMessage(Text.prefix("Invalid Player!")); + return; + } + p.sendMessage(Text.prefix("Heat of " + target.getName() + ": &8(&c" + AntiSpam.heatMap.get(target) + "&7/&4" + Config.punishHeat + "&8)")); + } + } + } + + @Override + public void dispatchCompletions(CompletionBuilder b) { + b.then(b.arg("reload","getheat")); + b.then(b.arg("debug").then( + b.arg("antiswear","antispam","lang","toggle"))); + } +} diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/SocialSpyCommand.java b/src/main/java/io/github/thetrouper/sentinel/cmds/SocialSpyCommand.java similarity index 67% rename from src/main/java/io/github/thetrouper/sentinel/commands/SocialSpyCommand.java rename to src/main/java/io/github/thetrouper/sentinel/cmds/SocialSpyCommand.java index 55b18dc..a88281c 100644 --- a/src/main/java/io/github/thetrouper/sentinel/commands/SocialSpyCommand.java +++ b/src/main/java/io/github/thetrouper/sentinel/cmds/SocialSpyCommand.java @@ -1,8 +1,10 @@ -package io.github.thetrouper.sentinel.commands; +package io.github.thetrouper.sentinel.cmds; +import io.github.itzispyder.pdk.commands.Args; +import io.github.itzispyder.pdk.commands.CustomCommand; +import io.github.itzispyder.pdk.commands.completions.CompletionBuilder; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -10,16 +12,11 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -public class SocialSpyCommand extends CustomCommand { +public class SocialSpyCommand implements CustomCommand { + public static Map spyMap = new HashMap<>(); - - public SocialSpyCommand() { - super("socialspy"); - this.setPrintStacktrace(true); - } - @Override - public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) { + public void dispatchCommand(CommandSender sender, Args args) { String name = sender.getName(); Player p = sender.getServer().getPlayer(name); UUID senderID = p.getUniqueId(); @@ -33,7 +30,7 @@ public class SocialSpyCommand extends CustomCommand { } @Override - public void registerCompletions(CompletionBuilder builder) { + public void dispatchCompletions(CompletionBuilder completionBuilder) { } } diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java deleted file mode 100644 index 6bb43ab..0000000 --- a/src/main/java/io/github/thetrouper/sentinel/commands/CustomCommand.java +++ /dev/null @@ -1,166 +0,0 @@ -package io.github.thetrouper.sentinel.commands; - -import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; - -import java.util.*; -import java.util.function.Function; -import java.util.function.Predicate; - -public abstract class CustomCommand implements TabExecutor { - - protected static final Sentinel system = Sentinel.getInstance(); - private final String name; - private boolean printStacktrace; - - public CustomCommand(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setPrintStacktrace(boolean printStacktrace) { - this.printStacktrace = printStacktrace; - } - - public boolean canPrintStacktrace() { - return printStacktrace; - } - - public abstract void dispatchCommand(CommandSender sender, Command command, String label, String[] args); - public abstract void registerCompletions(CompletionBuilder builder); - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - try { - dispatchCommand(sender, command, label, args); - } - catch (Exception ex) { - String msg = ex.getMessage(); - - if (ex instanceof IndexOutOfBoundsException) - msg = "command incomplete"; - else if (ex instanceof NullPointerException) - msg = "command contains a null value"; - - sender.sendMessage(Text.prefix("\u00a74Command Error: \u00a7cUnknown or incomplete command!")); - sender.sendMessage(Text.prefix("\u00a7cCaused by: \u00a78\u00a7o(" + ex.getClass().getSimpleName() + ") \u00a77" + msg)); - sender.sendMessage(Text.prefix("\u00a7cCorrect Usage: \u00a77" + command.getUsage())); - - if (printStacktrace) { - ex.printStackTrace(); - } - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { - CompletionBuilder builder = new CompletionBuilder(sender, command, label, args); - registerCompletions(builder); - return builder.build(); - } - - public CustomCommand register() { - return register(this); - } - - public static CustomCommand register(CustomCommand command) { - system.getCommand(command.name).setExecutor(command); - system.getCommand(command.name).setTabCompleter(command); - return command; - } - - public static class CompletionBuilder { - - public final CommandSender sender; - public final Command command; - public final String label; - public final String[] args; - private final Map> entries; - - public CompletionBuilder(CommandSender sender, Command command, String label, String[] args) { - this.sender = sender; - this.command = command; - this.label = label; - this.args = args; - this.entries = new HashMap<>(); - } - - public CompletionBuilder addCompletion(int index, Predicate condition, Iterable args) { - addCompletion(index, condition.test(this), args); - return this; - } - - public CompletionBuilder addCompletion(int index, Predicate condition, String... args) { - addCompletion(index, condition.test(this), args); - return this; - } - - public CompletionBuilder addCompletion(int index, Predicate condition, List args) { - addCompletion(index, condition.test(this), args); - return this; - } - - public CompletionBuilder addCompletion(int index, boolean condition, Iterable args) { - if (condition) { - addCompletion(index, args); - } - return this; - } - - public CompletionBuilder addCompletion(int index, boolean condition, String... args) { - if (condition) { - addCompletion(index, args); - } - return this; - } - - public CompletionBuilder addCompletion(int index, boolean condition, List args) { - if (condition) { - addCompletion(index, args); - } - return this; - } - - public CompletionBuilder addCompletion(int index, Iterable args) { - List list = new ArrayList<>(); - args.forEach(list::add); - addCompletion(index, list); - return this; - } - - public CompletionBuilder addCompletion(int index, String... args) { - addCompletion(index, Arrays.asList(args)); - return this; - } - - public CompletionBuilder addCompletion(int index, List args) { - entries.put(index, args); - return this; - } - - public void removeCompletion(int index) { - entries.remove(index); - } - - public List convertLists(Collection input, Function conversion) { - List list = new ArrayList<>(); - for (I i : input) { - list.add(conversion.apply(i)); - } - return list; - } - - public List build() { - return entries.getOrDefault(args.length, new ArrayList<>()).stream() - .filter(s -> s.toLowerCase().contains(args[args.length - 1].toLowerCase())) - .toList(); - } - } -} diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java deleted file mode 100644 index 0395c0c..0000000 --- a/src/main/java/io/github/thetrouper/sentinel/commands/MessageCommand.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.thetrouper.sentinel.commands; - -import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.server.functions.Message; -import io.github.thetrouper.sentinel.server.util.ArrayUtils; -import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class MessageCommand extends CustomCommand { - public static Map replyMap = new HashMap<>(); - - public MessageCommand() { - super("msg"); - this.setPrintStacktrace(true); - } - - @Override - public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) { - Player p = (Player) sender; - Player r = null; - if (args.length == 0) { - p.sendMessage(Text.prefix(Sentinel.dict.get("no-online-player"))); - } - if (args.length == 1) { - p.sendMessage(Text.prefix(Sentinel.dict.get("no-message-provided"))); - } - r = Bukkit.getPlayer(args[0]); - String msg = ""; - for (int i = 1; i < args.length; i++) { - msg = msg.concat(" " + args[i]); - } - msg = msg.trim(); - if (p.hasPermission("sentinel.message") && r != null) { - Message.messagePlayer(p,r,msg); - } else if (r == null) { - p.sendMessage(Text.prefix((Sentinel.dict.get("no-online-player")))); - } - else { - sender.sendMessage(Text.prefix(Sentinel.dict.get("no-permission"))); - } - } - - @Override - public void registerCompletions(CompletionBuilder builder) { - builder.addCompletion(1, ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName)); - builder.addCompletion(2,builder.args.length >= 2, "[]"); - } -} diff --git a/src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java b/src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java deleted file mode 100644 index 42f56aa..0000000 --- a/src/main/java/io/github/thetrouper/sentinel/commands/SentinelCommand.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :) - */ - -package io.github.thetrouper.sentinel.commands; - -import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.server.functions.AntiSpam; -import io.github.thetrouper.sentinel.server.functions.ProfanityFilter; -import io.github.thetrouper.sentinel.server.util.ArrayUtils; -import io.github.thetrouper.sentinel.server.util.Text; -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.player.AsyncPlayerChatEvent; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -/** - * Example command - */ -public class SentinelCommand extends CustomCommand { - public static boolean debugmode; - - public SentinelCommand() { - super("sentinel"); - this.setPrintStacktrace(true); - } - - @Override - public void dispatchCommand(CommandSender sender, Command command, String label, String[] args) { - Player p = (Player) sender; - Sentinel instance = Sentinel.getInstance(); - switch (args[0]) { - case "reload" -> { - if (!Sentinel.isTrusted(p)) return; - p.sendMessage(Text.prefix("Reloading Sentinel!")); - Sentinel.log.info("[Sentinel] Re-Initializing Sentinel!"); - instance.loadConfig(); - } - case "debug" -> { - switch (args[1]) { - case "antiswear" -> { - HashSet players = new HashSet<>(); - players.add((Player) sender); - String msg = ""; - for (int i = 1; i < args.length; i++) { - msg = msg.concat(" " + args[i]); - } - msg = msg.trim(); - AsyncPlayerChatEvent e = new AsyncPlayerChatEvent(true, (Player) sender, msg, players); - ProfanityFilter.handleProfanityFilter(e); - } - case "antispam" -> { - HashSet players = new HashSet<>(); - players.add((Player) sender); - String msg = ""; - for (int i = 1; i < args.length; i++) { - msg = msg.concat(" " + args[i]); - } - msg = msg.trim(); - AsyncPlayerChatEvent e = new AsyncPlayerChatEvent(true, (Player) sender, msg, players); - AntiSpam.handleAntiSpam(e); - } - case "lang" -> { - p.sendMessage(Sentinel.dict.get("exmaple-message")); - } - case "toggle" -> { - debugmode = !debugmode; - p.sendMessage(Text.prefix((debugmode ? "enabled" : "disabled") + " debug mode.")); - } - } - } - case "getHeat" -> { - Player target = Bukkit.getPlayer(args[1]); - if (target == null) { - p.sendMessage(Text.prefix("Invalid Player!")); - return; - } - p.sendMessage(Text.prefix("Heat of " + target.getName() + ": &8(&c" + AntiSpam.heatMap.get(target) + "&7/&4" + Config.punishHeat + "&8)")); - } - } - } - - @Override - public void registerCompletions(CompletionBuilder builder) { - builder.addCompletion(1, "debug", - "getHeat", - "reload"); - if (builder.args.length >= 2 && builder.args[1].equals("debug")) { - builder.addCompletion(2, "antiswear", - "antispam", - "lang", - "toggle"); - //builder.addCompletion(2, (builder.args.length >= 1 && builder.args[1].equals("getHeat")), ArrayUtils.toNewList(Bukkit.getOnlinePlayers(), Player::getName)); - } - } -} diff --git a/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java b/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java index 16bd7c4..45e3e9c 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/ActionType.java @@ -17,8 +17,8 @@ public enum ActionType { private final String messageTitle; private final Color embedColor; - ActionType(String messagetop, String messageTitle, Color embedColor) { - this.messageTop = messagetop; + ActionType(String messageTop, String messageTitle, Color embedColor) { + this.messageTop = messageTop; this.messageTitle = messageTitle; this.embedColor = embedColor; } diff --git a/src/main/java/io/github/thetrouper/sentinel/data/FAT.java b/src/main/java/io/github/thetrouper/sentinel/data/FAT.java index a10c09f..dbc26cb 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/FAT.java +++ b/src/main/java/io/github/thetrouper/sentinel/data/FAT.java @@ -1,5 +1,7 @@ package io.github.thetrouper.sentinel.data; +import io.github.thetrouper.sentinel.server.config.Config; + import java.awt.*; public enum FAT { diff --git a/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java b/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java index 2cf3e7e..0f67fc6 100644 --- a/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java +++ b/src/main/java/io/github/thetrouper/sentinel/discord/DiscordWebhook.java @@ -1,16 +1,13 @@ package io.github.thetrouper.sentinel.discord; import javax.net.ssl.HttpsURLConnection; -import java.awt.Color; -import java.io.*; +import java.awt.*; +import java.io.IOException; +import java.io.OutputStream; import java.lang.reflect.Array; import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Class used to execute Discord Webhooks with low effort diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java index 6615691..da4fe92 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockExecute.java @@ -1,15 +1,7 @@ package io.github.thetrouper.sentinel.events; -import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.commands.SentinelCommand; -import org.bukkit.Material; -import org.bukkit.block.CommandBlock; -import org.bukkit.command.BlockCommandSender; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.server.ServerCommandEvent; -import org.bukkit.inventory.meta.BlockDataMeta; +import io.github.itzispyder.pdk.events.CustomListener; -public class CMDBlockExecute implements Listener { +public class CMDBlockExecute implements CustomListener { } diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java index 53533d0..4f54237 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockPlace.java @@ -1,18 +1,18 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.Action; import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.server.Action; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; -public class CMDBlockPlace implements Listener { +public class CMDBlockPlace implements CustomListener { @EventHandler private void onCMDBlockPlace(BlockPlaceEvent e) { ServerUtils.sendDebugMessage("CommandBlockPlace: Detected block place"); diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java index 6548b94..2a22307 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDBlockUse.java @@ -1,9 +1,10 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.Action; import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.server.Action; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; import org.bukkit.Material; import org.bukkit.block.Block; @@ -11,11 +12,10 @@ import org.bukkit.block.BlockState; import org.bukkit.block.CommandBlock; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.player.PlayerInteractEvent; -public class CMDBlockUse implements Listener { +public class CMDBlockUse implements CustomListener { @EventHandler private void onCMDBlockUse(PlayerInteractEvent e) { ServerUtils.sendDebugMessage("CommandBlockUse: Detected Interaction"); diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java index cd25cb8..965bb28 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartPlace.java @@ -1,17 +1,17 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.Action; import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.server.Action; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEvent; -public class CMDMinecartPlace implements Listener { +public class CMDMinecartPlace implements CustomListener { @EventHandler private void onCMDMinecartPlace(PlayerInteractEvent e) { diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java index 058fb0f..a208195 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CMDMinecartUse.java @@ -1,17 +1,17 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.Action; import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.server.Action; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEntityEvent; -public class CMDMinecartUse implements Listener { +public class CMDMinecartUse implements CustomListener { @EventHandler private void onCMDBlockMinecartUse(PlayerInteractEntityEvent e) { ServerUtils.sendDebugMessage("MinecartCommandUse: Detected Interaction with entity"); diff --git a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java index 5225c00..8103bbf 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/ChatEvent.java @@ -1,17 +1,17 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; +import io.github.thetrouper.sentinel.server.config.Config; +import io.github.thetrouper.sentinel.server.config.MainConfig; import io.github.thetrouper.sentinel.server.functions.AntiSpam; import io.github.thetrouper.sentinel.server.functions.AntiUnicode; import io.github.thetrouper.sentinel.server.functions.ProfanityFilter; import io.github.thetrouper.sentinel.server.util.ServerUtils; -import io.github.thetrouper.sentinel.server.util.Text; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; -public class ChatEvent implements Listener { +public class ChatEvent implements CustomListener { @EventHandler public static void onChat(AsyncPlayerChatEvent e) { @@ -19,7 +19,7 @@ public class ChatEvent implements Listener { ServerUtils.sendDebugMessage("ChatEvent: Chat event detected!"); if (!Sentinel.isTrusted(e.getPlayer()) || !e.getPlayer().hasPermission("sentinel.chat.antiunicode.bypass")) { ServerUtils.sendDebugMessage("ChatEvent: Permission bypass failed, checking for unicode"); - if (Config.antiUnicode) { + if (MainConfig.Chat.antiUnicode) { ServerUtils.sendDebugMessage(("ChatEvent: Enabled, Continuing unicode check!")); AntiUnicode.handleAntiUnicode(e); } diff --git a/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java b/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java index 797ed6a..a198173 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/CommandEvent.java @@ -1,17 +1,16 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.Action; import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.server.Action; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; -import io.github.thetrouper.sentinel.server.util.Text; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -public class CommandEvent implements Listener { +public class CommandEvent implements CustomListener { private String trusted; @EventHandler private void onCommand(PlayerCommandPreprocessEvent e) { diff --git a/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java b/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java index 580b573..a6064ca 100644 --- a/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java +++ b/src/main/java/io/github/thetrouper/sentinel/events/NBTEvents.java @@ -1,9 +1,10 @@ package io.github.thetrouper.sentinel.events; +import io.github.itzispyder.pdk.events.CustomListener; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.Action; import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.server.Action; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -12,7 +13,6 @@ import org.bukkit.block.Container; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryCreativeEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -21,7 +21,7 @@ import org.bukkit.inventory.meta.ItemMeta; import java.util.Map; -public class NBTEvents implements Listener { +public class NBTEvents implements CustomListener { @EventHandler private void onNBTPull(InventoryCreativeEvent e) { ServerUtils.sendDebugMessage("NBT: Detected creative mode action"); diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Action.java b/src/main/java/io/github/thetrouper/sentinel/server/Action.java similarity index 88% rename from src/main/java/io/github/thetrouper/sentinel/data/Action.java rename to src/main/java/io/github/thetrouper/sentinel/server/Action.java index d9b74bc..db31a94 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/Action.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/Action.java @@ -1,15 +1,17 @@ -package io.github.thetrouper.sentinel.data; +package io.github.thetrouper.sentinel.server; import io.github.thetrouper.sentinel.Sentinel; +import io.github.thetrouper.sentinel.data.ActionType; +import io.github.thetrouper.sentinel.data.Emojis; import io.github.thetrouper.sentinel.discord.DiscordWebhook; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.FileUtils; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.Text; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.GameMode; -import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; @@ -19,36 +21,8 @@ import java.io.IOException; import java.util.List; public class Action { - private final Cancellable event; - private final ActionType action; - private final Player player; - private final String command; - private final String loggedCommand; - private final ItemStack item; - private final Block block; - private final boolean denied; - private final boolean deoped; - private final boolean punished; - private final boolean revertGM; - private final boolean notifyDiscord; - private final boolean notifyTrusted; - private final boolean notifyConsole; - private Action(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block,boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) { - this.event = event; - this.action = action; - this.player = player; - this.command = command; - this.loggedCommand = loggedCommand; - this.item = item; - this.block = block; - this.denied = denied; - this.deoped = deoped; - this.punished = punished; - this.revertGM = revertedGM; - this.notifyDiscord = notifyDiscord; - this.notifyTrusted = notifyTrusted; - this.notifyConsole = notifyConsole; + private Action(Cancellable event, ActionType action, Player player, String command, String loggedCommand, ItemStack item, Block block, boolean denied, boolean deoped, boolean punished, boolean revertedGM, boolean notifyDiscord, boolean notifyTrusted, boolean notifyConsole) { } public static class Builder { @@ -140,7 +114,7 @@ public class Action { if (punished) { for (String command : punishCommands) { - ServerUtils.sendCommand(command); + ServerUtils.sendCommand(command.replaceAll("%player%",player.getName())); } } diff --git a/src/main/java/io/github/thetrouper/sentinel/data/FilterAction.java b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java similarity index 97% rename from src/main/java/io/github/thetrouper/sentinel/data/FilterAction.java rename to src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java index 3b13352..299308d 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/FilterAction.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/FilterAction.java @@ -1,10 +1,11 @@ -package io.github.thetrouper.sentinel.data; +package io.github.thetrouper.sentinel.server; import io.github.thetrouper.sentinel.Sentinel; +import io.github.thetrouper.sentinel.data.Emojis; +import io.github.thetrouper.sentinel.data.FAT; import io.github.thetrouper.sentinel.discord.DiscordWebhook; -import io.github.thetrouper.sentinel.server.functions.ProfanityFilter; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.functions.ReportFalsePositives; -import io.github.thetrouper.sentinel.server.util.GPTUtils; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.Text; import net.md_5.bungee.api.chat.ClickEvent; @@ -13,7 +14,6 @@ import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; -import java.awt.*; import java.io.IOException; import java.math.RoundingMode; import java.text.DecimalFormat; diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/AdvancedConfig.java b/src/main/java/io/github/thetrouper/sentinel/server/config/AdvancedConfig.java new file mode 100644 index 0000000..27b184b --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/AdvancedConfig.java @@ -0,0 +1,38 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class AdvancedConfig implements JsonSerializable { + + @Override + public File getFile() { + return new File("plugins/Sentinel/advanced-config.json"); + } + + public static Map leetPatterns = new HashMap<>() {{ + put("0", "o"); + put("1", "i"); + put("3", "e"); + put("4", "a"); + put("5", "s"); + put("6", "g"); + put("7", "l"); + put("$", "s"); + put("!", "i"); + put("|", "i"); + put("+", "t"); + put("#", "h"); + put("@", "a"); + put("<", "c"); + put("V", "u"); + put("v", "u"); + }}; + public static String falsePosRegex = ""; + public static String swearRegex; + public static String strictRegex; + public static String urlRegex = "^(https?://)?([a-zA-Z0-9-]+\\.)*[a-zA-Z0-9-]+\\.[a-zA-Z]{2,}(/\\S*)?$\n"; +} diff --git a/src/main/java/io/github/thetrouper/sentinel/data/Config.java b/src/main/java/io/github/thetrouper/sentinel/server/config/Config.java similarity index 98% rename from src/main/java/io/github/thetrouper/sentinel/data/Config.java rename to src/main/java/io/github/thetrouper/sentinel/server/config/Config.java index f2b9850..e43d8c9 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/Config.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/Config.java @@ -2,18 +2,14 @@ * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :) */ -package io.github.thetrouper.sentinel.data; +package io.github.thetrouper.sentinel.server.config; -import com.google.common.base.Charsets; import io.github.thetrouper.sentinel.Sentinel; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/FPConfig.java b/src/main/java/io/github/thetrouper/sentinel/server/config/FPConfig.java new file mode 100644 index 0000000..8feb961 --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/FPConfig.java @@ -0,0 +1,16 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; +import java.util.List; + +public class FPConfig implements JsonSerializable { + + @Override + public File getFile() { + return new File("plugins/Sentinel/false-positives.json"); + } + + public static List swearWhitelist; +} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/Lang.java b/src/main/java/io/github/thetrouper/sentinel/server/config/Lang.java new file mode 100644 index 0000000..2561892 --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/Lang.java @@ -0,0 +1,15 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; + +public class Lang implements JsonSerializable { + + @Override + public File getFile() { + return new File("plugins/Sentinel/lang/" + Config.lang); + } + + +} diff --git a/src/main/java/io/github/thetrouper/sentinel/data/LanguageFile.java b/src/main/java/io/github/thetrouper/sentinel/server/config/LanguageFile.java similarity index 93% rename from src/main/java/io/github/thetrouper/sentinel/data/LanguageFile.java rename to src/main/java/io/github/thetrouper/sentinel/server/config/LanguageFile.java index e87d854..2ca3ce0 100644 --- a/src/main/java/io/github/thetrouper/sentinel/data/LanguageFile.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/LanguageFile.java @@ -1,4 +1,4 @@ -package io.github.thetrouper.sentinel.data; +package io.github.thetrouper.sentinel.server.config; import io.github.thetrouper.sentinel.Sentinel; import io.github.thetrouper.sentinel.server.util.JsonSerializable; diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/MainConfig.java b/src/main/java/io/github/thetrouper/sentinel/server/config/MainConfig.java new file mode 100644 index 0000000..5a18573 --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/MainConfig.java @@ -0,0 +1,77 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.thetrouper.sentinel.server.util.JsonSerializable; + +import java.io.File; +import java.util.List; +import java.util.Map; + +public class MainConfig implements JsonSerializable { + + @Override + public File getFile() { + return new File("plugins/Sentinel/main-config.json"); + } + + public static class Plugin { + public static String prefix = "§d§lSentinel §8» §7"; + public static String webhook; + public static String lang; + public static List trustedPlayers; + public static boolean blockSpecific; + public static boolean preventNBT; + public static boolean preventCmdBlockPlace; + public static boolean preventCmdBlockUse; + public static boolean preventCmdBlockChange; + public static boolean preventCmdCartPlace; + public static boolean preventCmdCartUse; + public static boolean cmdBlockOpCheck; + public static List dangerous; + public static boolean logDangerous; + public static boolean logCmdBlocks; + public static boolean logNBT; + public static boolean logSpecific; + public static List logged; + public static boolean deop; + public static boolean nbtPunish; + public static boolean cmdBlockPunish; + public static boolean commandPunish; + public static boolean specificPunish; + public static List punishCommands; + public static boolean reopCommand; + } + + public static class Chat { + public static boolean antiUnicode; + + public static class antiSpam { + public static boolean antiSpamEnabled; + public static int defaultGain; + public static int lowGain; + public static int mediumGain; + public static int highGain; + public static int heatDecay; + public static int blockHeat; + public static int punishHeat; + public static boolean clearChat; + public static String chatClearCommand; + public static String spamPunishCommand; + public static boolean logSpam; + } + public static class antiSwear { + public static boolean antiSwearEnabled; + public static int lowScore; + public static int mediumLowScore; + public static int mediumScore; + public static int mediumHighScore; + public static int highScore; + public static int scoreDecay; + public static int punishScore; + public static boolean strictInstaPunish; + public static String swearPunishCommand; + public static String strictPunishCommand; + public static boolean logSwears; + } + + } +} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/NBTConfig.java b/src/main/java/io/github/thetrouper/sentinel/server/config/NBTConfig.java new file mode 100644 index 0000000..7bc76a3 --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/NBTConfig.java @@ -0,0 +1,59 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.itzispyder.pdk.utils.FileValidationUtils; +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; + +public class NBTConfig implements JsonSerializable { + @Override + public File getFile() { + return new File("plugins/Sentinel/NBTConfig.json"); + } + + public static boolean allowName; + public static boolean allowLore; + public static boolean allowAttributes; + public static int globalMaxEnchant; + public static int maxMending; + public static int maxUnbreaking; + public static int maxVanishing; + public static int maxAquaAffinity; + public static int maxBlastProtection; + public static int maxCurseOfBinding; + public static int maxDepthStrider; + public static int maxFeatherFalling; + public static int maxFireProtection; + public static int maxFrostWalker; + public static int maxProjectileProtection; + public static int maxProtection; + public static int maxRespiration; + public static int maxSoulSpeed; + public static int maxThorns; + public static int maxSwiftSneak; + public static int maxBaneOfArthropods; + public static int maxEfficiency; + public static int maxFireAspect; + public static int maxLooting; + public static int maxImpaling; + public static int maxKnockback; + public static int maxSharpness; + public static int maxSmite; + public static int maxSweepingEdge; + public static int maxChanneling; + public static int maxFlame; + public static int maxInfinity; + public static int maxLoyalty; + public static int maxRiptide; + public static int maxMultishot; + public static int maxPiercing; + public static int maxPower; + public static int maxPunch; + public static int maxQuickCharge; + public static int maxFortune; + public static int maxLuckOfTheSea; + public static int maxLure; + public static int maxSilkTouch; +} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/StrictConfig.java b/src/main/java/io/github/thetrouper/sentinel/server/config/StrictConfig.java new file mode 100644 index 0000000..f45859e --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/StrictConfig.java @@ -0,0 +1,15 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; +import java.util.List; + +public class StrictConfig implements JsonSerializable { + @Override + public File getFile() { + return new File("plugins/Sentinel/strict.json"); + } + + public static List strict; +} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/config/SwearsConfig.java b/src/main/java/io/github/thetrouper/sentinel/server/config/SwearsConfig.java new file mode 100644 index 0000000..89f2a8f --- /dev/null +++ b/src/main/java/io/github/thetrouper/sentinel/server/config/SwearsConfig.java @@ -0,0 +1,15 @@ +package io.github.thetrouper.sentinel.server.config; + +import io.github.itzispyder.pdk.utils.misc.JsonSerializable; + +import java.io.File; +import java.util.List; + +public class SwearsConfig implements JsonSerializable { + @Override + public File getFile() { + return new File("plugins/Sentinel/swears.json"); + } + + public static List swears; +} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java index dc25594..60558e9 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/AntiSpam.java @@ -1,8 +1,8 @@ package io.github.thetrouper.sentinel.server.functions; -import io.github.thetrouper.sentinel.data.Config; import io.github.thetrouper.sentinel.data.FAT; -import io.github.thetrouper.sentinel.data.FilterAction; +import io.github.thetrouper.sentinel.server.FilterAction; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.GPTUtils; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.Text; @@ -29,6 +29,7 @@ public class AntiSpam { lastMessageMap.put(p,"/* Placeholder Message from Sentinel */"); ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " did not have a previous message, setting to placeholder!"); } + if (!heatMap.containsKey(p)) { heatMap.put(p,0); ServerUtils.sendDebugMessage("AntiSpam: " + p.getName() + " did not have a heat, setting it to 0!"); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java index d255bda..9f07a79 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/Message.java @@ -1,22 +1,22 @@ package io.github.thetrouper.sentinel.server.functions; +import io.github.itzispyder.pdk.utils.ServerUtils; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.commands.MessageCommand; -import io.github.thetrouper.sentinel.commands.SocialSpyCommand; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.server.util.ServerUtils; +import io.github.thetrouper.sentinel.cmds.SocialSpyCommand; +import io.github.thetrouper.sentinel.server.config.Config; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.hover.content.Text; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.UUID; public class Message { - private static final Map replyMap = MessageCommand.replyMap; + public static final Map replyMap = new HashMap<>(); public static void messagePlayer(Player sender, Player receiver, String message) { HashSet receivers = new HashSet<>(); receivers.add(receiver); @@ -26,9 +26,7 @@ public class Message { if (!Sentinel.isTrusted(sender) || !sender.hasPermission("sentinel.chat.antiswear.bypass")) if (Config.antiSwearEnabled) ProfanityFilter.handleProfanityFilter(checkEvent); if (!Sentinel.isTrusted(sender) || !sender.hasPermission("sentinel.chat.antispam.bypass")) if (Config.antiSpamEnabled) AntiSpam.handleAntiSpam(checkEvent); if (!Sentinel.isTrusted(sender) || !sender.hasPermission("sentinel.chat.antiunicode.bypass")) if (Config.antiUnicode) AntiUnicode.handleAntiUnicode(checkEvent); - if (checkEvent.isCancelled()) { - return; - } + if (checkEvent.isCancelled()) return; sender.sendMessage(Sentinel.dict.get("message-sent").formatted(receiver.getName(),message)); receiver.sendMessage(Sentinel.dict.get("message-received").formatted(sender.getName(),message)); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java index 597252c..20a7f62 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ProfanityFilter.java @@ -1,18 +1,17 @@ package io.github.thetrouper.sentinel.server.functions; -import io.github.thetrouper.sentinel.data.Config; -import io.github.thetrouper.sentinel.data.FilterAction; + import io.github.thetrouper.sentinel.data.FAT; +import io.github.thetrouper.sentinel.server.FilterAction; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.ServerUtils; import io.github.thetrouper.sentinel.server.util.Text; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; -import java.util.List; import java.util.HashMap; +import java.util.List; import java.util.Map; -import static io.github.thetrouper.sentinel.server.util.Text.SECTION_SYMBOL; - public class ProfanityFilter { public static Map scoreMap; private static final List swearBlacklist = Config.swearBlacklist; diff --git a/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java b/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java index d9b9166..4cc486c 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/functions/ReportFalsePositives.java @@ -1,12 +1,11 @@ package io.github.thetrouper.sentinel.server.functions; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; import io.github.thetrouper.sentinel.data.Emojis; import io.github.thetrouper.sentinel.discord.DiscordWebhook; +import io.github.thetrouper.sentinel.server.config.Config; import io.github.thetrouper.sentinel.server.util.Randomizer; import io.github.thetrouper.sentinel.server.util.ServerUtils; -import io.github.thetrouper.sentinel.server.util.Text; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java deleted file mode 100644 index 5415385..0000000 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/ArgBuilder.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * This file is for tutorial purposes made by ImproperIssues. Distribute if you want :) - */ - -package io.github.thetrouper.sentinel.server.util; - -import java.util.List; -import java.util.Set; - -/** - * Represents Argument builder - */ -public class ArgBuilder { - - private String result; - - /** - * Constructs an argument builder. - */ - public ArgBuilder() { - this.result = " "; - } - - /** - * Constructs an argument builder with a string. - * @param begin the beginner string - */ - public ArgBuilder(String begin) { - this.result = begin + " "; - } - - /** - * Appends a string - * @param string string - * @return this class - */ - public ArgBuilder append(String string) { - this.result += string + " "; - return this; - } - - /** - * Appends a string array - * @param args string array - * @return this class - */ - public ArgBuilder append(String[] args) { - StringBuilder builder = new StringBuilder(); - for (String arg : args) builder.append(arg).append(" "); - this.result += builder.toString(); - return this; - } - - /** - * Appends a string list - * @param args string list - * @return this class - */ - public ArgBuilder append(List args) { - StringBuilder builder = new StringBuilder(); - for (String arg : args) builder.append(arg).append(" "); - this.result += builder.toString(); - return this; - } - - /** - * Appends a string set - * @param args string set - * @return this class - */ - public ArgBuilder append(Set args) { - StringBuilder builder = new StringBuilder(); - for (String arg : args) builder.append(arg).append(" "); - this.result += builder.toString(); - return this; - } - - /** - * Returns this class as a string - * @return this class as a string - */ - public String build() { - return this.toString().trim(); - } - - @Override - public String toString() { - return result; - } -} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java deleted file mode 100644 index 3a8fbec..0000000 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/ArrayUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.github.thetrouper.sentinel.server.util; - -import org.bukkit.Material; -import org.bukkit.entity.EntityType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; - -public final class ArrayUtils { - - /** - * Transforms an array to another one - * @param e iterable list - * @param a action - * @return new transformed list - * @param input - * @param output - */ - public static List toNewList(Iterable e, Function a) { - List list = new ArrayList<>(); - e.forEach(i -> list.add(a.apply(i))); - return list; - } - - public static String list2string(List list) { - return ("\u00a77[\u00a7e" + String.join("\u00a77, \u00a7e", ArrayUtils.toNewList(list, Object::toString)) + "\u00a77]"); - } - - public static List bind(Iterable tList, T... ts) { - List list = Arrays.asList(ts); - tList.forEach(list::add); - return list; - } - - public static class Constants { - public static final List MATERIAL_NAMES = toNewList(Arrays.stream(Material.values()).toList(),m -> m.name().toLowerCase()); - public static final List ENTITY_NAMES = toNewList(Arrays.stream(EntityType.values()).toList(),e -> e.name().toLowerCase()); - } -} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java deleted file mode 100644 index f772a05..0000000 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Cooldown.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.thetrouper.sentinel.server.util; - -import java.util.HashMap; -import java.util.Map; - -public class Cooldown { - - private final Map timer; - - public Cooldown() { - this.timer = new HashMap<>(); - } - - private O getOrDefault(O value, O def) { - return value != null ? value : def; - } - - public long getCooldown(T obj) { - return Math.max(getOrDefault(timer.get(obj), 0L) - System.currentTimeMillis(), 0L); - } - - public double getCooldownSec(T obj) { - final long cooldown = this.getCooldown(obj); - return MathUtils.round(cooldown / 1000.0, 100); - } - - public boolean isOnCooldown(T obj) { - return getCooldown(obj) > 0L; - } - - public void setCooldown(T obj, long millis) { - timer.put(obj, System.currentTimeMillis() + millis); - } - - public void addCooldown(T obj, long millis) { - setCooldown(obj, getCooldown(obj) + millis); - } -} diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java index 92c7f60..086bc00 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/FileUtils.java @@ -1,33 +1,11 @@ package io.github.thetrouper.sentinel.server.util; -import com.google.gson.reflect.TypeToken; import io.github.thetrouper.sentinel.Sentinel; -import java.io.*; -import java.time.*; -import java.util.List; -import java.util.Random; -import com.google.gson.Gson; -import org.bukkit.Location; -import com.google.gson.Gson; -import java.io.FileReader; -import java.io.IOException; -import java.util.Map; +import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.Map; -import java.util.UUID; -import com.google.gson.Gson; -import java.lang.reflect.Type; -import java.io.FileWriter; -import java.io.FileReader; -import java.io.IOException; -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.UUID; -import org.bukkit.Location; public class FileUtils { public static boolean folderExists(String folderName) { File folder = new File(Sentinel.getInstance().getDataFolder(), folderName); diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java index 940965f..105ce8a 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Randomizer.java @@ -1,10 +1,10 @@ package io.github.thetrouper.sentinel.server.util; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Set; -import java.text.SimpleDateFormat; -import java.util.Date; /** * Randomize items from a list diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java b/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java index 84c2800..98326c5 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/ServerUtils.java @@ -1,12 +1,13 @@ package io.github.thetrouper.sentinel.server.util; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.commands.SentinelCommand; +import io.github.thetrouper.sentinel.cmds.SentinelCommand; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.metadata.MetadataValue; import java.util.ArrayList; import java.util.Arrays; @@ -27,7 +28,7 @@ public class ServerUtils { },1); } public static void sendDebugMessage(String message) { - if (SentinelCommand.debugmode) { + if (SentinelCommand.debugMode) { String log = "[Sentinel] [DEBUG]: " + message; Sentinel.log.info(log); for (Player trustedPlayer : Bukkit.getOnlinePlayers()) { @@ -90,4 +91,15 @@ public class ServerUtils { } return false; } + + public static boolean isVanished(Player player) { + for (MetadataValue meta : player.getMetadata("vanished")) { + if (meta.asBoolean()) return true; + } + return false; + } + + public static String[] unVanishedPlayers() { + return io.github.itzispyder.pdk.utils.ServerUtils.players(ServerUtils::isVanished).stream().map(Player::getName).toArray(String[]::new); + } } diff --git a/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java b/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java index ab15b1f..84286ee 100644 --- a/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java +++ b/src/main/java/io/github/thetrouper/sentinel/server/util/Text.java @@ -2,7 +2,7 @@ package io.github.thetrouper.sentinel.server.util; import io.github.thetrouper.sentinel.Sentinel; -import io.github.thetrouper.sentinel.data.Config; +import io.github.thetrouper.sentinel.server.config.Config; import java.util.Map; import java.util.regex.PatternSyntaxException; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6fe96f9..6594d27 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -15,7 +15,7 @@ # config: plugin: - key: "beta" # Put your license key here. If you do not have one, join the discord to verify your purchase + key: "beta" # Put your license key here. If you do not have one, join the discord to verify your purchase lang: "en_us.json" # Languages # -------------------------------- # Anti-Nuke Setup (Do this first)