From d6c97293040aff2596b5844d0a3f05efed228c4e Mon Sep 17 00:00:00 2001 From: ME1312 Date: Mon, 19 Dec 2016 18:31:01 -0500 Subject: [PATCH] SubServers 2 Beta 3 --- .gitignore | 2 - Artifacts/SubServers.Bungee.jar | Bin 172220 -> 176868 bytes Artifacts/SubServers.Client.Bukkit.jar | Bin 0 -> 145562 bytes README.md | 5 +- .../Proxy/Event/SubEditServerEvent.java | 67 + .../Proxy/Event/SubRemoveServerEvent.java | 64 + .../ME1312/SubServers/Proxy/Host/Host.java | 49 +- .../Proxy/Host/Internal/InternalHost.java | 40 +- .../Host/Internal/InternalSubServer.java | 199 ++- .../ME1312/SubServers/Proxy/Host/Server.java | 62 + .../SubServers/Proxy/Host/SubServer.java | 13 +- .../SubServers/Proxy/Library/Files/build.sh | 23 +- .../SubServers/Proxy/Library/Files/lang.yml | 5 +- .../Packet/PacketDownloadServerInfo.java | 1 + .../Network/Packet/PacketOutRunEvent.java | 15 + .../ME1312/SubServers/Proxy/SubCommand.java | 3 +- .../ME1312/SubServers/Proxy/SubPlugin.java | 2 +- SubServers.Client/Bukkit/src/config.yml | 7 + .../Bukkit/Event/SubAddServerEvent.java | 55 + .../Client/Bukkit/Event/SubCreateEvent.java | 136 ++ .../Event/SubDataRecieveGenericInfoEvent.java | 62 + .../Bukkit/Event/SubRemoveServerEvent.java | 55 + .../Bukkit/Event/SubSendCommandEvent.java | 64 + .../Client/Bukkit/Event/SubStartEvent.java | 45 + .../Client/Bukkit/Event/SubStopEvent.java | 57 + .../Client/Bukkit/Event/SubStoppedEvent.java | 33 + .../Client/Bukkit/Graphic/UIListener.java | 365 ++++++ .../Client/Bukkit/Graphic/UIRenderer.java | 1127 +++++++++++++++++ .../Bukkit/Library/Config/YAMLConfig.java | 65 + .../Bukkit/Library/Config/YAMLSection.java | 513 ++++++++ .../Bukkit/Library/Config/YAMLValue.java | 156 +++ .../Client/Bukkit/Library/Container.java | 37 + .../Exception/IllegalPacketException.java | 8 + .../Client/Bukkit/Library/JSONCallback.java | 7 + .../Client/Bukkit/Library/NamedContainer.java | 34 + .../Client/Bukkit/Library/SubEvent.java | 7 + .../Client/Bukkit/Library/UniversalFile.java | 72 ++ .../Client/Bukkit/Library/Util.java | 111 ++ .../Bukkit/Library/Version/Version.java | 224 ++++ .../Library/Version/VersionTokenizer.java | 64 + .../Network/Packet/PacketAuthorization.java | 45 + .../Network/Packet/PacketCommandServer.java | 55 + .../Network/Packet/PacketCreateServer.java | 108 ++ .../Packet/PacketDownloadHostInfo.java | 41 + .../Network/Packet/PacketDownloadLang.java | 38 + .../Packet/PacketDownloadPlayerList.java | 36 + .../Packet/PacketDownloadServerInfo.java | 44 + .../Packet/PacketDownloadServerList.java | 41 + .../Network/Packet/PacketInRunEvent.java | 92 ++ .../Network/Packet/PacketInShutdown.java | 21 + .../Network/Packet/PacketInfoPassthrough.java | 44 + .../Network/Packet/PacketLinkServer.java | 35 + .../Network/Packet/PacketStartServer.java | 51 + .../Network/Packet/PacketStopServer.java | 55 + .../Network/Packet/PacketTeleportPlayer.java | 45 + .../Client/Bukkit/Network/PacketIn.java | 25 + .../Client/Bukkit/Network/PacketOut.java | 25 + .../Client/Bukkit/Network/SubDataClient.java | 241 ++++ .../SubServers/Client/Bukkit/SubCommand.java | 20 + .../SubServers/Client/Bukkit/SubPlugin.java | 82 ++ SubServers.Client/Bukkit/src/plugin.yml | 56 + 61 files changed, 5003 insertions(+), 51 deletions(-) create mode 100644 Artifacts/SubServers.Client.Bukkit.jar create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubEditServerEvent.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubRemoveServerEvent.java create mode 100644 SubServers.Client/Bukkit/src/config.yml create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubAddServerEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubCreateEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubDataRecieveGenericInfoEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubRemoveServerEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubSendCommandEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStartEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStopEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStoppedEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIListener.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIRenderer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLConfig.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLSection.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLValue.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Container.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Exception/IllegalPacketException.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/JSONCallback.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/NamedContainer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/SubEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/UniversalFile.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Util.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/Version.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/VersionTokenizer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketAuthorization.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCommandServer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCreateServer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadHostInfo.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadLang.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadPlayerList.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerInfo.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerList.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInRunEvent.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInShutdown.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInfoPassthrough.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketLinkServer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStartServer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStopServer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketTeleportPlayer.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketIn.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketOut.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/SubDataClient.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubCommand.java create mode 100644 SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubPlugin.java create mode 100644 SubServers.Client/Bukkit/src/plugin.yml diff --git a/.gitignore b/.gitignore index c9cd3af9..785d3b2d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,9 +26,7 @@ crashlytics.properties crashlytics-build.properties # Hide Unfinished Project Files -/Artifacts/SubServers.Client.Bukkit.jar /Artifacts/SubServers.Host.jar -/SubServers.Client/Bukkit/ /SubServers.Host/ # Hide Others diff --git a/Artifacts/SubServers.Bungee.jar b/Artifacts/SubServers.Bungee.jar index 3059e52fc34218a9a54af7e5153a32f89d3e3d6c..f6fc1a0ee6757c6dcf7db970e64dca714c6768c7 100644 GIT binary patch delta 37932 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
jZ+?3@7o6F1IKMr46~RGDMRbB<9B0) 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 delta 33311 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 diff --git a/Artifacts/SubServers.Client.Bukkit.jar b/Artifacts/SubServers.Client.Bukkit.jar new file mode 100644 index 0000000000000000000000000000000000000000..dc43575d4c42a6e09b740228268c42bf5d318891 GIT binary patch literal 145562 zcmb@uW0Y*qmiAk<%eJd_*|u%lwr!icY`b>Zwr$(CjeYBXy8G>Ox^JJi&mA{&t&v|M zVnnX|t!F)R#*CDc1Oi3|00##LKuAas2l%@eG5|1uw6GFCwYZE3tu()kxQMW#5{528XdAXEaD%#!Ttq_0bnw1(Z$dt6%ERh8NK-}5+q&3=IE?d*hufsDnmUK zaDw+O$7yz+sQ}AX;p2H+vn(bLNWo-h&gUpp$ayfQ)}%&T)@)T>T|SPTTqF56rdp@1NNqMkZGDV)4%6 z#tL}_A~(cQgy2(1bh`%~ zM_8qWynd{)Se=6B`hh+%C4^MVKYVD8ykF{cXcG#Be%8FxF&;@1a06>AF?y!f^QE#i zRjF;{6U$t?-R)olAsXMB;WQHou`YsI?-(}Ola)dvYR6|X^&nc0T7pd}k-g+8!@Gnz zD>HM5tw^S$n+neq9hz74(!s&N&UZ}glh7@7d_0r0 zhQ92$iO>+RUWp$oehwwyDDXKJ7+VN0N#;tFE85Lr(WJ9g=tNXros< zuKYu=VvXlr9)Zc5{BZAJa77qX8I9^~3*aLXY!#D*fQ z6+#CE|4dn>F4520n00a6HR+Bf27|=D()fb83c!X+<2QW()X&-G1{aa)vB{zZQdUuw zqHJb?q%`TGSNmLvZqywiAkB2OEh<+h-1NG~G$q~yqxtGXgOd%k zzh+FWhc@f+J)gwy^RF3y&kY>lzul4FUkAX(*opRkZUOc0Eu@9%8R;4RNki0sY^dmL zplIyiV(j4fPx|2ek9`EK%#CgS*}RDUZ(RkPEiKLe*$5Q>%MpZK{$nQprfO^!|EOyG z|I#?$*M;B6=-)2Q-$te}w99S#X|H>KE$;rLs{_suFJL+bUI8?r|lJ|K!g`68IN2<=|{sREIfr^8xqbHYoE7c(H$4BQvf!3JJE}? znZ*;U+uTxOP_(or@rbUKW(Uy-w0qaGg8*p(@u@`JES4L!581)oYZ^+Kf*_`PMRA+} zM--)+6d_?hVig1O7m=U-Gw%i=JL6=(z^Cq-M*ivQRvIuF=F*9%jGszKNZ3Zm*K3%T zSQdse$)SeRSPHBb`ygX|uzQih43x*8KX<|w0Ey&vNZAps+s`7cRG?mq)oh1!B zhxAsuB+bqfwu4c+R+=Quo{U&kh|wjI!TiP=uqsq5L`8Hfh;r*e9fVC5&o1VY;6X?o zjF`9J$0f+abXb-w!cT<_xgS?wKmNMi-HvZ}xV{DI=pO{?zoN?Xuc9jGV65+C{CAu- zs%*<*Dv9O|G8X%`a*4qQj zfXoQBLS5xDxW~^RW>E%;`9)^X+k*te3^e}ZE&BLkRBlJ=($RFec0KNV)zWe?)D@&* zG8Y8`dXO`F-*%;3{^Sj-l z(9_-iZRtVUvvD(0P}615u?Tk+ZcS6u#;AJaL>S&?)!EehSD&FOL=n;`x?PbcFgaan zAB>m3=Wu>?>*Nf?^MwfX`tv}c?f50$1`@pTm>DTJ`RSMRusrGi%5wH(+@vjxlw#XzT+9}^M(MFEhTn43pW2d-c%PLycwRLF&m-Ord z8}KEZ>fIok=>%cwHK$Sq*J$UPdod>OPxuCvo z0WK{xxUCyu{k}Hk!@hxm-;d+Hh&T<^8r8@<+oklW=9YHUsXQ z5XR=U$$a@=3AVvs`S&nLMf{u1o)|Bm6LK1K_|=vln^G^v10J4BfysC zH&P@k`4b+!uS{p%>j=~MlqY7ZhiVY(m2f)_dNCm^P zQR~vljWAj3gHFuxa}bZ}34=2g!M5}N&_uB4v&Xi}F1p)wg z`!)&x>2Ch3c*y*#;vuB(q_1FXXm0FcENX0H>|kyvZewEmcVbehXe~Q0hwO8;RB0t8 zw-Q1|06wOohq4<8ksFRA#DH&a5{}#Mfa5yBa@t1xMJW&Q@6WuAb(`2(D$EausY~{0 z$F1y#AQHdFVU z2@Sq;clA*hoSazb)`)ZF36qSu_r?CeevgE89(<7i@eY>$ihzZ{^bSg_3y{$WGf684 zNwz-Up&2qQoOg``5m?mw3Teq=%#CfR#WB&(zOuA(x>14`h zr;L1u*|Df6u!OzI;1>M5C~bJ7poZ-_&Aj~EfDV_oGZ(ImYsl7%zMJ{P1AKqzNQhM0KghED!33*i&o0LQ-oTLRxA)KrfYQ?~U%oVkZ$8WW9fvTv?aV zOVjp%zaXc9E=WF^o)MFVm8N9k%gl1NV7ai2N-FiegsdFXmui~v>Y;Ege z{Qu(QtZnDMp{7CR(7{H+u!(3vW6i^2BAbPy`DH(4CC)6efyj&M0_3c1DS^M*?LeWP zAI{r@Ys~fB#PB03{pE1ObJ{)IG5fxO*T?4*HaFY@liaG1E>s%f>X#fsUYUR-VK@wm zCPkC-0(v~I)qSQXG}Mr%quCkIcHLt^LI1HVdSdqaGsYeNAWK%&)*biwsRH%t@s`}p zk;iXG1IOxVITo$z@@BB&;^gXkd{?heJTgp`ZL~t1@!AjVkm00L^Lj=T#zn)qhU09z zkW78{kHwve$lf` zgL=N(E+wf$){hCCI{=~tBJRaQA4;uOxl$4Je8dAj4w9Z~LEZcA-h?R=V5f_9NdB+A zjSm!lqmieqXq8ve-Qk%F1w92D$wZxtX1_=;<2#yG+D;D~&mi8lV0#JXuIfz(R`kc`W zIrs$DJbal|;|)mCb0f3GuGbeXnOmyuv)xvV>7{6GqIVoP2|8Byib883N`j<(vac}qUW z^5n0zaP>agXwY8YMs?Fb$6@0!;;Q$+%T?l#megyrXkS{_X}58|o@_I$osj8wf|Z&+ za!pnG5X=a=RMH-2-MUD|O~S=&)afKqJ;y{DHi@JCG1#t9OVvIpQIj(fcc(OdXPJjz zAG}B=*>b3TVtUkJydockNpaj{zL_W51m9V)#+voBl3skI(|;05=nJl(moTrMVPA))0zR5&fh-s4B?O9}<4ObA@QAgQ1iD zzM((xs+Vo19>W`W`f7!|cpw^BkOm!apH%cZ;@R_e3vTorq$RY0mdK{3hjQ9^jw-x? zGs`jv^S_G2&d-bGWQaH<>A{jbOBf{`9R^&p(2q_)PXMzS9Q`_Oz3^=-@JMVczVZEA zFmiH0qx>i2<+!&bNa~2#nXe#Z;YTwaE?{(2Knh`RGa)Hu!HxkDTMQ?@TSl9E5pV{x zQ5;Eq48*+f6a zSS2`Kb$(0n{oFb(Z?_LvjlTyf$r#CRyUKH)`t-ey z8gC1-koRRP4;sW|({-!I@h$EyYjg8h78hYDVb`zr1OC1euDt`}uRGNcZZ@;d3UnuD!Ty$fNc78+vpH z-5h7x%*99vLbGOx60Jq5pw8g@SWZaf6s0I2r>UTNer$K7@mppODbxI9GOjFz`YyW> z)~3%&{B+{gXLJ5}=5`;p3e|z0dP|Tw6k}?m9frGqFfTEh+f7bABAE>MaL-V;SX&u} z$1XmY8D{e7@AO<1eZ1bRnIaiG#x+IWgZd4`SEj+qJU*9f7wNu)1E?p6pe!ztJ{?Yx zxhkA~wz&&}RRRTU!LyH?i3FQCrm7hzDwx-n2unX5d!0PhOm_bB^A?0-#}UTly6&DA zw`9CZI9m&TOLTasInmsEaR-M?t+v>XFirZ_p9xX2Vo{E&qAem5%%$~;R{<;%Ij7f0JG=S1LogZ#4b>sq}LF>uB2A{XLlq z|6zQqJWD$w*+Bq{cUB;)2!dk2$rQl*i%f#;w#sPAMq=&epg#v-e`kF;l50zD$Jw8^ z9J7zPj?H~PKHhM8IDQ((^(ugxD+!fE=!Ml(=o9}!PG;g-kekUfPjI9iZk!am595_UM#ZKFPjU{ulX44Wq zbI5A_JOkU(G8`k}HX%Oz`;a~F)xgx*`mt91n&r$PCA#&}A@5Y3$W9az`EZ6e2~8o@ zoKv4$r&F#pT0^IyBO+`3kIlC`pX6-s%Rv>aQy~835VUgMu0$}Q>xJ3=BMdEn!=kO$ zSxCIg=-eko0k$uIZt#L8P)k9_q@fQ9%nywhCZCD|02hP(dr||8G6vN!(RVW z7oB8RTJrJ%kCB zE}njc7M}TpHXnP+$+uTf!a&)`XKxO7O=mMX0Yyj1)+q*bN4!ttf&hVVN5qVO;0WZr zHA<*EQHY`y^SOwT7#)r;j5b?HP45Cd67fUo-?I#v@y+bqKV_Ep{|mEr#(!@WvJ|vsk-n3Z^EBG++8R9pkVUAwc?&@hW54`g@ceIT z-s(aIhBsXlM3%G}Hd$_U!*TIv2XJ>{7`D=~kQE{^8AmrepR*mWxD#IgmZkJux!W=5 zjDTF@;BuP1-O<||4EZHW!-7FUm`5T&PX%IIAU=>lhI2=!%7AmlxWWEwj-Oy5EDy)X zVr2jJwRNI3HH_()RG2ZgAhRY3C~fS6z2D)vY2k@H&@mMTSdcKb)Q#B(4eF620x3__ z^plJ|DsiEen&UOCu=bsw!r|-A?D_Nx>1Xu*OaU9q5%C!|%1c5|2Cz7+A(9^^Y5#Z<*@fkw60^S!dVq}pdSCX)@ zOP_g*oc1eK8ALosM(P4oK))7y@Nd-`9TSe#Z!}_Q4Lg*#@E$fv9jA}m*sVKZz|~m9 zWekDJy@MW4q8#z$d9e$g$Z0V`HTVGj1<^eWO3?}+06@ie9^ijo4WRm8LL};-Z)aw1 z__x&mzh%u0%i{lGt>k~3iu{j}l*OgY9i9G4BM{O5Tgp63S=(`51eqI)GnpEgKHA(| z5{jDK89NLd0-g@WJP5GZLBPsU=46~Ka`bcNlTP6Opa0Q?|opZERt)p5{s7d-RzKe=;7xU&V3GkvO>ak=w)kifqETn zHLVr{mV6b#7tcO8sd48Z=*dPi*JTLlb@SJaKZ^}q7!IP4-F>;_g*FFtRJaiP+0&lu zGV5MS>xgxPALv9#Hk`c^hqLq-EkVHh$%I*U!MoFQEqI3UbT*sy(jg6p&cOYN(qdS% zG1R-f2h=H4AnTTn&7UQDmV-q!qNr5Bc#Nkq$$8_UizS}8 z5{^6!9S!Rn3D@-F^B5R1G0*rUEP^^ZHIF;lgcUFXw{8f!sjoOF4od^w?m4|;5{f9+ ztI%Sv&ImT1I4~_hmu^e_n{T82S#N&(&%2HHV60%CfwI($+9^=8Xw$SGr60EjNCLs# zU|f2_re9AkFT-4J&fjMxa*wTViZy{z@Hz9jc@KH)6hjk{Ti{ ztY;d_r?2Msan8aJo;qzhr=2!18De5wCAq%ro=cMcKm_+UyEkjhVyquLC{$E}TLFRKdqDM5O|9q2lG z&W*WQe9iPYc(=i$_PWPIGM4fbN5L!jCVt_ayaw$aC=Jg8u8fa-%QFRZE4ItvVREx8 zxxgEn52i-VJ1B&kFdcU)_zrXL7;J^hUiUluJ3?8xCPR(vw)5ZaZS*u4hNG{(V_OxgsJwzQ| zj-AE|7OhlvAMxlGFv`gxD;jN&_b)k#=R2URpaNMiW@!wCmy0O3^=^?+^%BI9;$-G zK|kOfovpqQ81W-7p~Tz$3^>Eu5YKB zHkon~n}e(%Xo1Cn*PC+M8Ms7DMrGGA~l|+vhZzMse9?<@e8A_ zWMOu>k6=Qn(jwLmWU@S)-h8YhDYMZd>k38mL*WDY5-mRVfA zRMXEJC!;2ZqRl|%L&iqz9CCrkOHpr*Y?562kj0ImJti+br0u6w$YrqyGS+uJGpUGI zowRbCR8e}H*5~9{YNDrMGKWM#w}!z$Wp)LDOyy?fm}~r{Ly#sPs)T%pbj@DodQ@N1@mm*@int8~`dLA{23?_-S9EKON#v0Ps3Eq=x?}v=xzuppcBAOlYOisWb`NzQ$#n(LLLD120jsH-yD=P zOzelvSqv?2|-G%lL7}_6c&(B0Y!m(RpbcrBHOzN9K?2(!jYfVca5=X6Sq4;r8RE z)D_0ZPqGHAWBYL~ID4vf=OrU%+i?o)A-yr0@K4|+%apGJa!F|YTB z7l*0ll(vu=fME1xKo-O(l9T0#^K8K{3I@{s(BLKT zs4TxE7l!RI9NAl?|D=3uyiHz?=CNwt6M2wCuhEC+B-$A8ov!aqX-S*6s@;8c^G9jkgL69<@M#^1 zM%yPw)EN`j8Cuo0>8HGrpm_*I{1WRcce}TswCT6Ba$2R?ZTxuV_ljobDf=hg8`A_>=(ZMDblws@zMb_@p1Kx*oC+I3-Qa}(ObNa zSK@^fD{(L9^>ZBYOSn&!=%YN$x1PWK?SUCWH|6FUu?v5fm*}H7%yvz$e(kv_=vwTB z7GfLawgiakB^!oj;F;H{Eey@DEYU||`D0qxpM)DngzlPNmXA45 z)m>ErpGyFQnAIH(E}GqDL?6;!2n5-+9g>eZK*XO3=n|3QQn9Jx1}0!?;`k&IQt_$E zMl4_}Etft4*NS3vt3wPkf@sO)bvi69p&h**_wPJT{n!NOmZ9(Jyb)YWIlR9CfnNLo zsS`*HM+3E*nt3URTBYiAL$1bs|a5wR$1 z?U6sMxF%tf_W{xlGx$GkTe47U1i*}H46rhKB*`SkI$GDuTRM` zH!WYW@KGnMYeeMy1;?vta4dGA1qLlw#1c^l z;Gt6EdgFlV3cQVb@K>h)l7*=!MnL1%=AJVs=LgeGrcgwhd<-Tg1zMuAyLRv1Swy@z zG19MdPRw)dFKHUz+?I`f7x%!ydrlTBJFs8n8&N*RzLK|lZ$-?9GBL%os||TpEaFHS z92?-KSv2fWpHojNu8Q`8##!U*7kBL+5y+D5#RY?x!em#dXlEtLpf`Dpn>wy`EPVr+ zKcgqL{q-oGnGAoyztXk@mCHB$ zbAMq=nO#y>>8Uve9kMI)_)6LraQF?i1!_iEa!*kUWn@%wqgXnif(Itli;k4Q#V3p= zq&pmu#I&0O^%bhgWwbCgr~G*#RG3Nq)09CpZIJ#i}keO|g)0BxYsz?V9sI0+9rFw~p;WJje`R6H_41~mEn%0*M0 zVggWk-ms@w$2U@TjwjmKs?q{vgUB>}{s@xA-#jhp&q{#M9pD%@zkVUll(hC~lauoi zNyh+TUn#=Bu$Mm;{EOl&g%BB?O*@K!T5n7{F?i$Vco?YS&`dS9TxKi;__?ffn7)Gq#ZU4U-< zP%#`c7*`e~YTGo7&i7(vBim`iRg)^r%b%TJGPF!vUMc1&6}XXag9Sw>3zQpV1=vXl z2@+-}XbB_;ER)hQD$!O!)7;fECORfa>s^}UjeOET&;hg3vuoLcVAHG(jz_H+*9q$G zja>lOCFGMP!WiBG+vQBqb{W#NCuk5>ix}D?wQ1@oja-P|@u^9b8?YlTL>by6w7-`t zidawXsvTKcBT(bSp~|(lqVo^0a)*iQtuHXstWEjTw8yKERv#JK{Xf-=SjR3%ngmTa zTXQp3sR`DJ>o+ePg7Oedpjt6DrG@WHugEixpWnp-HPwGj*cdkdx`0jF9Q7fn&#BA7 zh%U3YhAk_A7s0|`urApcyEwj}iQA;E_f#vMxQgmW#8BC%JYWS(`wZA5t$$z57V2~8 z9v8QaumFZ^YFzct^|fxA_^Agsc9CLLJ@M1Pvs8m#Ma2Z}zJ&h7`i4bOjjQh|oQkOa zGqa4Kvu0$8j>dX9B57g;jDfQUmH=8ZA4A;2QBe+d?pP@|Y`Qp~L}rI#EMXPDYPaX* z&A}&heSX4pr-z8p*d_H-!X#!FFO7Sula6K<8p`X~otwv$@s_g85o8U5c5tnF^=BH6 zzO2(c33JtsJI|kxJ&iiHxN_bI9~x)Bk?h1(MJqx9TZ+$s0|8UdM#_~lOW23Hnqtp= zuQzuQlj*wS7ozv55g*F>Xjip=ja%l zQZTWtZT_y_VG$}~oroAy=SlQyYEN$@ouB8F7^m5l+m2i9UTH7>5gj<2<&?;Ix}ACJ zNnbAA$K>#O8k+2!E)miN9s<$QF5<)=-vvX0c=U`QLM&Q_<0m(Q5n!g!&OWA34q>nq zNhHv>O5AKYHu84IAHRriWfoJet*(@SA%A%ciEdeKcGtN*ceq-!U>IpRVx&RbYh zddZtEZMGTXBbi8nY{2@MgO8{5h4&3`xo;N6;#Y0fz@b_|IQ8M3>>{TM=b~ZdKRB zko#_OF~zH72Qvp2%F$3kTKKZ4cfmj6DieYQT=J-pAqE?oBe(GtN#+m>sHAp0PZI0- zXNwFNM`4^SS%hX2&WP*i;+BuOxileZ&FN42-I*wNp}7RE!mxvs5k-m>Iw09U{HkOZ z=#=s7ZS6r8n|&8$Xp2k;ekLF}j#PDpQAOiZ6g(C~AqGixmk0OXQ3k{KN}Aa%RChy2 zQ7Eu$HdxtNm%1Ws@c`50<8#mH;Ip`GVsUCEHPmn#kR_tkf@9Dd!WWV>&JZenI+pEG zYbCd1>ifuUXAempwtyTqJ~{y*fC?bt-ZoESU$GHJiW~@YduEA-;D1qSdXEvJsoN@5 z+&3zY3*$5(tB_gS*t+I!oLW1$b9n&|qN9ny?m>HyD@)1<^D=NlL zhc&bOc{@D7>{Ow?i0cPu!i}bDF1}`4YSoNToh+{^BP~!AARVojjRFdYN}RV%J|?nQ z?rh#B=f7*!xw?P(s5-LyiEWElx-rv)x;zA19GYX`K!fAMD_*IzWk>o<<4jq-kl@KG z#gCEZsme}`g+5-LUPjiveo8)HHr6tX>~~Lb-e;?WG`ymj1xWLI4aKRfl)!jI`$lpwH2FDrgNl8$7s-N+&G1~8c8XOy=U$F2ezjoU%3b$b zUk;>yj_?@a$?qD@Dhg^>M~{`Bw{%0sMF`aR`WIy4Gcno;6zN{fMUO4_Sy}Ys=~h9v zAr#31UpU2j_1>xz=l|qG?`CJtKWwUXAR%=o@<{!JFEVcrm=^d^ntTt=*k*dNGTAc+ z`$%1%^%NNJ&24arf3y+A| zJVaQ{LN7@17AfX94gA{c&np=>WA+@=jjJJM1<&VG)*x;Dt1)bV)S>W#&!P}x02fzR z2Ck6>qrkh5TgmQ|+Mj^b>%9hJ(N`hr#l+?2+acXZ1yI|2YXX*p`PcmVbyC1xS_XuW zqKzk4bGpxd$$%-=?;=q(8`UyYW!u(YM+92QI!#=YuZrL|g{1Ms+*2fV9|2}B$nakt zYe4N}v19SvtQ*TCTI;`6R2@S@L*-f@y$xl!5<`XL93hD< zgEX~6m&f4>!u4HTW8);0=xAL*S(I+Qo9fO;xjPx->)DDx*bIxN(n4c%4%(#*ACNru zzCa_G52?xx923g5x!o{Q4F}X#@tZh5y=ZX{dX7j}{V;8pH@9{myGm7~$0(8@ljDUl z90>ICrMu#5$6k&79q4eBy3=b}Uf0A*EZME^k6fmw#kZ_xGWRzq6B)Qly06%je?wj| zz8L4#67OtKHPAi0w>~iweerH!X9hiM&OGBC zf-oviEJeFZ^&cY=FIPlK^RTippp8lKaBxl|TfmRJOy&XaSDf!9dx4b!=o5$cyRDuB zln2Od3jdmre@1;nlFxsl^Dq&{(!O*$J|;Y6rM2bN+tSx7e+sODlZyMzPV0-S2J4ra z;tNj%_*3C!)CmU~wJjO|3EE$WF7ZlqZj)>zcs7-v8%Sv?HM}#?S2(>Gk1u`$>)q_G zn&{`Zg}s)i3+<6$umT6`ozi2CJc3&!4dvGnc13-(;WY}vb2KjG1n!LX>qtR|fMm+( zW5Oj7cWr6n;wg~$$^LVL=V}f-Y(dRTp`~6-6ZleNFJO~O8qxFO97!(9r!eQkbpqEwFM7= zp&(rqlFJ|rdX7;~>n>oWJ&*$d(3>TYl+Z8yk;|Yus`>s{v>$zJMy$v~Fx231n=r7} zW~for(ERenpXP?`$drcINCI*MQqa8v+I?L{pD`I%K>;-1Yp>&l+5xikb)6(*BTw%7 zgzLpcOm_!i5FVBuL3-a+q-4=H7C|;GBF|(}P`yqzd*-6KOu&pBtLyd!V*~{>9v~?o2*D;A5pI0U(frG$l(y19asxsabhE+HUBml?wYxfp!2C zf;BBS@Kk{5vdZ`+S4NEy92E-oGSKaq!C89@0nKw_dkVpYuGZiduKhCssa?hr+x#Vl z8{8x)VmkW0_$6RFimgbxGRSQmmU%GbK~-WDPR42{?BN2_7aAvJ$O5XQC~YE0khnyU z+Ut!o^$OtJoTW34eFB__!P!`ZPOWirrjU72;=wHD0)x*{q{fa!I4@D;TDJ+fnhB4^ zsUKA@qcH_ZqqH=?(m(bBZVu2)oml%}qo->u5WNW8BXF>D3>FcV2cy)`FlK2fhACcK zNTe~;P=p}aJDn3c zNh-Hx7cPAThvqqh+NVSug7=nLf(Mh8);>$?& zxWTBnAGxHnU}f;2U-Qk+8GVvtqer^tj+U{_4CG^zc_Fyu-sCha&3W59;eaM@ChD!; zE2z2Do2*jfvvn()$x%@*41~Ah5gg^$q*g*0_{0iH39J6P4vrgi?P|L_nw|4R(Dk5I zN!}VpQM2;Ju8<_C;pnfSk@j;|M^v*G*TV@JSC!w;s>Q9!)OY!~0r)rp*E(!@qqEXX zN-?I{fLjjIYmfe1BfAhl_ey?+*Bai{o!;FS2jTI-0s8|A^ujCS=evIz;F|#IE84ts z9odsp-bWi1=<5jl)kOE9iMVqu@xxc0>SL39X-+ets;D^_?Ph&3vW5|M?-C&lEeL-r z4&Zi*2p-J|rI}YeOcQcF$D#i-5(`!+nqnI{Am`pYFWk0k<<$TAgBzTjfNcavb6!mS375Veg>gj zV5p7q1TtS>u}Pvsn?e!pV(XJ+QZo4|-t>X=IoBw!0P@2B41fwg-X++@X&EyLD3@kg zF~I~|PCe>znNPE;H;39VXajdivkBh(ExM~R4`tVUO4u^|!0wdp+247j^%Cq3d%-vz z8oLVeKFPW3_v*uD_Qi` z`yuQFuY>U1t2>yoW4lLrLvgvNoAB0uJ}39m&IGd+YtqYG_;@30PT4`O4Qeay+Os~V zeG}b)ww3hLzhJKY#`YAw!xRVRTJyLMYzgzFdJzU!!}})A8Oh746OgBN3pz(5CuF*! zy5~=YZO`#i^)A#o#LHYVobKvT|8f({%MxnPwbgPj#5ydSxhG=p6Gi?d8N)inM8mNG z?>o_jZFMi;(;?f84+L!8c7Xa*yM4_kJ+`SY9MnaQeqN@(u!AmD^6?(9J9Y914x4-z zYVkN{jndXH#sm1|(d!+lSM;f|k)c)$_7=PXcr=QPPnR0SNbXP|d-zmzB$HC=x=&II z$&F~kh2%@JK{Zt2tW_V^7UN0;9Ys(5h!5s;dvNd%COj`UzREl{X!ycN`!V_-{kvxf zfkW0oQ&AdY2>sM_=fLc+q7iHo1G7kw(Y;JA*d5yf+?z7&uuw6AMTcw^7|74A&~Hea zkK29fLaOn+JSH3VC0B;>G{d=gx3~7G#a}H2J|u7ownsmKcF`x7>9z3rCVqF<(qM<~ zm-?p`{0#0N7Y4uD4`n3D zl3~Yc%~2Tr$=oaK%vBR#90P_sH*FIV2=1p$_oG~&YpF*_3sSNMb!m^m&Y*K|FD}S} zYobSMLQ%#A^D!Yy#6hOZrOptPOGYsML`^SupVrW6BST;~H2?cUYPgf0g9p2MUt;c7 zYR(?zv?bk1OOT_AxX090aJbLrL@j7AJsK+<=$IbgYXUVu6t=IR%^@(Upy5XFkw|g{ z%$qPQ35nS%$iOOsLp~$dFr6=zL`Y^K0!0WF1mQcqm0807S_)c3^TSxTASH7jduw%#h|+$kzIhY*%Cd zSP|yKgqJ88@Vl$O*gBPLN0f;m=u|jjQfVQ)oW@2OQZZx%2h1V3JTIE^ zv_vtIivI)c;$x05Q^z#6N``PLcW~Y40$Jl^+nR~8^_&Z6vU!CKF*vr6d7g;`SnHf3 z-{UF@{);kcWO!qr;n~vutyfXVD{~s**6Mz*ggPaV0vUs z&xoayIoeg31eFR6ijKIu(~~I?Y9@ApA)D7p6i=b-(Zd~Ea{V^rx^UOuuZ%Rc*F}bE z{{b+(+Hq%SN$& zG=HQIvjM@cL00u!Zxzs0xYfA$Dmkl7)8))&72`bFzDyJKVT9Thv#ltf)aHAyAhqd< z;z8J$r0GZh2*#gC`ysW-Gkb?Esof|`eKPB% z-~Ep@&^CULc7$3#SbLd`_QP14&bL;oJPq5gqAumP;Q4cdooC1x4*Pz#?t=ok(tXWo z?B8~oj8`J>*^=XTQEs`|7T0WYiZs2eM)1M*wu9}Mfq!N7IiVqKN#cRg1iRZ|RD@8P zi8>H#0q{mJY^rQJX*$naFG@EvZ#ms3id9|2ozgHy9t?UA$u7GY9SNH!!%v`z+K(;- zx{E7C*HS=U%3bce(E?wSw(JBV)4asQL49HE2h>$b$AP8iVQbZ(YTyA>A}<|_x|@VvrQx)hx}0RMB3!54@z0O^RBlj}zpM@YF(;BG z8eDorm9U=x?}ZsK4cqqz-bAgA3T)T0kieDL*4y6>xGNLi!bqJ!8(UWxF1C)yx(9u0 z4pgna;x&D|YYPN*Udi!zRFzY9Yje8;N(K2wgMF!Qdq9o%Y2a8b;BnMv*sy}PgAb;* zX2KQ<5?a6)G!4~^9)(Qxpciy(_vc$TjMokbul96-cumq1e)G(xpwZKD9*|C;^bL)b zN~Esn;Wg$-AalcQ6JjW&mIU=xLqVHhG{ul;(V%vJBC2atZi5@MLH-k`nxv<&^Eo$i z;dL%Gh8A@|-c!@;bcnz3wndEKs*f}L_1 zMaD+007iZMeet1E{)@_=_1~Y#@hj`2BbN{F6rVP~x0_2SHenb%7mSR5>BrGI*d)tQ zFF-QK2E)yyKAQpE;@y4`Uls8-I*ZwUYS?lYHD}LjcF$}6S<>7N(ln~J8_#dP@URS8 zGiarXIkc!G=wueQO**Sg^C;J{RX(W{_OMJ_BfxlUgC-sS{9A>O|FY771Mc@9cj*0n zh0lN8RrRlz`6+zwQZaV;&oaM8)jz7p%E*5@K3UrL@hBts4AKy3$SPhyV2}q;oUIXn z2NoDiT|*j4g$+M!xpC@T*dQ|v| zagQcFpEsXdb6mGOpC>=uj_;HKEN^SU#%r=zIfWAO$?`Ec-S7Rt@EclcC50&0HdZFL zF9|qi$PM7yfG<$uLcxTohIkO(XAg$}S%2>Jg}%PvsdA1K<09CJ2_b;d225no*%D~s zQ}FE`wFwW*FoIFQdX9+DvLd7ALa-6=nch5%Yp5&D9vDKO3$_`&X{K8)EmSDY(ChEKRuQG<}D0?S!Fwd8*o-saULu&wM*l+$hSi24>9MrVm;{k$-K9X zWTpC0Vo*rWQr2d{LWkb98ZZ&>D~uLM2p>ZM{fZxdA@LJ}QluDrNlXDgLe!{Il0}JU z3LM9)8(KlG_z_TAh6ovRX)@kb9maawhUk>-f=4Dq_yi(0&A$cV5E*v-vraeRF}1s& zNr_wJO{$1=WJfBsPJd3~M*)jICbT=wZ|qa+xOb{HWQZmIVUP#$1o@^?FWlFC zqOw+)c&2j%>TEnL>WEdOVmc3{0RJFhTneH@!`2{)ia0$2@;qFiAJGzQA^#6&=NP0} zw5;i>>auOK%eHOXHo9!vwr$(CZGUB3U0pSO&Y8J0_r%1+og1+u*1!CYV z&|nkC1j8@yK3vjLOyt}lN~k$Nvi}mS>Qa9#^l(eN;!1IX6IE#q{Q+3_&jYebx3uvf6`lsn*A$u~p-#l~qi z9rATcI07}|=CMErMK7hbrGQO_q3AO;<1Zgs+5-4M6#!~{>krhhmL`%(2KIt<%~-Ra zPqHzl`1ggl5kH}*h^orNpXNG&RHn;8t`g&ZE?hCOO%{eWDSVrwvn-U78CS}MR+%;X zE5-bdGklbR*)0YfYsXTatQ)$WaOHg44N0?AA1M`DDuf<$(tuGpu5^Gokenct)qr{) zu^`@;{v}FG!H+pTPJybjeB2dmOKcGd^w}J_-XS+?F3i%Z$duw=(8V2N^-ou)ZBr!AOZeLJ|l(RfmH9rg2ElvQM> z%rlI}*eyoI5q=fIjAm@nQCk14~4(oq_JOI&;YJLxVsAzlUj%;s8P&}=3S`Fuot zw?=%Vm|Nu{-zX`d1^eZ>O6?79d9P{2{0nh55F|<|C+SjV-U%0b^b-|bMzfp6_*dh` zbRgv?r}SFE>Q3c$uUm$j37R@odcz15F9_P#MtX-|(9+lN+-rxx7HuGRgnwdy zFeuAIDNE@US@gxYYxhBW2N8QmX>~>*dksh0MrMto>AwI*&x{VeW8E5zTjMx zn~y=ga9&iL_9IFgk(_gSw3{ayC5^b>fNoC5iXiJI~L zpBT?_-R&+TI1rF9{Qs*tN&kOtv#Uz}M|1k8Fvc%Od3$HeUv^Iaa}Ors#Jl}yP}M=t+b+Vr)2AOq6xbl+sMZy@Y902;@;l`yWo6r zKLUPIjFT_?jve!IYs)g(5P&cHh|lP1V%~e-&fs<{`|~Hy>lGMxbPS4=aWjCfdvpYf zZnWJ!Cn`xN`|!{?veSIc7$k`jGF?h=*clpWx)gDwIv56d7a38PrK;6m<)yQ;n2Kyg zL&3~OnjJm#Jf|R)wespXlKddie>mEV)^e4G7bboTPPl1Q%BrPO6->q)Zbpq<4jva9 zQ^m}Rv&~u+i~2m%keb43q|lB!Dbr`DIdU>NlU~WK4ZDeDWpx|)`~y{lup!tE8$@g~ zaqfasx+OJ*({0^KR_eY{jjhHMc#y+Gg^|{g%U6Zn`FFa%tWR9$9>4gX(PFCGgS5x^C`w z0wKnU8p)x1mR@sggh-2^T{G{AnpO0gpgW3Qy6DFTL*?o*mpAfdT- zv25};C~eY%iP1Rj`lFDplN^yhm_iwU0w6<8x+95zy)N!L8%)qy$u5i8CiyP9Gu`5r zJ{r{xiu2BAghh;>AmaSAmAX-H}bb2r*R&LPCj*i*dfW2ZetMx@UW z>5G)R1MTjqS|ir#m30KPbc*@<&D3${77$`b>YZbT9^D6o6|&9eMfin2cJqj5V~j=; z5_aHoqy2m52aN3R9MATB_uf4^<;BZyjt5Xws;92{!r=GKNkw!F@>XRZ@x2fO-Y|!nW>dpWZil`Q_azYDniTdi90)-<4u91B0*wU?;HTK% z0{sL7_S-;qkAj$P80v?H4+Rnr>emkgK`>wd<+%7U71O^!c*hRv9p-P zpFRv^EU3RP1f&lc8uvAT8z%rDxX%yuMg;sV+V97Yl)e<2j>=i!<%EBqD8`e2gUoNk z@$R6{cyk6>>_no^#Lz%W_WqcS= z2^?=gd@!-GhdV3F0ZHTJw>)!Qx1YNn%#WY zFyEUP0d+WqMlp*qaG|}jB`G^b>EmCYIoxG4BlUDxOr|BrioYwVW-9dIOrl||eeG{> z(0Xk|$w z0}?kQuV0Q!8ja@OYDz03n*N|vTrNs9z5S3?Zilm!o`?r*Z2vMYr8eAJKB|pG$apWM z9c#hYnf5#r&5Pm;UG&3?HoS~0r|ZA2%(d~xx%B&C6tEj4d>a%n=9G9?tox)aldwfL zXDNG1(ElL)y5A-#n|X+M4dxdxq@Qs33p0QFNS&3(#9w4YMQo2jj7uiLJ)hkV!gpz8 z#B~1_YVG1V)YVIpe*HrqVKlERWhDm0iD{Vs=TAZ$q2su48)RZZ9VSvk=mobO*B_=u+MVb{ z1R?bMIJ@Zh&-Q@C?zTV!Car`|@jL!zrWA8DAFrxYX6NI!fBu#HF)0O7V?L-VO(ia%1^KUoc>P~u5!cSjogr}Z(yR1&IrXfXOUTTd! zda1!i=WNZhd{-P@XK42vs*P05QZtG-Vy~gX*+CMjwdi4jDU`OhHEU8NFQ&F)y$=Xb zOMWYvLXkeSB&zPT>S({$?aFj%5!7z+<_GgZ+rBmvEp%XTHOX0#A)!9vGbZrT`V+qifLIP9ux0d!4g%f_F8( z&cC6Q#D4L@3QsHAN!gZ>J5qXoM07=WI2OECz;pExH#peCUJ-j^eZ5mgxGz;P7z=RA zU{?ib8ApRG!Ov@pr&AMV@C8WtiJm<}4dxY;Sa$M(SE&C`Nq0@3APL?bAmlB|2)AyB zav@__4zy#Ez8+c1n|BG;&?2GnuEt|Vhj)ic^k=-2SNSG)CtV=5)KQ+uQR4 zagS6(GoAKo*A)eRM00O99tlKq07KC^F^*Otk0oFdq!#aTMspN=YshVGYfnxf3j#*5~0~w6dM|J!Ir36yJ4DT zeyg>*mbYe&vUIN|Np(;1KZp3*LTDa2Ba(3^q^=S`bP%z@HW}_B?7*xVNglDi#>k+N zeY%tc-;gV&LOHT~Nu?VY+rCdc01OtBz;;BSO#@HgEl6eWl*E5~IU;sz?x9nmYn_cW z-A82dqmuI!>{+zVY6-B)IPoIV7yCF}gT5xzJUd_^ls`YUu1E~Kp7K$Zf0P?;j*03# z%$uyg)!|}toepOKxuaCAH}~CbyaP1|m}`{^(=9$D+cM}7)&b@55#QQu1}{aYs!@1^ zbR*RMXy4@nvHlh~xJHT$+qXqlz77lf>Epr+m)MjJ@5%&K9~Y%HwfeKqWyFjLMiu4liKWKoO5UpUhPvLQzhx|Ckg)1 zcWGv6p|1WG-`@Yp3IB`k{r8vc{~zi3Uw!vqqtuKKguBWZ(%tlpwVS6E1ai0@D5R0d>u1)X}p{%}JM=GuC!?KaHK4#;Jm z&+SeZ_qm*e(EImyltA%mcK<>BkToMpNW*6QaoE{y%pW`6pcJ(2eT)chL zS%(r&EplAd2mt%OU5%#}CGIlkseK@V{SbX&6Z?mxyE5z-)-Uup?P23A_wC9<+rw8^ zV3#oWZAyGM&U-tX`MX@qZj4)}eSP~bl-n@~7Vr58go7b$K4M>jl{-cX69D|Z#j<_b z+fK=W-F??sfY-eP1#hmxy(C(ml0zO!1UV4AK{VH zk>u~?J1{tXRFt0LgFd6Xy|>0lh-?NdeZ_lK3Yn3$;rumK?;)s=H#68Th&|-Iz12HB z#(TdJtzESCUFCZp3jAS&VE_~ckncq>;EtKXH})@rR}vYf;fY5u(I7}<&mgA6$|gJs&U6U$izNnb zO`~&^i6yn7fhNY(nnv81geA4AApskwq+tO&x2k~=dunN2BPM2P-5rh>#I$#m+`^`C zlpKnSe5{_bJw_!~c10uLjZc;bnw3rWb9R1RCT0dXc@~|T4msXQ#WfoRpK!)(M9w|j zVhlQFhD^pr4>oHKJ$&pQbO61xe*nFsean_JR= zUz118N@BQ!wKbA-VvWqK;x;)rc~?o-#WzkCHuY_P$m9^O}32Gf`I7+|EI& zwz<>$3L9pjLz}ue0`QVXYQ#h6OP-tgUTP#29NDYT$xO%F(2W#6kd5GYh3?g!-5llH zy6Q>F(pf0T*u+UzRy#kR90)^;s5z9GS1Pxe%a!r<2)nycBMxF})P}viizJWx!m9TA!V63BS2oPFHJTBaOMkf{?syN7<}$nw248 zF%-x-a%Sp$t=1*wBT2guU`!)H*_1V1 zIRFxQYt-W5q^iqJr!42=_Db%9(65+1T}cok6VovUZ==iO;3w3TH(qNC_yL0n?aPXS zXIfzetE%lR9+!hb?e2Dq4^V*ipG+x`X-f>%C&K_n0oWW3P37~vXa?GvAY<)BMsKJE z?K4^mk70}@rqdPmx`$<2lNk**cWcWNq0^HCQi^Kj3O(I!JisJya> z4P)ugn?@I>ofdT8p6W?JZBxsx=E2JbJ&O=S%dD~EI%TtYMT2yBt!i*+Yj7O7mdZIs zdE%nhlnmiMAAbZX=inOgz2?LF4vXfT#9kCEWJjb%iuIpZ(%@ZHYb3`g>K@LPXS5rx zxH)Zo^^=JTx~Y2@rOF-F;s+Pbo6SkwAU3BsM0$mIET*}_NUmFO>F1P{8^<^WL{*mV zXJ4-9kqVg?h&+nRgU7eBFuU0BDKhw}<6NqS{06+muX&%M_Y3uR*Ze?3$; z_}{}nvm~nSz-ffj^FbIw4_C26i?xI2iXlM+1wC2}@<}&Mq=(~7osdqNf8B~OcpaE+ z5sE&8N1s>I4N|G>@v$QQT|e4XGmjIz%dQm`_ey^nGACppOGTG7N=Q~VRfiIVk8T}4 zuIC=7+PDUyKzGeVNkFg(!h7t(q!5xy>GD+V;BEo?Q_)d0-rW3YM#ICJCL`$?EUR-> zqn*^WdRjA)q0Ho$Yswv+(^EM~9lZLTt(Ud7wFjZJQ4#n#VOox2*9})%C~qs)BFauY11ORI?t48Tkv1hdCin zTIH0?FndRJ&4r&#%(%xAPH{xvq{Um?f<@ZZp)XoSknsiL%@a(-m5MASioC3;cSH84 zt?m@h&Ye?}Jbd~W;Yd%7y-nE}44>=WI<1Vs$vT2k$KUD63VX|%MsIw~)FH}<1R^Q4 z9JNKU4P2AuXP99Vq#Fv?HJYcC7+lpuzwWx=#rF~LGA);giI);>M;y4es61I;3& z9~?`VV>i7O$&mFaNMo*Jx5xnq=ND+N6r&6|t$Lk+Bi59j+9vk(EUw=O+ybY*@i2p` zlgMloTk%P=yGFk*IY69TUf_Sz4?0|DxaE%Z4QRK~nFHqlK<&Oj->l$~yu?gzFRplB z_@LY}*Dfi@yR6UGYwuEjAELQ31o$A;EWcZ>uNR2wn#|-}nPZD)u}+UH&vl4<08Hx6 zwT>~k^f}z)JdPA`M6YAcTF$kP8eDf5<09DFFGN@J`1n+lUE?5&*6hIpw&NrW$+-EeYGK}rZmOmpt02I~ zj|pA{4>w%$hZ9`4175^Wu@Z4}w>2|zWpGG;tWkZKBdCZVLBcsYr?q8WyL9qzx5$A8 z`_GtBGX)l~w2mvDSKmiy5+>@25W!nUbWtK*tx(n4XCw>n7i_2JM}4V~2p2}Z#!sW^ zAOO^qrp`wJ0*Wa4C&wZu3;9jxYw-_iYFK61@`hgLK(SVufpsv^mp#=&OC4#-)YhLB z&3@C`{CTrp_q$ZL!W3M$I3eNakQjGBw9T_Ll5i1>L!5I+ug45rp*xmnhfo5y^`B9fS2_JcHb-*kPt2NCen*VtcIHd| zWaNu3JNM?0k5l&m$KuSDjG9=fdZtMq3Y_8lDcf=;?ZUI(|Whv0r9JF2V zz$b7+<#5OOXOk*!uLwYzEz_wW z;5E*$1Ia7Q)(5%M2-oTrtb2xZtZY3t*q8|%0B3XQw91lbX5FgsLM5`5s4YiOuP%wi zAD_`~p_!E_76mE-9l@X9`T z3np=8f&QbgGbsRFNaqbrnJ|-$3sN?xqpLF{KSTO=L+zrj=t<&>Q;+$Vl|zg^3(uh} zFNK@(c6>xP0$lmiOnL3|FJzDONo8KKMRC%oRrgQg5v0%|xuTygxmLHHAabxogGZ!b zA}q_@x%Gn{jWw1-!gY)@GCFdYh=$jGsED9pG1x@hN*`nwG{JmT!s^tJawvisZK3U) zB}M0{D=F5FQZOgzS+beFi;P5w9b>UO$|3nbi7FDPnDW zhlmq;d6b}aYaZkMG{q+Qc&SdxnZ<Pa3arkbV=Ho zXl!EpdF@E64(>cYnRkwJiIFcY3^loO`^d!C^o@$6a?l&!pTGQd8I->>ENc>P3UJBD zs-J#MG8TwF`%4%sWiA!|!0MQz0?gLLoH?Ly|%1CP!HwZhi8}zSBPY1z^nTr#jOxT^ZQ>tJ zccqHj?QsPImI?{b6ReCkb$SIXbE8;My)j2CY8zKKH-t$tCnQQkc{Ux}?vOUeBKlV_ zfMv=IPsX4O;e*$KMC5X^4#TV-N6;AX2k;J$nmiH|1Ccl>0l~lCaD$_`=+`09!0?b; z3CrenRa+)y>N-hEY_(sVJ;4hU0o=48LtHD#S?URp@7KoKZ=&QItWo!4L^|te(YMRM zJAt=USRor?;OfX^ihbx8Gii+_dlw!5)z8 zU;6q&!N_S6Ac#*h;_HhkYDLn|nuzTJJh9^K@84V)MJZzgcnC{8VZxBcT?v(?yoEifAU1CFVhpPgK^Q(!;E=7MriU6Nc1~+drVx;_XLvIB7da z-=N~)ZOQgqh*hxHdi(QT(&{>XDNNCQinorvxcA4-R-k z1$#l0p6*K?&Ji)eTn;()t|=L2Ol3T8<@br^eWN-zT_4&(n1ZYkA%oTF>C(IANq{sf z5s9dyA~?3zZbjTlvTYpR?nl)fp7i+7rByA-GS#ltp!qsm4ot|sen=pDAe0t&|9O#L zu<${olMm&z5tBUk)RB+T`mu@rNFzSL?kW}f!VoQ8QI)(!@?#nwcoO=D4ETsBXV>Wa zPyGH4=iC8hw_p{{6yw|il4E%JkzuKH*Fa$woFhRck9delxeY%Uc%2~55OC5_&NJYQ zQY%FC5yHcA=kb)z{Ce^UoU1{49AXpo0y{4>;UFV|%5LXVVwrfNBgs02cLL6Q z{)))Fk8XEHOl9MEVP>07V9%^9nmSP;(V7jM&ntLjiroNGeVZ-gnZn7EI`C zsh@7FZLR7Fm|jlK3;sCD?Bfuq?72bEWZa zcQ$K4@V;O3k%UDvQ;%grHwY%=!b4iSLYmFW08IspoG81!YUC+Ia3w57{`1UQSwRLB zQpig*JHlj{ghM`?=nPu|gq~8=cAUv;1NJiP5A8HcbxXxLRyC5RUE4ys&L*l*q19z< z~QeS?6jB&yx?+#0x8Rgi%&#W=k;=2bgBhxk*sJe35YBS2Y#ZJv#nm;`Kc8z z_9w%70(=tiedGByq>qjd_CcUEfeIvW+W>y^c5rr~3pGp|mQb4jJ*?V-7>4M$>9m8Wvbos0*Rc-2YW4YCqsUTmT;F0teX)C?{q)Qj;Qh>Ulu zysZ9=!WYZn1nJ+{vc$&Ai=^k|;gX6;;qeR7$|}SPdtk=cMDm-tbr09Y-l*(@cI(1h z3o3&X%?`k|fkgIj&$`lC&s^yc?EO&oB!au3Y5jQ>uV(9FX2#sSZUZ$eA8hWpc3~6; zbU|q?%?r?k=*o)a*A9P+F|?gNNCyXMSb)?#?2~iuB{XLW3Gxk&Vg04cs z38z47Bk%|Zb{Qjq^-@Gouh^?g zy>y+-feEeaU`iA5*TH3_#~Od~Z1TISkio^L=^O?h_UZllX5f#7Hx9;J#914E_l0eF zbj|gHFt{ZGmTrVWd-w3-XNKfK5(TI@AzmKvv;k^+)@~^#FSwiFwF5o(rPVi2iO~d( z$^8o-wz=D(g}_se(ai#K75oXAJ54YT_lx9qOc2Z{K(%gbZYNmc=M#h7G*f#6j2XL7 z!n@(D9!D*zo1g>9wCvov@baKs`W_^V7Ix(8`8Ee6z(H_aZmvyodh9;^*VPjgF!10x zI-K&5B?q4fG3`%HjZCECViASLa#k{TkQ~Gk2CzJ+0+UMF36*S%jciGdjlv_Ws6>~8 zWEyy-Mp6mboFb}cnjL5#SZb-_Y@lWe=@2lq{6ir4f^^S75qcQ1&Fz6d7LNU=h74aQ zi+5n-0~itGX$EY)u+|$;L{S>%^hS7c0~I3O9`gn$)1_%3*=99k=2(CNV577!#4h6G zb(Dy8baQ$y43ii9vn!voDfmIe7eh!WVO!)-WT+5ysAk461t+fAddN3wP3;2IsU_yT zpk#*9ToZ!w%VNN9k`7 z>G8d7Y#)DG3gso4GBS3VSs6o{bW0x#%BI-Ts++UUPAV1kDbSVU8kZD(m>+L045FFn zqUz?_om#<8g%hhN#9J!`jk-%(t&6zvB>;i6$bvc+j8KWkqRE$b#0_!=q;d_=qae!_ zG)8ezd%@9j8niG%6`SD5i1<5&W#hw$C<;6x^EFK*!d@l;?^0`9l4>VaR-tFL2LN_K z=>R7$Ud>F|HQ29n5(R3q;oD&4hhx+Zq>G0X)DfN_x1cz|$m~LvKtD?I;#Q(MPcG%h zW>Q+w9k|N`_~9GpCo9SayY>D9Z#bMx{({?#+L)O72^TAp>{d}NgB+sTCAT50=ewE8@{R-Zj#;~4C&=F&PfL)engVI-q*Wph-86#r$;6t*_yLbN2Z0P+^st+TC@~s; z%@BY$N_b%Ji2oMVvNF}wtH3C?Au?EO!nIOjy5vYm6r4xX5{bYN%F1L@22xR3`^*|3 z1iF~PpsCJah%~oUh_sf0AS7U_qjH*d9uSx#AQ;pv3`SRJgwx5qLVHuEH2dSoSw~YR zul7Q*<4H86_QDMs$VSl?Z3kECT|2Viri;m+)t!~n8ZIv8nl7qcY>F}}db)T4>QFtl z5%4(M{P2664%cCCi zx<@lDbFuZrqgCn75tBzYn8%tYi{LHSp=*hTd%VDzl7q{RCNKnhn{siW-f%AKC1-W& zOyc_YGZrwidTtYdZ2$_fmYvs2*A}yvurv{U#MRGrjay5ERj;82a5zJL?a@Eit3XXF z@DRtn60I)rF&6ggtLU*i`oZip*Z!DWXlB9($X0p?5ue~^bH9QMys1s@vJ61`z)J6I z8Ity($v)XMW^etM-gWKK`*7$0aQ3`?5MR@`LAKu9+jF;J2=71c@ca;c4-gI*z8KUV z#2tS4!Orb--+}kS{5t4r2)G>xdk4Hx`hoZz${V5hMVj9ERA=%J$sPNdnm?LvsP*RU zjOH1?-uE?$zw@u7e0sd#`UT(}&_7^)Ardz(tUao~3xB%wCiM-x z-m||ye)2CrqWh)w&F}+m?{43_l(7BeCjqz8DDQ$5k$!}{{rrjerv%b-ck;zIw_R9HkApt zO)4X{tAu83NvRcJY#9uQPriK9#6AbLOkScq=Jb*>&iPa9Fzc}Beu_%Dr%5VnpDK}* zT~$0W%etsSlDGjMaffF!{NC;_RG^;^A2$|4n2F}7l?wu|6Xk` zi(&Fg*;8rV^ojCMF>w<@DaTTM@P|qIIc|7VxqQG9p8lbcj!?m=X6&3jC6hzgc{QYn z>N3-i@B$aGbWOf1#S`u(EQS9Ntg)&NIh_{etZu07HYjvf;SqXHMYMC+4YrB=xjrrYRk5VCHr@z+`I5F zOl@tDOz+Q%figjO!KWrVmS7p8s75cOnU~df4M;b8z_C4dK$?vZj}yhbA~9i)$J2l6 z1xUr4Y1T+gbeTg!d{_)Z34{^vkL}h2>cK+8)kp^U#%I-)i&0bj-RMffm063{LQmMS z_jQ;Nl6u2nIj(@pBG^D$7Zq&CRU$X7Txms{_QN7m!EW<6@IW@xcahS+oN6!7p_QG^V2@hD^G%QdAPAfqN9vjY{CJcO)7^<XgGEgZB-`+^e464Epb5KY8G766<{$7B>hC#)ZY&vY>7lD+vPk79g zs+~{N!kPQBICHy28sd9~-;R<^lJ315Ei|KV1+Q)zaPZBW7q{N}_p^K_P?wQ3DWSjvB;^>pDp~!r5xrz{r##h%y{1_`cB_s(4bZgWXLhDuzR6+j~v2WsAdzw+(cy@^wyxzDjY)x`g zw;)l73VO?TA-37iTOd?~a-%hR7-h}qGA5{~Gox`Xs2u6F4KjQ{*_F;LPNoF(pstI+ z<%j=qdz0L9t%iKO6S6=kx|+z3!ziW_Y%4D`v#G~2XOH3T236-&JZRnpX%&Fk43r1) zhX=-NA{&=$fs4$I6iMia`LPt%iv?r;gx@dgDkmMz$Zq?_QbV)PHw8j2?&P&4Ebx|P zF`-t17wb^u3w#8hu0^7cIPrGePvJoO5m^Nzz&y+@(N*zC~>e$7KIgJ-Tnp2-V z)-P2%q=gUD!h?U|0n)J@VUOW9VBL+=J=QgJ$^!*|Z}JxUDstq*5b!#J-%U{Z@RdFR zVFXVQ{O-+wey36m5WbV*gVjH@eADN{#YZ=Rt|PvkB!1dp_)-35zp(e8X%_ zJ#D~w*KkE37<0Y9Kk__nVt*5HO_wKr^zG!;9&*_<2ck?u^KN_-!UENXk#I>*l?#ooO?2>5pMWYZ^$KZ-tR^lH!@NFS|u zS9AxYO_n{NJz#y3z7zX4dh_a2?oIDJ$n{G3My5^7JvzR#-X!duqCF7lQGQRZQDxUD z<92IF9_p1~)Tu7MQA)wrDMz-)Z9DWiGS#VDy?c&~vH!e$7dwXTmF&pPtK^xJSBAe^ zN_l<9nq2#oIcDIOwmdPfYWT!$Vdq!J8=h09cz9en{{(R%>QmrN&@WWGmtIkRGaXzT zv}6EEO$3KRkPcbP=k8Qg>D~rwvQIf9(bP3-Z=~`=xtK|HW<=Gh3928lY4BPHrWtay zZ_vHMdQzyu@rvb*tg2Ya=^41`XI+*eo-n~~dXE1EZ=mRy-){pIN4Ni~I5l~#Fg1RS zNqd0kB%!8m0H&50w4+Zu&~nE;{-*!VHS|X<`SJh{g@F8L73{0_5dP#}8sF6*R>^{6 zM{Zhu^nlB1#2_FsN_Ba$Ay#L>%4*~=>KJ3KATDBo@{4xMYtjY>gqdhro6{r#oXd)Y=Q$#5j22ZFiBB3;J4!5ar$T zRAj}|QK3d%K!1)Cdoyo#X_;-G_s8IB$j8v8FUNDcwk-;8CtQ;@D?JVodsAQj$Jfev zf4{x$d(|HADAj)Y1ThoNbn+h3Itw)KG$G9i9cU7!`7ZI8l)@HBH31-plc?c zwNxbGnlaeM_0})758h(QCw9Z*Nt?_p{TsyRf_fIHl#z-Vr%D;OO7A=VFi2e0{F&GO z3Gh9$t6bM?HMrpJ3})ZTI{hs_Y$7|(RD=QE{Z|N9e0^%VMVlm!c7=IUjHMK>0>2xN z>dXTO{E(UfRX>Er8&B-eZ=Bl;#tg7kkGU6sa<9t)u^0AuPpA_?&@cN&v>lq)&-+Hn za%g_{m!J;2lYWCk5M=fZ$#`QGh1^T@y2DEayrP1A3fzp#yMup4rybC{qkTon18(1t z*$%4Q(~0m6GuEfY7Vdc>h_XgFvc~>uwocffDX*`{7;mKq?Tln!0Yx1|k2pd^0d_Qa zZl{nvsGRN-s&Pcic09nOPoAqG_+y@rUh7f6pf6|kjC|h2tLeWppHKT5ffEP8rMPfN zWlbuSkZ_1+%!NyqHW)0qap-s_7fUEKLZ5J_67`HW7P)D}Km23jb!pUZhQua@HY_;9 zViKY>a=ZOwlF}OQ8?%n5F4slgsn{fUN6Dw$8YmyEZ7M%;s1-PrX!O#Y+@VZ@ye+_FMB*=o&Wn6lEG%p=2{rrC)IH z#$Rv@(ec4KZS7hev>rq$?zC2fZn>J}=gRqPR+lBQgI%2O!mlp%7%xMmmpDH((ovSc z&@b7BHKG4(d;68_80FSgynWa+o2nfwPvCp-`)z^e0AAgoIcxg0NX#IDx%u$hH)hR-3X*V>#tj@8#B)Rzj$oe#xDg@|()H z_Z7NB4>lSfOiCan($F$|zrS1igNYx&o^-$?+HpM(pda|;h;IQV|AZF`EJKl|g{J^B}~9U$yp zO>$tX7_?jWBE(Ii!o7_J8K=0yJ&pzCHf7sA&l$ol4S)1^NzR+UGY~th5q8l zS=Cd3#|4fllp0p>Px-gOpYo9Hu=?OtV9|r&9-0{ggCW8-m5_lIMG9d9ljsTjh}FdQ zq?{sX0UTa|qM$!!+DOC7iR`slK|6OWlkwBZKp6{z3CX*I1u)1!KPJQd{3`hP*}6pp zkVCM=BK%W}VQxuNyHP05a=bH$kH;dgrjY~E>yd#o_h^v9p(v3M$yHS#+m&?8LV#`% zX{&_twbi89n@IZ|aO@iNv)%TOCGQLQ1eh;=ur&QWF8^`(OORwL9Zr7$(N^OV4tOG< z0+D7uNS>oNpOkIAAAnjP3yB?Vg={!65?kmWv%z`VhqBdpGBD;~njU&>vO2&F$t5Pi zG2;?9rkg3FqePfzP7H`71&JAH!5|eRq_>h{BIbKS-}@@F1#1*!t9CQ@>O{7 z)oI*5v{#;jHqODVZI)dm^XBYD-kcfm$j)Xo`cA4Lb&W87;|D4C2B~w$_!J;d2*Ve` zc!xFZFI*4V8+d%js?yJn>f;N+_l7?kOt25~hJ+uIw{Q9u()$VRr?6eue~T&I+C_mo z>U#$PA83~C9}c51h@E^cqgIckx*dnz8+-We$PVr&ikHQh`aH_f8Y%NYnLf@|7^NGv zvrZ>t^qV2$4~kb~8bgRrK+ihT)eNAXUVa$3n;ZVn$AMvPScMNd?5=|&nSRvJo2>NS zg(JIeOvabaY=JXprp*9;FSO&6o+FY!xad8JBlH{Y@y&}P)h`n8CeM*Od+9w9fI^B# zv6#Uti5;F)0>vRpHC(ZHuR)j-y;N*PlWgVC=?p#_PdAjYxWXa58QWAcRxjZRekwtK zsB?~&O@Sx!cpL2l&RdT)8J(nNhEwxdE5pMP`N`N`XgudoBvIG6pCK*$AP8w6|rTL!yt9NPUkqs zf$E*4-lYz|G8OwnD}1{E*TVP~*MTDC*!b3H|CCZ;Lfgs#&R5U@$}sZYE0)I=hfaST z+e7R9i+&aBPolbLm^h%i0N@#WxM9#l$tkT;gRZ$&<$4c93~1LUnTj8sExi5Hy_#5y z??hOOH{t{sxkcOCwM4E~iY8>*@ZpJZHYqVS-=vNV>UjfExls|XK@>^O*^kuJ8m2d zfp6wMrWQVbawlA?hV5uuwQ;UiLtHP3KfnHEooMDRxr;^%1jOn4FZSiHWAk5!6{LUj zvi+~xG|5;RIT|{8{L`lC{~n3?zeo-IuSmkb?9439{}11%fQE$s)o=yegkrRO z#eISFc`OT~#AO5SoA{-2yqe;VulExWI=J0jZ>E{&rmtr7{l32-{9o^aqP5dg7{d_A zyh(}30OYxokj8vcN?L;;esq)N!l70Csdo|4hD4Z85W8lPslQmqRuVeh-mYwYI0O z%i>tap5T^CI!MjP(iS&)?lRj%{q{7`2xT9bN9B((F$no9-Rm-lDUFlbtFf)QltX44 zQ)DN%xNmQWD1`}nf%Xe)hOIlYNKLXjk9WK!C$Jf9;ILKUjF z_a;N1(^#04=;NJ#+Lu11*>!gG%(*b!VD%o#VF%{MASJ3?4=iPV=$Wn5n>HO7NRfUt zp!d@qg4YDogv}H!5u?D;YUIWa9SGYAN(O-2;+Y$OZG)CZ5KNuDMjDuD(<6pfbsrjC7 z;bT~Sb{2W~7SsJ1bsR6itLg9aDHBwnx=hX)|HM5@I{GX)v9o$Cy+*$E!C2SlIG!8J^l(^&8(a5)5m9w^n^UB$dF#K%haI1iYWafA> z^GU}g*ov$9B+MSCF#8(s{gS6MJM;Z^Rg+s{3qk|Rvqa3)lTg9ge5F1roqCnkqKCV{1w$PO6#1B6Zp z@!q|fI`@4US7%UbL*Hu|NpX_S z8}e@vi!A^>=!Ib<_mrp(YJ~ zw{9Ur{h#fO|7th?yX}nsVu=5;n@T1|f3Xz&gQP$cLSOk$6E9i%XwWDKD7ZgAAaQ*V zH8i*|;7Cesa8MlZst)OB9CT1RJ(EBwIc;mp5=b$x5AX7xS20cZ(vM=*1yn7o2bC(T zP0iFb!^Q4$l;ZoWudTP~Y%Vuaws7T%Y`;stPp2ujl&|l}&|(ke4s6oHI(aY?LLpkYNm{he%0?_J2H5qK@UK79YC0qGm>hEmQvfOh?c@INz4Xu&-gY< zo7G=G<-Dt`n>NifUvJNO*ipLyL*kD5&8mC>**)RBOU))dwCc^V9_+M1k8*Ttk^^+Q^dw~)Q>`}wRb}#D~}X_VqeV+ ziTtV$#yPw-20PU{9AK*d)SPLz;u82o)&LpkPm*r4=C&|lnm;YQa+(s{TR}I1`piz% z;u(0ppIbjzb9XOToP{# zEGV$Izp}e7$mnP#xT{JR+ZCT@*Ps`*G#4z+XbKkKe~b;N#q5AmRSMnojNycTthd!x zJc_4#VrBW%kdtq!_eQD5-n-qD8Dp-6A3)zJ4uSygkqXMiSr{~Mways%QVb#pE=2PS zVFRj#?Tt%)ISh&oA3FTT;`&YV-Jp+jP{7W`Xwz}B7Z76GcvThH zxrcoAy7PRGFtOw96eRMe_#sS6t}Gk8<6c!)p-{{7itRvET49Bs(ZX_PI{0r!Nm)t1 zF`G3kZFk!KNfFnT_ssYX&5v1=PaI^qzz9;zd#n3~o}u(BjpK=tH-uD`?nl|4Fsc2F zF?p|!3Fsr%lKh>ul37paBo=@0NNt05mW~!sgx5INMijzIi2~)^HX>uz&;SKJd~^xK ztutXp8weYsovB0Dp4bFRp1oK?=~{fbjg}RuKqNaPHABXpY&RyS$Lj=$=7MMns>oMN zrwNg8XV>R}HJl(2<7?ilqV(Cga!SGG%id=mE+Wi57*GTBNv$i6lPc>oP^#to$rt5( z1kLl8TDt^r;Yh#2(ik?)(KDnw-ZR!;HPG&Gd&<9}m*%7(yn>QvCyn)lOsAz!weFTo z^NnQdW$2eZi4ai^3_B3hzd0mxQZ&1Nn))|wRZ2)~t9Z0}sl3u2GN;8!6ettkLv@)C4t1Q2C$~_(0uWbNCPZi5-8G z;$la?s_d|M<6!^czV%$T8BpdQ#f}JiUkyMt-)s^xRpd;iK=_BAE5&9vDiR5yS+`lQ z?jb}nuB7e?7W_jk7DKG=>Pey0K7_^_=M>h$yoRbX$#5L9yVp1CRLV?hIjFIrnkr-T zHeBB9CJNHyM)jaGC6!X8EGwF6DwQQJHxxPjWKDZzP)khp#cJiZ;&#4thZg57MozLgMWqwy{;#w{G#vMCQSb0}j~0n&hDQ)!zkLDe>O#(GRO zLc!iI{=`RqY&j-Y{gomqWyF!`K{BXQ{D5klD%Y$5p~6iAe*Nm9WpZc41-X^QQ z$~b3TDs^?SLJyx1&WGFZ-_;jjx1WqP>^i7`m9T3CFp%BmQ~)7b zsqR&=ZwgR2Cq`1|?l2+K6+5baUQyYBZJiHZch1F}-htE|LEVnwa;Je{2X-4;)rBzv z>G4NnSd|U(FQJv_i@ZV1Sw|t`Kf^%oM5fzc9e3$6CQ!MC+?Z5S8)85S7U`?Fw#?}e z?PGpU1jJ(qvO?*Etx?-idXCzomuRGVmPrubdQS;p+i5}I@58zw?cR{i2VBng z+vr(`ELQy3xTzS97Ha&C8Wb*}Yq^w$Fd4x^&Dz=8NQkA`xbV6Na56Vi0}3rc(`^Py ze3{j{EZWY~YG-{Xk~05Evb9r9^boiw^{xe3Ca8@Re`=u1DZq;2XEQ|_C{>m6nYms3 zs;MdMQ&i1>K{<~$D>OGNs4&yzV2HwX7``$OV!4vBaG+P*t>ql<7U_bu>Twq3eShS< z(9{xU!>`2;TWRQ15%qiRChl}XbPMIXczR_tGOFlwH)4R)JP%2%thIMO7DriY-J&Nf zUiFUa*^;Qtd_uxCh%FY~fN0z{sv+83>x7l7NaBGwS-GiBU?eicr%$|t?lgB>whpVv zKW#S`OStun@C6~o z0O(ME?v!Uvlw#1Q!dbp&-neFvyH z%GmNVQS=9r3?od!QhaFw?Fc6%WEnhChL99M2v*QxLKuRee$1FM(g+bAbNr5}0dNp% zeo)V_64$xovIc`4nzIC!8V?2MoF7 zIpt9X_KpL3cX-$V{GjwH?IQ#9D0{A`qgnW%!Z;qL!sp?*_)LX_Ob7Ik5(Eob&dM#f z)4|Xn)TmwQ2!)s#^pJ35*+F_tNpKAcpG;xXJ4Ia?((GSxc)uXMoyc$1l(T?r z5G^uO0=f4prI3iG2Amo8pq=^UO~K|v%@+jr72;eWO$9@sn%nWIs}azIb!H&!0~!_X zJh2q?z}H#8WRYM&7-0=iP&x2N#IJ@f zi^ud2H5F$BlO>;m>gqZIJ1#S7q|@6wU_@_%8T>XtPajJ0Z9e$P+=NNnfRALF=sz7o zV*J~LUX7eBBuYv8+Rf6md~snSDA=AsThQ_pRO#w`4x07HoNPZmnzkeHvynfXXb6Yk*jPe($JM;0Gy_3MSw((dG$4wGq-)Nmlq#DZQ9sik!NU#V)E-Btazn z5Ibc;At8q@MavGxjVyMs{$Wd0f5T9J{0JFrGE|O0v(ee6-Ya@kH%>_sZt$!QeM#D_ z2v&;yXYJgY8-WZlNM(r#NQ)4{B(gabWYhr&=o(_dWEW1znNypNeCafdvR%2JMV2eH z<1x`kTAIWW*PxC)=)M%%vuOgFKV(`Yq5*xeEU$+HCrZt#@h{4HWtigl*jmR^ZRyOR zrbbITjXhpUQqOaEQ;Y34mbY7TGHs!yeQ^hWC(qH5O6`nR)arS{Pgw;ffKC!rgB&!d zyS;iumR^Y)pI=)sHh6)9x29{fn&t!7^QLtQr_34L#lsD1mPaJe4? z5#Wb_G-)+xn0`u7Nmwk=zf#qY4v*Q3O$;Hsw!>Dn7rFRd43TUsGcAxTQa#b;R7=lz zbWVA)8?|i~9P?%zsW)FyH}Wiw7W-F5b6D+!2!!rAP44F$?jrEdQA;L79h{Vo6^jlXeuK6}+*|+~zjx*!=R_U14}3TIxe^PqNs$VM7Y$B#t~) z%*%vRdRLMOa_#~14o7_a-~v^aVSZ)P`GFQrV|krLr?9=6)kfKJ$)yEG=S!%hx^W37 zsowImdlW+^w;~Et*($k$)%A{CnjKmMe0;nS8bgbe(YT~AX>rm8Kf`i~su+x3wMjI5 z=m7IrPJ%s&H3m|0gi~@D6!I+@xeK~5&75jvw{x96%(A*vK+%)Ujz4tTRBEu$eEjQM!n0*Ktyy$u%TnjM$H&@7$* zT$=w~F&*Oyx8IA3<)HR2*f9E1Fubde;R}q^)%F4%9xmyqQHT%)K_9m;#U)DCnht!PNiQhWBP zk{jG^xh%Fm+da8y-2DBEL75dz*cuEQhdwqv2J52A~W$L6>1*#faviMx?1Q% zD*Yr7$e<1tSRw!_5~Qe*7o=onmydV*9EMg@IrS2*)qBi>VyO*`(x(uYnv^+`gK-Cw zzyX!`brE`HMa{*WwV$x({0AqXJ`KI_DF!nyCed(6qI4g81rEBGQswHSHgxN)4dx05 z-uvycOYd>a3r@r9$}fCJ4B5LhJA4r~Z=rM{jYz(BDNJ`3YJ<3fbjKo)LbBMi_(q1G zp{!OV%vZfZELBy#>t>GHx&WPp9_#1}dWhjMr`@5`IO3Ik|2kVf;Sk??6+0+;(%*83 z*8fkQ=@1kPH4nW}fAd`cfOr9hN26L+oeU@sG0;=%64`Hzh9%Kl`h4jMj0kfSNa(75 z;;x^a=ChQY(j*5clvm#)R}NX~$FC&jmnDYTOe*NLlBPUoDXHVC`ZdFCtMXNLekh&@ zC4APJ%*$h1VfqqM=dr=)nad1}1tpxwY%wE`CX|JB=l9OAeUES@UYK?RfA3J{+x}(w zL{^@RCqI2{Hg`%F@>&*f^r}H{b|eYmTkL!xDYV@SAfKNupy#2k)rJ^v{vEsgpdM1B2L^k-XQT5i-NSApkwV?m(u(gn;x-4#Bz=n~&oR2r8g zSt+S#REPdgXo<{wg{|aV;dNR*@eK!~hy*1ku-VXWbjHljt8QYR9QA~pV+{$x(CCDF zr@oeH5(p+Ql>}b{orD;KzC`6eitcunXwq-~5H)krPdPz)t9Il=xB({&45C*a*6vqj z!dD;dp?^8f2T%!gok0Hz_*RWYWZbEe zpG@8QRu4BaH>01nf?B+iyqpXTqqZ{52E6>l@3-*0j=Lzaw!FlyFFKx5?#H~YG`+5P z2;FnrMWkU_*P)w9Nz@OY{JF0fPvVd9R`2nd=wc<$CEv3%bmch=o{s!o!( zW3=8bgb1H2?zI{~S!K(z*vW7M+EB?%HuUNF3luYU7>L;kflp&Dc*$Ib6SNy9psWvy zg6;Scx_#1lU(_|sl5{Qh)zkGzw`I8`zhjh4-xPPM8~SjX8N3hr@2&`I>tK=<&~f@7 zO|7f;Y0BG-H@o&B+|o-D(k>9w+3AvQ7Vil4*TUMreTa!JbuK29v+YeYQr{<-C3Dj2 z2h&G?Jiy%5L2!W|s}{ucibn~8xb_Qfi2kHw#?DmE^R~VnGg4{-)}+Z+%eJ?^g&a9q z%Yxl!ZOjpV*PL96&VIc5|RNGdbFAl&Q4IwYfbg= z<#F_MC|nxR`&4@C=ijOH+=?)GUz~@npn64v!aVd5h88z%KfmB$K97W_%sxShyxklm ze9@?9?gHwygK^)2$1sNUN)I@1otXCOdJ@j)g?i%iwt-jOp$_(O(}G(BVYWm`SE&4= z7$cLmD14(5=(ZMh3AwlM^V!6YVKhCj#UEO8$WO=i*T!0fM|mM|Upyt5hR}Xr26-RY zC|uwMB05dGn6U-FjW4_-Gxc^`Yj`X)}kUtWc5k1o8IWW4aK!1VZ)9IDwKw)9~6 z{!+Zl)IW5?XW=817_I4_pnG`3A`YQ=G0A+vksPH<^z*E~mC}8O+1aBAFuNzZ|KBR9CiMw>BiGb$Zmdcl20@X2z) zJ2&G6Gq~9y(W!MVErcrX&|j54x@2BR*@oh3OzyOd7PObODCG!!lJh~Ha zU~yl!pKM99kw)bN4~SX9G9Ca3UNAN{q{lNl^4>l@PVUe2XQ)$xm_CnZ;^*sBdxTHO z>fT>FwC^k%fpP-~?=al{)4f>F)Sc1OeR?+@&%l16D$j_tL#cI`dV`wYFlswzD`9p! zl-^Lwd+V(LUtvf4Tq{9W`FPvItnWYA_H!A+h8?JU!xY}p>H6fZ8Q-xkhkEvL-;wct zPhTTo^2Oxt&p*R?qxSS3T}vgnCJ=K=YRiSI>j`3gde}piIN=as<6`oNq1cda`NOVN z;{;tRI7dW#{oswo*z1EC@G&AI@a>)T)*n_su$Lb-hpzcq+#-A0D?d_$@ z?<@Nd+h0S9a|O)0=OeK|B_p8x`Ws1LZ+!sY0qTz*Wb*$GRTuo9XCqY&tX)k0fvKxn zDPgIg`?3PF2H99B^#WRIU4Q_l304&plLMD8{A|7_d}#M4v6f(K?Ibcdj8XssDxr`T74P-(k2fT&wAcqq*n zDHkPmuzIa!wYZ9t&sO1tpv9kOqIi*0PQo$u=5y4OJMP0=+pk(iUa=MLTLmhfvO_T23*-I*o zj)?`@d9bxgc1lrsDp)RfnfM$k?t~9qG?_kW{EkV&kd-n{bP|l8(Myn0l97*{u)7jRIU1l)o;q&3bB~L_2G!*%*KPRKk=@ zKvGhD|ISgc`i2`y%Sh_P7K66w)i82?&1yF6GC8HPV{mpw6|%oX&|S94EUfDCphvU? z+tIo&QNsLEfyi}AM|9Z9!%1ALDqaJKM#d1f3-*Ps?BlLcIfLLC_#w0tl?TM$gh$Dtc!x}*Oc)3XZaZ!n zi!f{~%UUb=BWN+HWG<4kP@YE@^aPz3&+gM_T6`O%X+LhSwrLlqu6pl&39kcP#(-2FhhuO%Mp2K*=Pw| zoq3|I&44$$7wG_{I`L`&h&C^|+LZk?n2etZuK3YyC{5gLh%M+nsIGE@vX4}91YwP0 zjp%IhxOj6V?=u9YJ;0Xf0YAt9FF@>ENY=}7;MPq&>u`koJx*+jFMsH&C%>1E z@V&(;)5`ox^Bxj$9Yi)ekcbZ7aSg1g>__=jp`*^A^4hp!Th61ayCE#p+frm{wta1Z zwAyP;!Phm%!b^S!WS$m}r4KF(C%g$XdMCKa9=2)`@F0{rg+b#T;3-K)R;GEKB;o$C zI#}c;i3H&mNG0shY2?Q5ijvHjIU$!e7%qynXlMK(V;&VrER_}6`@0Mb zDP!yx7XzO=z*Rc@cWS()JpRhC%F-r&8kArbSFY0Fl)PD}d{e?dVuFNF z?piCTW4X+)WMf0=xM+@MPeT=fNZQ5=9W$yc)4fuy4^>;zwT3v`$s^YLdr})~MT35o zAuuicW@1Kt2tchagtZ^?ty%8Zg3?T@b9TLiwcdCDA>0V`3I>;0GoVX;T@pc=+E?s> z7h{hn9bWL_T1@1(sNN$k2_oi$7jaGUB^Wi&CpOX%On}j;CSDHZ(#jl=RaQ&e=KSd2 z5EEmvu-0N0wazH*~K&Fg4#-vps=P#HPB#b^U>3UL7 z==y+O-R{5hf5@OX!h3kbgSyZC{&Dw~3x2=sp#J6 z_f66Z20qcaY< zgp-Y{9Se=aj{ru<0>oB)nOWzooRiV%SgRy@(DMft-0Owg5hF0gF=DZh>vA{Un&@V; z>+<{je1+KodE{nyR}PH6pmZ%?F{zz5ADh9HeaQl2kR$CoGN&ARg%PqLCWBZ`M`U(I zM%;TeCUnU)81M1SLt2ca*QF)j3<#?QcRypLJ5?{LtuBnlIsv)`-wI~_d3uLCM zN!8+JDRf!5ZjFJ|4oPKW9GFpGEYkUq4dd|ygYAL>9S4`MR5US&wts!QChrju7oIIR zcJT{v$$kI%5KW2Y@>;C~jQM-M2#IE+q`WJwWD7LTEIO;JZNVzJt4Z+%)+BR<(s^5P zkX*HW+rWp0WE0yvPHGViC|KDEf&ma}jn%+SifcF+$89howeZdPaVG($rEzy}E8_dh zz%$iGUBor_k@;qq?=MYJk`G?*`(_vo{0GD6e_fcy`X6eFh`W)=--b2(o7yzR|FKL7 zYikoT18aE$BP$c<|8=XsD`k~@o$LTTGIxsw5P>{-QZPVWGNA#=N(84o3Iv6+xWHz% zK8jKz{&Lw)LmDN+HGnsAziff)PXxH9_sdP5-1mo%8;Bi18aP;2YG$4D_7$R1y$IoB zUV$bbZc=;D6Cg5kV8Y$PbB?{!9FaNtN&M(^Y$g(Gy@VKFWTpUxIC~kp(9OF`444M; z1Iww!DA=N%@DjCEXG&%m;i5Fp!hz+q9`kt8dr?VVgWH%vrRr4Y*t|v9oRutv(F6#X zCdAPqv-$XRm|H91onVU+Lth%}^1z;_9L?NV%u`hF06!TS`_?fPNx?~GJxcqa@)r*; zN_^H(fo10fWkbuVh94f&!&abY94Gpld3xYG1_R1gk5W$CrBte$92$A`j$R;ENw(bv zJ?D`ykIms#@4KRxtDgXWDS|T?&KJwKB9QzO&-cF;#_;}!FHKTOPFBdk+S>5@UH$z9 z$;eJZ2JoY2O;cAWZF&Z^-y67qx0ASlj|a~9B#SJV1iPSkHo@}n!=X^}B%?DgHzlR`@uLPVOVr$6*qfZk1@7jABH0w_I-KuSK8^5I1lv9D*cP5`Fh0R#2dR40e7BuVwyH*I}!Zk8T zfHB$kx=MG#I~w8h^?ifg!B|6CX;l-2eTsCK7mn5fi8c%Ypc*Ut~ih|S1-PR&M5q!Wu8g&Mk`hc(WRE$pO6p8D3{{>O043|CEY z8Nxgi?+?X*K6coQ$D8NV$z={x_Pa;twl{j~+c>fv2W5h}{kJQUF&+ZRhX-D{20A5XX*cUPujK^9 zXJ;6~HH=1?K{iHY7;iZR#YgWXHHd{Yr#8b4nIXxNRK#^(x%)#`n(R{U^q7Hp|3+D%Iuu4>jqVCS1hT#Mb%myNc_6)fH6L z6_iyJw0h@#uHZnqWg<&i6m)B6j(E9#p%byI@^`(kC}?8m0-}$envjtYkx!noy`_SN zr9xe|lPsxxbhna)tE*{vx16b>f}uh&uQVM|;1BT@Us*%l_HI8#RZB;R8C+3NQc!Sx zV|~yBX=v)dg&ZAqXCmKa(m$fVumAgg;rkC)sbXv4YU1c*U@dB4{g3m1wvv_HUmWNI zh3hHB!ME2cz##e7`BZs;G1I2?4_DVFVf$K^Si|J7|VGY3DlpC>2 z%t^vjno?CGqcE5H!w3oubOu0$^kr81^Yw}2y^ONeO;_vTCOV0Ned5wL&5lP^C9?=J zkXZdR`DpE5HYk%Qkj7OaR6Vv61gpA?W1Yw?q0_S_ah%+|3@i+0Czhc+XysZf(^uhKs<2jr$-#PbqOQn*8fl-^J+1NM7%U^d@$6VIyT; z>ZfxreFDQHiVhuLKG)J6Mi&gQAtnqAFcvsW5g*|O|2Ek%UTHfNnmKd_nNb?aK_qfC zYrH)~stzfT8ax^9Alu1@R@MEZ4*^_*rl9L6YU0dMa-xM4|EjXV^)u&wUXYsURfj)#v(^udN*1L#x$ zEq=ftYtt;MIkFOMX@qUuWyzWa+$T!k(+oDjbDh)d@@y;&+NQZ`%M20CeOPEU;U7sh z6SKH$_moYR89Qcrac&?BL(lC3h}KLl+Tbnfdvf$HKoygB;J@sO)2n_L$amQ0`8|5; z|Gwk?)6h-D*~0qoHYHhA#~x`J<+HkSaqMick^vO?fS8?mgjF<+d1l2Qc^y4+gnb3n z@cajrhYekd+L$FsD>EN+k>813!e9>@VMy8AV;%o~tI-g_d z^%E+R{B51l<|vVp2m7lnr%Rrr9H+}CoSUssz7LR}vHR^Irco7XGw{8wA!hcP)l(xU zm7quzC>AgV(&e?x=4o^E(HJnSQ==BD5e<}#n9vi8eFCZ?vI7nF#gU!b9tOxo_PPTg z+6(ltauPQQ5posoviSF{7b{x;{u%0L5dQjhu5*a$xs5pA^n|n~ZH1KTtGS3LZAB!+MI0z*0RPBxJ6D2ha>pE~~>?ss9VJ9fIu8MrPz?n!X{$++}> zZ#6S(2T@*TB!e?$1Y9>7bvpE5vNhWuSkSO_vyzBs$Ub=vJ6fA!h5@`R`swhbaC%4K zKY|&V6Oc`TCw>GhEU3R3W>#VbHkpOTdq$gw)1KDsn3L^tOPPaKDrM$$_hIXL8Fm7R z9j4NHF`4$_&3Lxm&f49CsUf@Bbc;;mWLvreVXYaHV_3bD+>CBmMJ+nrX;zn!uWVpB zws+xwgDblv;$H%JH4ZROopdvRu;Lxd4$>cmuVp{~iKJR)xmlF_WIddOOF=W7X`fPK z(hBj5QPZP5*7TzpSm5K9g2JuBU0^Vhk`}3hlDE(h4?q%&s|TB7zl!?YzR%$x(77dN zk4vLs9w*zO0qtEUUFxN%cgXS)n6H7FU6t47u#$*dUQ%giS3UWuOf^P-ZP;(6j@Gk_ z2@$A3jnF&$u2z|| zJ4`JsaSTzCPY-cLv8>{E!49J?uds|{m4=R{ncwMMWN-)8h)ex=?NU5<4Ll{u-dX+etY zS(O4}%c#_Kj`huTu&M%(_bEi10H2;N^$n*~-f`h&3XM$sp$;`$7qHVa;_dR)B@)EL#>B}h3HsP`et2)eBps2gS#prSDYvS2cD9#dp<~osP zrOWh)f#vRbif%92hFD4nHNo#Nma5CLh_#0s@+Qk?*07(U8Z8nW{`y^%?8s7SO@ck0 zk>Ub(B+X{0U@TU-M@ukY#$R@jpZ-`>d}>mhlxjhyIgBCaWc^N*1CnFZha?hV8ZL28BCpwSX18^?*eYPlY&Do*I zv)M4$^8*naUvmF-@QM`|tmuHcz^xI1*VErQilT;5?euOTYwiu6_oV$sTxbgGD4h^C z)QH-`I;nH|J7&AIO+*E#`LP!;I>87EgqAW&rC~1Lx5ib7D7_*#`~YmE6_JFwn(6ZA z#Xi)QG=UocD2B&mXEUVANE;(P?>BX3@|WA=&9N&PR3%P3R!Gq);q0?-VeArn=EDmf z6}cuyf_A6@@v4g*l#u^|;2ui1$cxY2o^l%pRUcS|{ZM zIKb^VD)>}o_UMbNs6fwzoD%dW*NUQzQWD!)-bNFIEs0>%8+Z;i&=GVGfbZFwZvYJO zWVG>h2ws-=`jAS^W8gGGH0e;Z_C5X90=J@T{cIo;I^P8n%}(tRT^w z%Qr^8j~_qS#(r+rwuRBi2oNUYUno`s3$MP@Or+8jFK*0bl$fq62N+6e=uLjsLB7R6 zzS-c}Y~w0KU3Y{ftpxfpgZPbPyf2dBzOSLMyV`5t<^!ujh&yB*r0uzf4D5#~x;y5DkIMg#saN^Y`> zr2GTCR*?TExxEvzrpOFk+Nx%5tEe;bEn>y_wA>iKs&9*>E!kTJ9{= z>HVnIsD?dA#XXmz!Sys`zN1&Q+TV8cB)*{*H(o1yv1urNqM`11PM_;A-%ay3n4;*3 z{qvw|ToQM*H=v>pS>&-1dI{ab>3&_$K-ZFoQOY zVZJv2TcmPtwgw-5^p#0pt+<`Ry)@)4?@N4#PtQtUAbz1?xJa>))>1(q{`zItLX(=xFlNlDmmY|!3WbEi z8q}AjGR8WdX6>{dyjcfTY;r-fiW)sjJ@gwc5|2PZ0WExNFA8%0WI?)+7BiZORCE9h z=|i8H;U;o6?8|AL(2j{A?HDZ4Q8(u<>*#&j!}my=_8TVj_<^PGSqFK6n?$%L0@gfg z*b#uE%RWmR*|8Zm)~4}1kY+pQ4gm8sKZhN&H(xfjP`2uGu z1m<;b{A&qm-lSEy2K8(%A>`aF8uqR>9&u#>cX?9ZSgMp&87Zp7tH9GyU9Kd6hCwJc zvv2amA7B8w8H-1P#)EogkbnqbdQrKl+;AG3Ww*8L>0~qto5~Arvbl&Rnb&!Q9W%pb5#HD}Y5~<_4)BTYiaRBnWVp6iT~*PRRq3m~`Z@rst?HNF z6$?!VndSW;3zLn7_IW}bdN{rsb7Pu=wyu8&hcC?%XtB$FJu~arxfs%kam|+L$asyZ z*wT2DvUac#rRu&Uhz}*~fV@Jm@76_ds;$#n7|uc>B`81UZ_icqq^U(pL48ThF9_x0 z92P)%1Tn$ExCJNRMQ;>kViU5UqzD>wBy;s4Pe2hUrv6{1Wl0AUP>zgr{FhbrY9lRn zg9T)NR(CW&*ky?mj&de0q1;Ranoe3qIK z?mgT-?ddO$#%l^^D0u~GxK~VYdWZ8!LoV+rRRJ(+dC&nY3VUD+ldMdmx0a7<<}G!P zufOo${nZS-!g;W&4K#jmjVIgZ0pmW~(|8qQ*bQ~#)@m}A_Xb9J2(cc5OgYusrZ50K zW=O0|_aoG?flhJd2oFMZu!EUBA#1B7%13Nc16my)qzAFp4>{o5`&yf>=_Mx{wiIoM z1LT>5p^@hmhZ#yzuUPwt)0T4Pg8D+T^|Wq*+M!x8h;Lf_6(Fb zf)%`n9y-9w(9tBFlzEh8+gEuHxbZus)|k^kDYFPx_e9!!y%0KndJ(d?8hoGv=O}Jl zhb1_`Gt^pTJY`<@sD7DZF!;gt(_;)fksPz{gpuq_;n~DbBwI>#@WD3M3faSCVss3F z9S14p?s%fn$FMsytFu5hUd5qn_~@2GZonclE?Q}c8-t)_nbR)a%$9BX2uC1?&JMWx zCOzrgKIEKHFkS04Wuc5Wd4Si&(AzY$*f~h@h^}0`I44R`*7-1Liep`&1jBrHwJBkN zwZxMOj&|aHYxKVPE_W21)ewuPdA=T~173u!J+JP3Q1|{$ub*fov~VRB%-kn!Ni1)l z`1KlHZ1{PuJ4~RnkL?B!v2`T%8d32X(n8t@ecSO6jy)vTK^uI7?A)FIV3#017D=^R zj^4*8s3k?RGfG(mmK8siVWX5NuUy(T2DF)xnLQY-MIGNO7^$V+xw(5AG7c0?{p z-LCGL$gL$ND0$!O`&>;Rv7H~!w4r^5wK0`4Tu=c)!o=)RCDp6f`^s`dCR_rBT#cIJ z=%$JKd~UMH1k%%2dJpzp z?A>_|zLF8~J_YUulkpBR(mVAFCK<}~O=m9I9bMeZe9;H=iEp~IT*4^@qhHEFx9H(? z{0rOYyVk@Km+_~LsCR5px7;Bg{vBSzOYF$mu<<7n;}=ExSJZ?a;azUx3*E?js_~~4 zBi{#Gnq9g{_e0OPw*nL1ewD_dRl|hWyMK$q*e_qhzR-TIBca_0UqAH4Q)6%vWT(;zN8uaT8}Pr$;?-0Ru3MLmpqROz383Gg%50lImP;syEY| zJP&Q^e^335W~tcCxI7Z=;#vydJhqk^eidwo+Vr(ls2Lbk?D3!Pf+#i0Ake789@j%2 zLHmlNTLh^$bDmi8ZfNVWy$lixa@;1_dYG#A#((lwERpCj@$aj)26m&!D02a9p-`j2 z<@RfSv7oIo1RkIijaRw>-BM-%DQH_bE4N&)H(8UirE(V>t2}4_04N`Sq)7FhjYqhI+IZtr#m{@l_-L&o$^5j+M}m;>KxFl} zJtfJsnb#pKRjf=g-vgjCcSmq8Qm=Z{AT~XzT0X{06plF}q8l!ZkG?U_#|b|-cgHi5 z870lzA%uiSFH96rwO9Va*uxKs4sFDq*rTacCHR4qMqIIDqkWo){dOaL`_esnwX?}P zdee}6=aXoWsc@SbhJ>58kSj#-<$q2m&OJerOZ1Sb%PXu&$2ZVRz{rO{ihHX|Y#Ij) z86H=n6yq*>Vj4i{P!&(BrySY!1VJQE><9jR#xdBKG;p7Zt&u`bS=2H{5C_NE9X94i4v3C@d<;-?k#}oeX5P#<<@XJd#LR_)<=cD8g*!q zC5Z};y*BBWfH*Y4*kHbhpzVIp8(6XaSVEp^Y$M6{=sF|vJ#?gla_TOGZU&~mmx+o0 zAVUcFMyxpgfmr?5(e8hjPeazk+0D+;>Tgl*e=X_1%ct?bB>gR;_;12y>Hnrt`d5K} zlPlojY;Nah;c4){`@^eLy_7bTk-xs_`l2oTX^@aXfAH ze0|)}{Q!Cv5hW8XXbn<8u)uggkEcf+WG6N549-L(HQDH2|7OZi^5&dOHzl69y}_A! zsSb;ZGMyN8hr1)R9XIa_i+ZZV-;0T2t#*o!#S?#yi;kQo`XDsC`)A8&*V^r%?>+o5ks>l z+>eV@@?4EgaU|uZr8mnFWNQ6j8|fPWuEx;NYPl-Q-90(p>_?yixS7{Xjv8%0l)>9C-&P6l6M#gU|&p?!_+2?L~7cqU1IY# zIDqa31tlVP5OH=P%1EiQuv%e^Nvn4!=k?j1+orA9d!sR{71wZLj{x~5%OnGsM1U7r z?V6>V0DB49JMv1{yJiQBTlt#Ew*Xj~0t1AvkR0D7$}q3;{^{}ILHDNNL%#QSg9QbE zjMwpb(m4M`JDJ41{)HhEZF+^=bx4Qyyn%2R0=9ornu%po1}2RRqo{xmdiq=dMblce z5k($;=^aSa(#q|ZQWC^iq&5a`PRI`On$84CxE^Sh^(k|HK!fWFLv?`;E zq81Vbmh=m-^kS$v`qU~QMq!5V?|CQIXSfWcm-d22>5tf7oY@Tz*g{}Dy_^c6YH>gL zi8gKSxg%$?Y$0FuN)~}<&&-oLTJW98{KPhmG#B$zKgmuMK$sJRkqYjSl`LF1cZN{z z0Y0Owik+}OS}{+xNg<{dyP{u%X@nb%&)Y7^O1%O=;S8m3;iE_2pE|(?2g27!w;xxn zgN0KN?{n50R&mynjtSU)3Tz)%xYIPgz^xu6ycnMsg%0V>BB@)iiQWO`+7cY@F3{Em zV_T8*6Wzc2&##*ox_F&~z|oN!(Rr{7A;FpPWI>Uf@?`k|Ta*tA4I9-%P#cEprap8p zX9vOAr+gkAbIGYY>!-YH7iE)Z7m=Ni9FW6tW70aMcKYBfzqj6Ys2?&M3?~)v~QS^Mmt=KKS`;~8T-7@t3=FCsuA^@z(9tV(v`D0KsVjhoMKMCDeZI=vVglQdeY zKdOyHdnF-%YLn$m16Q*Wgk^2kSGXSPOb>sG7d+Ulu4GU~HYC#l6;?T6qHH2@HIumz zcmyt2G)TCzXurpF{bu&2;wdf}PiwHg&hU`Vnbx)FoxM)=^q`ki)W%)^k#in9S3!6G z33RGGhO;q_KP|7jV{)wKn7q`NQrylan%1)n{ z*>EEty}Gb6s8t2L>GTVOERl;xBR>6y!wPndfO(I%g|aO6c4-RM{Byb0^+{|QEUV{g z2jb9AVz(lzXob%3qq)t4a#5;dI%fB0DadWH>71c=75ORp?@hZi5bk28W%*h2&9Z|* z?0S=S8QR}+VYMh`exa;KTYu}DJs3+Y))fyn^|!YeCun5TnU|fKPT2)Q+Dy4E!PgD) zT%m_WVjl2hJBeVVj~;chsLv19WpUupXLnEGiL&=?E})9b_1iz#oQQUVASi?7e4Ir4 zDFur&^a|j%Uc`D!@C5sh@v`?2kziRN6H^7yk+kKkSN4eK-}8~&KA4h?9*mUI$3!?* z`b0wMC-=yS*+bLV}JSjG8M{cirzuQqR3RoG3XQJJL{Ydz}&Vyp$*7drx4>M zjbQ`O7WJS2rXk#X=h^qoH;JE4%#T~RzcOWWe-#pR`zq}F^ufIbl^_NhInORL^oj&p zm=5ycbG0O2`poBW-cuZs1AW%R7W^gIQS@cf!hyx7!hxSpMeGsegQixdpBk>MsiZm# zMP!*9NI;wuGo%nWy5y*36)@EqLHcA)%kX+Af$g7X9MD5_(KjmbpD^{h?ONhgaz0iY z_C3gk8^ab3FrSayA!D8N{f@C)dD~(U$&f5nr0BExEs0tVLfY%vp2>u>r6Q51vLA*v@Jc3%TWV8h(l!A@*!AEGru~q@ZS*eF=z?W;V z=c)f%!ZiLJ2`K7fZtQ0Mj|xWqj~_K}r++RsG^$;z&g-BG zq!!DEEB`P-gZcTaq>5>Zl_L}(RhFz7&46wMx>ePw2Ex-MQgUB+t7OtRW*6*RzEclx zHWYmQ=@;a7N)Me^?2U=E(rC#Pelk*&blSITTM^NS+Sq_>i$kx{Bv-GH7p9p z#10x$eTU{jGmn7`fT-A6qJSHPdu5+pVl`zRX!$9gPqyIv;u(DnQ5+wm12Kb;p7!d7=1j1Y#VL@nBJZ$)6V(C1Z% z-e$>3QI=?OVX%whJdFS{e3HgOU+PBqja5G4TL$G5j)m7n<+t8o^7JANHAnaDdWoVrSFf1R$-^p! zwzy1etW=kiO+$?D7tb_*iU%=|8gAEbH16%Ge%obN4;i-wC9k46a0z=f*bc8CXCJ1K zNTB~|2@@iA3ZJ2<`)$RCYX9K(d5@4JP{>+-unS@@cHbpcD74EOCbIt-sa&w=ebu>pvu_g%i$rcv% z3#mM2bClL**0`5IQ*kr5oC>HmraQS47uoz0T#9&H`}72cD!%>^M0u4Kuo&&!&k$+A zOcfJm%;5P^pqXk89EC?*t!6SIV6|eD(CiWg^*Z2z4dWZZfOF=6wuolgidb_Czr)}! zPVW{+H``rC2@A7SR06_#4aro@k*s8ict_1Y8zHvN2Jy53JKY9Jc+g_PO*V~C^Y zMJPk$5NHt6&{-J@$;~9Bcp}JYl>x>YBTym)B(5TQBdP_PilUU*S4&bTVzOK z?OfV0>*mNfjM?22TXm^GPOe(yz%jS#hL>;UDOPFlfX4#RiWYcaNMX3DZhJE>N)Do|@aVvYY2cDIP~*D|FD?e1%c z)>2R&dNUizqGt^k(1i8Um=_7hE8EnnTgEybN3a(Rpg32qL(Q(Wq@C)3H9al2T4{Dp zOmE_Fb~b+hbc{yGWL>IRt&!QQooe~x`?f;ms70*lqyjc#+WvEahxdj@*!^(|C*HIy zcBp~2i?jXX<+8xS&Fop*lYI~urJcWsmMUHoMfwZvl$eE0Od|>Y$Km3OAUZ;YVs>^t z6Ky6hL7Ntvl_Fz*X*FL?RF)s*L4hzpX#0j&3chU&G74l+BV~_r&EU<76tW6 zcNtD@Eh_E^zjpK8mhCI9RU$(c2lTnk_K+_)W&`~w>qK~G&GYeJ`^K6oICl%d&)#ZJ&hsvqSTj7V__BPsg&B7c1P zK(t)LsdeZqs@X<#{`82qe_z3sjS{AP>wG=N)DqyXG0k3;ZNlhX1-oEsYnxxTz!-wY7e?f>*QclcUdXB-NSv#JCqp)92j%t~~X2M`n&|a>=Oneh(Tyzt-RfD2Y@vwCGJB0o{nt}*^LGR?e#)EHxI*x_eN5kmMIZ9eLQPTXf` zWoz}FpF7ie9~_Q_bTboH4>6}-GCLKVoA?G-Z!v{V?laeL@)$g1=K2ZDM>y`<4tT6` zO6>&-jXAs#eWc|bq3*av7{@$c$ApNbT!l-hsTyIR6Utzq6Hj465+)JZ@lY6uGwn)s zzh>LPG4)6d{e%${6lbp5x8wj;F{3ll0MT?zHM7{Y$bT#JEr5W}!c{4IO? zO*=gsb@cUj;6CegK+e)q{!)k%{b5g9z0UdXQCyu#;%W072X>AtKzR9TfM=B+j84D-c;{dzh_$MJ{0f z!T4jReSWw7Lu0U@N4@`-lXx-W)8{&ZKm)-3_Xyz{5j3TQTsT_HVL!}m7y74rx`g8b zsaNVb!H9-f(#ya8rVC(B-YPKwzn!cY_nnYL8T5@{459V4WH7(L7346(wy+i&HGG+( z?;l~JVy*cAlazFik*4`oM31N!o@geZmDE--OVaLvpy{E=L^m-fSbWJTi2sI=v&3XM zq9M$l_4N8&ak$BqlUnsuE7N2I<6XGc0d3j4;G746X%E)XjZE@|)FI!CO6#k>#1}1%lDw!4(!w zh33bY0tims4eP^!#_Y7iB=)(7(z9q^l$URf73Glm$IjG2eK@)69UVLBw0w z9Hgzprl=fv1L|U*p-N}91hunfK!Mz%@)k<($(qzfV{0XTE8Aw;U)tD2BE)Q+86pHX zOQxTvJQ)+;j@OTwK2Rzzv4r^&K(&yjR=CidoD3&{YxbF(>L)R!;_RQL-V z9TZ9tCY~-`tY(JQGt;bB4n};_9dZR+?m!^`VEhm+29Me#uqz1p;&3rPkYa=D<^u}u zUH2LU6vY96KY=*(J)TS5*MvV6U#LdKdtzq!mpSXidlQM}$!6BEg*=e*5k*LGfaz-6 zeze4C*S+;fx4Y4(X^rF518ed1IOjCR_Bbzget|O!IOQQMB~K!~ml={~tj^24~bqPSwKsLJ}!ZaGtT4sQ6fCAu>at77!` z5WDgNIdOnL(b;w)seEOlT_p2ANE4MHVu>Z(&q{csm6E5Z6A&1QMPg}&oMM8aD==Oo z(Bv1-`CTAFEg?e5i{xgxW*g!6ncOUe@~A?v4|`K|9^x?6<`w1*>nPk@N?@hsN@oB# zCx?!(8EVf^FPuI(lrK$jUiBr01q^@YJm*?k<}V5(Al>W>a%eqH1V|m#Wj#p>?^3nJLK4x=*YxT}`I@8@Wcaz1^yoESm!k6a@(ad=q-gFUQ%>elqUJ94T-NJj0w z&qnPU0d zcda)G?kgktO!kAY(};JYDos$dh9YwbYQ9Q^2%w@%xP*=*XEXi_1RV6EeURtYAAZaU zx#yo|b`qnS-z?6Rwv}inE$S($Ny`y(@ON-yPi2=;(7GQcoE+J;C>$w)Rw^o6S+ERK zW&upsaW6W08S)VD7KuF^F{Dw&w3A7!`|X2oK$O3!;gUVXYM}LgPza7ML@N|}f?t~# zoAXK8a!ZiQEN<=P5G02 zb#boHShTM<>?;cn-spURa>FlXql_BNpHocW-`85!8iTJG zGFL>Vu?v?^nZkS}-Q0cgYir^>XDVoQxmPW)l86KTB&|~T422a>R$SiNv_#R7Y^&?p zicczM2T8rfJe99CN52JcXuj>FJhlvrFkEu|#o39GM~IwYxN80vWBjjhRsQebY$ZEm zZ*vzpYuA6C9#yIR;~uA;L4U0p=JO{(udtdXqf`;)LO78{Xa)vpB-lR<_EhfHtMVZI zxPYQ?5OFy8Re&)s%XUoa1h{nhUsD^ckC|+)*Avr*+g(s2#5kV;`?Qp#O3a^zu=t}$ zVe|*hFi8pz&144Ms94cLSjdiJ)%Z17D)z!7ctB2rR_tREMO~9KS=;O$fKB%aP&QX{ z7Cl4iM7lXRCl&DAbokscNa*)d+=o}7D0RanJd%*H>8D=*K}rEr`_HyhB{OZHiDG~{ zEw+oGrbl3|=zXy{FCrk&%Os2Bdwqr2TrwAffm8FCUI)t<(%r*>{alL!oa&UH<;=5D z!ro$cg3``ZHN)8pp0cXfJb$xi706y~8E@zl&YK6H?Z#f8QWoKyr+aP z|2k*`Rh%ftFEYoL0P0h*3XLJi@USVQei21{zGO+3DN#+#KC#40`7v?xBGg2)Ilr&M zjvqnd>KueM$Lo6AkT2_2JI@5MX?$jR_UlQ8bel0oh7gr8J`{Sp&a(x;w=P#V3n|gK z*5u<>u(iwC>A>Q1)HZ{3CavvJ*ZF`<+X6zyQ;nSo_{u*HHv@N~a1~5}l4o~8c7xSB zZSX++#}pHy4*}f<$8XuXn8Vcxiffd0qc1L&>$65R&4nr=$$__zq8V+~gmKhU+VyBf z9HF%TXJ)6b$S^{vctT&xdpzA~z1A7+W}rS%3d3)2hurKQS|!DZ%HZ`A=1}iD^0WYXqEDcQav+K;A$d|E}dwZZ*sRqm5-8B{4&H;RP+ww}t%;1A#JQHi&O;uR7=p znp~Mxe?t)NE}puRVJ{R63f2UxSfoU&9&JcxHmH?}0k6wP9^E~S&d^y$Z*FQo_iF#&m@~g57FX5Ti zx8B$Gfqc`^B59E?cIb|?PIAtde4}14Q&N4LIh1fz+F#i)_X! ze-0Hlk$q_n-(9+0H-@7WlZ{7jZZU09bJQeFtIta4QmJLY?NHL%6;Blr?HinN9;xly zzRjm1Zo@zlE%cBD*)o?>TrsLd7k|hkA1ZL$p}Nv08S<*VK>3>9EKo9Xogwm?-49KG zN|u+0B8?=#U6ZFtU*as$PsU%|>!{StJ!bvAzXJrrZw%zCzQD^CS-z3`YWAMzI_GOe zoQMldsye_`SQ3Z=#J=xuuryo>$*QXZL9q(VvPH230`|RRZ9C~&!^nciZ@!CP5`HqO z{GP4})3Mp7iJd#pNCZ~13(Ii&NW##ZHs1)T1Ks%1sV{DtfAPvYOOmCF>*Y2FP(hxE za0Mw1J_PO3`_VvhO9rIdwq7T5%31m)^*hB^FHw_;HSskERBNTFsJDZX6rYNIWZ zuRNCZ`ImoPDu)ncCo6Br`JLVa?X=C<$K;uNFjp&eh7q(L)+IHpwg!9PQ4hjTG|z_e z!z>HGe>hJj$WkZBArqPS(?ThWA4h@Eq$#MISxAy^&+aJt8k6#X(*Wz#T(S|u*dSgldzcD^xuij=3W=`$@qtN|t#Q1+=PIcYCE?M7-t2RBfQ6q>A zP#Z}*iEYsubp{Z(7;-gieOc#OX%O90?L3vib~h{mnB#lHg}a}2iV$5Tv4DCsk;#*K z?R#u@Jl>2#1RWg5nZj`N zrvz(Pa3{Gf4vm1edO}||8_Ik@x2|-dRj7}fslzg+-DHcx&TI=)Gt1Irb2m~xHGlC2 z4yfp!yDNlFh8X?F3akIQJ66ourVpF(F)X^X%x%`$_Q<8bHhERVTwBfjGg_Gm@M+N9 zbF{!{!C#zik}Q}qJF=Xq0J(_Qr_6%EC6?`kV>cQ82ZgI1IVv9wmD6t$bMg5_A7%`n z(c8`P7Kc#_l=pH|j5-cjY^UWOfep)%cY72- zQXJcjFf7e)(Zhk~12IPMcbR+_msfLnZq{;7^f4>X^Gk6?C9~Wme=kFjzt6D)qF@nX z%^1h_ODD|zVzqR0McD0jK)G&p)<+?Q#C10l?ky6Pw)ts|@0tFr?}U9n&M`hKYx27< zSw(#0Euz_n6ZjYmXUqgb1u>T306w0a!tE0Onb)iM6PBRdR^VLnlR8T-A?l!d0(OPY zJOvOX>^R7x6I~1eK5Qv;`-GUONuwWf5a%{!woQ_R8}RMMR%}SI(sa4t(ku7?bL(c0VmA^Rw3XL z5b$400QbKf=qvm?;`uLPS2A{Wb+dADbhotnhuv*de^tfM#C&t8GfOqcfwuB>Fcdq!4D(&4mTc; z%;dhu^kmi1LAiS8c~x=SYOFOzJn+pqrrpa+wgo=tb~YYDTdbBnr@W6Fp> zL6VtIH&0Gt}w_sb`%I0*Q-C%J@^zZ{%GqsY10@4x^BFLh44v!rNV-z z8a5`6N4OHi(CT71r`HVa#2fOYXvodsbr%fU7|uQcn7QXz;`Q)K`DlN$&ER&;UtiFrCH7XV&GNe@)b(CaAbf}E4uC0<+jfUw z3K2j-%=sgN14{8$PJFP()tCO}fLaQNw}a$f^z2t!C0`vG5nG}{mT{;BlzIp1cRq>Z zjVUVFrCS=?oU*5l9-OCyY7>uQt;|*%LbNO8?1~=YM{|h>xTGz?S5p0_pUo(`_NuK9 zvIfU*em1{|)=6U35j&_QjJ|K__mx=1LD`~(!6E)sxOT5vZ6fqsbz#tbfyCMK4ihj0 zY1}g@BvqzDKAy`{d{7i)PB@V2cMVE#&p;cYqLjN@S1`E@c&^L*gQ5|J`O?AJPlEb= zgwRYG6pWEhjWabrJp)wXj&`Odw{|+^q8qHom%-asnuAWf2;6xt{wc7QMh=sM?Lp#? zu*o==4v+GYS-b*`X9wMdoQIp}V}Rn80QoRa3v*|*+U_0aTqxbT5<*F`{ev4@jH<#+ zY)%lp4@*cQu-H9BI2NQXqg>pAU<(t(Bx0Z5pjN71tTC785t^<%B8bt{W93hb_+@iV z)WQ$P#+$bS%U{CgV<%H_J#X2m)FqkvY9QLB!b~-lTEK7o6?iK(uQ0F7LLo-KU~aP? z1*6U9*G5)2{oN+yp^Tb7 zK(F`&MMCP-fPVQ;%X=;qda>ilrC%&$j}cat$F}UL+9vw~*B7=oj$ZSYqlNx18O1aw zP|e_yar$3M2I{}O4ES%g$D|!p+#UXo_#kKbXM0TTTmj=VP(YMUHzipX4ZL<*)?%NW z_cbVpI?09Q5S@~x2R+Yp9XU)q)3ZMqla1e!;RI%F*^uNM+TUy_aG=SqQL`n)YM8ASHH+s(ArL8h?hyg(!o zlNpU7Oob&@J@01z1VBt%g%tXA4s&yPFFp_L-Xzc`IolHnyZww1J@0w=WJa58k8 zjB$wKVeK*l&PRXq9Qn75zmqCo`rtKu6vZFK;{S#)&76Nct)dKNnUG2Xib1^>nBUXY zt%zJOB_jB89V@rD%~~QUWhT=drZ2c895%=Llw(9g+g7Y0kPP+md=U17XZp&g(oLr| z8rI+N6r0Ni8hseNLzI=95a{j>gA;Bri~aJr1Dn^$o>AcbwY2O3=f?tzj$mk}Af9eG zhLhvmil%8EQFEXZb}0)ug-t=f0)fKp7DKFy>_w2U+aqKNgZk7fit^M8KYCcHJHHdA zY}&|~!9C>M5|$4YUY=s)fI5wrZ9);rbz@L~71(R!&NkG!P=QSiWlIj^b*Q(#+rsZ~xpU3r^_xm#6 z2SZbDR4QlfejuZD3#4qXI#wcHv6FnksiT^2#U3BlGKX(05&MCYXm2cSF$ckrJQg@R zwJCxRPh|vUml1*X%6eq4E9fIa1i~j)K*+d9T-TTqbt`Fu1w!I7Wl5!sS_ND;#qXXm zz9uKpbA^UBn{P{%Z~?c!)oo*zHQ}?}#2=jxuyvrv<9qR&Y`@I|P$sgqGPR7P4m-tr zof^#AO*nNb;Je3ck*%W=G>@ksAMJS@=u}xLU^`FR`lk8#;h>SOA4$_6FwIx4B^mp_ zYv26_HKKb}|NNnn&9JN?)=5~c#v0`Y!)%4cba%d&%@9oZJTsV#wY8UI+grtFVALLs zi^ljR62X7Y8J2=DXBXTlAgrfm(-V?XsnzGndW1m{=P!)5;q}#jLO62c?=ywLB2=GH zeHu3)J`P?1LSfRMcmTNqY3a$e7uAmvxpLOiB(8_=aGAJPe`!a1f5 zmv3Q(5+93?zqx?uN>58o<9A24R@~v}(M-S8Y6o+O~6h4WO~h zm2_O6_OUzvl7FZ6R5hG~WL8+KCzqesvT2a}h4N#9 z^2I-r<+zlP7+|&NZ6k?+DL4#6oKnakp@?VLWdA2352(H=@~&H$Z5}O(4_paK;7~)a z8#3CkS#U72LVVFBpqxR&bKJ990&exxRvIg{hwlgMi4n1O2jh~ZAw^wDa72hM#3cHr zba4+Ulb4CGTuEqehSx$DGuGZxG*mi?g9HU^`6#*!8z}-3*Vi`2t|LV@^$ka6=23fckL;#t!m#E&n~v+kYyI|T za<$m%j8@fEQ#eD~Epf0Wtip^nM7i=2vTeN}_HpGRq-?b$KqO0F75Wi0$`aEPtU!!H7#pl+;ma<= z%wGu4D$_gx$JA0jYd${D7?~d%)D#3ZbflNf`XrzGPHPk;G2a^DxeS*EDT)%G+^kwz1oW*@2>;`xYI_|XI#LoXSaJC-u~tn66C>aRF0Te6#B4DTN!^t$RJ zkfjs6o6UH1QyPL@_5UF^Lv~otwH9eh_A4yB64UeG$mVbWojzO1=B~|W2>0^Fe)gR$ zjx*#bCwZ&_9fe;nN{ z4!Bi1`T|azbEu|QR`rX!+9FC{=(bi+4>Qy1rnk+NkUn`=w8Dgv&r?;@%kdY);=kyu zSB^JFW9z!SZw9ChNj+!j=v7;nkKIy%=-x~Ly223$+FfZ zV*mMtO{-484;uWm2mzXoq%(@?gHmh`n{{S7yVFO{QMC}IKm(!Bk3ORxnZvebDDcKm z{{a&7?epGBFi4R8M?k{yzd!?V4;1s61N@gftZF((`tWg3`>zf9Skqb{h< zZIxnO9}sJv|26$DX1Secnxo~oE3oF}b3NkQZk>9*y+8N-kT}v*fQX_Vf~L+AC5d1{ zGN4W#r*;ce6am5qj^CF?5D)P($AqI&ssoH=dKRuzT0|urjd1 zJ?;IR=@b*HdPFminlg^lp)%_9+~y>-q7d$Q7K+|WmlO4KseW!4I)kE*r=NAh8%z=4;%hj|x4izU4zk4axzQ7a-bAqAnAnBse^3v)^ZsMIEO>{aR!pWUgccLzjl^^- z(`$=_C^aj-dTeC1SwAX^6e%S;E{l-DQAsSCR#h_hBZ6x|P=1tAR0}jMze#&1(+9Mu z7Rlnci@C~tN>ey3PNQ-Fse#>D(6E_$&A81G9W9ppT@&?&{5&1rQo6&bcv@4Q7QgN{ z{yWEKBI2{aE7+>u8HK;-C7%s2T-T_k7E*sZP6|>mJZc4vHaD?GE*O4^@q5akd~r-i z#9B=>^X_eu&l?}IFRWK}Ei3lIZ6;IYc*=oRDtxe;wDI|9@)I7zzkX@Uztl;25^U7; zPu00>kV%IH(({a!tb6;6pMO|2G|hB>>?FS|*yPVD5|bwv3Z|Hvxtkr{$Zd>f?xB9M zzO2Y~!hrhPooE;3-|Sp6rXI9c@WcbTjp~~d)sUTkNg%_Do-fZj=a29cKxmlTNPG)V z@5105F_qq{0Bw~eoOJXKS9}JzN9-r?WRZe}!pvM~kNx<7G`A4DmvRl9#3l;=TcDNu zroBvpQ6%?2f+EiUK#{HDyb{nK8Q+aAIhrIQpB1KdJ;^1p-Pb5B;uO{yG%&z)$&G9N zGbytP7?2VklsZ7P6U*9li7l*0O0-m5BH);F-!c7#=Xm-0S_p#Pgf05>hGrf~4Y-AY zC0BH#G|2v`OiF}E3}O&W$dor)y%;cT2mnyvPS0(L1ukvzPM~tt1jEE6{?D0eSMP}; z$0Yr4kv%I2x(rmzHvCUJqbaqv96HdB-A#k%N@_9iO$s6SF-}49pj014AmSImXkGI( zE^9HF7lW^(>+?{Ze%*mwjdAOj6t{fu;qOu4wnkIvPThr0*R=IZK8{Us3Uyxy0H*)D zgHN3`!Amx?!J?-P-!BqJw*v_Y&}{Vw*v6~Sy51bV_?6jlMhoOB(@2x5FwpsPjFpDB z)6ON`_r<;ai2$hEOr(l+eWL;MXWpDNWC9V%KQl3 zpdU6{Ipcvm60k}w*WV~MZ$$+%KBQeJHkFn2k7Cnl(p#o<0J)&3DT5y+@#$Ayy!e&y zOGah=ptl;IlTf)aWbq)uScU03PMqYe;XV_pxpSc`B6DGQ^(QG>#{LF}?2>$YJ*MBb z`3k47SVq3C+!#^X-y*F@=@fjAmWlt4wJT=!uHfhBUM&==k0(bGWIPu+C zvUL3(%vj`>2>k5l`0Gjs=Wu@P(Yy!_en-Rm2nR*K&l}CPMjf?Bi5eho7j?z5apu%1 z8W1%WAino8!BMvL4FixV@(fZVipc48Io*R_a77W7nrV@!Ja?0D(7QBl3?CIt2=0qF1d7TgVlTU~FpYSAH|MAJ6gFOjQK$eb%#DxY& zSxt$yxT+4UuEg?^B2^hhLvaI&%^C7Yj5(zVKaJzUEZ`FLd~^AopdnmJCd8ZN;4z&o zu>BvN#H0wuUaHh;I4(jGsByy$t1pfYj?3f^-?avi(dO?|0SC3fOEsTNM0yK@ED^HV z*uQ|sPC)aKBfH((#*4pc<2AG+4vR!TyH?Kli*GMes(fq>;&lPpxbHl5O1QzF$~E1t ztSVG{5VWQI`oj@W;{ilX=?ToowbW#8IF{3`eEkSRvW*K98Rs=cgSQkzGHIj_Rq$B~ zuvTu5m{to|#%j=W2;mB+iC`x6%g9rl=BXQa)E_=_yvIMs5A{>7Y{mZy5O9YF*lgXJ zE7PY1)(fP{M_u4!1)EH+iH|$Ww>MCB2v}-@`+1Duex8_KFCr4tXC2q&zx#R31A(e& z>MC$5t;h`fQc{0)^o$k2yy3{K`1yk8A0544K|xUb2*wI^S@Ujx79LW&*?W8iaf|%{)w(*~M zfded3u@-!#W=4dBz3%zV4dHM4CzK7}EL- z*hNO2g5;3s_TQ+oPRSd zzhQ(=%05LF2opu@+RH4&HsOr&IBEn9wcGlcKi4s7>xE@VWW7Wl#Nz~37oL|i(;%;ke?Z))~8JY3Fd*J_s zjE1h}UlTJ0^fYDwWVljovQLpTrb%2mYPktQ5XdMzsI*EU!5Rq1#+{b?;NQLS+W7`) z_%c(yxRSvgje`+67#K9Ti|nIh2_JWz*EH5>VUw_g`R$BO6u=nc;_Vs*4xfnGfdcUMhI zLRJv%S�*y4H%1!Y*Wx6hABn6mnHd7*g7AD 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 z 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�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 changes; + + /** + * Server Edit Event + * + * @param player Player Starting Server + * @param server Server Being Changed + * @param change Pending Changes + */ + public SubEditServerEvent(UUID player, SubServer server, NamedContainer... change) { + this.player = player; + this.server = server; + this.changes = Arrays.asList(change); + } + + /** + * Gets the Server to be Added + * @return The Server to be Added + */ + public Server getServer() { return server; } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + /** + * Gets the Changes to made by this Edit + * @return Pending Changes + */ + public List> getChanges() { + return changes; + } + + /** + * Gets the Cancelled Status + * @return Cancelled Status + */ + public boolean isCancelled() { + return cancelled; + } + + /** + * Sets the Cancelled Status + */ + public void setCancelled(boolean value) { + cancelled = value; + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubRemoveServerEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubRemoveServerEvent.java new file mode 100644 index 00000000..6f644075 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubRemoveServerEvent.java @@ -0,0 +1,64 @@ +package net.ME1312.SubServers.Proxy.Event; + +import net.ME1312.SubServers.Proxy.Host.Host; +import net.ME1312.SubServers.Proxy.Host.Server; +import net.ME1312.SubServers.Proxy.Library.SubEvent; +import net.md_5.bungee.api.plugin.Cancellable; +import net.md_5.bungee.api.plugin.Event; + +import java.util.UUID; + +public class SubRemoveServerEvent extends Event implements SubEvent, Cancellable { + private boolean cancelled = false; + private UUID player; + private Host host; + private Server server; + + /** + * Server Add Event + * + * @param player Player Adding Server + * @param server Server Starting + */ + public SubRemoveServerEvent(UUID player, Host host, Server server) { + this.player = player; + this.host = host; + this.server = server; + } + + /** + * Gets the Server to be Added + * @return The Server to be Added + */ + public Server getServer() { return server; } + + /** + * Gets the Host of the Server + * + * @return The Host of the Server or null if isn't a SubServer + */ + public Host getHost() { + return host; + } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + /** + * Gets the Cancelled Status + * @return Cancelled Status + */ + public boolean isCancelled() { + return cancelled; + } + + /** + * Sets the Cancelled Status + */ + public void setCancelled(boolean value) { + cancelled = value; + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Host.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Host.java index 4c1c793a..ae6574ce 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Host.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Host.java @@ -76,6 +76,7 @@ public abstract class Host { * Starts the Servers Specified * * @param servers Servers + * @return Success Status */ public int start(String... servers) { return start(null, servers); @@ -86,6 +87,7 @@ public abstract class Host { * * @param player Player who started * @param servers Servers + * @return Success Status */ public abstract int start(UUID player, String... servers); @@ -93,6 +95,7 @@ public abstract class Host { * Stops the Servers Specified * * @param servers Servers + * @return Success Status */ public int stop(String... servers) { return stop(null, servers); @@ -103,6 +106,7 @@ public abstract class Host { * * @param player Player who started * @param servers Servers + * @return Success Status */ public abstract int stop(UUID player, String... servers); @@ -110,6 +114,7 @@ public abstract class Host { * Terminates the Servers Specified * * @param servers Servers + * @return Success Status */ public int terminate(String... servers) { return terminate(null, servers); @@ -120,6 +125,7 @@ public abstract class Host { * * @param player Player who started * @param servers Servers + * @return Success Status */ public abstract int terminate(UUID player, String... servers); @@ -128,6 +134,7 @@ public abstract class Host { * * @param command Command to send * @param servers Servers + * @return Success Status */ public int command(String command, String... servers) { return command(null, command, servers); @@ -139,15 +146,28 @@ public abstract class Host { * @param player Player who started * @param command Command to send * @param servers Servers + * @return Success Status */ public abstract int command(UUID player, String command, String... servers); /** * Applies edits to the Host * + * @param player Player Editing * @param change Change(s) to be applied + * @return Success Status */ - public abstract boolean edit(NamedContainer... change); + public abstract int edit(UUID player, NamedContainer... change); + + /** + * Applies edits to the SubServer + * + * @param change Change(s) to be applied + * @return Success Status + */ + public int edit(NamedContainer... change) { + return edit(null, change); + } /** * Gets the SubCreator Instance for this Host @@ -219,14 +239,37 @@ public abstract class Host { * * @param name SubServer Name * @throws InterruptedException + * @return Success Status */ - public abstract void removeSubServer(String name) throws InterruptedException; + public boolean removeSubServer(String name) throws InterruptedException { + return removeSubServer(null, name); + }; + + /** + * Removes a SubServer + * + * @param player Player Removing + * @param name SubServer Name + * @throws InterruptedException + * @return Success Status + */ + public abstract boolean removeSubServer(UUID player, String name) throws InterruptedException; /** * Forces the Removal of a SubServer * * @param name SubServer Name */ - public abstract void forceRemoveSubServer(String name); + public boolean forceRemoveSubServer(String name) { + return forceRemoveSubServer(null, name); + } + + /** + * Forces the Removal of a SubServer + * + * @param player Player Removing + * @param name SubServer Name + */ + public abstract boolean forceRemoveSubServer(UUID player, String name); } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalHost.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalHost.java index 25add58c..97846799 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalHost.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalHost.java @@ -1,6 +1,7 @@ package net.ME1312.SubServers.Proxy.Host.Internal; import net.ME1312.SubServers.Proxy.Event.SubAddServerEvent; +import net.ME1312.SubServers.Proxy.Event.SubRemoveServerEvent; import net.ME1312.SubServers.Proxy.Host.Executable; import net.ME1312.SubServers.Proxy.Library.Exception.InvalidServerException; import net.ME1312.SubServers.Proxy.Host.Host; @@ -16,7 +17,7 @@ import java.util.TreeMap; import java.util.UUID; public class InternalHost extends Host { - private HashMap servers = new HashMap(); + HashMap servers = new HashMap(); private String name; private boolean enabled; @@ -102,13 +103,14 @@ public class InternalHost extends Host { } @Override - public boolean edit(NamedContainer... changes) { + public int edit(UUID player, NamedContainer... changes) { + int i = 0; for (NamedContainer change : changes) { switch (change.name().toLowerCase()) { // TODO SubEditor } } - return true; + return i; } @Override @@ -141,19 +143,29 @@ public class InternalHost extends Host { } @Override - public void removeSubServer(String name) throws InterruptedException { - if (getSubServer(name).isRunning()) { - getSubServer(name).stop(); - getSubServer(name).waitFor(); - } - servers.remove(name.toLowerCase()); + public boolean removeSubServer(UUID player, String name) throws InterruptedException { + SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(name)); + plugin.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + if (getSubServer(name).isRunning()) { + getSubServer(name).stop(); + getSubServer(name).waitFor(); + } + servers.remove(name.toLowerCase()); + return true; + } else return false; } @Override - public void forceRemoveSubServer(String name) { - if (getSubServer(name).isRunning()) { - getSubServer(name).terminate(); - } - servers.remove(name.toLowerCase()); + public boolean forceRemoveSubServer(UUID player, String name) { + SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(name)); + plugin.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + if (getSubServer(name).isRunning()) { + getSubServer(name).terminate(); + } + servers.remove(name.toLowerCase()); + return true; + } else return false; } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubServer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubServer.java index b65bcbc8..2dfed2e4 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubServer.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubServer.java @@ -1,15 +1,13 @@ package net.ME1312.SubServers.Proxy.Host.Internal; -import net.ME1312.SubServers.Proxy.Event.SubSendCommandEvent; -import net.ME1312.SubServers.Proxy.Event.SubStartEvent; -import net.ME1312.SubServers.Proxy.Event.SubStopEvent; -import net.ME1312.SubServers.Proxy.Event.SubStoppedEvent; +import net.ME1312.SubServers.Proxy.Event.*; import net.ME1312.SubServers.Proxy.Host.Executable; import net.ME1312.SubServers.Proxy.Library.Container; import net.ME1312.SubServers.Proxy.Library.Exception.InvalidServerException; import net.ME1312.SubServers.Proxy.Host.Host; import net.ME1312.SubServers.Proxy.Host.SubServer; import net.ME1312.SubServers.Proxy.Library.NamedContainer; +import net.ME1312.SubServers.Proxy.SubPlugin; import java.io.BufferedWriter; import java.io.File; @@ -19,12 +17,14 @@ import java.util.UUID; public class InternalSubServer extends SubServer { private InternalHost host; + private String name; private boolean enabled; private Container log; private File directory; private Executable executable; private String stopcmd; private Process process; + private Thread thread; private BufferedWriter command; private boolean restart; private boolean allowrestart; @@ -33,12 +33,14 @@ public class InternalSubServer extends SubServer { public InternalSubServer(Host host, String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean hidden, boolean restricted, boolean temporary) throws InvalidServerException { super(host, name, port, motd, hidden, restricted); this.host = (InternalHost) host; + this.name = name; this.enabled = enabled; this.log = new Container(log); this.directory = new File(host.getDirectory(), directory); this.executable = executable; this.stopcmd = stopcmd; this.process = null; + this.thread = null; this.command = null; this.restart = restart; this.temporary = temporary; @@ -47,7 +49,7 @@ public class InternalSubServer extends SubServer { } private void run() { - new Thread(() -> { + (thread = new Thread(() -> { allowrestart = true; try { process = Runtime.getRuntime().exec(executable.toString(), null, directory); @@ -88,7 +90,7 @@ public class InternalSubServer extends SubServer { } } } - }).start(); + })).start(); } @Override @@ -157,22 +159,193 @@ public class InternalSubServer extends SubServer { } @Override - public boolean edit(NamedContainer... changes) { - for (NamedContainer change : changes) { - switch (change.name().toLowerCase()) { - // TODO SubEditor + public int edit(UUID player, NamedContainer... changes) { + int i = 0; + SubEditServerEvent eEvent = new SubEditServerEvent(player, this, changes); + host.plugin.getPluginManager().callEvent(eEvent); + if (!eEvent.isCancelled()) { + for (NamedContainer change : changes) { + try { + boolean running = isRunning(); + switch (change.name().toLowerCase()) { + case "host": + if (change.get() instanceof String) { + InternalHost oldhost = host; + Host newhost = host.plugin.hosts.get(((String) change.get()).toLowerCase()); + if (newhost != null) { + if (running) allowrestart = false; + if (host.removeSubServer(player, getName())) { + if (newhost.addSubServer(player, getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), directory.getPath(), executable, getStopCommand(), running, willAutoRestart(), isHidden(), isRestricted(), isTemporary()) != null) { + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Host", newhost.getName()); + host.plugin.config.save(); + } + i++; + } else { + oldhost.servers.put(getName().toLowerCase(), this); + if (running) start(player); + } + } + } + } + break; + case "name": + if (change.get() instanceof String) { + host.servers.remove(getName().toLowerCase()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").set((String) change.get(), host.plugin.config.get().getSection("Servers").getSection(getName())); + host.plugin.config.get().getSection("Servers").remove(getName()); + host.plugin.config.save(); + } + name = (String) change.get(); + host.servers.put(((String) change.get()).toLowerCase(), this); + i++; + } + break; + case "enabled": + if (change.get() instanceof Boolean) { + setEnabled((Boolean) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Enabled", isEnabled()); + host.plugin.config.save(); + } + i++; + } + break; + case "log": + if (change.get() instanceof Boolean) { + setLogging((Boolean) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Log", isLogging()); + host.plugin.config.save(); + } + i++; + } + break; + case "dir": + if (change.get() instanceof String) { + directory = new File((String) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Directory", directory.getPath()); + host.plugin.config.save(); + } + i++; + } else if (change.get() instanceof File) { + directory = (File) change.get(); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Directory", directory.getPath()); + host.plugin.config.save(); + } + i++; + } + break; + case "exec": + if (change.get() instanceof String) { + executable = new Executable((String) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Executable", executable.toString()); + host.plugin.config.save(); + } + i++; + } else if (change.get() instanceof Executable) { + executable = (Executable) change.get(); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Executable", executable.toString()); + host.plugin.config.save(); + } + i++; + } + break; + case "running": + if (change.get() instanceof Boolean) { + if (running) { + if (!((Boolean) change.get())) stop(player); + } else { + if (((Boolean) change.get())) start(player); + } + i++; + } + break; + case "stop-cmd": + if (change.get() instanceof String) { + setStopCommand((String) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Stop-Command", getStopCommand()); + host.plugin.config.save(); + } + i++; + } + break; + case "auto-run": + if (change.get() instanceof Boolean) { + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Run-On-Launch", change.get()); + host.plugin.config.save(); + i++; + } + } + break; + case "auto-restart": + if (change.get() instanceof Boolean) { + setAutoRestart((Boolean) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Auto-Restart", willAutoRestart()); + host.plugin.config.save(); + } + i++; + } + break; + case "restricted": + if (change.get() instanceof Boolean) { + setRestricted((Boolean) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Restricted", isRestricted()); + host.plugin.config.save(); + } + i++; + } + break; + case "hidden": + if (change.get() instanceof Boolean) { + setHidden((Boolean) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Hidden", isHidden()); + host.plugin.config.save(); + } + i++; + } + break; + case "motd": + if (change.get() instanceof String) { + setMotd((String) change.get()); + if (host.plugin.config.get().getSection("Servers").getKeys().contains(getName())) { + host.plugin.config.get().getSection("Servers").getSection(getName()).set("Motd", getMotd()); + host.plugin.config.save(); + } + i++; + } + break; + } + } catch (Throwable e) { + e.printStackTrace(); + } } } - return true; + return i; } @Override public void waitFor() throws InterruptedException { - if (isRunning()) { - process.waitFor(); + while (thread != null && thread.isAlive()) { + Thread.sleep(250); } } + @Override + public String getName() { + return name; + } + @Override public boolean isRunning() { return process != null && process.isAlive(); diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Server.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Server.java index 3d64c2d6..35f03ed6 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Server.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Server.java @@ -15,10 +15,16 @@ import java.net.InetSocketAddress; */ public class Server extends BungeeServerInfo implements ClientHandler { private Client client = null; + private String motd; + private boolean restricted; + private boolean hidden; public Server(String name, InetSocketAddress address, String motd, boolean hidden, boolean restricted) throws InvalidServerException { super(name, address, ChatColor.translateAlternateColorCodes('&', motd), restricted); if (name.contains(" ")) throw new InvalidServerException("Server names cannot have spaces: " + name); + this.motd = motd; + this.restricted = restricted; + this.hidden = hidden; } @Override @@ -35,4 +41,60 @@ public class Server extends BungeeServerInfo implements ClientHandler { this.client = null; } else throw new IllegalStateException("A SubData Client is already linked to Server: " + getName()); } + + /** + * If the server is hidden from players + * + * @return Hidden Status + */ + public boolean isHidden() { + return hidden; + } + + /** + * Set if the server is hidden from players + * + * @param value Value + */ + public void setHidden(boolean value) { + this.hidden = value; + } + + /** + * Gets the MOTD of the Server + * + * @return Server MOTD + */ + @Override + public String getMotd() { + return motd; + } + + /** + * Sets the MOTD of the Server + * + * @param value Value + */ + public void setMotd(String value) { + this.motd = value; + } + + /** + * Gets if the Server is Restricted + * + * @return Restricted Status + */ + @Override + public boolean isRestricted() { + return restricted; + } + + /** + * Sets if the Server is Restricted + * + * @param value Value + */ + public void setRestricted(boolean value) { + this.restricted = value; + } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubServer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubServer.java index 786f3714..ec5a39eb 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubServer.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubServer.java @@ -100,10 +100,21 @@ public abstract class SubServer extends Server { /** * Applies edits to the SubServer * + * @param player Player Editing * @param change Change(s) to be applied * @return Success Status */ - public abstract boolean edit(NamedContainer... change); + public abstract int edit(UUID player, NamedContainer... change); + + /** + * Applies edits to the SubServer + * + * @param change Change(s) to be applied + * @return Success Status + */ + public int edit(NamedContainer... change) { + return edit(null, change); + } /** * Waits for the Server to Stop diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/build.sh b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/build.sh index 4fc78dda..2a2eb00b 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/build.sh +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/build.sh @@ -26,7 +26,7 @@ if [ $2 == bukkit ] || [ $2 == spigot ] else echo ERROR: Failed Downloading Buildtools. Is SpigotMC.org down? rm -Rf build-subserver.sh - exit 1 + exit 3 fi if [ -d "Buildtools" ] then @@ -62,7 +62,7 @@ if [ $2 == bukkit ] || [ $2 == spigot ] rm -Rf BuildTools.jar rm -Rf Buildtools rm -Rf build-subserver.sh - exit 1 + exit 4 fi else if [ $2 == "vanilla" ]; then @@ -76,7 +76,7 @@ else curl -o Buildtools/Vanilla/minecraft_server.$1.jar https://s3.amazonaws.com/Minecraft.Download/versions/$1/minecraft_server.$1.jar; retvald=$? if [ $retvald -eq 0 ]; then echo Downloading Vanilla Patches... - curl -o Buildtools/Vanilla/bungee-patch.jar http://minecraft.me1312.net/lib/subservers/vanilla-bungee-patch.1.2.jar; retvale=$? + curl -o Buildtools/Vanilla/bungee-patch.jar https://raw.githubusercontent.com/ME1312/SubServers-2/master/SubServers.Bungee/Vanilla-Patch.jar; retvale=$? if [ $retvale -eq 0 ]; then echo Patching Vanilla for BungeeCord Support cd Buildtools/Vanilla @@ -96,19 +96,19 @@ else echo ERROR: Failed Applying Patch. rm -Rf Buildtools rm -Rf build-subserver.sh - exit 1 + exit 5 fi else - echo ERROR: Failed Downloading Patch. Is Dropbox.com down? + echo ERROR: Failed Downloading Patch. Is Github.com down? rm -Rf Buildtools rm -Rf build-subserver.sh - exit 1 + exit 4 fi else echo ERROR: Failed Downloading Jarfile. Is Minecraft.net down? rm -Rf Buildtools rm -Rf build-subserver.sh - exit 1 + exit 3 fi else if [ $2 == "sponge" ]; then @@ -137,20 +137,21 @@ else rm -Rf forge-${version[0]}-installer.jar.log rm -Rf forge-${version[0]}-universal.jar rm -Rf build-subserver.sh - exit 1 + exit 5 fi else echo ERROR: Failed Installing Forge. rm -Rf forge-${version[0]}-installer.jar rm -Rf forge-${version[0]}-installer.jar.log rm -Rf build-subserver.sh - exit 1 + exit 4 fi else echo ERROR: Failed Downloading Jarfile. Is MinecraftForge.net down? rm -Rf build-subserver.sh - exit 1 + exit 3 fi fi fi -fi \ No newline at end of file +fi +exit 2 \ No newline at end of file diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/lang.yml b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/lang.yml index de8e6bca..2ce3c259 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/lang.yml +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/lang.yml @@ -9,9 +9,10 @@ Lang: 'Interface.Generic.Downloading.Title-Color': '&b' 'Interface.Generic.Downloading.Title-Color-Alt': '&3' 'Interface.Generic.Downloading.Response': '&eWaiting for response' + 'Interface.Generic.Invalid-Permission': '&4You need &n$str$' 'Interface.Host-Menu.Title': 'Host Menu' 'Interface.Host-Menu.Host-Disabled': '&4Disabled' - 'Interface.Host-Menu.Host-Server-Count': '&9$int$ Servers' + 'Interface.Host-Menu.Host-Server-Count': '&9$int$ Server(s)' 'Interface.Host-Menu.No-Hosts': '&c&oThere are No Hosts' 'Interface.Host-Menu.SubServer-Menu': '&a&lSubServer Menu' 'Interface.Host-Admin.Title': 'Host/$str$' @@ -53,7 +54,7 @@ Lang: 'Interface.Host-Editor.Title': 'Host/$str$/Edit' 'Interface.Host-SubServer.Title': 'Host/$str$/SubServers' 'Interface.SubServer-Menu.Title': 'SubServer Menu' - 'Interface.SubServer-Menu.SubServer-Player-Count': '&2$int$ Players Online' + 'Interface.SubServer-Menu.SubServer-Player-Count': '&2$int$ Player(s) Online' 'Interface.SubServer-Menu.SubServer-Temporary': '&9Temporary' 'Interface.SubServer-Menu.SubServer-Offline': '&6Offline' 'Interface.SubServer-Menu.SubServer-Disabled': '&4Disabled' diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java index 88ddd7c9..26d413af 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java @@ -48,6 +48,7 @@ public class PacketDownloadServerInfo implements PacketIn, PacketOut { info.put("name", server.getName()); info.put("address", server.getAddress().toString()); info.put("restricted", server.isRestricted()); + info.put("hidden", server.isHidden()); info.put("motd", server.getMotd()); info.put("subdata", server.getSubDataClient() == null); diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketOutRunEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketOutRunEvent.java index d66ad1a5..0ea71e76 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketOutRunEvent.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketOutRunEvent.java @@ -111,6 +111,7 @@ public class PacketOutRunEvent implements Listener, PacketOut { HashMap args = new HashMap(); args.put("player", ((event.getPlayer() == null)?null:event.getPlayer().toString())); args.put("server", event.getServer().getName()); + args.put("force", event.isForced()); if (server.getSubDataClient() != null) server.getSubDataClient().sendPacket(new PacketOutRunEvent(event.getClass(), args)); } } @@ -125,4 +126,18 @@ public class PacketOutRunEvent implements Listener, PacketOut { if (server.getSubDataClient() != null) server.getSubDataClient().sendPacket(new PacketOutRunEvent(event.getClass(), args)); } } + @EventHandler(priority = EventPriority.HIGHEST) + public void event(SubRemoveServerEvent event) { + if (!event.isCancelled()) { + List list = new ArrayList(); + list.addAll(plugin.api.getServers().values()); + for (Server server : list) { + HashMap args = new HashMap(); + args.put("player", ((event.getPlayer() == null)?null:event.getPlayer().toString())); + args.put("host", event.getHost().getName()); + args.put("server", event.getServer().getName()); + if (server.getSubDataClient() != null) server.getSubDataClient().sendPacket(new PacketOutRunEvent(event.getClass(), args)); + } + } + } } \ No newline at end of file diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java index b73f6987..137e7c45 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java @@ -151,8 +151,7 @@ public final class SubCommand extends Command { i++; str = str + " " + args[i]; } - System.out.println("/subserver" + str); - ((ProxiedPlayer) sender).chat("/subserver" + str); + ((ProxiedPlayer) sender).chat("/subservers" + str); } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java index e72a4b00..4b670291 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java @@ -36,7 +36,7 @@ public final class SubPlugin extends BungeeCord { public HashMap exLang = new HashMap(); public SubDataServer subdata = null; public final Version version = new Version("2.11.0a"); - protected Version bversion = new Version(2); + protected Version bversion = new Version(3); protected boolean running = false; public final SubAPI api = new SubAPI(this); diff --git a/SubServers.Client/Bukkit/src/config.yml b/SubServers.Client/Bukkit/src/config.yml new file mode 100644 index 00000000..87e1b877 --- /dev/null +++ b/SubServers.Client/Bukkit/src/config.yml @@ -0,0 +1,7 @@ +Settings: + Version: '2.11.0a+' + Use-Title-Messages: true + SubData: + Name: 'Server_1' + Address: '127.0.0.1:4391' + Password: 'password123' \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubAddServerEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubAddServerEvent.java new file mode 100644 index 00000000..b5f8eb0b --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubAddServerEvent.java @@ -0,0 +1,55 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +public class SubAddServerEvent extends Event implements SubEvent { + private UUID player; + private String host; + private String server; + + /** + * Server Add Event + * + * @param player Player Adding Server + * @param server Server Starting + */ + public SubAddServerEvent(UUID player, String host, String server) { + this.player = player; + this.host = host; + this.server = server; + } + + /** + * Gets the Server to be Added + * @return The Server to be Added + */ + public String getServer() { return server; } + + /** + * Gets the Host of the Server + * + * @return The Host of the Server or null if isn't a SubServer + */ + public String getHost() { + return host; + } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubCreateEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubCreateEvent.java new file mode 100644 index 00000000..eebb7794 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubCreateEvent.java @@ -0,0 +1,136 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.PacketCreateServer; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +public class SubCreateEvent extends Event implements SubEvent { + private UUID player; + private String host; + private String name; + private PacketCreateServer.ServerType type; + private Version version; + private int memory; + private int port; + + /** + * Server Create Event + * + * @param player Player Creating + * @param host Potential Host + * @param name Server Name + * @param type Server Type + * @param version Server Version + * @param memory Server RAM Amount + * @param port Server Port Number + */ + public SubCreateEvent(UUID player, String host, String name, PacketCreateServer.ServerType type, Version version, int memory, int port) { + this.player = player; + this.host = host; + this.name = name; + this.type = type; + this.version = version; + this.memory = memory; + this.port = port; + } + + /** + * Get the Host the SubServer will run on + * + * @return Potential Host + */ + public String getHost() { + return host; + } + + /** + * Get the name the SubServer will use + * + * @return SubServer Name + */ + public String getName() { + return name; + } + + /** + * Get the type of Server to create + * + * @return Server Type + */ + public PacketCreateServer.ServerType getType() { + return type; + } + + /** + * Set the Type of Server to Create + * + * @param value Value + */ + public void setType(PacketCreateServer.ServerType value) { + this.type = value; + } + + /** + * Get the Version the Server will use + * + * @return Server Version + */ + public Version getVersion() { + return version; + } + + /** + * Set the Version the Server will use + * + * @param value Value + */ + public void setVersion(Version value) { + this.version = value; + } + + /** + * Get the Server RAM Amount (in MB) + * + * @return RAM Amount + */ + public int getMemory() { + return memory; + } + + /** + * Set the Server RAM Amount (in MB) + * + * @param value Value + */ + public void setMemory(int value) { + this.memory = value; + } + + /** + * Get the Port the Server will use + * + * @return Port Number + */ + public int getPort() { + return port; + } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubDataRecieveGenericInfoEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubDataRecieveGenericInfoEvent.java new file mode 100644 index 00000000..3eb15fa4 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubDataRecieveGenericInfoEvent.java @@ -0,0 +1,62 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.json.JSONObject; + +public class SubDataRecieveGenericInfoEvent extends Event implements SubEvent { + private String handle; + private Version version; + private JSONObject content; + + /** + * SubData Generic Info Event + * + * @param handle Content Handle + * @param version Content Version + * @param content Content + */ + public SubDataRecieveGenericInfoEvent(String handle, Version version, JSONObject content) { + this.handle = handle; + this.version = version; + this.content = content; + } + + /** + * Get Content Handle + * + * @return Content Handle + */ + public String getHandle() { + return handle; + } + + /** + * Get Content Version + * + * @return Content Version + */ + public Version getVersion() { + return version; + } + + /** + * Get Content + * + * @return Content + */ + public JSONObject getContent() { + return content; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubRemoveServerEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubRemoveServerEvent.java new file mode 100644 index 00000000..7dd98e48 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubRemoveServerEvent.java @@ -0,0 +1,55 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +public class SubRemoveServerEvent extends Event implements SubEvent { + private UUID player; + private String host; + private String server; + + /** + * Server Add Event + * + * @param player Player Adding Server + * @param server Server Starting + */ + public SubRemoveServerEvent(UUID player, String host, String server) { + this.player = player; + this.host = host; + this.server = server; + } + + /** + * Gets the Server to be Added + * @return The Server to be Added + */ + public String getServer() { return server; } + + /** + * Gets the Host of the Server + * + * @return The Host of the Server or null if isn't a SubServer + */ + public String getHost() { + return host; + } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubSendCommandEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubSendCommandEvent.java new file mode 100644 index 00000000..9745b1e0 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubSendCommandEvent.java @@ -0,0 +1,64 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +public class SubSendCommandEvent extends Event implements SubEvent { + private UUID player; + private String server; + private String command; + + /** + * Server Command Event + * + * @param player Player Commanding Server + * @param server Server being Commanded + */ + public SubSendCommandEvent(UUID player, String server, String command) { + this.player = player; + this.server = server; + this.command = command; + } + + /** + * Gets the Server Effected + * @return The Server Effected + */ + public String getServer() { return server; } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + /** + * Gets the Command to Send + * + * @return Command to Send + */ + public String getCommand() { + return command; + } + + /** + * Sets the Command to be Sent + * + * @param value Value + */ + public void setCommand(String value) { + command = value; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStartEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStartEvent.java new file mode 100644 index 00000000..fa8d689c --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStartEvent.java @@ -0,0 +1,45 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +public class SubStartEvent extends Event implements SubEvent { + private boolean cancelled = false; + private UUID player; + private String server; + + /** + * Server Start Event + * + * @param player Player Starting Server + * @param server Server Starting + */ + public SubStartEvent(UUID player, String server) { + this.player = player; + this.server = server; + } + + /** + * Gets the Server Effected + * @return The Server Effected + */ + public String getServer() { return server; } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStopEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStopEvent.java new file mode 100644 index 00000000..9b17bb1c --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStopEvent.java @@ -0,0 +1,57 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +public class SubStopEvent extends Event implements SubEvent { + private UUID player; + private String server; + private boolean force; + + /** + * Server Stop Event + * + * @param player Player Stopping Server + * @param server Server Stopping + * @param force If it was a Forced Shutdown + */ + public SubStopEvent(UUID player, String server, boolean force) { + this.player = player; + this.server = server; + this.force = force; + } + + /** + * Gets the Server Effected + * @return The Server Effected + */ + public String getServer() { return server; } + + /** + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console + */ + public UUID getPlayer() { return player; } + + /** + * Gets if it was a forced shutdown + * + * @return Forced Shutdown Status + */ + public boolean isForced() { + return force; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStoppedEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStoppedEvent.java new file mode 100644 index 00000000..8e1adcfc --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Event/SubStoppedEvent.java @@ -0,0 +1,33 @@ +package net.ME1312.SubServers.Client.Bukkit.Event; + +import net.ME1312.SubServers.Client.Bukkit.Library.SubEvent; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class SubStoppedEvent extends Event implements SubEvent { + private String server; + + /** + * Server Shell Exit Event + * + * @param server Server that Stopped + */ + public SubStoppedEvent(String server) { + this.server = server; + } + + /** + * Gets the Server Effected + * @return The Server Effected + */ + public String getServer() { return server; } + + @Override + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } + private static HandlerList handlers = new HandlerList(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIListener.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIListener.java new file mode 100644 index 00000000..f39b0eb2 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIListener.java @@ -0,0 +1,365 @@ +package net.ME1312.SubServers.Client.Bukkit.Graphic; + +import net.ME1312.SubServers.Client.Bukkit.Library.Container; +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Util; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.*; +import net.ME1312.SubServers.Client.Bukkit.Network.SubDataClient; +import net.ME1312.SubServers.Client.Bukkit.SubPlugin; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.UUID; + +public class UIListener implements Listener { + private HashMap input = new HashMap(); + private HashMap gui = new HashMap(); + private SubPlugin plugin; + + public UIListener(SubPlugin plugin) { + this.plugin = plugin; + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + /** + * Grabs the current UIRenderer for the player + * + * @param player Player + * @return UIRenderer + */ + public UIRenderer getRenderer(Player player) { + if (!gui.keySet().contains(player.getUniqueId())) gui.put(player.getUniqueId(), new UIRenderer(plugin, player.getUniqueId())); + return gui.get(player.getUniqueId()); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void click(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + if (!event.isCancelled() && gui.keySet().contains(player.getUniqueId())) { + UIRenderer gui = this.gui.get(player.getUniqueId()); + if (gui.open && event.getClickedInventory() != null && event.getClickedInventory().getTitle() != null) { + if (event.getClickedInventory().getTitle().equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Title", '&'))) { // Host Menu + if (event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR && event.getCurrentItem().hasItemMeta()) { + String item = event.getCurrentItem().getItemMeta().getDisplayName(); + + if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back-Arrow", '&'))) { + player.closeInventory(); + gui.hostMenu(gui.lastPage - 1); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Next-Arrow", '&'))) { + player.closeInventory(); + gui.hostMenu(gui.lastPage + 1); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.SubServer-Menu", '&'))) { + player.closeInventory(); + gui.subserverMenu(1, null); + } else if (!item.equals(ChatColor.RESET.toString()) && !item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.No-Hosts", '&'))) { + player.closeInventory(); + gui.hostAdmin(ChatColor.stripColor(item)); + } + } + } else if (event.getClickedInventory().getTitle().startsWith(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Title", '&').split("\\$str\\$")[0]) && // Host Creator + (plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Title", '&').split("\\$str\\$").length == 1 || + event.getClickedInventory().getTitle().endsWith(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Title", '&').split("\\$str\\$")[1]))) { + if (event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR && event.getCurrentItem().hasItemMeta()) { + String item = event.getCurrentItem().getItemMeta().getDisplayName(); + if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&'))) { + player.closeInventory(); + gui.back(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Undo", '&'))) { + player.closeInventory(); + gui.lastUsedOptions.undo(); + gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Submit", '&'))) { + if (player.hasPermission("subservers.host.create.*") || player.hasPermission("subservers.host.create." + gui.lastVistedObject.toLowerCase())) { + player.closeInventory(); + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + plugin.subdata.sendPacket(new PacketCreateServer(player.getUniqueId(), (UIRenderer.CreatorOptions) gui.lastUsedOptions, UUID.randomUUID().toString(), json -> { + gui.back(); + })); + } else { + gui.back(); + } + } else if (ChatColor.stripColor(item).equals(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name", '&')))) { + player.closeInventory(); + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name.Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name.Message", '&')); + input.put(player.getUniqueId(), m -> { + if (m.getString("message").contains(" ")) { + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name.Invalid-Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name.Invalid", '&')); + Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions), 4 * 20); + } else { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + plugin.subdata.sendPacket(new PacketDownloadServerList(null, UUID.randomUUID().toString(), json -> { + boolean match = false; + for (String tmphost : json.getJSONObject("hosts").keySet()) { + for (String tmpsubserver : json.getJSONObject("hosts").getJSONObject(tmphost).getJSONObject("servers").keySet()) { + if (tmpsubserver.equalsIgnoreCase(m.getString("message"))) match = true; + } + } + if (match) { + gui.setDownloading(null); + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name.Exists-Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name.Exists", '&')); + Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions), 4 * 20); + } else { + ((UIRenderer.CreatorOptions) gui.lastUsedOptions).setName(m.getString("message")); + gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions); + } + })); + } + }); + } else if (ChatColor.stripColor(item).equals(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type", '&')))) { + player.closeInventory(); + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type.Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type.Message", '&')); + input.put(player.getUniqueId(), m -> { + if (Util.isException(() -> PacketCreateServer.ServerType.valueOf(m.getString("message").toUpperCase()))) { + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type.Invalid-Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type.Invalid", '&')); + Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions), 4 * 20); + } else { + ((UIRenderer.CreatorOptions) gui.lastUsedOptions).setType(PacketCreateServer.ServerType.valueOf(m.getString("message").toUpperCase())); + gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions); + } + }); + } else if (ChatColor.stripColor(item).equals(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version", '&')))) { + player.closeInventory(); + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version.Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version.Message", '&')); + input.put(player.getUniqueId(), m -> { + if (new Version("1.8").compareTo(new Version(m.getString("message"))) > 0) { + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version.Unavailable-Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version.Unavailable", '&')); + Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions), 4 * 20); + } else { + ((UIRenderer.CreatorOptions) gui.lastUsedOptions).setVersion(new Version(m.getString("message"))); + gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions); + } + }); + } else if (ChatColor.stripColor(item).equals(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port", '&')))) { + player.closeInventory(); + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port.Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port.Message", '&')); + input.put(player.getUniqueId(), m -> { + if (Util.isException(() -> Integer.parseInt(m.getString("message"))) || Integer.parseInt(m.getString("message")) <= 0 || Integer.parseInt(m.getString("message")) > 65535) { + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port.Invalid-Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port.Invalid", '&')); + Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions), 4 * 20); + } else { + ((UIRenderer.CreatorOptions) gui.lastUsedOptions).setPort(Integer.valueOf(m.getString("message"))); + gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions); + } + }); + } else if (ChatColor.stripColor(item).equals(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM", '&')))) { + player.closeInventory(); + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM.Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM.Message", '&')); + input.put(player.getUniqueId(), m -> { + if (Util.isException(() -> Integer.parseInt(m.getString("message"))) || Integer.parseInt(m.getString("message")) < 256) { + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM.Invalid-Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM.Invalid", '&')); + Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions), 4 * 20); + } else { + ((UIRenderer.CreatorOptions) gui.lastUsedOptions).setMemory(Integer.valueOf(m.getString("message"))); + gui.hostCreator((UIRenderer.CreatorOptions) gui.lastUsedOptions); + } + }); + } + + } + } else if (event.getClickedInventory().getTitle().equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.Title", '&')) || // SubServer Menu + event.getClickedInventory().getTitle().startsWith(plugin.lang.getSection("Lang").getColoredString("Interface.Host-SubServer.Title", '&').split("\\$str\\$")[0]) && + (plugin.lang.getSection("Lang").getColoredString("Interface.Host-SubServer.Title", '&').split("\\$str\\$").length == 1 || + event.getClickedInventory().getTitle().endsWith(plugin.lang.getSection("Lang").getColoredString("Interface.Host-SubServer.Title", '&').split("\\$str\\$")[1]))) { + if (event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR && event.getCurrentItem().hasItemMeta()) { + String item = event.getCurrentItem().getItemMeta().getDisplayName(); + + if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back-Arrow", '&'))) { + player.closeInventory(); + gui.subserverMenu(gui.lastPage - 1, null); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Next-Arrow", '&'))) { + player.closeInventory(); + gui.subserverMenu(gui.lastPage + 1, null); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.Host-Menu", '&'))) { + player.closeInventory(); + gui.hostMenu(1); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&'))) { + player.closeInventory(); + gui.back(); + } else if (!item.equals(ChatColor.RESET.toString()) && !item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.No-SubServers", '&'))) { + player.closeInventory(); + gui.subserverAdmin(ChatColor.stripColor(item)); + } + } + } else if (event.getClickedInventory().getTitle().startsWith(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Title", '&').split("\\$str\\$")[0]) && // Host Admin + (plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Title", '&').split("\\$str\\$").length == 1 || + event.getClickedInventory().getTitle().endsWith(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Title", '&').split("\\$str\\$")[1]))) { + if (event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR && event.getCurrentItem().hasItemMeta()) { + String item = event.getCurrentItem().getItemMeta().getDisplayName(); + + if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&'))) { + player.closeInventory(); + gui.back(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Creator", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.host.create.*") || player.hasPermission("subservers.host.create." + gui.lastVistedObject.toLowerCase())) { + gui.hostCreator(new UIRenderer.CreatorOptions(gui.lastVistedObject)); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Editor", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.host.edit.*") || player.hasPermission("subservers.host.edit." + gui.lastVistedObject.toLowerCase())) { + gui.hostEditor(new UIRenderer.HostEditorOptions(gui.lastVistedObject)); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.SubServers", '&'))) { + player.closeInventory(); + gui.subserverMenu(1, gui.lastVistedObject); + } + } + } else if (event.getClickedInventory().getTitle().startsWith(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Title", '&').split("\\$str\\$")[0]) && // SubServer Admin + (plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Title", '&').split("\\$str\\$").length == 1 || + event.getClickedInventory().getTitle().endsWith(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Title", '&').split("\\$str\\$")[1]))) { + if (event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR && event.getCurrentItem().hasItemMeta()) { + String item = event.getCurrentItem().getItemMeta().getDisplayName(); + + if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&'))) { + player.closeInventory(); + gui.back(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Editor", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.subserver.edit.*") || player.hasPermission("subservers.subserver.edit." + gui.lastVistedObject.toLowerCase())) { + gui.subserverEditor(new UIRenderer.SubServerEditorOptions(gui.lastVistedObject)); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Start", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.subserver.start.*") || player.hasPermission("subservers.subserver.start." + gui.lastVistedObject.toLowerCase())) { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + plugin.subdata.sendPacket(new PacketStartServer(player.getUniqueId(), gui.lastVistedObject, UUID.randomUUID().toString(), json -> { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Start.Title", '&')); + Bukkit.getScheduler().runTaskLater(plugin, gui::reopen, 30); + })); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Stop", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.subserver.stop.*") || player.hasPermission("subservers.subserver.stop." + gui.lastVistedObject.toLowerCase())) { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + final Container listening = new Container(true); + ((PacketInRunEvent) SubDataClient.getPacket("SubRunEvent")).callback("SubStoppedEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + try { + if (listening.get()) if (!json.getString("server").equalsIgnoreCase(gui.lastVistedObject)) { + ((PacketInRunEvent) SubDataClient.getPacket("RunEvent")).callback("SubStoppedEvent", this); + } else { + gui.reopen(); + } + } catch (Exception e) {} + } + }); + plugin.subdata.sendPacket(new PacketStopServer(player.getUniqueId(), gui.lastVistedObject, false, UUID.randomUUID().toString(), json -> { + if (json.getInt("r") != 0) { + gui.reopen(); + listening.set(false); + } else gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Stop.Title", '&').replace("$str$", gui.lastVistedObject)); + })); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Terminate", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.subserver.terminate.*") || player.hasPermission("subservers.subserver.terminate." + gui.lastVistedObject.toLowerCase())) { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + final Container listening = new Container(true); + ((PacketInRunEvent) SubDataClient.getPacket("SubRunEvent")).callback("SubStoppedEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + try { + if (listening.get()) if (!json.getString("server").equalsIgnoreCase(gui.lastVistedObject)) { + ((PacketInRunEvent) SubDataClient.getPacket("RunEvent")).callback("SubStoppedEvent", this); + } else { + gui.reopen(); + } + } catch (Exception e) {} + } + }); + plugin.subdata.sendPacket(new PacketStopServer(player.getUniqueId(), gui.lastVistedObject, false, UUID.randomUUID().toString(), json -> { + if (json.getInt("r") != 0) { + gui.reopen(); + listening.set(false); + } else gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Terminate.Title", '&').replace("$str$", gui.lastVistedObject)); + })); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Command", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.subserver.command.*") || player.hasPermission("subservers.subserver.command." + gui.lastVistedObject.toLowerCase())) { + if (!gui.sendTitle(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Command.Title", '&'), 4 * 20)) + player.sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Command.Message", '&')); + input.put(player.getUniqueId(), m -> { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + plugin.subdata.sendPacket(new PacketCommandServer(player.getUniqueId(), gui.lastVistedObject, m.getString("message"), UUID.randomUUID().toString(), json -> { + gui.reopen(); + })); + }); + } else gui.reopen(); + } else if (item.equals(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Teleport", '&'))) { + player.closeInventory(); + if (player.hasPermission("subservers.subserver.teleport.*") || player.hasPermission("subservers.subserver.teleport." + gui.lastVistedObject.toLowerCase())) { + gui.setDownloading(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Response", '&')); + plugin.subdata.sendPacket(new PacketTeleportPlayer(player.getUniqueId(), gui.lastVistedObject, UUID.randomUUID().toString(), json -> { + if (json.getInt("r") != 0) gui.reopen(); + })); + } else gui.reopen(); + } + } + } + event.setCancelled(true); + } + } + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.HIGHEST) + public void input(org.bukkit.event.player.PlayerChatEvent event) { + if (!event.isCancelled() && input.keySet().contains(event.getPlayer().getUniqueId())) { + JSONObject json = new JSONObject(); + json.put("message", event.getMessage()); + input.get(event.getPlayer().getUniqueId()).run(json); + input.remove(event.getPlayer().getUniqueId()); + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void input(PlayerCommandPreprocessEvent event) { + if (!event.isCancelled() && input.keySet().contains(event.getPlayer().getUniqueId())) { + JSONObject json = new JSONObject(); + json.put("message", event.getMessage()); + input.get(event.getPlayer().getUniqueId()).run(json); + input.remove(event.getPlayer().getUniqueId()); + event.setCancelled(true); + } + } + + @EventHandler + public void close(InventoryCloseEvent event) { + if (gui.keySet().contains(event.getPlayer().getUniqueId())) gui.get(event.getPlayer().getUniqueId()).open = false; + } + + @EventHandler + public void clean(PlayerQuitEvent event) { + if (gui.keySet().contains(event.getPlayer().getUniqueId())) { + gui.get(event.getPlayer().getUniqueId()).setDownloading(null); + gui.remove(event.getPlayer().getUniqueId()); + input.remove(event.getPlayer().getUniqueId()); + } + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIRenderer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIRenderer.java new file mode 100644 index 00000000..54c569a1 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Graphic/UIRenderer.java @@ -0,0 +1,1127 @@ +package net.ME1312.SubServers.Client.Bukkit.Graphic; + +import net.ME1312.SubServers.Client.Bukkit.Library.Container; +import net.ME1312.SubServers.Client.Bukkit.Library.NamedContainer; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.PacketCreateServer; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.PacketDownloadHostInfo; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.PacketDownloadServerInfo; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.PacketDownloadServerList; +import net.ME1312.SubServers.Client.Bukkit.SubPlugin; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.scheduler.BukkitTask; + +import java.util.*; + +public class UIRenderer { + private List windowHistory = new LinkedList(); + protected Options lastUsedOptions = null; + protected String lastVistedObject = null; + protected int lastPage = 1; + protected Runnable lastMenu = null; + private NamedContainer downloading = null; + protected boolean open = false; + protected final UUID player; + private SubPlugin plugin; + public abstract static class Options { + List history = new LinkedList(); + private boolean init = false; + + boolean init() { + if (!init) { + init = true; + return false; + } else { + return true; + } + } + + /** + * If there is any undo history + * + * @return Undo History Status + */ + public boolean hasHistory() { + return !history.isEmpty(); + } + + /** + * Reverts the last change + */ + public void undo() { + Runnable lastWindow = history.get(history.size() - 1); + history.remove(history.size() - 1); + lastWindow.run(); + } + } + + protected UIRenderer(SubPlugin plugin, UUID player) { + this.plugin = plugin; + this.player = player; + } + + /** + * Opens a new window + */ + public void newUI() { + clearHistory(); + if (lastMenu == null) { + hostMenu(1); + } else { + lastMenu.run(); + } + } + + /** + * Clears the Window History + */ + public void clearHistory() { + windowHistory.clear(); + } + + /** + * If there is any Window History + * + * @return Window History Status + */ + public boolean hasHistory() { + return !windowHistory.isEmpty(); + } + + /** + * Reopens the current window + */ + public void reopen() { + Runnable lastWindow = windowHistory.get(windowHistory.size() - 1); + windowHistory.remove(windowHistory.size() - 1); + lastWindow.run(); + } + + /** + * Reopens the previous window + */ + public void back() { + windowHistory.remove(windowHistory.size() - 1); + reopen(); + } + + /** + * Attempt to send a Title Message + * + * @param str Message + * @return Success Status + */ + public boolean sendTitle(String str) { + return sendTitle(str, -1); + } + + /** + * Attempt to send a Title Message + * + * @param str Message + * @param stay How long the message should stay + * @return Success Status + */ + public boolean sendTitle(String str, int stay) { + return sendTitle(str, -1, stay, -1); + } + + /** + * Attempt to send a Title Message + * + * @param str Message + * @param fadein FadeIn Transition length + * @param stay How long the message should stay + * @param fadeout FadeOut Transition length + * @return Success Status + */ + public boolean sendTitle(String str, int fadein, int stay, int fadeout) { + if (Bukkit.getPluginManager().getPlugin("TitleManager") != null && plugin.pluginconf.get().getSection("Settings").getBoolean("Use-Title-Messages", true)) { + String line1, line2; + if (!str.startsWith("\n") && str.contains("\n")) { + line1 = str.split("\\n")[0]; + line2 = str.split("\\n")[1]; + } else { + line1 = str.replace("\n", ""); + line2 = ChatColor.RESET.toString(); + } + try { + io.puharesource.mc.titlemanager.api.TitleObject obj = io.puharesource.mc.titlemanager.api.TitleObject.class.getConstructor(String.class, String.class).newInstance(line1, line2); + if (fadein >= 0) obj.setFadeIn(fadein); + if (stay >= 0) obj.setStay(stay); + if (fadeout >= 0) obj.setFadeOut(fadeout); + obj.send(Bukkit.getPlayer(player)); + return true; + } catch (Throwable e) { + return false; + } + } else { + return false; + } + } + + /** + * Shows/Hides the Downloading Title Message + * + * @param subtitle Subtitle to display (or null to hide) + */ + public void setDownloading(String subtitle) { + if (subtitle != null && !(Bukkit.getPluginManager().getPlugin("TitleManager") != null && plugin.pluginconf.get().getSection("Settings").getBoolean("Use-Title-Messages", true))) { + Bukkit.getPlayer(player).sendMessage(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading", '&').replace("$str$", subtitle)); + } if (subtitle != null && downloading == null) { + downloading = new NamedContainer(subtitle, 0); + final Container delay = new Container(0); + Bukkit.getScheduler().runTask(plugin, new Runnable() { + @Override + public void run() { + if (downloading != null) { + String word = ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Title", '&')); + int i = 0; + int start = (downloading.get() - 3 < 0)?0:downloading.get()-3; + int end = (downloading.get() >= word.length())?word.length():downloading.get(); + String str = plugin.lang.getSection("Lang").getColoredString((delay.get() > 7 && start == 0)?"Interface.Generic.Downloading.Title-Color-Alt":"Interface.Generic.Downloading.Title-Color", '&'); + delay.set(delay.get() + 1); + if (delay.get() > 7) downloading.set(downloading.get() + 1); + if (downloading.get() >= word.length() + 3) { + downloading.set(0); + delay.set(0); + } + + for (char c : word.toCharArray()) { + i++; + if (i == start) str += plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Title-Color-Alt", '&'); + str += c; + if (i == end) str += plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Title-Color", '&'); + } + + str += '\n' + plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Downloading.Title-Color-Alt", '&') + downloading.name(); + sendTitle(str, 0, 10, 5); + Bukkit.getScheduler().runTaskLater(plugin, this, 1); + } else { + sendTitle(ChatColor.RESET.toString(), 0, 1, 0); + } + } + }); + } else if (subtitle != null) { + downloading.rename(subtitle); + } else if (downloading != null) { + downloading = null; + } + } + + /** + * Opens the Host Menu + * + * @param page Page Number (starting from page 1) + */ + public void hostMenu(final Integer page) { + setDownloading(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Title", '&'))); + plugin.subdata.sendPacket(new PacketDownloadServerList(null, UUID.randomUUID().toString(), (json) -> { + setDownloading(null); + lastVistedObject = null; + lastPage = page; + lastMenu = () -> hostMenu(1); + windowHistory.add(() -> hostMenu(page)); + List hosts = new ArrayList(); + hosts.addAll(json.getJSONObject("hosts").keySet()); + + ItemStack block; + ItemMeta blockMeta; + ItemStack div = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 15); + ItemMeta divMeta = div.getItemMeta(); + divMeta.setDisplayName(ChatColor.RESET.toString()); + div.setItemMeta(divMeta); + + int i = 0; + int min = ((page - 1) * 36); + int max = (min + 35); + int count = (hosts.size() == 0)?27:((hosts.size() - min - 1 >= max)?36:hosts.size() - min); + int area = (count % 9 == 0) ? count : (int) (Math.floor(count / 9) + 1) * 9; + + Inventory inv = Bukkit.createInventory(null, 18 + area, plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Title", '&')); + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + block.setItemMeta(divMeta); + while (i < area) { + inv.setItem(i, block); + i++; + } + ItemStack adiv = block; + i = (int) ((count < 9) ? Math.floor((9 - count) / 2) : 0); + + boolean even = (count & 1) == 0 && count < 9; + short enabled, disabled; + + for (String host : hosts) { + if (hosts.indexOf(host) >= min && hosts.indexOf(host) <= max) { + if (even && (i == 4 || i == 13 || i == 22 || i == 31)) inv.setItem(i++, adiv); + enabled = (short) (((i & 1) == 0) ? 3 : 11); + disabled = (short) (((i & 1) == 0) ? 2 : 14); + + if (json.getJSONObject("hosts").getJSONObject(host).getBoolean("enabled")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, enabled); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.AQUA + host); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Host-Server-Count", '&').replace("$int$", Integer.toString(json.getJSONObject("hosts").getJSONObject(host).getJSONObject("servers").keySet().size())))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, disabled); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + host); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Host-Disabled", '&'))); + } + block.setItemMeta(blockMeta); + inv.setItem(i, block); + + count--; + if (count < 9 && (i == 8 || i == 17 || i == 26)) { + i += (int) Math.floor((9 - count) / 2) + 1; + even = (count & 1) == 0; + } else { + i++; + } + } + } + + if (hosts.size() == 0) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.No-Hosts", '&')); + block.setItemMeta(blockMeta); + inv.setItem(12, block); + inv.setItem(13, block); + inv.setItem(14, block); + } + + i = inv.getSize() - 18; + while (i < inv.getSize()) { + inv.setItem(i, div); + i++; + } + i = inv.getSize() - 9; + + if (min != 0) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back-Arrow", '&')); + block.setItemMeta(blockMeta); + inv.setItem(i++, block); + inv.setItem(i++, block); + } else i += 2; + i++; + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.SubServer-Menu", '&')); + block.setItemMeta(blockMeta); + inv.setItem(i++, block); + inv.setItem(i++, block); + inv.setItem(i++, block); + i++; + if (hosts.size() - 1 > max) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Next-Arrow", '&')); + block.setItemMeta(blockMeta); + inv.setItem(i++, block); + inv.setItem(i, block); + } + + Bukkit.getPlayer(player).openInventory(inv); + open = true; + })); + } + + /** + * Opens Hosts/<name> + * + * @param host Host Name + */ + public void hostAdmin(final String host) { + setDownloading(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Title", '&').replace("$str$", host))); + plugin.subdata.sendPacket(new PacketDownloadHostInfo(host, UUID.randomUUID().toString(), (json) -> { + windowHistory.add(() -> hostAdmin(host)); + if (!json.getBoolean("valid")) { + back(); + } else { + setDownloading(null); + lastVistedObject = host; + + ItemStack block; + ItemMeta blockMeta; + ItemStack div = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 15); + ItemMeta divMeta = div.getItemMeta(); + divMeta.setDisplayName(ChatColor.RESET.toString()); + div.setItemMeta(divMeta); + + Inventory inv = Bukkit.createInventory(null, 36, plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Title", '&').replace("$str$", host)); + + int i = 0; + while (i < inv.getSize()) { + inv.setItem(i, div); + i++; + } + + if (!(Bukkit.getPlayer(player).hasPermission("subservers.host.create.*") || Bukkit.getPlayer(player).hasPermission("subservers.host.create." + host.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Creator", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.host.create." + host.toLowerCase()))); + } else if (!json.getJSONObject("host").getBoolean("enabled") || json.getJSONObject("host").getJSONObject("creator").getBoolean("busy")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Creator", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Creator-Busy", '&'))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Creator", '&')); + + } + block.setItemMeta(blockMeta); + inv.setItem(1, block); + inv.setItem(10, block); + + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.SubServers", '&')); + block.setItemMeta(blockMeta); + inv.setItem(2, block); + inv.setItem(3, block); + inv.setItem(11, block); + inv.setItem(12, block); + + if (!(Bukkit.getPlayer(player).hasPermission("subservers.host.edit.*") || Bukkit.getPlayer(player).hasPermission("subservers.host.edit." + host.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Editor", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.host.edit." + host.toLowerCase()))); + } else if (!json.getJSONObject("host").getBoolean("editable")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Editor", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Editor-Unavailable", '&'))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 1); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Admin.Editor", '&')); + + } + block.setItemMeta(blockMeta); + inv.setItem(5, block); + inv.setItem(6, block); + inv.setItem(7, block); + inv.setItem(14, block); + inv.setItem(15, block); + inv.setItem(16, block); + + + if (json.getJSONObject("host").getBoolean("enabled")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 11); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.AQUA + host); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Host-Server-Count", '&').replace("$int$", Integer.toString(json.getJSONObject("host").getJSONObject("servers").keySet().size())))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + host); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Menu.Host-Disabled", '&'))); + } + block.setItemMeta(blockMeta); + inv.setItem(30, block); + inv.setItem(31, block); + inv.setItem(32, block); + + + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&')); + block.setItemMeta(blockMeta); + inv.setItem(34, block); + inv.setItem(35, block); + + Bukkit.getPlayer(player).openInventory(inv); + open = true; + } + })); + } + + /** + * Opens Hosts/<name>/Create + * + * @param options Creator Options + */ + public void hostCreator(final CreatorOptions options) { + setDownloading(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Title", '&').replace("$str$", options.getHost()))); + lastUsedOptions = options; + if (!options.init()) { + windowHistory.add(() -> hostCreator(options)); + lastVistedObject = options.getHost(); + } + + plugin.subdata.sendPacket(new PacketDownloadHostInfo(options.getHost(), UUID.randomUUID().toString(), json -> { + if (!json.getJSONObject("host").getBoolean("enabled") || json.getJSONObject("host").getJSONObject("creator").getBoolean("busy")) { + lastUsedOptions = null; + back(); + } else { + setDownloading(null); + ItemStack block; + ItemMeta blockMeta; + ItemStack div = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 15); + ItemMeta divMeta = div.getItemMeta(); + divMeta.setDisplayName(ChatColor.RESET.toString()); + div.setItemMeta(divMeta); + + Inventory inv = Bukkit.createInventory(null, 54, plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Title", '&').replace("$str$", options.getHost())); + + int i = 0; + while (i < inv.getSize()) { + inv.setItem(i, div); + i++; + } + + if (options.getName() == null) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name", '&')); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Name", '&')); + blockMeta.setLore(Arrays.asList(ChatColor.GRAY + options.getName())); + } + block.setItemMeta(blockMeta); + inv.setItem(3, block); + inv.setItem(4, block); + inv.setItem(5, block); + + if (options.getType() == null) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type", '&')); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Type", '&')); + blockMeta.setLore(Arrays.asList(ChatColor.GRAY + options.getType().toString())); + } + block.setItemMeta(blockMeta); + inv.setItem(10, block); + inv.setItem(11, block); + + if (options.getVersion() == null) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version", '&')); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Version", '&')); + blockMeta.setLore(Arrays.asList(ChatColor.GRAY + "v" + options.getVersion().toString())); + } + block.setItemMeta(blockMeta); + inv.setItem(15, block); + inv.setItem(16, block); + + if (options.getPort() <= 0) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port", '&')); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-Port", '&')); + blockMeta.setLore(Arrays.asList(ChatColor.GRAY.toString() + options.getPort())); + } + block.setItemMeta(blockMeta); + inv.setItem(28, block); + inv.setItem(29, block); + + if (options.getMemory() < 256) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM", '&')); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Edit-RAM", '&')); + blockMeta.setLore(Arrays.asList(ChatColor.GRAY.toString() + options.getMemory() + "MB")); + } + block.setItemMeta(blockMeta); + inv.setItem(33, block); + inv.setItem(34, block); + + if (!options.hasHistory()) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY + ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Undo", '&'))); + block.setItemMeta(blockMeta); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 1); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Undo", '&')); + block.setItemMeta(blockMeta); + } + block.setItemMeta(blockMeta); + inv.setItem(45, block); + inv.setItem(46, block); + + if (options.getName() == null || options.getType() == null || options.getVersion() == null || options.getPort() <= 0 && options.getMemory() < 256) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY + ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Submit", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Form-Incomplete", '&'))); + block.setItemMeta(blockMeta); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Host-Creator.Submit", '&')); + block.setItemMeta(blockMeta); + } + block.setItemMeta(blockMeta); + inv.setItem(48, block); + inv.setItem(49, block); + inv.setItem(50, block); + + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&')); + block.setItemMeta(blockMeta); + inv.setItem(52, block); + inv.setItem(53, block); + + Bukkit.getPlayer(player).openInventory(inv); + open = true; + } + })); + } + public static class CreatorOptions extends Options { + private String host; + private String name = null; + private PacketCreateServer.ServerType type = null; + private Version version = null; + private int memory = 1024; + private int port = -1; + + /** + * Grabs a raw CreatorOptions instance + * + * @param host Host Name + */ + public CreatorOptions(String host) { + this.host = host; + } + + /** + * Gets the Host Name + * + * @return Host Name + */ + public String getHost() { + return this.host; + } + + /** + * Gets the Server Name + * + * @return Server Name + */ + public String getName() { + return name; + } + + /** + * Sets the Server Name + * + * @param value Value + */ + public void setName(String value) { + final String name = this.name; + history.add(() -> this.name = name); + this.name = value; + } + + /** + * Gets the ServerType + * + * @return ServerType + */ + public PacketCreateServer.ServerType getType() { + return type; + } + + /** + * Sets the ServerType + * + * @param value Value + */ + public void setType(PacketCreateServer.ServerType value) { + final PacketCreateServer.ServerType type = this.type; + history.add(() -> this.type = type); + this.type = value; + } + + /** + * Gets the Server Version + * + * @return Server Version + */ + public Version getVersion() { + return version; + } + + /** + * Sets the Server Version + * + * @param value Value + */ + public void setVersion(Version value) { + final Version version = this.version; + history.add(() -> this.version = version); + this.version = value; + } + + /** + * Gets the RAM Amount for the Server + * + * @return Server RAM Amount (in MB) + */ + public int getMemory() { + return memory; + } + + /** + * Sets the RAM AMount for the Server + * + * @param value Value (in MB) + */ + public void setMemory(int value) { + final int memory = this.memory; + history.add(() -> this.memory = memory); + this.memory = value; + } + + /** + * Gets the Port Number for the Server + * + * @return Server Port Number + */ + public int getPort() { + return port; + } + + /** + * Sets the Port Number for the Server + * + * @param value Value + */ + public void setPort(int value) { + final int port = this.port; + history.add(() -> this.port = port); + this.port = value; + } + } + + /** + * Opens Hosts/<name>/Edit + * + * @param options Host Editor Options + */ + public void hostEditor(final HostEditorOptions options) { + lastUsedOptions = options; + if (!options.init()) { + windowHistory.add(() -> hostEditor(options)); + lastVistedObject = options.getHost(); + } + } + public static class HostEditorOptions extends Options { + private String host; + + /** + * Grabs a raw HostCreatorOptions instance + * + * @param host Host Name + */ + public HostEditorOptions(String host) { + this.host = host; + } + + /** + * Gets the Host Name + * + * @return Host Name + */ + public String getHost() { + return this.host; + } + } + + /** + * Opens the SubServer Menu + * + * @param page Page Number (starting from page 1) + * @param host Host Name (or null to scan all hosts) + */ + public void subserverMenu(final Integer page, final String host) { + setDownloading(ChatColor.stripColor((host == null)?plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.Title", '&'):plugin.lang.getSection("Lang").getColoredString("Interface.Host-SubServer.Title", '&').replace("$str$", host))); + plugin.subdata.sendPacket(new PacketDownloadServerList(host, UUID.randomUUID().toString(), json -> { + setDownloading(null); + lastPage = page; + + HashMap hosts = new HashMap(); + List subservers = new ArrayList(); + if (host != null) { + lastVistedObject = host; + for (String subserver : json.getJSONObject("hosts").getJSONObject(host).getJSONObject("servers").keySet()) { + hosts.put(subserver, host); + subservers.add(subserver); + } + } else { + lastVistedObject = null; + lastMenu = () -> subserverMenu(1, null); + for (String tmphost : json.getJSONObject("hosts").keySet()) { + for (String tmpsubserver : json.getJSONObject("hosts").getJSONObject(tmphost).getJSONObject("servers").keySet()) { + hosts.put(tmpsubserver, tmphost); + subservers.add(tmpsubserver); + } + } + } + windowHistory.add(() -> subserverMenu(page, host)); + + ItemStack block; + ItemMeta blockMeta; + ItemStack div = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 15); + ItemMeta divMeta = div.getItemMeta(); + divMeta.setDisplayName(ChatColor.RESET.toString()); + div.setItemMeta(divMeta); + + int i = 0; + int min = ((page - 1) * 36); + int max = (min + 35); + int count = (subservers.size() == 0)?27:((subservers.size() - min - 1 >= max)?36:subservers.size() - min); + int area = (count % 9 == 0) ? count : (int) (Math.floor(count / 9) + 1) * 9; + + Inventory inv = Bukkit.createInventory(null, 18 + area, (host == null)?plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.Title", '&'):plugin.lang.getSection("Lang").getColoredString("Interface.Host-SubServer.Title", '&').replace("$str$", host)); + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + block.setItemMeta(divMeta); + while (i < area) { + inv.setItem(i, block); + i++; + } + ItemStack adiv = block; + i = (int) ((count < 9) ? Math.floor((9 - count) / 2) : 0); + + boolean even = (count & 1) == 0 && count < 9; + short online, temp, offline, disabled; + + for (String subserver : subservers) { + if (subservers.indexOf(subserver) >= min && subservers.indexOf(subserver) <= max) { + if (even && (i == 4 || i == 13 || i == 22 || i == 31)) inv.setItem(i++, adiv); + online = (short) (((i & 1) == 0) ? 5 : 13); + temp = (short) (((i & 1) == 0) ? 3 : 11); + offline = (short) (((i & 1) == 0) ? 4 : 1); + disabled = (short) (((i & 1) == 0) ? 2 : 14); + + if (json.getJSONObject("hosts").getJSONObject(hosts.get(subserver)).getJSONObject("servers").getJSONObject(subserver).getBoolean("temp")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, temp); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.BLUE + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Player-Count", '&').replace("$int$", Integer.toString(json.getJSONObject("hosts").getJSONObject(hosts.get(subserver)).getJSONObject("servers").getJSONObject(subserver).getJSONObject("players").keySet().size())), plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Temporary", '&'))); + } else if (json.getJSONObject("hosts").getJSONObject(hosts.get(subserver)).getJSONObject("servers").getJSONObject(subserver).getBoolean("running")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, online); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Player-Count", '&').replace("$int$", Integer.toString(json.getJSONObject("hosts").getJSONObject(hosts.get(subserver)).getJSONObject("servers").getJSONObject(subserver).getJSONObject("players").keySet().size())))); + } else if (json.getJSONObject("hosts").getJSONObject(hosts.get(subserver)).getJSONObject("servers").getJSONObject(subserver).getBoolean("enabled")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, offline); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.YELLOW + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Offline", '&'))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, disabled); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Disabled", '&'))); + } + block.setItemMeta(blockMeta); + inv.setItem(i, block); + + count--; + if (count < 9 && (i == 8 || i == 17 || i == 26)) { + i += (int) Math.floor((9 - count) / 2) + 1; + even = (count & 1) == 0; + } else { + i++; + } + } + } + + if (subservers.size() == 0) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.No-SubServers", '&')); + block.setItemMeta(blockMeta); + inv.setItem(12, block); + inv.setItem(13, block); + inv.setItem(14, block); + } + + i = inv.getSize() - 18; + while (i < inv.getSize()) { + inv.setItem(i, div); + i++; + } + i = inv.getSize() - 9; + + if (min != 0) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back-Arrow", '&')); + block.setItemMeta(blockMeta); + inv.setItem(i++, block); + inv.setItem(i++, block); + } else i += 2; + i++; + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) ((host == null)?11:14)); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName((host == null)?plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.Host-Menu", '&'):plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&')); + block.setItemMeta(blockMeta); + inv.setItem(i++, block); + inv.setItem(i++, block); + inv.setItem(i++, block); + i++; + if (subservers.size() - 1 > max) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Next-Arrow", '&')); + block.setItemMeta(blockMeta); + inv.setItem(i++, block); + inv.setItem(i, block); + } + + Bukkit.getPlayer(player).openInventory(inv); + open = true; + })); + } + + /** + * Opens SubServer/<name> + * + * @param subserver SubServer Name + */ + public void subserverAdmin(final String subserver) { + setDownloading(ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Title", '&').replace("$str$", subserver))); + plugin.subdata.sendPacket(new PacketDownloadServerInfo(subserver, UUID.randomUUID().toString(), json -> { + windowHistory.add(() -> subserverAdmin(subserver)); + if (!json.getString("type").equals("subserver")) { + back(); + } else { + setDownloading(null); + lastVistedObject = subserver; + ItemStack block; + ItemMeta blockMeta; + ItemStack div = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 15); + ItemMeta divMeta = div.getItemMeta(); + divMeta.setDisplayName(ChatColor.RESET.toString()); + div.setItemMeta(divMeta); + + Inventory inv = Bukkit.createInventory(null, 36, plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Title", '&').replace("$str$", subserver)); + + int i = 0; + while (i < inv.getSize()) { + inv.setItem(i, div); + i++; + } + i = 0; + + if (json.getJSONObject("server").getBoolean("running")) { + if (!(Bukkit.getPlayer(player).hasPermission("subservers.subserver.terminate.*") || Bukkit.getPlayer(player).hasPermission("subservers.subserver.terminate." + subserver.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Terminate", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.subserver.terminate." + subserver.toLowerCase()))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Terminate", '&')); + } + + block.setItemMeta(blockMeta); + inv.setItem(1, block); + inv.setItem(10, block); + + if (!(Bukkit.getPlayer(player).hasPermission("subservers.subserver.stop.*") || Bukkit.getPlayer(player).hasPermission("subservers.subserver.stop." + subserver.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Stop", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.subserver.stop." + subserver.toLowerCase()))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 2); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Stop", '&')); + } + block.setItemMeta(blockMeta); + inv.setItem(2, block); + inv.setItem(3, block); + inv.setItem(11, block); + inv.setItem(12, block); + + if (!(Bukkit.getPlayer(player).hasPermission("subservers.subserver.command.*") || Bukkit.getPlayer(player).hasPermission("subservers.subserver.command." + subserver.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Command", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.subserver.command." + subserver.toLowerCase()))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Command", '&')); + } + block.setItemMeta(blockMeta); + inv.setItem(5, block); + inv.setItem(6, block); + inv.setItem(7, block); + inv.setItem(14, block); + inv.setItem(15, block); + inv.setItem(16, block); + + if (!(Bukkit.getPlayer(player).hasPermission("subservers.subserver.teleport.*") || Bukkit.getPlayer(player).hasPermission("subservers.subserver.teleport." + subserver.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Teleport", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.subserver.teleport." + subserver.toLowerCase()))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 11); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Teleport", '&')); + } + block.setItemMeta(blockMeta); + inv.setItem(27, block); + inv.setItem(28, block); + } else { + if (!(Bukkit.getPlayer(player).hasPermission("subservers.subserver.start.*") || Bukkit.getPlayer(player).hasPermission("subservers.subserver.start." + subserver.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Start", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.subserver.start." + subserver.toLowerCase()))); + } else if (!json.getJSONObject("server").getBoolean("enabled")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Start", '&'))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Start", '&')); + } + block.setItemMeta(blockMeta); + inv.setItem(1, block); + inv.setItem(2, block); + inv.setItem(3, block); + inv.setItem(10, block); + inv.setItem(11, block); + inv.setItem(12, block); + + if (!(Bukkit.getPlayer(player).hasPermission("subservers.subserver.edit.*") || Bukkit.getPlayer(player).hasPermission("subservers.subserver.edit." + subserver.toLowerCase()))) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Editor", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Invalid-Permission", '&').replace("$str$", "subservers.subserver.edit." + subserver.toLowerCase()))); + } else if (!json.getJSONObject("server").getBoolean("editable")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GRAY+ChatColor.stripColor(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Editor", '&'))); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Editor-Unavailable", '&'))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 1); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Admin.Editor", '&')); + + } + block.setItemMeta(blockMeta); + inv.setItem(5, block); + inv.setItem(6, block); + inv.setItem(7, block); + inv.setItem(14, block); + inv.setItem(15, block); + inv.setItem(16, block); + } + + if (json.getJSONObject("server").getBoolean("temp")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 11); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.BLUE + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Player-Count", '&').replace("$int$", Integer.toString(json.getJSONObject("server").getJSONObject("players").keySet().size())), plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Temporary", '&'))); + } else if (json.getJSONObject("server").getBoolean("running")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.GREEN + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Player-Count", '&').replace("$int$", Integer.toString(json.getJSONObject("server").getJSONObject("players").keySet().size())))); + } else if (json.getJSONObject("server").getBoolean("enabled")) { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 4); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.YELLOW + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Offline", '&'))); + } else { + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(ChatColor.RED + subserver); + blockMeta.setLore(Arrays.asList(plugin.lang.getSection("Lang").getColoredString("Interface.SubServer-Menu.SubServer-Disabled", '&'))); + } + block.setItemMeta(blockMeta); + inv.setItem(30, block); + inv.setItem(31, block); + inv.setItem(32, block); + + + block = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 14); + blockMeta = block.getItemMeta(); + blockMeta.setDisplayName(plugin.lang.getSection("Lang").getColoredString("Interface.Generic.Back", '&')); + block.setItemMeta(blockMeta); + inv.setItem(34, block); + inv.setItem(35, block); + + Bukkit.getPlayer(player).openInventory(inv); + open = true; + } + })); + + } + + /** + * Opens SubServer/<name>/Edit + * + * @param options SubServerEditorOptions + */ + public void subserverEditor(final SubServerEditorOptions options) { + lastUsedOptions = options; + if (!options.init()) { + windowHistory.add(() -> subserverEditor(options)); + lastVistedObject = options.getSubserver(); + } + } + public static class SubServerEditorOptions extends Options { + private List history = new LinkedList(); + private String subserver; + private boolean init = false; + + /** + * Grabs a raw SubServerEditorOptions instance + * + * @param subserver SubServer Name + */ + public SubServerEditorOptions(String subserver) { + this.subserver = subserver; + } + + /** + * Gets the SubServer Name + * + * @return SubServer Name + */ + public String getSubserver() { + return this.subserver; + } + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLConfig.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLConfig.java new file mode 100644 index 00000000..15558c06 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLConfig.java @@ -0,0 +1,65 @@ +package net.ME1312.SubServers.Client.Bukkit.Library.Config; + +import org.json.JSONObject; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Map; + +@SuppressWarnings("unused") +public class YAMLConfig { + private File file; + private Yaml yaml; + private YAMLSection config; + + @SuppressWarnings("unchecked") + public YAMLConfig(File file) throws IOException, YAMLException { + if (file.exists()) { + this.config = new YAMLSection((Map) (this.yaml = new Yaml(getDumperOptions())).load(new FileInputStream(this.file = file)), null, null, yaml); + } else { + this.config = new YAMLSection(null, null, null, yaml); + } + } + + public YAMLSection get() { + return config; + } + + public void set(YAMLSection yaml) { + config = yaml; + } + + @SuppressWarnings("unchecked") + public void reload() throws IOException { + config = new YAMLSection((Map) yaml.load(new FileInputStream(file)), null, null, yaml); + } + + public void save() throws IOException { + FileWriter writer = new FileWriter(file); + yaml.dump(config.map, writer); + writer.close(); + } + + @Override + public String toString() { + return yaml.dump(config.map); + } + + public JSONObject toJSON() { + return new JSONObject(config.map); + } + + protected static DumperOptions getDumperOptions() { + DumperOptions options = new DumperOptions(); + options.setAllowUnicode(true); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setIndent(4); + + return options; + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLSection.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLSection.java new file mode 100644 index 00000000..cb75e27b --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLSection.java @@ -0,0 +1,513 @@ +package net.ME1312.SubServers.Client.Bukkit.Library.Config; + +import org.bukkit.ChatColor; +import org.json.JSONObject; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; + +import java.io.InputStream; +import java.io.Reader; +import java.util.*; + +@SuppressWarnings({"unchecked", "unused"}) +public class YAMLSection { + protected Map map; + protected String label = null; + protected YAMLSection up = null; + private Yaml yaml; + + public YAMLSection() { + this.map = new HashMap<>(); + this.yaml = new Yaml(YAMLConfig.getDumperOptions()); + } + + public YAMLSection(InputStream io) throws YAMLException { + this.map = (Map) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).load(io); + } + + public YAMLSection(Reader reader) throws YAMLException { + this.map = (Map) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).load(reader); + } + + public YAMLSection(JSONObject json) { + this.map = (Map) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).load(json.toString(4)); + } + + public YAMLSection(String yaml) throws YAMLException { + this.map = (Map) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).load(yaml); + } + + protected YAMLSection(Map map, YAMLSection up, String label, Yaml yaml) { + this.map = new HashMap(); + this.yaml = yaml; + this.label = label; + this.up = up; + + if (map != null) { + for (String key : map.keySet()) { + this.map.put(key, map.get(key)); + } + } + } + + public Set getKeys() { + return map.keySet(); + } + + + public Collection getValues() { + List values = new ArrayList(); + for (String value : map.keySet()) { + values.add(new YAMLValue(map.get(value), this, value, yaml)); + } + return values; + } + + public boolean contains(String label) { + return map.keySet().contains(label); + } + + public void remove(String label) { + map.remove(label); + } + + public void clear() { + map.clear(); + } + + public void set(String label, Object value) { + if (value instanceof YAMLConfig) { // YAML Handler Values + ((YAMLConfig) value).get().up = this; + ((YAMLConfig) value).get().label = label; + map.put(label, ((YAMLConfig) value).get().map); + } else if (value instanceof YAMLSection) { + ((YAMLSection) value).up = this; + ((YAMLSection) value).label = label; + map.put(label, ((YAMLSection) value).map); + } else if (value instanceof YAMLValue) { + map.put(label, ((YAMLValue) value).asObject()); + } else { + map.put(label, value); + } + + if (this.label != null && this.up != null) { + this.up.set(this.label, this); + } + } + + public void setAll(Map values) { + for (String value : values.keySet()) { + set(value, values.get(value)); + } + } + + public void setAll(YAMLSection values) { + for (String value : values.map.keySet()) { + set(value, values.map.get(value)); + } + } + + public YAMLSection superSection() { + return up; + } + + @Override + public String toString() { + return yaml.dump(map); + } + + public JSONObject toJSON() { + return new JSONObject(map); + } + + public YAMLValue get(String label) { + return (map.get(label) != null)?(new YAMLValue(map.get(label), this, label, yaml)):null; + } + + public YAMLValue get(String label, Object def) { + return new YAMLValue((map.get(label) != null)?map.get(label):def, this, label, yaml); + } + + public YAMLValue get(String label, YAMLValue def) { + return (map.get(label) != null) ? (new YAMLValue(map.get(label), this, label, yaml)) : def; + } + + public List getList(String label) { + if (map.get(label) != null) { + List values = new ArrayList(); + for (Object value : (List) map.get(label)) { + values.add(new YAMLValue(value, null, null, yaml)); + } + return values; + } else { + return null; + } + } + + public List getList(String label, Collection def) { + if (map.get(label) != null) { + return getList(label); + } else { + List values = new ArrayList(); + for (Object value : def) { + values.add(new YAMLValue(value, null, null, yaml)); + } + return values; + } + } + + public List getList(String label, List def) { + if (map.get(label) != null) { + return getList(label); + } else { + List values = new ArrayList(); + for (YAMLValue value : def) { + values.add(value); + } + return values; + } + } + + public Object getObject(String label) { + return map.get(label); + } + + public Object getObject(String label, Object def) { + return (map.get(label) != null)?map.get(label):def; + } + + public List getObjectList(String label) { + return (List) map.get(label); + } + + public List getObjectList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public boolean getBoolean(String label) { + return (boolean) map.get(label); + } + + public boolean getBoolean(String label, boolean def) { + return (boolean) ((map.get(label) != null)?map.get(label):def); + } + + public List getBooleanList(String label) { + return (List) map.get(label); + } + + public List getBooleanList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public YAMLSection getSection(String label) { + return (map.get(label) != null)?(new YAMLSection((Map) map.get(label), this, label, yaml)):null; + } + + public YAMLSection getSection(String label, Map def) { + return new YAMLSection((Map) ((map.get(label) != null)?map.get(label):def), this, label, yaml); + } + + public YAMLSection getSection(String label, YAMLSection def) { + return (map.get(label) != null)?(new YAMLSection((Map) map.get(label), this, label, yaml)):def; + } + + public List getSectionList(String label) { + if (map.get(label) != null) { + List values = new ArrayList(); + for (Map value : (List>) map.get(label)) { + values.add(new YAMLSection(value, null, null, yaml)); + } + return values; + } else { + return null; + } + } + + public List getSectionList(String label, Collection> def) { + if (map.get(label) != null) { + return getSectionList(label); + } else { + List values = new ArrayList(); + for (Map value : def) { + values.add(new YAMLSection(value, null, null, yaml)); + } + return values; + } + } + + public List getSectionList(String label, List def) { + if (map.get(label) != null) { + return getSectionList(label); + } else { + List values = new ArrayList(); + for (YAMLSection value : def) { + values.add(value); + } + return values; + } + } + + public double getDouble(String label) { + return (double) map.get(label); + } + + public double getDouble(String label, double def) { + return (double) ((map.get(label) != null)?map.get(label):def); + } + + public List getDoubleList(String label) { + return (List) map.get(label); + } + + public List getDoubleList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public float getFloat(String label) { + return (float) map.get(label); + } + + public float getFloat(String label, float def) { + return (float) ((map.get(label) != null)?map.get(label):def); + } + + public List getFloatList(String label) { + return (List) map.get(label); + } + + public List getFloatList(String label, float def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public int getInt(String label) { + return (int) map.get(label); + } + + public int getInt(String label, int def) { + return (int) ((map.get(label) != null)?map.get(label):def); + } + + public List getIntList(String label) { + return (List) map.get(label); + } + + public List getIntList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public long getLong(String label) { + return (long) map.get(label); + } + + public long getLong(String label, long def) { + return (long) ((map.get(label) != null)?map.get(label):def); + } + + public List getLongList(String label) { + return (List) map.get(label); + } + + public List getLongList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public short getShort(String label) { + return (short) map.get(label); + } + + public short getShort(String label, short def) { + return (short) ((map.get(label) != null)?map.get(label):def); + } + + public List getShortList(String label) { + return (List) map.get(label); + } + + public List getShortList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public String getRawString(String label) { + return (String) map.get(label); + } + + public String getRawString(String label, String def) { + return (String) ((map.get(label) != null)?map.get(label):def); + } + + public List getRawStringList(String label) { + return (List) map.get(label); + } + + public List getRawStringList(String label, List def) { + return (List) ((map.get(label) != null)?map.get(label):def); + } + + public String getString(String label) { + return (map.get(label) != null)?unescapeJavaString((String) map.get(label)):null; + } + + public String getString(String label, String def) { + return unescapeJavaString((String) ((map.get(label) != null) ? map.get(label) : def)); + } + + public List getStringList(String label) { + if (map.get(label) != null) { + List values = new ArrayList(); + for (String value : (List) map.get(label)) { + values.add(unescapeJavaString(value)); + } + return values; + } else { + return null; + } + } + + public List getStringList(String label, List def) { + if (map.get(label) != null) { + return getStringList(label); + } else { + List values = new ArrayList(); + for (String value : def) { + values.add(unescapeJavaString(value)); + } + return values; + } + } + + public String getColoredString(String label, char color) { + return (map.get(label) != null)? ChatColor.translateAlternateColorCodes(color, unescapeJavaString((String) map.get(label))):null; + } + + public String getColoredString(String label, String def, char color) { + return ChatColor.translateAlternateColorCodes(color, unescapeJavaString((String) ((map.get(label) != null) ? map.get(label) : def))); + } + + public List getColoredStringList(String label, char color) { + if (map.get(label) != null) { + List values = new ArrayList(); + for (String value : (List) map.get(label)) { + values.add(ChatColor.translateAlternateColorCodes(color, unescapeJavaString(value))); + } + return values; + } else { + return null; + } + } + + public List getColoredStringList(String label, List def, char color) { + if (map.get(label) != null) { + return getColoredStringList(label, color); + } else { + List values = new ArrayList(); + for (String value : def) { + values.add(ChatColor.translateAlternateColorCodes(color, unescapeJavaString(value))); + } + return values; + } + } + + public boolean isBoolean(String label) { + return (map.get(label) instanceof Boolean); + } + + public boolean isSection(String label) { + return (map.get(label) instanceof Map); + } + + public boolean isDouble(String label) { + return (map.get(label) instanceof Double); + } + + public boolean isFloat(String label) { + return (map.get(label) instanceof Float); + } + + public boolean isInt(String label) { + return (map.get(label) instanceof Integer); + } + + public boolean isList(String label) { + return (map.get(label) instanceof List); + } + + public boolean isLong(String label) { + return (map.get(label) instanceof Long); + } + + public boolean isString(String label) { + return (map.get(label) instanceof String); + } + + static String unescapeJavaString(String str) { + + StringBuilder sb = new StringBuilder(str.length()); + + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch == '\\') { + char nextChar = (i == str.length() - 1) ? '\\' : str + .charAt(i + 1); + // Octal escape? + if (nextChar >= '0' && nextChar <= '7') { + String code = "" + nextChar; + i++; + if ((i < str.length() - 1) && str.charAt(i + 1) >= '0' + && str.charAt(i + 1) <= '7') { + code += str.charAt(i + 1); + i++; + if ((i < str.length() - 1) && str.charAt(i + 1) >= '0' + && str.charAt(i + 1) <= '7') { + code += str.charAt(i + 1); + i++; + } + } + sb.append((char) Integer.parseInt(code, 8)); + continue; + } + switch (nextChar) { + case '\\': + ch = '\\'; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + case '\"': + ch = '\"'; + break; + case '\'': + ch = '\''; + break; + // Hex Unicode: u???? + case 'u': + if (i >= str.length() - 5) { + ch = 'u'; + break; + } + int code = Integer.parseInt( + "" + str.charAt(i + 2) + str.charAt(i + 3) + + str.charAt(i + 4) + str.charAt(i + 5), 16); + sb.append(Character.toChars(code)); + i += 5; + continue; + } + i++; + } + sb.append(ch); + } + return sb.toString(); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLValue.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLValue.java new file mode 100644 index 00000000..0e21649e --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Config/YAMLValue.java @@ -0,0 +1,156 @@ +package net.ME1312.SubServers.Client.Bukkit.Library.Config; + +import org.bukkit.ChatColor; +import org.yaml.snakeyaml.Yaml; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@SuppressWarnings({"unchecked", "unused"}) +public class YAMLValue { + protected Object obj; + protected String label; + protected YAMLSection up; + private Yaml yaml; + + public YAMLValue(Object obj, YAMLSection up, String label, Yaml yaml) { + this.obj = obj; + this.label = label; + this.yaml = yaml; + this.up = up; + } + + public YAMLSection getDefiningSection() { + return up; + } + + public Object asObject() { + return obj; + } + + public List asObjectList() { + return (List) obj; + } + + public boolean asBoolean() { + return (boolean) obj; + } + + public List asBooleanList() { + return (List) obj; + } + + public YAMLSection asSection() { + return new YAMLSection((Map) obj, up, label, yaml); + } + + public List asSectionList() { + List values = new ArrayList(); + for (Map value : (List>) obj) { + values.add(new YAMLSection(value, null, null, yaml)); + } + return values; + } + + public double asDouble() { + return (double) obj; + } + + public List asDoubleList() { + return (List) obj; + } + + public float asFloat() { + return (float) obj; + } + + public List asFloatList() { + return (List) obj; + } + + public int asInt() { + return (int) obj; + } + + public List asIntList() { + return (List) obj; + } + + public long asLong() { + return (long) obj; + } + + public List asLongList() { + return (List) obj; + } + + public String asRawString() { + return (String) obj; + } + + public List asRawStringList() { + return (List) obj; + } + + public String asString() { + return YAMLSection.unescapeJavaString((String) obj); + } + + public List asStringList() { + List values = new ArrayList(); + for (String value : (List) obj) { + values.add(YAMLSection.unescapeJavaString(value)); + } + return values; + } + + public String asColoredString(char color) { + return ChatColor.translateAlternateColorCodes(color, YAMLSection.unescapeJavaString((String) obj)); + } + + public List asColoredStringList(char color) { + List values = new ArrayList(); + for (String value : (List) obj) { + values.add(ChatColor.translateAlternateColorCodes(color, YAMLSection.unescapeJavaString(value))); + } + return values; + } + + public boolean isBoolean() { + return (obj instanceof Boolean); + } + + public boolean isSection() { + return (obj instanceof Map); + } + + public boolean isDouble() { + return (obj instanceof Double); + } + + public boolean isFloat(String path) { + return (obj instanceof Float); + } + + public boolean isInt() { + return (obj instanceof Integer); + } + + public boolean isList() { + return (obj instanceof List); + } + + public boolean isLong() { + return (obj instanceof Long); + } + + public boolean isString() { + return (obj instanceof String); + } + + @Override + public String toString() { + return obj.toString(); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Container.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Container.java new file mode 100644 index 00000000..6f9b77a0 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Container.java @@ -0,0 +1,37 @@ +package net.ME1312.SubServers.Client.Bukkit.Library; + +/** + * Container Class + * + * @author ME1312 + */ +public class Container { + private V obj; + + /** + * Creates a Container + * + * @param item Object to Store + */ + public Container(V item) { + obj = item; + } + + /** + * Grabs the Object + * + * @return The Object + */ + public V get() { + return obj; + } + + /** + * Overwrite the Object + * + * @param value Object to Store + */ + public void set(V value) { + obj = value; + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Exception/IllegalPacketException.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Exception/IllegalPacketException.java new file mode 100644 index 00000000..69d9527f --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Exception/IllegalPacketException.java @@ -0,0 +1,8 @@ +package net.ME1312.SubServers.Client.Bukkit.Library.Exception; + +public class IllegalPacketException extends IllegalStateException { + public IllegalPacketException() {} + public IllegalPacketException(String s) { + super(s); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/JSONCallback.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/JSONCallback.java new file mode 100644 index 00000000..6c9af10a --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/JSONCallback.java @@ -0,0 +1,7 @@ +package net.ME1312.SubServers.Client.Bukkit.Library; + +import org.json.JSONObject; + +public interface JSONCallback { + void run(JSONObject json); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/NamedContainer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/NamedContainer.java new file mode 100644 index 00000000..dfa384b0 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/NamedContainer.java @@ -0,0 +1,34 @@ +package net.ME1312.SubServers.Client.Bukkit.Library; + +public class NamedContainer extends Container { + private T name; + + /** + * Creates a TaggedContainer + * + * @param name Tag to Bind + * @param item Object to Store + */ + public NamedContainer(T name, V item) { + super(item); + this.name = name; + } + + /** + * Gets the name of the Container + * + * @return Container name + */ + public T name() { + return name; + } + + /** + * Renames the Container + * + * @param name New Container Name + */ + public void rename(T name) { + this.name = name; + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/SubEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/SubEvent.java new file mode 100644 index 00000000..46a2fd56 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/SubEvent.java @@ -0,0 +1,7 @@ +package net.ME1312.SubServers.Client.Bukkit.Library; + +public interface SubEvent { + /* + This Class is used to define a SubEvent + */ +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/UniversalFile.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/UniversalFile.java new file mode 100644 index 00000000..56ebd5d3 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/UniversalFile.java @@ -0,0 +1,72 @@ +package net.ME1312.SubServers.Client.Bukkit.Library; + +import java.io.File; + +/** + * Universal File Class + * + * @author ME1312 + */ +public class UniversalFile extends File { + + /** + * Creates a File Link. Path names are separated by ':' + * + * @param pathname Path name + */ + public UniversalFile(String pathname) { + super(pathname.replace(".:", System.getProperty("user.dir") + ":").replace(':', File.separatorChar)); + } + + /** + * Creates a File Link. Path names are separated by the divider + * + * @param pathname Path name + * @param divider Divider to use + */ + public UniversalFile(String pathname, char divider) { + super(pathname.replace("." + divider, System.getProperty("user.dir") + divider).replace(divider, File.separatorChar)); + } + + /** + * Creates a File Link. + * + * @see File + * @param file File + */ + public UniversalFile(File file) { + super(file.getPath()); + } + + /** + * Creates a File. Path names are separated by the ':' + * + * @see File + * @param parent Parent File + * @param child Path name + */ + public UniversalFile(File parent, String child) { + super(parent, child.replace(':', File.separatorChar)); + } + + /** + * Creates a File. Path names are separated by the divider + * + * @see File + * @param parent Parent File + * @param child Path name + * @param divider Divider to use + */ + public UniversalFile(File parent, String child, char divider) { + super(parent, child.replace(divider, File.separatorChar)); + } + + /** + * Gets the Universal File Path (separated by ':') + * + * @return + */ + public String getUniversalPath() { + return getPath().replace(File.separatorChar, ':'); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Util.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Util.java new file mode 100644 index 00000000..2d875b02 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Util.java @@ -0,0 +1,111 @@ +package net.ME1312.SubServers.Client.Bukkit.Library; + +import java.io.*; + +public final class Util { + public static String readAll(Reader rd) throws IOException { + StringBuilder sb = new StringBuilder(); + int cp; + while ((cp = rd.read()) != -1) { + sb.append((char) cp); + } + return sb.toString(); + } + + public static void copyFromJar(ClassLoader loader, String resource, String destination) { + InputStream resStreamIn = loader.getResourceAsStream(resource); + File resDestFile = new File(destination); + try { + OutputStream resStreamOut = new FileOutputStream(resDestFile); + int readBytes; + byte[] buffer = new byte[4096]; + while ((readBytes = resStreamIn.read(buffer)) > 0) { + resStreamOut.write(buffer, 0, readBytes); + } + resStreamOut.close(); + resStreamIn.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static boolean isException(Runnable runnable) { + try { + runnable.run(); + return false; + } catch (Throwable e) { + return true; + } + } + + public static String unescapeJavaString(String str) { + + StringBuilder sb = new StringBuilder(str.length()); + + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch == '\\') { + char nextChar = (i == str.length() - 1) ? '\\' : str + .charAt(i + 1); + // Octal escape? + if (nextChar >= '0' && nextChar <= '7') { + String code = "" + nextChar; + i++; + if ((i < str.length() - 1) && str.charAt(i + 1) >= '0' + && str.charAt(i + 1) <= '7') { + code += str.charAt(i + 1); + i++; + if ((i < str.length() - 1) && str.charAt(i + 1) >= '0' + && str.charAt(i + 1) <= '7') { + code += str.charAt(i + 1); + i++; + } + } + sb.append((char) Integer.parseInt(code, 8)); + continue; + } + switch (nextChar) { + case '\\': + ch = '\\'; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + case '\"': + ch = '\"'; + break; + case '\'': + ch = '\''; + break; + // Hex Unicode: u???? + case 'u': + if (i >= str.length() - 5) { + ch = 'u'; + break; + } + int code = Integer.parseInt( + "" + str.charAt(i + 2) + str.charAt(i + 3) + + str.charAt(i + 4) + str.charAt(i + 5), 16); + sb.append(Character.toChars(code)); + i += 5; + continue; + } + i++; + } + sb.append(ch); + } + return sb.toString(); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/Version.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/Version.java new file mode 100644 index 00000000..433f4b15 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/Version.java @@ -0,0 +1,224 @@ +package net.ME1312.SubServers.Client.Bukkit.Library.Version; + +import java.io.Serializable; + +/** + * Version Class + * + * @author ME1312 + */ +@SuppressWarnings("serial") +public class Version implements Serializable, Comparable { + private String string; + + /** + * Creates a Version + * + * @param string Version String + */ + public Version(String string) { + this.string = string; + } + + + /** + * Creates a Version + * + * @param ints Version Numbers (Will be separated with dots) + */ + public Version(Integer... ints) { + String string = Integer.toString(ints[0]); + int i = 0; + if (ints.length != 1) { + do { + i++; + string = string + "." + ints[i]; + } while ((i + 1) != ints.length); + } + this.string = string; + } + + @Override + public String toString() { + return string; + } + + /** + * See if Versions are Equal + * + * @param version Version to Compare + * @return + */ + public boolean equals(Version version) { + return compareTo(version) == 0; + } + + /* + * Returns 1 if Greater than + * Returns 0 if Equal + * Returns -1 if Less than + *//** + * + * Compare Versions + * + * @param version The version to compare to + */ + public int compareTo(Version version) { + String version1 = this.string; + String version2 = version.toString(); + + VersionTokenizer tokenizer1 = new VersionTokenizer(version1); + VersionTokenizer tokenizer2 = new VersionTokenizer(version2); + + int number1 = 0, number2 = 0; + String suffix1 = "", suffix2 = ""; + + while (tokenizer1.MoveNext()) { + if (!tokenizer2.MoveNext()) { + do { + number1 = tokenizer1.getNumber(); + suffix1 = tokenizer1.getSuffix(); + if (number1 != 0 || suffix1.length() != 0) { + // Version one is longer than number two, and non-zero + return 1; + } + } + while (tokenizer1.MoveNext()); + + // Version one is longer than version two, but zero + return 0; + } + + number1 = tokenizer1.getNumber(); + suffix1 = tokenizer1.getSuffix(); + number2 = tokenizer2.getNumber(); + suffix2 = tokenizer2.getSuffix(); + + if (number1 < number2) { + // Number one is less than number two + return -1; + } + if (number1 > number2) { + // Number one is greater than number two + return 1; + } + + boolean empty1 = suffix1.length() == 0; + boolean empty2 = suffix2.length() == 0; + + if (empty1 && empty2) continue; // No suffixes + if (empty1) return 1; // First suffix is empty (1.2 > 1.2b) + if (empty2) return -1; // Second suffix is empty (1.2a < 1.2) + + // Lexical comparison of suffixes + int result = suffix1.compareTo(suffix2); + if (result != 0) return result; + + } + if (tokenizer2.MoveNext()) { + do { + number2 = tokenizer2.getNumber(); + suffix2 = tokenizer2.getSuffix(); + if (number2 != 0 || suffix2.length() != 0) { + // Version one is longer than version two, and non-zero + return -1; + } + } + while (tokenizer2.MoveNext()); + + // Version two is longer than version one, but zero + return 0; + } + return 0; + } + + /** + * See if Versions are Equal + * + * @param ver1 Version to Compare + * @param ver2 Version to Compare + * @return + */ + public static boolean isEqual(Version ver1, Version ver2) { + return compare(ver1, ver2) == 0; + } + + /* + * Returns 1 if Greater than + * Returns 0 if Equal + * Returns -1 if Less than + *//** + * Compare Versions + * + * @param ver1 Version to Compare + * @param ver2 Version to Compare + */ + public static int compare(Version ver1, Version ver2) { + String version1 = ver1.toString(); + String version2 = ver2.toString(); + + VersionTokenizer tokenizer1 = new VersionTokenizer(version1); + VersionTokenizer tokenizer2 = new VersionTokenizer(version2); + + int number1 = 0, number2 = 0; + String suffix1 = "", suffix2 = ""; + + while (tokenizer1.MoveNext()) { + if (!tokenizer2.MoveNext()) { + do { + number1 = tokenizer1.getNumber(); + suffix1 = tokenizer1.getSuffix(); + if (number1 != 0 || suffix1.length() != 0) { + // Version one is longer than number two, and non-zero + return 1; + } + } + while (tokenizer1.MoveNext()); + + // Version one is longer than version two, but zero + return 0; + } + + number1 = tokenizer1.getNumber(); + suffix1 = tokenizer1.getSuffix(); + number2 = tokenizer2.getNumber(); + suffix2 = tokenizer2.getSuffix(); + + if (number1 < number2) { + // Number one is less than number two + return -1; + } + if (number1 > number2) { + // Number one is greater than number two + return 1; + } + + boolean empty1 = suffix1.length() == 0; + boolean empty2 = suffix2.length() == 0; + + if (empty1 && empty2) continue; // No suffixes + if (empty1) return 1; // First suffix is empty (1.2 > 1.2b) + if (empty2) return -1; // Second suffix is empty (1.2a < 1.2) + + // Lexical comparison of suffixes + int result = suffix1.compareTo(suffix2); + if (result != 0) return result; + + } + if (tokenizer2.MoveNext()) { + do { + number2 = tokenizer2.getNumber(); + suffix2 = tokenizer2.getSuffix(); + if (number2 != 0 || suffix2.length() != 0) { + // Version one is longer than version two, and non-zero + return -1; + } + } + while (tokenizer2.MoveNext()); + + // Version two is longer than version one, but zero + return 0; + } + return 0; + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/VersionTokenizer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/VersionTokenizer.java new file mode 100644 index 00000000..56c8f322 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Library/Version/VersionTokenizer.java @@ -0,0 +1,64 @@ +package net.ME1312.SubServers.Client.Bukkit.Library.Version; + +public final class VersionTokenizer { + private final String _versionString; + private final int _length; + + private int _position; + private int _number; + private String _suffix; + private boolean _hasValue; + + protected int getNumber() { + return _number; + } + + protected String getSuffix() { + return _suffix; + } + + protected boolean hasValue() { + return _hasValue; + } + + protected VersionTokenizer(String versionString) { + if (versionString == null) + throw new IllegalArgumentException("versionString is null"); + + _versionString = versionString; + _length = versionString.length(); + } + + protected boolean MoveNext() { + _number = 0; + _suffix = ""; + _hasValue = false; + + // No more characters + if (_position >= _length) + return false; + + _hasValue = true; + + while (_position < _length) { + char c = _versionString.charAt(_position); + if (c < '0' || c > '9') break; + _number = _number * 10 + (c - '0'); + _position++; + } + + int suffixStart = _position; + + while (_position < _length) { + char c = _versionString.charAt(_position); + if (c == '.') break; + _position++; + } + + _suffix = _versionString.substring(suffixStart, _position); + + if (_position < _length) _position++; + + return true; + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketAuthorization.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketAuthorization.java new file mode 100644 index 00000000..adcf53c4 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketAuthorization.java @@ -0,0 +1,45 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import net.ME1312.SubServers.Client.Bukkit.SubPlugin; +import org.bukkit.Bukkit; +import org.json.JSONObject; + +import java.io.IOException; + +public class PacketAuthorization implements PacketIn, PacketOut { + private SubPlugin plugin; + + public PacketAuthorization(SubPlugin plugin) { + this.plugin = plugin; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("password", plugin.pluginconf.get().getSection("Settings").getSection("SubData").getString("Password")); + return json; + } + + @Override + public void execute(JSONObject data) { + try { + if (data.getInt("r") == 0) { + plugin.subdata.sendPacket(new PacketLinkServer(plugin)); + plugin.subdata.sendPacket(new PacketDownloadLang()); + } else { + Bukkit.getLogger().info("SubServers > Could not authorize SubData connection: " + data.getString("m")); + plugin.subdata.destroy(false); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCommandServer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCommandServer.java new file mode 100644 index 00000000..aa1de353 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCommandServer.java @@ -0,0 +1,55 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.UUID; + +public class PacketCommandServer implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private UUID player; + private String server; + private String command; + private String id; + + public PacketCommandServer() {} + public PacketCommandServer(String server, String command, String id, JSONCallback callback) { + this.player = null; + this.server = server; + this.command = command; + this.id = id; + callbacks.put(id, callback); + } + public PacketCommandServer(UUID player, String server, String command, String id, JSONCallback callback) { + this.player = player; + this.server = server; + this.command = command; + this.id = id; + callbacks.put(id, callback); + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (player != null) json.put("player", player.toString()); + json.put("server", server); + json.put("command", command); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCreateServer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCreateServer.java new file mode 100644 index 00000000..dc4ee13b --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketCreateServer.java @@ -0,0 +1,108 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Graphic.UIRenderer; +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.UUID; + +public class PacketCreateServer implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + public enum ServerType { + SPIGOT, + VANILLA, + SPONGE,; + + @Override + public String toString() { + return super.toString().substring(0, 1).toUpperCase()+super.toString().substring(1).toLowerCase(); + } + } + private UUID player; + private String name; + private String host; + private ServerType type; + private Version version; + private int port; + private int ram; + private String id; + + public PacketCreateServer() {} + public PacketCreateServer(String name, String host, ServerType type, Version version, int port, int memory, String id, JSONCallback callback) { + this.player = null; + this.name = name; + this.host = host; + this.type = type; + this.version = version; + this.port = port; + this.ram = memory; + this.id = id; + callbacks.put(id, callback); + } + public PacketCreateServer(UUID player, String name, String host, ServerType type, Version version, int port, int memory, String id, JSONCallback callback) { + this.player = player; + this.name = name; + this.host = host; + this.type = type; + this.version = version; + this.port = port; + this.ram = memory; + this.id = id; + callbacks.put(id, callback); + } + public PacketCreateServer(UIRenderer.CreatorOptions options, String id, JSONCallback callback) { + this.player = null; + this.name = options.getName(); + this.host = options.getHost(); + this.type = options.getType(); + this.version = options.getVersion(); + this.port = options.getPort(); + this.ram = options.getMemory(); + this.id = id; + callbacks.put(id, callback); + + } + public PacketCreateServer(UUID player, UIRenderer.CreatorOptions options, String id, JSONCallback callback) { + this.player = player; + this.name = options.getName(); + this.host = options.getHost(); + this.type = options.getType(); + this.version = options.getVersion(); + this.port = options.getPort(); + this.ram = options.getMemory(); + this.id = id; + callbacks.put(id, callback); + + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (player != null) json.put("player", player.toString()); + JSONObject creator = new JSONObject(); + creator.put("name", name); + creator.put("host", host); + creator.put("type", type.toString()); + creator.put("version", version.toString()); + creator.put("port", port); + creator.put("ram", ram); + json.put("creator", creator); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadHostInfo.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadHostInfo.java new file mode 100644 index 00000000..6863defa --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadHostInfo.java @@ -0,0 +1,41 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; + +public class PacketDownloadHostInfo implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private String host; + private String id; + + public PacketDownloadHostInfo() {} + public PacketDownloadHostInfo(String host, String id, JSONCallback callback) { + this.host = host; + this.id = id; + callbacks.put(id, callback); + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (host != null) json.put("host", host); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadLang.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadLang.java new file mode 100644 index 00000000..edeee8d9 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadLang.java @@ -0,0 +1,38 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.Config.YAMLSection; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import net.ME1312.SubServers.Client.Bukkit.SubPlugin; +import org.bukkit.Bukkit; +import org.json.JSONObject; + +import java.util.Calendar; + +public class PacketDownloadLang implements PacketIn, PacketOut { + private SubPlugin plugin; + + public PacketDownloadLang() {}; + + public PacketDownloadLang(SubPlugin plugin) { + this.plugin = plugin; + } + + @Override + public JSONObject generate() { + return null; + } + + @Override + public void execute(JSONObject data) { + data.put("Updated", Calendar.getInstance().getTime().getTime()); + plugin.lang = new YAMLSection(data); + Bukkit.getLogger().info("SubData > Lang Settings Downloaded"); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadPlayerList.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadPlayerList.java new file mode 100644 index 00000000..3f213961 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadPlayerList.java @@ -0,0 +1,36 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class PacketDownloadPlayerList implements PacketIn, PacketOut { + private List callbacks = new ArrayList(); + + public PacketDownloadPlayerList() {} + + @Override + public JSONObject generate() { + return null; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(0).run(data); + callbacks.remove(0); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } + + public void callback(String id, JSONCallback callback) { + callbacks.add(callback); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerInfo.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerInfo.java new file mode 100644 index 00000000..12a2154c --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerInfo.java @@ -0,0 +1,44 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class PacketDownloadServerInfo implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private String server; + private String id; + + public PacketDownloadServerInfo(String server, String id, JSONCallback callback) { + this.server = server; + this.id = id; + callbacks.put(id, callback); + } + + public PacketDownloadServerInfo() {} + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + json.put("server", server); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerList.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerList.java new file mode 100644 index 00000000..d1f3a634 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketDownloadServerList.java @@ -0,0 +1,41 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; + +public class PacketDownloadServerList implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private String host; + private String id; + + public PacketDownloadServerList() {} + public PacketDownloadServerList(String host, String id, JSONCallback callback) { + this.host = host; + this.id = id; + callbacks.put(id, callback); + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (host != null) json.put("host", host); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInRunEvent.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInRunEvent.java new file mode 100644 index 00000000..5bd5bcac --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInRunEvent.java @@ -0,0 +1,92 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Event.*; +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import org.bukkit.Bukkit; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +public class PacketInRunEvent implements PacketIn { + private HashMap> callbacks = new HashMap>(); + + public PacketInRunEvent() { + callback("SubAddServerEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubAddServerEvent(UUID.fromString(json.getString("player")), json.getString("host"), json.getString("server"))); + callback("SubAddServerEvent", this); + } + }); + callback("SubCreateEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubCreateEvent(UUID.fromString(json.getString("player")), json.getString("host"), json.getString("server"), + PacketCreateServer.ServerType.valueOf(json.getString("").toUpperCase()), new Version(json.getString("version")), json.getInt("memory"), json.getInt("port"))); + callback("SubCreateEvent", this); + } + }); + callback("SubSendCommandEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubSendCommandEvent(UUID.fromString(json.getString("player")), json.getString("server"), json.getString("command"))); + callback("SubSendCommandEvent", this); + } + }); + callback("SubStartEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubStartEvent(UUID.fromString(json.getString("player")), json.getString("server"))); + callback("SubStartEvent", this); + } + }); + callback("SubStopEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubStopEvent(UUID.fromString(json.getString("player")), json.getString("server"), json.getBoolean("force"))); + callback("SubStopEvent", this); + } + }); + callback("SubStoppedEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubStoppedEvent(json.getString("server"))); + callback("SubStoppedEvent", this); + } + }); + callback("SubRemoveServerEvent", new JSONCallback() { + @Override + public void run(JSONObject json) { + Bukkit.getPluginManager().callEvent(new SubRemoveServerEvent(UUID.fromString(json.getString("player")), json.getString("host"), json.getString("server"))); + callback("SubRemoveServerEvent", this); + } + }); + } + + @Override + public void execute(JSONObject data) { + if (callbacks.keySet().contains(data.getString("type"))) { + List callbacks = this.callbacks.get(data.getString("type")); + this.callbacks.remove(data.getString("type")); + for (JSONCallback callback : callbacks) { + callback.run(data.getJSONObject("args")); + } + } + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } + + public void callback(String event, JSONCallback callback) { + List callbacks = (this.callbacks.keySet().contains(event))?this.callbacks.get(event):new ArrayList(); + callbacks.add(callback); + this.callbacks.put(event, callbacks); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInShutdown.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInShutdown.java new file mode 100644 index 00000000..8aa37023 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInShutdown.java @@ -0,0 +1,21 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import org.bukkit.Bukkit; +import org.json.JSONObject; + +public class PacketInShutdown implements PacketIn { + + @Override + public void execute(JSONObject data) { + if (data != null && data.keySet().contains("m")) Bukkit.getLogger().warning("SubData > Received request for a server shutdown: " + data.getString("m")); + else Bukkit.getLogger().warning("SubData > Received request for a server shutdown"); + Bukkit.shutdown(); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInfoPassthrough.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInfoPassthrough.java new file mode 100644 index 00000000..9025f868 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketInfoPassthrough.java @@ -0,0 +1,44 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Event.SubDataRecieveGenericInfoEvent; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.bukkit.Bukkit; +import org.json.JSONObject; + +public class PacketInfoPassthrough implements PacketIn, PacketOut { + private String t; + private String h; + private Version v; + private JSONObject c; + + public PacketInfoPassthrough() {} + public PacketInfoPassthrough(String target, String handle, Version version, JSONObject content) { + this.t = target; + this.h = handle; + this.v = version; + this.c = content; + } + + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("t", t); + json.put("h", h); + json.put("v", v.toString()); + json.put("c", c); + return json; + } + + @Override + public void execute(JSONObject data) { + Bukkit.getPluginManager().callEvent(new SubDataRecieveGenericInfoEvent(data.getString("h"), new Version(data.getString("v")), data.getJSONObject("c"))); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketLinkServer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketLinkServer.java new file mode 100644 index 00000000..98a917e9 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketLinkServer.java @@ -0,0 +1,35 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import net.ME1312.SubServers.Client.Bukkit.SubPlugin; +import org.bukkit.Bukkit; +import org.json.JSONObject; + +public class PacketLinkServer implements PacketIn, PacketOut { + private SubPlugin plugin; + + public PacketLinkServer(SubPlugin plugin) { + this.plugin = plugin; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("name", plugin.subdata.getName()); + return json; + } + + @Override + public void execute(JSONObject data) { + if (data.getInt("r") != 0) { + Bukkit.getLogger().info("SubData > Could not link name with server: " + data.getString("m")); + } + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStartServer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStartServer.java new file mode 100644 index 00000000..ed0e8d8a --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStartServer.java @@ -0,0 +1,51 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.UUID; + +public class PacketStartServer implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private UUID player; + private String server; + private String id; + + public PacketStartServer() {} + public PacketStartServer(String server, String id, JSONCallback callback) { + this.player = null; + this.server = server; + this.id = id; + callbacks.put(id, callback); + } + public PacketStartServer(UUID player, String server, String id, JSONCallback callback) { + this.player = player; + this.server = server; + this.id = id; + callbacks.put(id, callback); + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (player != null) json.put("player", player.toString()); + json.put("server", server); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStopServer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStopServer.java new file mode 100644 index 00000000..9cc59d24 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketStopServer.java @@ -0,0 +1,55 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.UUID; + +public class PacketStopServer implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private UUID player; + private boolean force; + private String server; + private String id; + + public PacketStopServer() {} + public PacketStopServer(String server, boolean force, String id, JSONCallback callback) { + this.player = null; + this.server = server; + this.force = force; + this.id = id; + callbacks.put(id, callback); + } + public PacketStopServer(UUID player, String server, boolean force, String id, JSONCallback callback) { + this.player = player; + this.server = server; + this.force = force; + this.id = id; + callbacks.put(id, callback); + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (player != null) json.put("player", player.toString()); + json.put("server", server); + json.put("force", force); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketTeleportPlayer.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketTeleportPlayer.java new file mode 100644 index 00000000..073460f7 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/Packet/PacketTeleportPlayer.java @@ -0,0 +1,45 @@ +package net.ME1312.SubServers.Client.Bukkit.Network.Packet; + +import net.ME1312.SubServers.Client.Bukkit.Library.JSONCallback; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketIn; +import net.ME1312.SubServers.Client.Bukkit.Network.PacketOut; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.UUID; + +public class PacketTeleportPlayer implements PacketIn, PacketOut { + private static HashMap callbacks = new HashMap(); + private UUID player; + private String server; + private String id; + + public PacketTeleportPlayer() {} + public PacketTeleportPlayer(UUID player, String server, String id, JSONCallback callback) { + this.player = player; + this.server = server; + this.id = id; + callbacks.put(id, callback); + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + json.put("player", player.toString()); + json.put("server", server); + return json; + } + + @Override + public void execute(JSONObject data) { + callbacks.get(data.getString("id")).run(data); + callbacks.remove(data.getString("id")); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketIn.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketIn.java new file mode 100644 index 00000000..bce372b8 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketIn.java @@ -0,0 +1,25 @@ +package net.ME1312.SubServers.Client.Bukkit.Network; + +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import org.json.JSONObject; + +/** + * PacketIn Layout Class + * + * @author ME1312 + */ +public interface PacketIn { + /** + * Execute Incoming Packet + * + * @param data Incoming Data + */ + void execute(JSONObject data); + + /** + * Get Packet Version + * + * @return Packet Version + */ + Version getVersion(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketOut.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketOut.java new file mode 100644 index 00000000..8d54e3b6 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/PacketOut.java @@ -0,0 +1,25 @@ +package net.ME1312.SubServers.Client.Bukkit.Network; + +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import org.json.JSONObject; + +/** + * PacketOut Layout Class + * + * @author ME1312 + */ +public interface PacketOut { + /** + * Generate JSON Packet Contents + * + * @return Packet Contents + */ + JSONObject generate(); + + /** + * Get Packet Version + * + * @return Packet Version + */ + Version getVersion(); +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/SubDataClient.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/SubDataClient.java new file mode 100644 index 00000000..a1f05f25 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/SubDataClient.java @@ -0,0 +1,241 @@ +package net.ME1312.SubServers.Client.Bukkit.Network; + +import net.ME1312.SubServers.Client.Bukkit.Library.Exception.IllegalPacketException; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.Packet.*; +import net.ME1312.SubServers.Client.Bukkit.SubPlugin; +import org.bukkit.Bukkit; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.net.InetAddress; +import java.net.Socket; +import java.util.HashMap; + +public final class SubDataClient { + private static HashMap, String> pOut = new HashMap, String>(); + private static HashMap pIn = new HashMap(); + private static boolean defaults = false; + private PrintWriter writer; + private Socket socket; + private String name; + private SubPlugin plugin; + + /** + * SubServers Client Instance + * + * @param plugin SubPlugin + * @param address Bind Address + * @param port Port + * @throws IOException + */ + public SubDataClient(SubPlugin plugin, String name, InetAddress address, int port) throws IOException { + socket = new Socket(address, port); + this.plugin = plugin; + this.name = name; + this.writer = new PrintWriter(socket.getOutputStream(), true); + + if (!defaults) loadDefaults(); + loop(); + + Bukkit.getScheduler().runTaskLater(plugin, () -> sendPacket(new PacketAuthorization(plugin)), 10); + } + + private void loadDefaults() { + defaults = true; + + registerPacket(new PacketAuthorization(plugin), "Authorization"); + registerPacket(new PacketCommandServer(), "SubCommandServer"); + registerPacket(new PacketCreateServer(), "SubCreateServer"); + registerPacket(new PacketDownloadHostInfo(), "SubDownloadHostInfo"); + registerPacket(new PacketDownloadLang(plugin), "SubDownloadLang"); + registerPacket(new PacketDownloadPlayerList(), "SubDownloadPlayerList"); + registerPacket(new PacketDownloadServerInfo(), "SubDownloadServerInfo"); + registerPacket(new PacketDownloadServerList(), "SubDownloadServerList"); + registerPacket(new PacketInfoPassthrough(), "SubInfoPassthrough"); + registerPacket(new PacketInRunEvent(), "SubRunEvent"); + registerPacket(new PacketInShutdown(), "SubShutdown"); + registerPacket(new PacketLinkServer(plugin), "SubLinkServer"); + registerPacket(new PacketStartServer(), "SubStartServer"); + registerPacket(new PacketStopServer(), "SubStopServer"); + registerPacket(new PacketTeleportPlayer(), "SubTeleportPlayer"); + + registerPacket(PacketAuthorization.class, "Authorization"); + registerPacket(PacketCommandServer.class, "SubCommandServer"); + registerPacket(PacketCreateServer.class, "SubCreateServer"); + registerPacket(PacketDownloadHostInfo.class, "SubDownloadHostInfo"); + registerPacket(PacketDownloadLang.class, "SubDownloadLang"); + registerPacket(PacketDownloadPlayerList.class, "SubDownloadPlayerList"); + registerPacket(PacketDownloadServerInfo.class, "SubDownloadServerInfo"); + registerPacket(PacketDownloadServerList.class, "SubDownloadServerList"); + registerPacket(PacketInfoPassthrough.class, "SubInfoPassthrough"); + registerPacket(PacketLinkServer.class, "SubLinkServer"); + registerPacket(PacketStartServer.class, "SubStartServer"); + registerPacket(PacketStopServer.class, "SubStopServer"); + registerPacket(PacketTeleportPlayer.class, "SubTeleportPlayer"); + } + + private void loop() { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String input; + while ((input = in.readLine()) != null) { + try { + JSONObject json = new JSONObject(input); + PacketIn packet = decodePacket(json); + try { + packet.execute((json.keySet().contains("c")) ? json.getJSONObject("c") : null); + } catch (Exception e) { + new InvocationTargetException(e, "Exception while executing PacketIn").printStackTrace(); + } + } catch (IllegalPacketException e) { + e.printStackTrace(); + } catch (JSONException e) { + new IllegalPacketException("Unknown Packet Format: " + input).printStackTrace(); + } + } + try { + destroy(true); + } catch (IOException e1) { + e1.printStackTrace(); + } + } catch (Exception e) { + if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace(); + try { + destroy(true); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + }); + } + + /** + * Gets the Assigned Server Name + * + * @return Server Name + */ + public String getName() { + return name; + } + + /** + * Gets the Server Socket + * + * @return Server Socket + */ + public Socket getClient() { + return socket; + } + + /** + * Register Packet to the Network + * + * @param packet PacketIn to register + * @param handle Handle to Bind + */ + public static void registerPacket(PacketIn packet, String handle) { + pIn.put(handle, packet); + } + + /** + * Register Packet to the Network + * + * @param packet PacketOut to register + * @param handle Handle to bind + */ + public static void registerPacket(Class packet, String handle) { + pOut.put(packet, handle); + } + + /** + * Grab PacketIn Instance via handle + * + * @param handle Handle + * @return PacketIn + */ + public static PacketIn getPacket(String handle) { + return pIn.get(handle); + } + + /** + * Send Packet to Client + * + * @param packet Packet to send + */ + public void sendPacket(PacketOut packet) { + try { + writer.println(encodePacket(packet)); + } catch (IllegalPacketException e) { + e.printStackTrace(); + } + } + + /** + * JSON Encode PacketOut + * + * @param packet PacketOut + * @return JSON Formatted Packet + * @throws IllegalPacketException + */ + protected static JSONObject encodePacket(PacketOut packet) throws IllegalPacketException { + JSONObject json = new JSONObject(); + + if (!pOut.keySet().contains(packet.getClass())) throw new IllegalPacketException("Unknown PacketOut Channel: " + packet.getClass().getCanonicalName()); + if (packet.getVersion().toString() == null) throw new NullPointerException("PacketOut Version cannot be null: " + packet.getClass().getCanonicalName()); + + JSONObject contents = packet.generate(); + json.put("h", pOut.get(packet.getClass())); + json.put("v", packet.getVersion().toString()); + if (contents != null) json.put("c", contents); + return json; + } + + /** + * JSON Decode PacketIn + * + * @param json JSON to Decode + * @return PacketIn + * @throws IllegalPacketException + * @throws InvocationTargetException + */ + protected static PacketIn decodePacket(JSONObject json) throws IllegalPacketException, InvocationTargetException { + if (!json.keySet().contains("h") || !json.keySet().contains("v")) throw new IllegalPacketException("Unknown Packet Format: " + json.toString()); + if (!pIn.keySet().contains(json.getString("h"))) throw new IllegalPacketException("Unknown PacketIn Channel: " + json.getString("h")); + + PacketIn packet = pIn.get(json.getString("h")); + if (!new Version(json.getString("v")).equals(packet.getVersion())) throw new IllegalPacketException("Packet Version Mismatch in " + json.getString("h") + ": " + json.getString("v") + "->" + packet.getVersion().toString()); + return packet; + } + + /** + * Drops All Connections and Stops the SubData Listener + * + * @throws IOException + */ + public void destroy(boolean reconnect) throws IOException { + if (socket != null) { + final Socket socket = this.socket; + this.socket = null; + if (!socket.isClosed()) socket.close(); + Bukkit.getLogger().info("SubServers > The SubData Connection was closed"); + if (reconnect) { + Bukkit.getLogger().info("SubServers > Attempting to reconnect in 10 seconds"); + Bukkit.getScheduler().runTaskLater(plugin, () -> { + try { + plugin.subdata = new SubDataClient(plugin, name, socket.getInetAddress(), socket.getPort()); + } catch (IOException e) { + e.printStackTrace(); + } + }, 10 * 20); + } + plugin.subdata = null; + } + } +} diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubCommand.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubCommand.java new file mode 100644 index 00000000..252472ad --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubCommand.java @@ -0,0 +1,20 @@ +package net.ME1312.SubServers.Client.Bukkit; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public final class SubCommand implements CommandExecutor { + private SubPlugin plugin; + + public SubCommand(SubPlugin plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + plugin.gui.getRenderer((Player) sender).newUI(); + return true; + } +} \ No newline at end of file diff --git a/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubPlugin.java b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubPlugin.java new file mode 100644 index 00000000..934d1a09 --- /dev/null +++ b/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/SubPlugin.java @@ -0,0 +1,82 @@ +package net.ME1312.SubServers.Client.Bukkit; + +import net.ME1312.SubServers.Client.Bukkit.Graphic.UIListener; +import net.ME1312.SubServers.Client.Bukkit.Library.Config.YAMLConfig; +import net.ME1312.SubServers.Client.Bukkit.Library.Config.YAMLSection; +import net.ME1312.SubServers.Client.Bukkit.Library.UniversalFile; +import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version; +import net.ME1312.SubServers.Client.Bukkit.Network.SubDataClient; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.*; +import java.net.InetAddress; +import java.nio.file.Files; +import java.util.Arrays; + +public final class SubPlugin extends JavaPlugin { + public YAMLConfig pluginconf; + public YAMLSection lang = null; + public SubDataClient subdata = null; + + public UIListener gui = null; + public final Version version = new Version("2.11.0a"); + protected Version bversion = new Version(3); + + //public final SubAPI api = new SubAPI(this); + + @Override + public void onEnable() { + try { + Bukkit.getLogger().info("SubServers > Loading SubServers v" + version.toString() + " Libraries... "); + getDataFolder().mkdirs(); + if (!(new UniversalFile(getDataFolder(), "config.yml").exists())) { + copyFromJar("config.yml", new UniversalFile(getDataFolder(), "config.yml").getPath()); + Bukkit.getLogger().info("SubServers > Created ~/plugins/SubServers/config.yml"); + } else if ((new Version((new YAMLConfig(new UniversalFile(getDataFolder(), "config.yml"))).get().getSection("Settings").getString("Version", "0")).compareTo(new Version("2.11.0a+"))) != 0) { + Files.move(new UniversalFile(getDataFolder(), "config.yml").toPath(), new UniversalFile(getDataFolder(), "config.old" + Math.round(Math.random() * 100000) + ".yml").toPath()); + + copyFromJar("config.yml", new UniversalFile(getDataFolder(), "config.yml").getPath()); + Bukkit.getLogger().info("SubServers > Updated ~/plugins/SubServers/config.yml"); + } + pluginconf = new YAMLConfig(new UniversalFile(getDataFolder(), "config.yml")); + subdata = new SubDataClient(this, pluginconf.get().getSection("Settings").getSection("SubData").getString("Name", "~no_name"), + InetAddress.getByName(pluginconf.get().getSection("Settings").getSection("SubData").getString("Address", "127.0.0.1:4391").split(":")[0]), + Integer.parseInt(pluginconf.get().getSection("Settings").getSection("SubData").getString("Address", "127.0.0.1:4391").split(":")[1])); + Bukkit.getLogger().info("SubServers > SubData Connected to " + subdata.getClient().getRemoteSocketAddress().toString()); + + gui = new UIListener(this); + getCommand("subservers").setExecutor(new SubCommand(this)); + getCommand("subservers").setAliases(Arrays.asList("sub", "subserver")); + } catch (IOException e) { + setEnabled(false); + e.printStackTrace(); + } + } + + @Override + public void onDisable() { + try { + subdata.destroy(false); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void copyFromJar(String resource, String destination) { + InputStream resStreamIn = SubPlugin.class.getClassLoader().getResourceAsStream(resource); + File resDestFile = new File(destination); + try { + OutputStream resStreamOut = new FileOutputStream(resDestFile); + int readBytes; + byte[] buffer = new byte[4096]; + while ((readBytes = resStreamIn.read(buffer)) > 0) { + resStreamOut.write(buffer, 0, readBytes); + } + resStreamOut.close(); + resStreamIn.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/SubServers.Client/Bukkit/src/plugin.yml b/SubServers.Client/Bukkit/src/plugin.yml new file mode 100644 index 00000000..6cc40dd0 --- /dev/null +++ b/SubServers.Client/Bukkit/src/plugin.yml @@ -0,0 +1,56 @@ +name: 'SubServers' +main: 'net.ME1312.SubServers.Client.Bukkit.SubPlugin' +version: '2.11.0a' +authors: [ME1312] +softdepend: [TitleManager] +website: 'http://www.ME1312.net/' +commands: + subservers: + description: 'The SubServers Command' + usage: /subservers help +permissions: + subservers.*: + description: 'Grants Access to to Everything in SubServers.Client' + default: op + children: + subserver.interface: + description: 'Grants Access to the SubServers Interface' + default: op + subserver.command: + description: 'Grants Access to the SubServers Command' + default: op + subservers.reload: + description: 'Grants Access to Reload SubServers.Client' + default: op + subservers.host.*: + description: 'Grants Access to SubServers Host Actions' + default: op + children: + subservers.host.create.*: + description: 'Grants Access to Create a SubServer' + default: op + subservers.host.edit.*: + description: 'Grants Access to Edit a Host' + default: op + subservers.subserver.*: + description: 'Grants Access to SubServers Server Actions' + default: op + children: + subservers.subserver.start.*: + description: 'Grants Access to Start a SubServer' + default: op + subservers.subserver.stop.*: + description: 'Grants Access to Stop a SubServer' + default: op + subservers.subserver.terminate.*: + description: 'Grants Access to Terminate a SubServer' + default: op + subservers.subserver.command.*: + description: 'Grants Access to Send Commands to a SubServer' + default: op + subservers.subserver.edit.*: + description: 'Grants Access to Edit a SubServer' + default: op + subservers.subserver.teleport.*: + description: 'Grants Acces to Teleport to a SubServer' + default: op \ No newline at end of file