From 6fd13e81dc6be2d3a34a1bfe168f8c69503d401d Mon Sep 17 00:00:00 2001 From: ME1312 Date: Thu, 15 Dec 2016 16:04:39 -0500 Subject: [PATCH] SubServers.Bungee Beta 1 The first beta release of SubServers.Bungee --- .gitignore | 8 +- Artifacts/SubServers.Bungee.jar | Bin 122175 -> 154414 bytes .../Proxy/Event/SubAddServerEvent.java | 62 +++ .../Proxy/Event/SubCreateEvent.java | 143 ++++- .../Event/SubDataRecieveGenericInfoEvent.java | 51 ++ .../Proxy/Event/SubSendCommandEvent.java | 14 +- .../SubServers/Proxy/Event/SubStartEvent.java | 8 +- .../SubServers/Proxy/Event/SubStopEvent.java | 8 +- .../ME1312/SubServers/Proxy/Host/Host.java | 47 +- .../Proxy/Host/Internal/InternalHost.java | 49 +- .../Host/Internal/InternalSubCreator.java | 520 +++++++++++++++++- .../Host/Internal/InternalSubLogger.java | 22 +- .../Host/Internal/InternalSubServer.java | 147 +++-- .../ME1312/SubServers/Proxy/Host/Server.java | 2 +- .../SubServers/Proxy/Host/SubCreator.java | 11 +- .../SubServers/Proxy/Host/SubServer.java | 22 +- .../net/ME1312/SubServers/Proxy/Launch.java | 1 + .../SubServers/Proxy/Libraries/Files/lang.yml | 3 - .../Config/YAMLConfig.java | 2 +- .../Config/YAMLSection.java | 94 +--- .../Config/YAMLValue.java | 11 +- .../{Libraries => Library}/Container.java | 12 +- .../Exception/IllegalPacketException.java | 2 +- .../Exception/InvalidDriverException.java | 2 +- .../Exception/InvalidHostException.java | 2 +- .../Exception/InvalidServerException.java | 2 +- .../{Libraries => Library}/Files/build.sh | 0 .../{Libraries => Library}/Files/config.yml | 13 +- .../SubServers/Proxy/Library/Files/lang.yml | 22 + .../Proxy/Library/JSONCallback.java | 7 + .../Proxy/Library/NamedContainer.java | 34 ++ .../{Libraries => Library}/UniversalFile.java | 2 +- .../ME1312/SubServers/Proxy/Library/Util.java | 111 ++++ .../Version/Version.java | 2 +- .../Version/VersionTokenizer.java | 2 +- .../SubServers/Proxy/Network/Client.java | 112 ++-- .../Network/Packet/PacketAuthorization.java | 7 +- .../Packet/PacketDownloadBuildScript.java | 55 ++ .../Packet/PacketDownloadHostInfo.java | 80 +++ .../Network/Packet/PacketDownloadLang.java | 39 ++ .../Packet/PacketDownloadPlayerList.java | 48 ++ ...nfo.java => PacketDownloadServerInfo.java} | 33 +- .../Packet/PacketDownloadServerList.java | 95 ++++ .../Network/Packet/PacketInfoPassthrough.java | 73 +++ .../Network/Packet/PacketLinkServer.java | 17 +- .../Network/Packet/PacketRequestServers.java | 53 -- .../SubServers/Proxy/Network/PacketIn.java | 3 +- .../SubServers/Proxy/Network/PacketOut.java | 2 +- ...NetworkManager.java => SubDataServer.java} | 98 ++-- .../net/ME1312/SubServers/Proxy/SubAPI.java | 49 +- .../ME1312/SubServers/Proxy/SubCommand.java | 52 +- .../ME1312/SubServers/Proxy/SubPlugin.java | 112 ++-- SubServers.Client/src/plugin.yml | 54 -- 53 files changed, 1861 insertions(+), 559 deletions(-) create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubAddServerEvent.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubDataRecieveGenericInfoEvent.java delete mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/lang.yml rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Config/YAMLConfig.java (96%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Config/YAMLSection.java (80%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Config/YAMLValue.java (90%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Container.java (68%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Exception/IllegalPacketException.java (75%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Exception/InvalidDriverException.java (75%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Exception/InvalidHostException.java (75%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Exception/InvalidServerException.java (75%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Files/build.sh (100%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Files/config.yml (73%) create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/lang.yml create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/JSONCallback.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/NamedContainer.java rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/UniversalFile.java (97%) create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Util.java rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Version/Version.java (99%) rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/{Libraries => Library}/Version/VersionTokenizer.java (95%) create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadBuildScript.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadHostInfo.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadLang.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadPlayerList.java rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/{PacketRequestServerInfo.java => PacketDownloadServerInfo.java} (67%) create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerList.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketInfoPassthrough.java delete mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServers.java rename SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/{NetworkManager.java => SubDataServer.java} (63%) delete mode 100644 SubServers.Client/src/plugin.yml diff --git a/.gitignore b/.gitignore index fb1b0391..c9cd3af9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,11 @@ crashlytics.properties crashlytics-build.properties # Hide Unfinished Project Files -# (none) +/Artifacts/SubServers.Client.Bukkit.jar +/Artifacts/SubServers.Host.jar +/SubServers.Client/Bukkit/ +/SubServers.Host/ # Hide Others -.DS_STORE \ No newline at end of file +.DS_STORE +.alias \ No newline at end of file diff --git a/Artifacts/SubServers.Bungee.jar b/Artifacts/SubServers.Bungee.jar index 9f16b654f8ae94c81956d97773f0ffcc422632fd..1c75f513a4f67d5f4e5befb6d7e6e011a05e3fbe 100644 GIT binary patch delta 94201 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�LA`&bsh?lV9;Gn~Ro{{x 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 Ip>Z4bf8(63q5uE@ delta 64013 zcmZU4Q+Q@g(Cx&wJ+Y06ZQFJxw)4ieZQHhO+nCr+&V1j0&abm?s{3;HvwC%{RaMo^ zP(AGsaPm?hpr}6}At8S()dj}E6@&Z}nhE|5t7QL#1Rx;BeCSttpC)kZ) z>ON@dXx#uM~;W=5kCg20&7G*_1dv+Y%_rr8zOdQfLT~$>u7}D+wWh|izckWi>@Bo z2OJh$UN`J!_r5$U4(yPI&NXE>?yPSK0wizd@EN&3&7y}>JM0l#)MBE^7&!q_)iVLA zn?>ciym~pHuRm=7exooLu_gX*7W5G%XaHAcK2D{Ea&lKv=H|@U=?>$VKMn74=O!LN z>4>R*;XWjougMs1I$!hX)|yi6UMiRt>V46{FryZuMiK$R5!iGFX?ah2v?i;lodVZF zQx}0YIgSh1><D@6DFOq=|rzsEvnm6^{pK#r_;sN+f~lM8Rp)KvT4bcKftp;Lo5y zY8E}_?f|SaC`C~d|He8VKf?>@SdO?wYL@B*F!{neT<;1JHKGry zZ3&W{Tw$a(vU4b|G-BSkLB&RnOYi|&&bFJ4!U@d>Iq$Rt_qbC4gsagVz6wl4Wt~6^ z8%$ivDX%@YnZI#~Ks_o6c~lF@$u_}1xNGi7F;M~j@q-@hzvJ%j^^^Du#{c{h9N@SB zV>T!Ph{504Q&?s{`!E{8Suqvp4pp$62&dYv6zzx}D9dYsYQ0sL@_^i)xAH5m|AqRVhtE8leibH%*y!+;aU z3?~HPGOZoXbEQHKe!POP-M{6A5%h5aJiHAlc}R&c#o2Cbi5q|D_uQA>$38pslsqI7 zkll_beNo9aq*1k*37{Hxz|Lq*_}+sxzQYdda-+gpZv8~Iy+hF>vE|_-DO!$#&|Q6w z=iio^8{LMW6gugten&wd4!#OW56+j-S;i+z$*SsV(Pe} zWu4xc5PpF$XO1@!JQapp+2Y>V zr^fh)rVuLI5M(@r(Y)z$vRFux%e<9mRa*S&D=ofnte%@9*D2|`@&R#tq-1gRgx>1n z3%V6iIB#SN1*YrI)n@x6te39^f+22=&i%WPKdTTyiTtc`u1)qfh@eELJMBshGiL^t zhE!J#3TBlCMUAPxt@Fq7$zD~^4Vt#j56hh6-6z2pY&J=^lzdjKOPkqH(||InM<7PL zq&x-TEVzOEY}LeDxS`FDzjO@&nW*v&b@!KszCivbBvKg7fap@LIe=kObU1 zrx}4d-g#@6(c*vB)-#g+7)MaQP%JbE-=K+<7<=V565d8hCLQJ^-)`Rou-A#x=}d*| z^6cDyBqmcW4p07mSrtgl6_pxUbo~cI6yx=Fo?e3-ck(DIK2vOHZpU zwf%zo_OpEgQ}e!ocq!1n@+2o=3?zFTSZhTiI|GFN$wX`elQ_<`dR~a^%lT< z43=omYQh)N&z)LOD^F?W@)9lkaONkIKVa6fzFYncZlp=*HxspPfk6k&M7^vnXTV8c zSs<~kijLNE(G)#NtdUSKK5PCZ9L*zci|YU=U1p=Q)LMPUpZlat>iPRTEB-ko=qH!?^OCEbKwyAvHObFw$VeZai=-B1WVjDZzslB z$l#|4{fi-|-=8U&NrR^7MbA}l_ZT4Fpu6j(Hhq6b9j)#+H8*T|!f(fbzwTUu4d$Zn zN3C<^Ke2b%lAc%j1ZoF;jkEIloZon!8JynVVP-Zb?X}X%V{_^KMDn$cbH>+ ziQ)%=z9h<^9X`gxJ0_iBI#=Sa0G8pVUl9lf=C<%ygRp)vqoCC(b{aKmb}E3H6}v2Z zzJ{Kh#v^W$kbP#1p?SvPcK>*6A8|@c%|$EJWh9e*rOiMF)U{4B9rggH&K#$ZLi*rX zx<-jAX7MN=#f-uu!a~&ymWUy?GiEkfRz`t&t&z~j2JlV1-^-Q?+99k0$rhgq$mxJd z`A(_!sTMn}8rN8(L9=wnv>AY_z1#u!_+ZaZ8@o?rX!l;sqEonrvJWh(b|(&_LZdXd z;YpHtlrv+GJIvdix9LeO+UpW?B{5ym9MrrnEU%)7v0ckUXDqDBo2tAn+ZVRtE)GNc z%c}Z~;-}?M(ni++dz5ugVfwPJkq5GlpxQ=f?lVg3fKf7}*>BZzpErDjf0*}i_^k8o zFYC5L{|ATs4Uj+nNt_d$>;9n%%ztev{lwc06Dp6L-%%DJ#I?Hm>TdI>%k?4V`OATT|5q|Au3wd* zt`J&w#gM__U>pV@q#(~1Oh5-?BtM)K4x5*nmzzEsgT)Iz2P2)n{KY>Q&rJeX4|ODE z&|YXLg*EUN4Nh-p!r2W>uVP^377lHvvabT$xih0W|ZtZ5AmJzLZ*)8SQ+Fo_v%WSSE5MIV<~V`S1Ks!>kf zYIX@DZblQp!7Sn-(RT}hjnic6AUe%-A10+Cbrbbao5W^8%#uSlsi6TThHvg038N@q z`kGOdFGnsnT} zB=UjeanLLV%dT3zay`sCQP}SN<5(L5S<3h*WEmS!$hq8)K6h7q&;VR#;m6vlUkD?d zH}&dA?Z&=**Ucl`#<-Tyu^hPUYQk`h$syLar#=?c>SS@~w8M-u1m+*>IcCg0AePP>mbF{&9 z1t&Mc97b3S@zUUt;`PTzqr71DtkzBqV%VOB=81?Q;4jPtyP)yS-700y&-n#L%i^lc ze)m+O?;Vc*iwbs@;Y*g-bmpc?584%A-AlEI5V21>na0! z6mOHG^$sl1dggAmK4gbBIDKOHC@{A-;cqMlW7*}aG}LCz97nRk+dE6+OiLT26ddQq zxn575C)$wFsDDzae){;Gl>2vEliJfhpu7}BbGeC)uw>8Ok}KreD|GTj9O!gXI@|^O zXJ1y~f`#zP&n0cBUC3DcR7-W8T#E-Z+A+#hClxsX>?bE%7YjRb_7QYny5%@3T@&@7 zz?`Fbe(U{m3=qv;F6Tgtpq7Nr&S@LRNbgRLqOr+=W0rN}Xbc-8Kg2dNDbS^|{qs1q z#r3sZs%I90bD!Rph#FU^M{fLBg_6v~O38JOnT$!iC+T+&w)bS3@bQg%E3FH7^y;Iu zxu2(C(~$4RkwLB3Si}0`Jm3&Kq>0eBfcE}+unP%jEd3DZwTEya;8V#<`o{H$KkiJB zi{^ek90Wc@$U3+igBok_YsW3&_Iy37fxJavN3*rIi~%L;Q=z!^EKS!Gd1L~nc3{n?45dw0VZrJd<26+%g`L-4$T%>RgB z428$d-4L@!hM1Ep16tw0CkK;&iVZImR#%Dt(~DA?oCrz#lM+ceHlAFfBah?-HNEep zqttyP1SNhl)v2TdIGYPh&Tv)TYd~ZP}-XTz(4$7Gl6pi+vU!-sLga zoCy)CYBvv!-`aykJ}Ew)4speD(#b`e3j>Yo8^PBM~Spfl|EtZRX-SfwPq)FgzE0~eB%r2fzd6n zYVpXdY-3Y=xcut{$~<;JLii4fGjTUjlzWhmEFL_7`ejsydlJJEyE{T0%_jc~-$jn~ zN@Gau+Xcb1WZxR#Ie^=;CodeeDExasvz4y0#!%0;>j%jL(Id6np+n)9tVYo>yHJhY zmB!?=3e>gAN*#jjX3b11pUB9OM``k6$&E$LaZX%;j68S`oJ9FX#WQ<=+}IcP2#tGF zJa%3t8D)ZUR$(@25z3tG(>QJgK$l1rRC+eff9sA*5?&ylXKd6rY%S

-#L8AJJK1Q<@l(f)S#f@cR?RR0 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 diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubAddServerEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubAddServerEvent.java new file mode 100644 index 00000000..be9cac97 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubAddServerEvent.java @@ -0,0 +1,62 @@ +package net.ME1312.SubServers.Proxy.Event; + +import net.ME1312.SubServers.Proxy.Host.Host; +import net.ME1312.SubServers.Proxy.Host.Server; +import net.md_5.bungee.api.plugin.Event; + +import java.util.UUID; + +public class SubAddServerEvent extends Event { + 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 SubAddServerEvent(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/Event/SubCreateEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubCreateEvent.java index 13c6bc05..75c38591 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubCreateEvent.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubCreateEvent.java @@ -1,7 +1,142 @@ package net.ME1312.SubServers.Proxy.Event; -/** - * Created by christian on 12/4/16. - */ -public class SubCreateEvent { +import net.ME1312.SubServers.Proxy.Host.Host; +import net.ME1312.SubServers.Proxy.Host.SubCreator; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.md_5.bungee.api.plugin.Event; + +import java.util.UUID; + +public class SubCreateEvent extends Event { + private boolean cancelled = false; + private UUID player; + private Host host; + private String name; + private SubCreator.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, Host host, String name, SubCreator.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 Host 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 SubCreator.ServerType getType() { + return type; + } + + /** + * Set the Type of Server to Create + * + * @param value Value + */ + public void setType(SubCreator.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; } + + /** + * 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/SubDataRecieveGenericInfoEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubDataRecieveGenericInfoEvent.java new file mode 100644 index 00000000..95b67712 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubDataRecieveGenericInfoEvent.java @@ -0,0 +1,51 @@ +package net.ME1312.SubServers.Proxy.Event; + +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.md_5.bungee.api.plugin.Event; +import org.json.JSONObject; + +public class SubDataRecieveGenericInfoEvent extends Event { + 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; + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubSendCommandEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubSendCommandEvent.java index 89ed41d6..aa5b4398 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubSendCommandEvent.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubSendCommandEvent.java @@ -12,12 +12,12 @@ public class SubSendCommandEvent extends Event { private String command; /** - * Server Start Event + * Server Command Event * - * @param server Server Starting - * @param player Player Starting Server + * @param player Player Commanding Server + * @param server Server being Commanded */ - public SubSendCommandEvent(SubServer server, UUID player, String command) { + public SubSendCommandEvent(UUID player, SubServer server, String command) { this.player = player; this.server = server; this.command = command; @@ -30,8 +30,8 @@ public class SubSendCommandEvent extends Event { public SubServer getServer() { return server; } /** - * Gets the player that Triggered the Event - * @return The Player that triggered this Event or Null if Console + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console */ public UUID getPlayer() { return player; } @@ -50,7 +50,7 @@ public class SubSendCommandEvent extends Event { * @param value Value */ public void setCommand(String value) { - + command = value; } /** diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStartEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStartEvent.java index 04102a9b..c612c3fc 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStartEvent.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStartEvent.java @@ -13,10 +13,10 @@ public class SubStartEvent extends Event { /** * Server Start Event * - * @param server Server Starting * @param player Player Starting Server + * @param server Server Starting */ - public SubStartEvent(SubServer server, UUID player) { + public SubStartEvent(UUID player, SubServer server) { this.player = player; this.server = server; } @@ -28,8 +28,8 @@ public class SubStartEvent extends Event { public SubServer getServer() { return server; } /** - * Gets the player that Triggered the Event - * @return The Player that triggered this Event or Null if Console + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console */ public UUID getPlayer() { return player; } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStopEvent.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStopEvent.java index 23422f47..7346d41e 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStopEvent.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Event/SubStopEvent.java @@ -14,11 +14,11 @@ public class SubStopEvent extends Event { /** * Server Stop Event * - * @param server Server Stopping * @param player Player Stopping Server + * @param server Server Stopping * @param force If it was a Forced Shutdown */ - public SubStopEvent(SubServer server, UUID player, boolean force) { + public SubStopEvent(UUID player, SubServer server, boolean force) { this.player = player; this.server = server; this.force = force; @@ -31,8 +31,8 @@ public class SubStopEvent extends Event { public SubServer getServer() { return server; } /** - * Gets the player that Triggered the Event - * @return The Player that triggered this Event or Null if Console + * Gets the player that triggered the Event + * @return The Player that triggered this Event or null if Console */ public UUID getPlayer() { return player; } 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 16c31100..ee41ae7e 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Host.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Host.java @@ -1,10 +1,10 @@ package net.ME1312.SubServers.Proxy.Host; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidServerException; -import net.ME1312.SubServers.Proxy.Libraries.UniversalFile; +import net.ME1312.SubServers.Proxy.Library.Exception.InvalidHostException; +import net.ME1312.SubServers.Proxy.Library.Exception.InvalidServerException; +import net.ME1312.SubServers.Proxy.Library.NamedContainer; import net.ME1312.SubServers.Proxy.SubPlugin; -import java.io.File; import java.net.InetAddress; import java.util.Map; import java.util.UUID; @@ -20,11 +20,15 @@ public abstract class Host { * This constructor is required to launch your host from the drivers list. Do not add or remove any arguments. * * @param plugin SubServers Internals - * @param enabled If your host is enabled - * @param address The address of your host - * @param directory The runtime directory of your host + * @param name The Name of your Host + * @param enabled If your host is Enabled + * @param address The address of your Host + * @param directory The runtime directory of your Host + * @param gitBash The Git Bash directory */ - public Host(SubPlugin plugin, String name, Boolean enabled, InetAddress address, UniversalFile directory) {} + public Host(SubPlugin plugin, String name, Boolean enabled, InetAddress address, String directory, String gitBash) { + if (name.contains(" ")) throw new InvalidHostException("Host names cannot have spaces: " + name); + } /** * Is this Host Enabled? @@ -47,6 +51,20 @@ public abstract class Host { */ public abstract InetAddress getAddress(); + /** + * Get the Directory of this Host + * + * @return Host Directory + */ + public abstract String getDirectory(); + + /** + * Get if the Host can be Edited + * + * @return Editable Status + */ + public abstract boolean isEditable(); + /** * Get the Name of this Host * @@ -124,6 +142,13 @@ public abstract class Host { */ public abstract void command(UUID player, String command, String... servers); + /** + * Applies edits to the Host + * + * @param change Change(s) to be applied + */ + public abstract void edit(NamedContainer... change); + /** * Gets the SubCreator Instance for this Host * @@ -159,11 +184,12 @@ public abstract class Host { * @param executable Executable * @param stopcmd Command to Stop the Server * @param restart Auto Restart Status + * @param restricted Players will need a permission to join if true * @param temporary Temporary Status * @return The SubServer * @throws InvalidServerException */ - public abstract SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean temporary) throws InvalidServerException; + public abstract SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean restricted, boolean temporary) throws InvalidServerException; /** * Adds a SubServer @@ -177,12 +203,13 @@ public abstract class Host { * @param executable Executable * @param stopcmd Command to Stop the Server * @param restart Auto Restart Status + * @param restricted Players will need a permission to join if true * @param temporary Temporary Status * @return The SubServer * @throws InvalidServerException */ - public SubServer addSubServer(String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean temporary) throws InvalidServerException { - return addSubServer(null, name, enabled, port, motd, log, directory, executable, stopcmd, start, restart, temporary); + public SubServer addSubServer(String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean restricted, boolean temporary) throws InvalidServerException { + return addSubServer(null, name, enabled, port, motd, log, directory, executable, stopcmd, start, restart, restricted, temporary); } /** 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 d8d0d73f..6ff1f1f9 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,14 +1,14 @@ package net.ME1312.SubServers.Proxy.Host.Internal; +import net.ME1312.SubServers.Proxy.Event.SubAddServerEvent; import net.ME1312.SubServers.Proxy.Host.Executable; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidServerException; +import net.ME1312.SubServers.Proxy.Library.Exception.InvalidServerException; import net.ME1312.SubServers.Proxy.Host.Host; import net.ME1312.SubServers.Proxy.Host.SubCreator; import net.ME1312.SubServers.Proxy.Host.SubServer; -import net.ME1312.SubServers.Proxy.Libraries.UniversalFile; +import net.ME1312.SubServers.Proxy.Library.NamedContainer; import net.ME1312.SubServers.Proxy.SubPlugin; -import java.io.File; import java.net.InetAddress; import java.util.HashMap; import java.util.Map; @@ -22,16 +22,16 @@ public class InternalHost extends Host { private boolean enabled; private InetAddress address; private InternalSubCreator creator; - UniversalFile directory; + private String directory; SubPlugin plugin; - public InternalHost(SubPlugin plugin, String name, Boolean enabled, InetAddress address, UniversalFile directory) { - super(plugin, name, enabled, address, directory); + public InternalHost(SubPlugin plugin, String name, Boolean enabled, InetAddress address, String directory, String gitBash) { + super(plugin, name, enabled, address, directory, gitBash); this.plugin = plugin; this.name = name; this.enabled = enabled; this.address = address; - this.creator = new InternalSubCreator(this); + this.creator = new InternalSubCreator(this, gitBash); this.directory = directory; } @@ -50,6 +50,16 @@ public class InternalHost extends Host { return address; } + @Override + public String getDirectory() { + return directory; + } + + @Override + public boolean isEditable() { + return true; + } + @Override public String getName() { return name; @@ -83,6 +93,15 @@ public class InternalHost extends Host { } } + @Override + public void edit(NamedContainer... changes) { + for (NamedContainer change : changes) { + switch (change.name().toLowerCase()) { + // TODO SubEditor + } + } + } + @Override public SubCreator getCreator() { return creator; @@ -99,11 +118,17 @@ public class InternalHost extends Host { } @Override - public SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean temporary) throws InvalidServerException { - if (plugin.getServers().keySet().contains(name.toLowerCase())) throw new InvalidServerException("A Server already exists with this name!"); - SubServer server = new InternalSubServer(this, name, enabled, port, motd, log, directory, executable, stopcmd, start, restart, temporary); - servers.put(name.toLowerCase(), server); - return server; + public SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, Executable executable, String stopcmd, boolean start, boolean restart, boolean restricted, boolean temporary) throws InvalidServerException { + if (plugin.api.getServers().keySet().contains(name.toLowerCase())) throw new InvalidServerException("A Server already exists with this name!"); + SubServer server = new InternalSubServer(this, name, enabled, port, motd, log, directory, executable, stopcmd, start, restart, restricted, temporary); + SubAddServerEvent event = new SubAddServerEvent(player, this, server); + plugin.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + servers.put(name.toLowerCase(), server); + return server; + } else { + return null; + } } @Override diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubCreator.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubCreator.java index 5b28ccb7..55ff8d1b 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubCreator.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubCreator.java @@ -1,27 +1,524 @@ package net.ME1312.SubServers.Proxy.Host.Internal; +import net.ME1312.SubServers.Proxy.Event.SubCreateEvent; +import net.ME1312.SubServers.Proxy.Host.Executable; import net.ME1312.SubServers.Proxy.Host.Host; import net.ME1312.SubServers.Proxy.Host.SubCreator; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; +import net.ME1312.SubServers.Proxy.Library.Config.YAMLSection; +import net.ME1312.SubServers.Proxy.Library.Container; +import net.ME1312.SubServers.Proxy.Library.UniversalFile; +import net.ME1312.SubServers.Proxy.Library.Util; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; -import java.io.File; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; +import java.net.URL; +import java.nio.charset.Charset; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; import java.util.UUID; public class InternalSubCreator extends SubCreator { - private Host host; + private InternalHost host; + private String gitBash; + private Thread thread = null; - public InternalSubCreator(Host host) { - this.host = host; + public InternalSubCreator(Host host, String gitBash) { + this.host = (InternalHost) host; + this.gitBash = gitBash; + } + + private void GenerateEULA(File dir) throws FileNotFoundException, UnsupportedEncodingException { + PrintWriter writer = new PrintWriter(new File(dir, "eula.txt"), "UTF-8"); + + writer.println("#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); + writer.println("#" + new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy").format(Calendar.getInstance().getTime())); + writer.println("eula=true"); + + writer.close(); + } + + private void GenerateProperties(File dir, int port) throws FileNotFoundException, UnsupportedEncodingException { + PrintWriter writer = new PrintWriter(new File(dir, "server.properties"), "UTF-8"); + + writer.println("#Minecraft server properties"); + writer.println("#" + new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy").format(Calendar.getInstance().getTime())); + writer.println("generator-settings="); + writer.println("op-permission-level=4"); + writer.println("allow-nether=true"); + writer.println("resource-pack-hash="); + writer.println("level-name=world"); + writer.println("enable-query=true"); + writer.println("allow-flight=false"); + writer.println("announce-player-achievements=false"); + writer.println("server-port=" + port); + writer.println("max-world-size=29999984"); + writer.println("level-type=DEFAULT"); + writer.println("enable-rcon=false"); + writer.println("level-seed="); + writer.println("force-gamemode=false"); + writer.println("server-ip=" + host.getAddress().toString().substring(1)); + writer.println("network-compression-threshold=-1"); + writer.println("max-build-height=256"); + writer.println("spawn-npcs=true"); + writer.println("white-list=false"); + writer.println("spawn-animals=true"); + writer.println("snooper-enabled=true"); + writer.println("online-mode=false"); + writer.println("resource-pack="); + writer.println("pvp=true"); + writer.println("difficulty=1"); + writer.println("enable-command-block=true"); + writer.println("gamemode=0"); + writer.println("player-idle-timeout=0"); + writer.println("max-players=20"); + writer.println("max-tick-time=60000"); + writer.println("spawn-monsters=true"); + writer.println("generate-structures=true"); + writer.println("view-distance=10"); + writer.println("motd=A Generated SubServer"); + + writer.close(); + } + private void GenerateSpigotYAML(File dir) throws FileNotFoundException, UnsupportedEncodingException { + PrintWriter writer = new PrintWriter(new File(dir, "spigot.yml"), "UTF-8"); + + writer.println("# This is the main configuration file for Spigot."); + writer.println("# As you can see, there's tons to configure. Some options may impact gameplay, so use"); + writer.println("# with caution, and make sure you know what each option does before configuring."); + writer.println("# For a reference for any variable inside this file, check out the Spigot wiki at"); + writer.println("# http://www.spigotmc.org/wiki/spigot-configuration/"); + writer.println("#"); + writer.println("# If you need help with the configuration or have any questions related to Spigot,"); + writer.println("# join us at the IRC or drop by our forums and leave a post."); + writer.println("#"); + writer.println("# IRC: #spigot @ irc.spi.gt ( http://www.spigotmc.org/pages/irc/ )"); + writer.println("# Forums: http://www.spigotmc.org/"); + writer.println(); + writer.println("config-version: 8"); + writer.println("settings:"); + writer.println(" debug: false"); + writer.println(" save-user-cache-on-stop-only: false"); + writer.println(" bungeecord: true"); + writer.println(" late-bind: false"); + writer.println(" sample-count: 12"); + writer.println(" player-shuffle: 0"); + writer.println(" filter-creative-items: true"); + writer.println(" user-cache-size: 1000"); + writer.println(" int-cache-limit: 1024"); + writer.println(" moved-wrongly-threshold: 0.0625"); + writer.println(" moved-too-quickly-threshold: 100.0"); + writer.println(" timeout-time: 60"); + writer.println(" restart-on-crash: false"); + writer.println(" restart-script: ./start.sh"); + writer.println(" netty-threads: 4"); + writer.println(" attribute:"); + writer.println(" maxHealth:"); + writer.println(" max: 2048.0"); + writer.println(" movementSpeed:"); + writer.println(" max: 2048.0"); + writer.println(" attackDamage:"); + writer.println(" max: 2048.0"); + writer.println("commands:"); + writer.println(" tab-complete: 0"); + writer.println(" log: true"); + writer.println(" spam-exclusions:"); + writer.println(" - /skill"); + writer.println(" silent-commandblock-console: true"); + writer.println(" replace-commands:"); + writer.println(" - setblock"); + writer.println(" - summon"); + writer.println(" - testforblock"); + writer.println(" - tellraw"); + writer.println("messages:"); + writer.println(" whitelist: You are not whitelisted on this server!"); + writer.println(" unknown-command: Unknown command. Type \"/help\" for help."); + writer.println(" server-full: The server is full!"); + writer.println(" outdated-client: Outdated client! Please use {0}"); + writer.println(" outdated-server: Outdated server! I'm still on {0}"); + writer.println(" restart: Server is restarting"); + writer.println("stats:"); + writer.println(" disable-saving: false"); + writer.println(" forced-stats: {}"); + writer.println("world-settings:"); + writer.println(" default:"); + writer.println(" verbose: true"); + writer.println(" wither-spawn-sound-radius: 0"); + writer.println(" view-distance: 10"); + writer.println(" item-despawn-rate: 6000"); + writer.println(" merge-radius:"); + writer.println(" item: 2.5"); + writer.println(" exp: 3.0"); + writer.println(" arrow-despawn-rate: 1200"); + writer.println(" enable-zombie-pigmen-portal-spawns: true"); + writer.println(" zombie-aggressive-towards-villager: true"); + writer.println(" hanging-tick-frequency: 100"); + writer.println(" max-bulk-chunks: 10"); + writer.println(" max-entity-collisions: 8"); + writer.println(" random-light-updates: false"); + writer.println(" save-structure-info: true"); + writer.println(" mob-spawn-range: 4"); + writer.println(" anti-xray:"); + writer.println(" enabled: true"); + writer.println(" engine-mode: 1"); + writer.println(" hide-blocks:"); + writer.println(" - 14"); + writer.println(" - 15"); + writer.println(" - 16"); + writer.println(" - 21"); + writer.println(" - 48"); + writer.println(" - 49"); + writer.println(" - 54"); + writer.println(" - 56"); + writer.println(" - 73"); + writer.println(" - 74"); + writer.println(" - 82"); + writer.println(" - 129"); + writer.println(" - 130"); + writer.println(" replace-blocks:"); + writer.println(" - 1"); + writer.println(" - 5"); + writer.println(" dragon-death-sound-radius: 0"); + writer.println(" seed-village: 10387312"); + writer.println(" seed-feature: 14357617"); + writer.println(" hunger:"); + writer.println(" walk-exhaustion: 0.2"); + writer.println(" sprint-exhaustion: 0.8"); + writer.println(" combat-exhaustion: 0.3"); + writer.println(" regen-exhaustion: 3.0"); + writer.println(" max-tnt-per-tick: 100"); + writer.println(" max-tick-time:"); + writer.println(" tile: 50"); + writer.println(" entity: 50"); + writer.println(" entity-activation-range:"); + writer.println(" animals: 32"); + writer.println(" monsters: 32"); + writer.println(" misc: 16"); + writer.println(" entity-tracking-range:"); + writer.println(" players: 48"); + writer.println(" animals: 48"); + writer.println(" monsters: 48"); + writer.println(" misc: 32"); + writer.println(" other: 64"); + writer.println(" ticks-per:"); + writer.println(" hopper-transfer: 8"); + writer.println(" hopper-check: 8"); + writer.println(" hopper-amount: 1"); + writer.println(" growth:"); + writer.println(" cactus-modifier: 100"); + writer.println(" cane-modifier: 100"); + writer.println(" melon-modifier: 100"); + writer.println(" mushroom-modifier: 100"); + writer.println(" pumpkin-modifier: 100"); + writer.println(" sapling-modifier: 100"); + writer.println(" wheat-modifier: 100"); + writer.println(" netherwart-modifier: 100"); + writer.println(" nerf-spawner-mobs: false"); + writer.println(" chunks-per-tick: 650"); + writer.println(" clear-tick-list: false"); + writer.println(); + + writer.close(); + } + private void GenerateSpongeConf(File dir) throws FileNotFoundException, UnsupportedEncodingException { + new File(dir, "config" + File.separator + "sponge").mkdirs(); + PrintWriter writer = new PrintWriter(new File(dir, "config" + File.separator + "sponge" + File.separator + "global.conf"), "UTF-8"); + writer.println("# 1.0"); + writer.println("#"); + writer.println("# # If you need help with the configuration or have any questions related to Sponge,"); + writer.println("# # join us at the IRC or drop by our forums and leave a post."); + writer.println("#"); + writer.println("# # IRC: #sponge @ irc.esper.net ( http://webchat.esper.net/?channel=sponge )"); + writer.println("# # Forums: https://forums.spongepowered.org/"); + writer.println("#"); + writer.println(); + writer.println("sponge {"); + writer.println(" block-tracking {"); + writer.println(" # If enabled, adds player tracking support for block positions. Note: This should only be disabled if you do not care who caused a block to change."); + writer.println(" enabled=true"); + writer.println(" }"); + writer.println(" bungeecord {"); + writer.println(" # If enabled, allows BungeeCord to forward IP address, UUID, and Game Profile to this server"); + writer.println(" ip-forwarding=true"); + writer.println(" }"); + writer.println(" commands {}"); + writer.println(" debug {"); + writer.println(" # Dump chunks in the event of a deadlock"); + writer.println(" dump-chunks-on-deadlock=false"); + writer.println(" # Dump the heap in the event of a deadlock"); + writer.println(" dump-heap-on-deadlock=false"); + writer.println(" # Dump the server thread on deadlock warning"); + writer.println(" dump-threads-on-warn=false"); + writer.println(" # Enable Java's thread contention monitoring for thread dumps"); + writer.println(" thread-contention-monitoring=false"); + writer.println(" }"); + writer.println(" entity {"); + writer.println(" # Number of colliding entities in one spot before logging a warning. Set to 0 to disable"); + writer.println(" collision-warn-size=200"); + writer.println(" # Number of entities in one dimension before logging a warning. Set to 0 to disable"); + writer.println(" count-warn-size=0"); + writer.println(" # Number of ticks before a painting is respawned on clients when their art is changed"); + writer.println(" entity-painting-respawn-delay=2"); + writer.println(" # Number of ticks before the fake player entry of a human is removed from the tab list (range of 0 to 100 ticks)."); + writer.println(" human-player-list-remove-delay=10"); + writer.println(" # Controls the time in ticks for when an item despawns."); + writer.println(" item-despawn-rate=6000"); + writer.println(" # Max size of an entity's bounding box before removing it. Set to 0 to disable"); + writer.println(" max-bounding-box-size=1000"); + writer.println(" # Square of the max speed of an entity before removing it. Set to 0 to disable"); + writer.println(" max-speed=100"); + writer.println(" }"); + writer.println(" entity-activation-range {"); + writer.println(" ambient-activation-range=32"); + writer.println(" aquatic-activation-range=32"); + writer.println(" creature-activation-range=32"); + writer.println(" minecraft {"); + writer.println(" creature {"); + writer.println(" entityhorse=true"); + writer.println(" pig=true"); + writer.println(" sheep=true"); + writer.println(" }"); + writer.println(" enabled=true"); + writer.println(" misc {"); + writer.println(" item=true"); + writer.println(" minecartchest=true"); + writer.println(" }"); + writer.println(" monster {"); + writer.println(" guardian=true"); + writer.println(" }"); + writer.println(" }"); + writer.println(" misc-activation-range=16"); + writer.println(" monster-activation-range=32"); + writer.println(" }"); + writer.println(" general {"); + writer.println(" # Forces Chunk Loading on provide requests (speedup for mods that don't check if a chunk is loaded)"); + writer.println(" chunk-load-override=false"); + writer.println(" # Disable warning messages to server admins"); + writer.println(" disable-warnings=false"); + writer.println(" }"); + writer.println(" logging {"); + writer.println(" # Log when blocks are broken"); + writer.println(" block-break=false"); + writer.println(" # Log when blocks are modified"); + writer.println(" block-modify=false"); + writer.println(" # Log when blocks are placed"); + writer.println(" block-place=false"); + writer.println(" # Log when blocks are populated in a chunk"); + writer.println(" block-populate=false"); + writer.println(" # Log when blocks are placed by players and tracked"); + writer.println(" block-tracking=false"); + writer.println(" # Log when chunks are loaded"); + writer.println(" chunk-load=false"); + writer.println(" # Log when chunks are unloaded"); + writer.println(" chunk-unload=false"); + writer.println(" # Whether to log entity collision/count checks"); + writer.println(" entity-collision-checks=false"); + writer.println(" # Log when living entities are destroyed"); + writer.println(" entity-death=false"); + writer.println(" # Log when living entities are despawned"); + writer.println(" entity-despawn=false"); + writer.println(" # Log when living entities are spawned"); + writer.println(" entity-spawn=false"); + writer.println(" # Whether to log entity removals due to speed"); + writer.println(" entity-speed-removal=false"); + writer.println(" # Add stack traces to dev logging"); + writer.println(" log-stacktraces=false"); + writer.println(" }"); + writer.println(" modules {"); + writer.println(" bungeecord=true"); + writer.println(" entity-activation-range=true"); + writer.println(" timings=true"); + writer.println(" }"); + writer.println(" # Configuration options related to the Sql service, including connection aliases etc"); + writer.println(" sql {}"); + writer.println(" timings {"); + writer.println(" enabled=true"); + writer.println(" hidden-config-entries=["); + writer.println(" \"sponge.sql\""); + writer.println(" ]"); + writer.println(" history-interval=300"); + writer.println(" history-length=3600"); + writer.println(" server-name-privacy=false"); + writer.println(" verbose=false"); + writer.println(" }"); + writer.println(" world {"); + writer.println(" # Lava behaves like vanilla water when source block is removed"); + writer.println(" flowing-lava-decay=false"); + writer.println(" # Vanilla water source behavior - is infinite"); + writer.println(" infinite-water-source=false"); + writer.println(" }"); + writer.println("}"); + writer.println(); + + writer.close(); + + } + + private void run(String name, ServerType type, Version version, int memory, int port) { + Executable exec = null; + UniversalFile dir = new UniversalFile(new File(host.getDirectory()), name); + dir.mkdirs(); + + if (type == ServerType.SPIGOT) { + exec = new Executable("java -Xmx" + memory + "M -Djline.terminal=jline.UnsupportedTerminal -Dcom.mojang.eula.agree=true -jar Spigot.jar"); + + try { + GenerateSpigotYAML(dir); + GenerateProperties(dir, port); + } catch (IOException e) { + e.printStackTrace(); + } + + } else if (type == ServerType.VANILLA) { + exec = new Executable("java -Xmx" + memory + "M -jar Vanilla.jar nogui"); + + try { + GenerateEULA(dir); + GenerateProperties(dir, port); + } catch (FileNotFoundException | UnsupportedEncodingException e) { + e.printStackTrace(); + } + } else if (type == ServerType.SPONGE) { + try { + Document spongexml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(Util.readAll(new BufferedReader(new InputStreamReader(new URL("http://files.minecraftforge.net/maven/org/spongepowered/spongeforge/maven-metadata.xml").openStream(), Charset.forName("UTF-8"))))))); + Document forgexml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(Util.readAll(new BufferedReader(new InputStreamReader(new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/maven-metadata.xml").openStream(), Charset.forName("UTF-8"))))))); + + NodeList spnodeList = spongexml.getElementsByTagName("version"); + Version spversion = null; + for (int i = 0; i < spnodeList.getLength(); i++) { + Node node = spnodeList.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + if (node.getTextContent().startsWith(version.toString() + '-') && (spversion == null || new Version(node.getTextContent()).compareTo(spversion) >= 0)) { + spversion = new Version(node.getTextContent()); + } + } + } + + NodeList mcfnodeList = forgexml.getElementsByTagName("version"); + Version mcfversion = null; + for (int i = 0; i < mcfnodeList.getLength(); i++) { + Node node = mcfnodeList.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + if (node.getTextContent().contains(spversion.toString().split("\\-")[1]) && (mcfversion == null || new Version(node.getTextContent()).compareTo(mcfversion) >= 0)) { + mcfversion = new Version(node.getTextContent()); + } + } + } + + exec = new Executable("java -Xmx" + memory + "M -jar Forge.jar"); + version = new Version(mcfversion.toString() + "::" + spversion.toString()); + + GenerateEULA(dir); + GenerateProperties(dir, port); + GenerateSpongeConf(dir); + } catch (ParserConfigurationException | IOException | SAXException | NullPointerException e) { + e.printStackTrace(); + } + } + + try { + InputStream input = null; + OutputStream output = null; + try { + input = new FileInputStream(new UniversalFile(host.plugin.dir, "SubServers:build.sh")); + output = new FileOutputStream(new File(dir, "build-subserver.sh")); + byte[] buf = new byte[1024]; + int bytesRead; + while ((bytesRead = input.read(buf)) > 0) { + output.write(buf, 0, bytesRead); + } + } finally { + if (input != null) + input.close(); + if (output != null) + output.close(); + } + + if (!(new File(dir, "build-subserver.sh").exists())) { + System.out.println("SubCreator > Problem Copying build-subserver.sh!"); + } else { + File gitBash = new File(this.gitBash, "bin" + File.separatorChar + "bash.exe"); + if (!(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)) { + Process process1 = Runtime.getRuntime().exec("chmod +x build-subserver.sh", null, dir); + try { + process1.waitFor(); + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (process1.exitValue() != 0) { + System.out.println("SubCreator > Problem Setting Executable Permissions for build-subserver.sh"); + System.out.println("SubCreator > This may cause errors in the Build Process"); + } + } + + Process process2 = Runtime.getRuntime().exec((System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)? + "\"" + gitBash + "\" --login -i -c \"bash build-subserver.sh " + version.toString() + " " + type.toString().toLowerCase() + "\"" + :("bash build-subserver.sh " + version.toString() + " " + type.toString().toLowerCase() + " " + System.getProperty("user.home")), null, dir); + InternalSubLogger read = new InternalSubLogger(process2.getInputStream(), host.getName() + "/Creator", new Container(host.plugin.config.get().getSection("Settings").getBoolean("Log-Creator")), new File(dir, "SubCreator-" + type.toString() + "-" + version.toString().replace("::", "@") + ".log")); + read.start(); + try { + process2.waitFor(); + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (process2.exitValue() == 0) { + host.addSubServer(name, true, port, "&aThis is a SubServer", true, dir.getPath(), exec, "stop", true, false, false, false); + + YAMLSection server = new YAMLSection(); + server.set("Enabled", true); + server.set("Host", host.getName()); + server.set("Port", port); + server.set("Motd", "&aThis is a SubServer"); + server.set("Log", true); + server.set("Directory", dir.getPath()); + server.set("Executable", exec.toString()); + server.set("Stop-Command", "stop"); + server.set("Run-On-Launch", false); + server.set("Auto-Restart", false); + server.set("Auto-Restart", false); + server.set("Restricted", false); + host.plugin.config.get().getSection("Servers").set(name, server); + host.plugin.config.save(); + + } else { + System.out.println("SubCreator > build-subserver.sh exited with an errors. Please try again."); + } + } + } catch (IOException e) { + e.printStackTrace(); + } } @Override - public void create(UUID player, String name, int port, File directory, ServerType type, Version version, int memory) { - + public void create(UUID player, String name, ServerType type, Version version, int memory, int port) { + if (!isBusy()) { + final SubCreateEvent event = new SubCreateEvent(player, host, name, type, version, memory, port); + host.plugin.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + (thread = new Thread(() -> { + InternalSubCreator.this.run(name, event.getType(), event.getVersion(), event.getMemory(), port); + })).start(); + } + } } @Override public void waitFor() throws InterruptedException { - + while (thread != null && thread.isAlive()) { + Thread.sleep(250); + } } @Override @@ -29,8 +526,13 @@ public class InternalSubCreator extends SubCreator { return host; } + @Override + public String getGitBashDirectory() { + return gitBash; + } + @Override public boolean isBusy() { - return false; + return thread != null && thread.isAlive(); } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubLogger.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubLogger.java index 1d75eb3e..c4eeb879 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubLogger.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Internal/InternalSubLogger.java @@ -1,6 +1,7 @@ package net.ME1312.SubServers.Proxy.Host.Internal; -import net.ME1312.SubServers.Proxy.Libraries.Container; +import net.ME1312.SubServers.Proxy.Library.Container; +import net.md_5.bungee.api.ProxyServer; import java.io.*; import java.util.regex.Matcher; @@ -35,16 +36,29 @@ public class InternalSubLogger extends Thread { while ((line = br.readLine()) != null) { if (log.get() && !line.startsWith(">")) { String msg = line; - /* REGEX Formatting + // REGEX Formatting String type = "INFO"; Matcher matcher = Pattern.compile("^((?:\\s*\\[?[0-9]{2}:[0-9]{2}:[0-9]{2}]?)?\\s*(?:\\[|\\[.*\\/)?(INFO|WARN|WARNING|ERROR|ERR|SEVERE)\\]:?\\s*)").matcher(msg); while (matcher.find()) { type = matcher.group(2); } - */ + msg = msg.replaceAll("^((?:\\s*\\[?[0-9]{2}:[0-9]{2}:[0-9]{2}]?)?\\s*(?:\\[|\\[.*\\/)?(INFO|WARN|WARNING|ERROR|ERR|SEVERE)\\]:?\\s*)", ""); - System.out.println(name + " > " + msg); + switch (type) { + case "INFO": + ProxyServer.getInstance().getLogger().info(name + " > " + msg); + break; + case "WARNING": + case "WARN": + ProxyServer.getInstance().getLogger().warning(name + " > " + msg); + break; + case "SEVERE": + case "ERROR": + case "ERR": + ProxyServer.getInstance().getLogger().severe(name + " > " + msg); + break; + } if (writer != null) { writer.println(line); 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 0c848dea..5a9d483a 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 @@ -5,17 +5,16 @@ 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.Host.Executable; -import net.ME1312.SubServers.Proxy.Libraries.Container; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidServerException; +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 java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; public class InternalSubServer extends SubServer { @@ -26,21 +25,22 @@ public class InternalSubServer extends SubServer { private Executable executable; private String stopcmd; private Process process; - private List queue; + private BufferedWriter command; private boolean restart; + private boolean allowrestart; private boolean temporary; private InternalSubServer instance; - 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 temporary) throws InvalidServerException { - super(host, name, port, motd); + 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 restricted, boolean temporary) throws InvalidServerException { + super(host, name, port, motd, restricted); this.host = (InternalHost) host; this.enabled = enabled; this.log = new Container(log); - this.directory = new File(((InternalHost) host).directory, directory); + this.directory = new File(host.getDirectory(), directory); this.executable = executable; this.stopcmd = stopcmd; this.process = null; - this.queue = new ArrayList(); + this.command = null; this.restart = restart; this.temporary = temporary; this.instance = this; @@ -49,82 +49,54 @@ public class InternalSubServer extends SubServer { } private void run() { - new Thread() { - public void run() { - final Container allowRestart = new Container(true); + new Thread(() -> { + allowrestart = true; + try { + process = Runtime.getRuntime().exec(executable.toString(), null, directory); + System.out.println("SubServers > Now starting " + instance.getName()); + final InternalSubLogger read = new InternalSubLogger(process.getInputStream(), instance.getName(), log, null); + read.start(); + command = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); + try { - process = Runtime.getRuntime().exec(executable.toString(), null, directory); - System.out.println("SubServers > Now starting " + instance.getName()); - final InternalSubLogger read = new InternalSubLogger(process.getInputStream(), instance.getName(), log, null); - read.start(); - final BufferedWriter cmd = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); - new Thread() { - @Override - public void run() { - try { - do { - if (!queue.isEmpty()) { - while (queue.size() > 0) { - try { - if (queue.get(0).equalsIgnoreCase(stopcmd)) allowRestart.set(false); - cmd.write(queue.get(0)); - cmd.newLine(); - cmd.flush(); - queue.remove(0); - Thread.sleep(100); - } catch (IOException | InterruptedException e) { - e.printStackTrace(); - } - } - } - Thread.sleep(500); - - } while (read.isAlive()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }.start(); - try { - process.waitFor(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } catch (IOException e) { + process.waitFor(); + } catch (InterruptedException e) { e.printStackTrace(); - allowRestart.set(false); } + } catch (IOException e) { + e.printStackTrace(); + allowrestart = false; + } - SubStoppedEvent event = new SubStoppedEvent(instance); - host.plugin.getPluginManager().callEvent(event); - System.out.println("SubServers > " + instance.getName() + " has stopped"); - process = null; - queue.clear(); + SubStoppedEvent event = new SubStoppedEvent(instance); + host.plugin.getPluginManager().callEvent(event); + System.out.println("SubServers > " + instance.getName() + " has stopped"); + process = null; + command = null; - if (temporary) { + if (temporary) { + try { + host.removeSubServer(instance.getName()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + if (restart && allowrestart) { try { - host.removeSubServer(instance.getName()); + Thread.sleep(2500); + start(); } catch (InterruptedException e) { e.printStackTrace(); } - } else { - if (restart && allowRestart.get()) { - try { - Thread.sleep(2500); - start(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } } } - }.start(); + }).start(); } @Override public void start(UUID player) { if (enabled && !isRunning()) { - SubStartEvent event = new SubStartEvent(this, player); + SubStartEvent event = new SubStartEvent(player, this); host.plugin.getPluginManager().callEvent(event); if (!event.isCancelled()) { run(); @@ -135,10 +107,17 @@ public class InternalSubServer extends SubServer { @Override public void stop(UUID player) { if (isRunning()) { - SubStopEvent event = new SubStopEvent(this, player, false); + SubStopEvent event = new SubStopEvent(player, this, false); host.plugin.getPluginManager().callEvent(event); if (!event.isCancelled()) { - queue.add(stopcmd); + try { + command.write(stopcmd); + command.newLine(); + command.flush(); + allowrestart = false; + } catch (IOException e) { + e.printStackTrace(); + } } } } @@ -146,7 +125,7 @@ public class InternalSubServer extends SubServer { @Override public void terminate(UUID player) { if (isRunning()) { - SubStopEvent event = new SubStopEvent(this, player, true); + SubStopEvent event = new SubStopEvent(player, this, true); host.plugin.getPluginManager().callEvent(event); if (!event.isCancelled()) { process.destroyForcibly(); @@ -157,10 +136,25 @@ public class InternalSubServer extends SubServer { @Override public void command(UUID player, String command) { if (isRunning()) { - SubSendCommandEvent event = new SubSendCommandEvent(this, player, command); + SubSendCommandEvent event = new SubSendCommandEvent(player, this, command); host.plugin.getPluginManager().callEvent(event); if (!event.isCancelled()) { - queue.add(command); + try { + this.command.write(event.getCommand()); + this.command.newLine(); + this.command.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public void edit(NamedContainer... changes) { + for (NamedContainer change : changes) { + switch (change.name().toLowerCase()) { + // TODO SubEditor } } } @@ -192,6 +186,11 @@ public class InternalSubServer extends SubServer { enabled = value; } + @Override + public boolean isEditable() { + return host.isEditable() && !isRunning(); + } + @Override public boolean isLogging() { return log.get(); 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 fe36c478..f866a027 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Server.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/Server.java @@ -1,6 +1,6 @@ package net.ME1312.SubServers.Proxy.Host; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidServerException; +import net.ME1312.SubServers.Proxy.Library.Exception.InvalidServerException; import net.ME1312.SubServers.Proxy.Network.Client; import net.ME1312.SubServers.Proxy.Network.ClientHandler; import net.md_5.bungee.BungeeServerInfo; diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubCreator.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubCreator.java index c2607910..7785d3c7 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubCreator.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubCreator.java @@ -1,6 +1,6 @@ package net.ME1312.SubServers.Proxy.Host; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import java.io.File; import java.util.UUID; @@ -13,19 +13,20 @@ import java.util.UUID; public abstract class SubCreator { public enum ServerType { SPIGOT, - BUKKIT, VANILLA, SPONGE, } - public abstract void create(UUID player, String name, int port, File directory, ServerType type, Version version, int memory); - public void create(String name, int port, File directory, ServerType type, Version version, int memory) { - create(null, name, port, directory, type, version, memory); + public abstract void create(UUID player, String name, ServerType type, Version version, int memory, int port); + public void create(String name, ServerType type, Version version, int memory, int port) { + create(null, name, type, version, memory, port); } public abstract void waitFor() throws InterruptedException; public abstract Host getHost(); + public abstract String getGitBashDirectory(); + public abstract boolean isBusy(); } 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 006a3972..41293674 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubServer.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Host/SubServer.java @@ -1,6 +1,7 @@ package net.ME1312.SubServers.Proxy.Host; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidServerException; +import net.ME1312.SubServers.Proxy.Library.Exception.InvalidServerException; +import net.ME1312.SubServers.Proxy.Library.NamedContainer; import java.net.InetSocketAddress; import java.util.UUID; @@ -19,10 +20,11 @@ public abstract class SubServer extends Server { * @param name Server Name * @param port Port Number * @param motd Server MOTD + * @param restricted Players will need a permission to join if true * @throws InvalidServerException */ - public SubServer(Host host, String name, int port, String motd) throws InvalidServerException { - super(name, InetSocketAddress.createUnresolved(host.getAddress().getHostAddress(), port), motd, false); + public SubServer(Host host, String name, int port, String motd, boolean restricted) throws InvalidServerException { + super(name, InetSocketAddress.createUnresolved(host.getAddress().getHostAddress(), port), motd, restricted); } /** @@ -84,6 +86,13 @@ public abstract class SubServer extends Server { command(null, command); } + /** + * Applies edits to the SubServer + * + * @param change Change(s) to be applied + */ + public abstract void edit(NamedContainer... change); + /** * Waits for the Server to Stop * @@ -119,6 +128,13 @@ public abstract class SubServer extends Server { */ public abstract void setEnabled(boolean value); + /** + * Get if the SubServer can be Edited + * + * @return Editable Status + */ + public abstract boolean isEditable(); + /** * If the Server is Logging * diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Launch.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Launch.java index 57175e25..b8e35d63 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Launch.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Launch.java @@ -25,6 +25,7 @@ public final class Launch { * @param args * @throws Exception */ + @SuppressWarnings("deprecation") public static void main(String[] args) throws Exception { System.out.println(""); System.out.println("*******************************************"); diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/lang.yml b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/lang.yml deleted file mode 100644 index d9022879..00000000 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/lang.yml +++ /dev/null @@ -1,3 +0,0 @@ -Version: '2.11.0a+' -Lang: - 'Console-Only-Command': '&4Console Access Only.' \ No newline at end of file diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLConfig.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLConfig.java similarity index 96% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLConfig.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLConfig.java index 40ff7ad1..4d2702fd 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLConfig.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLConfig.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Config; +package net.ME1312.SubServers.Proxy.Library.Config; import org.json.JSONObject; import org.yaml.snakeyaml.DumperOptions; diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLSection.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLSection.java similarity index 80% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLSection.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLSection.java index f22edd25..d1bcbec2 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLSection.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLSection.java @@ -1,5 +1,6 @@ -package net.ME1312.SubServers.Proxy.Libraries.Config; +package net.ME1312.SubServers.Proxy.Library.Config; +import net.ME1312.SubServers.Proxy.Library.Util; import net.md_5.bungee.api.ChatColor; import org.json.JSONObject; import org.yaml.snakeyaml.Yaml; @@ -29,6 +30,10 @@ public class YAMLSection { 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); } @@ -341,18 +346,18 @@ public class YAMLSection { } public String getString(String label) { - return (map.get(label) != null)?unescapeJavaString((String) map.get(label)):null; + return (map.get(label) != null)?Util.unescapeJavaString((String) map.get(label)):null; } public String getString(String label, String def) { - return unescapeJavaString((String) ((map.get(label) != null) ? map.get(label) : def)); + return Util.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)); + values.add(Util.unescapeJavaString(value)); } return values; } else { @@ -366,25 +371,25 @@ public class YAMLSection { } else { List values = new ArrayList(); for (String value : def) { - values.add(unescapeJavaString(value)); + values.add(Util.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; + return (map.get(label) != null)? ChatColor.translateAlternateColorCodes(color, Util.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))); + return ChatColor.translateAlternateColorCodes(color, Util.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))); + values.add(ChatColor.translateAlternateColorCodes(color, Util.unescapeJavaString(value))); } return values; } else { @@ -398,7 +403,7 @@ public class YAMLSection { } else { List values = new ArrayList(); for (String value : def) { - values.add(ChatColor.translateAlternateColorCodes(color, unescapeJavaString(value))); + values.add(ChatColor.translateAlternateColorCodes(color, Util.unescapeJavaString(value))); } return values; } @@ -435,75 +440,4 @@ public class YAMLSection { 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.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLValue.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLValue.java similarity index 90% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLValue.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLValue.java index c5567135..8ff81ed0 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Config/YAMLValue.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Config/YAMLValue.java @@ -1,5 +1,6 @@ -package net.ME1312.SubServers.Proxy.Libraries.Config; +package net.ME1312.SubServers.Proxy.Library.Config; +import net.ME1312.SubServers.Proxy.Library.Util; import net.md_5.bungee.api.ChatColor; import org.yaml.snakeyaml.Yaml; @@ -94,25 +95,25 @@ public class YAMLValue { } public String asString() { - return YAMLSection.unescapeJavaString((String) obj); + return Util.unescapeJavaString((String) obj); } public List asStringList() { List values = new ArrayList(); for (String value : (List) obj) { - values.add(YAMLSection.unescapeJavaString(value)); + values.add(Util.unescapeJavaString(value)); } return values; } public String asColoredString(char color) { - return ChatColor.translateAlternateColorCodes(color, YAMLSection.unescapeJavaString((String) obj)); + return ChatColor.translateAlternateColorCodes(color, Util.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))); + values.add(ChatColor.translateAlternateColorCodes(color, Util.unescapeJavaString(value))); } return values; } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Container.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Container.java similarity index 68% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Container.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Container.java index 4b6b08a0..a3f3ba7a 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Container.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Container.java @@ -1,19 +1,19 @@ -package net.ME1312.SubServers.Proxy.Libraries; +package net.ME1312.SubServers.Proxy.Library; /** * Container Class * * @author ME1312 */ -public class Container { - private T obj; +public class Container { + private V obj; /** * Creates a Container * * @param item Object to Store */ - public Container(T item) { + public Container(V item) { obj = item; } @@ -22,7 +22,7 @@ public class Container { * * @return The Object */ - public T get() { + public V get() { return obj; } @@ -31,7 +31,7 @@ public class Container { * * @param value Object to Store */ - public void set(T value) { + public void set(V value) { obj = value; } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/IllegalPacketException.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/IllegalPacketException.java similarity index 75% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/IllegalPacketException.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/IllegalPacketException.java index 71591d40..d2778333 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/IllegalPacketException.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/IllegalPacketException.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Exception; +package net.ME1312.SubServers.Proxy.Library.Exception; public class IllegalPacketException extends IllegalStateException { public IllegalPacketException() {} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidDriverException.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidDriverException.java similarity index 75% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidDriverException.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidDriverException.java index 190b46ee..03aa7beb 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidDriverException.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidDriverException.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Exception; +package net.ME1312.SubServers.Proxy.Library.Exception; public class InvalidDriverException extends IllegalStateException { public InvalidDriverException() {} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidHostException.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidHostException.java similarity index 75% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidHostException.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidHostException.java index 68bf6320..459235ae 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidHostException.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidHostException.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Exception; +package net.ME1312.SubServers.Proxy.Library.Exception; public class InvalidHostException extends IllegalStateException { public InvalidHostException() {} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidServerException.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidServerException.java similarity index 75% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidServerException.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidServerException.java index fb6021b8..594bbaa0 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Exception/InvalidServerException.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Exception/InvalidServerException.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Exception; +package net.ME1312.SubServers.Proxy.Library.Exception; public class InvalidServerException extends IllegalStateException { public InvalidServerException() {} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/build.sh b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/build.sh similarity index 100% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/build.sh rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/build.sh diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/config.yml b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/config.yml similarity index 73% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/config.yml rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/config.yml index 6b058469..ad3c2c03 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Files/config.yml +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/config.yml @@ -1,30 +1,29 @@ Settings: Version: '2.11.0a+' - Git-Bash: 'C:\Program Files\Git' Log-Creator: true - Enable-Graphic-Interface: true - Update-External-Files: true SubData: Address: '127.0.0.1:4391' Password: 'password123' Allowed-Connections: [] Hosts: - '~': + '~Built-In': Enabled: true Driver: 'BUILT-IN' Address: '127.0.0.1' Directory: './' + Git-Bash: 'C:\Program Files\Git' Servers: 'Server_1': Enabled: false - Host: '~' + Host: '~Built-In' Port: 25566 Motd: '&aThis is a SubServer' Log: true - Directory: '~/Server_1' + Directory: './Server_1' Executable: 'java -Djline.terminal=jline.UnsupportedTerminal -jar Spigot.jar' Stop-Command: 'stop' Run-On-Launch: false - Auto-Restart: false \ No newline at end of file + Auto-Restart: false + Restricted: false \ 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 new file mode 100644 index 00000000..ec313a4b --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Files/lang.yml @@ -0,0 +1,22 @@ +Version: '2.11.0a+' +Lang: + 'Interface.Generic.Back': '&cBack' + 'Interface.Generic.Back-Arrow': '&e&l<--' + 'Interface.Generic.Next-Arrow': '&e&l-->' + 'Interface.Host-Menu.Title': 'Host Menu' + 'Interface.Host-Menu.Host-Disabled': '&4Disabled' + 'Interface.Host-Menu.Host-Server-Count': '&9$int$ Servers' + 'Interface.Host-Menu.No-Hosts': '&4&oThere are No Hosts' + 'Interface.Host-Menu.SubServer-Menu': '&a&lSubServer Menu' + 'Interface.Host-Admin.Title': 'Host/$str$' + 'Interface.Host-Creator.Title': 'Host/$str$/Create' + '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': '&e$int$ Players Online' + 'Interface.SubServer-Menu.SubServer-Online': '&2Online' + 'Interface.SubServer-Menu.SubServer-Temporary': '&9Temporary' + 'Interface.SubServer-Menu.SubServer-Offline': '&6Offline' + 'Interface.SubServer-Menu.SubServer-Disabled': '&4Disabled' + 'Interface.SubServer-Menu.No-SubServers': '&4&oThere are No SubServers' + 'Interface.SubServer-Menu.Host-Menu': '&b&lHost Menu' \ No newline at end of file diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/JSONCallback.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/JSONCallback.java new file mode 100644 index 00000000..c02eb39f --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/JSONCallback.java @@ -0,0 +1,7 @@ +package net.ME1312.SubServers.Proxy.Library; + +import org.json.JSONObject; + +public interface JSONCallback { + void run(JSONObject json); +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/NamedContainer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/NamedContainer.java new file mode 100644 index 00000000..39eda262 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/NamedContainer.java @@ -0,0 +1,34 @@ +package net.ME1312.SubServers.Proxy.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.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/UniversalFile.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/UniversalFile.java similarity index 97% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/UniversalFile.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/UniversalFile.java index 29e36c80..85ccd9fc 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/UniversalFile.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/UniversalFile.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries; +package net.ME1312.SubServers.Proxy.Library; import java.io.File; diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Util.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Util.java new file mode 100644 index 00000000..9a289e8c --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Util.java @@ -0,0 +1,111 @@ +package net.ME1312.SubServers.Proxy.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.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Version/Version.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Version/Version.java similarity index 99% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Version/Version.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Version/Version.java index 03cae495..611f1bab 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Version/Version.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Version/Version.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Version; +package net.ME1312.SubServers.Proxy.Library.Version; import java.io.Serializable; diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Version/VersionTokenizer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Version/VersionTokenizer.java similarity index 95% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Version/VersionTokenizer.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Version/VersionTokenizer.java index 34ecf2e6..8c9a23c8 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Libraries/Version/VersionTokenizer.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Library/Version/VersionTokenizer.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Proxy.Libraries.Version; +package net.ME1312.SubServers.Proxy.Library.Version; public final class VersionTokenizer { private final String _versionString; diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Client.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Client.java index 66547214..f2890185 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Client.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Client.java @@ -1,6 +1,6 @@ package net.ME1312.SubServers.Proxy.Network; -import net.ME1312.SubServers.Proxy.Libraries.Exception.IllegalPacketException; +import net.ME1312.SubServers.Proxy.Library.Exception.IllegalPacketException; import net.ME1312.SubServers.Proxy.Network.Packet.PacketAuthorization; import net.ME1312.SubServers.Proxy.SubPlugin; import org.json.JSONException; @@ -11,10 +11,9 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -23,11 +22,11 @@ import java.util.TimerTask; * * @author ME1312 */ -public class Client { +public final class Client { private Socket socket; - private SocketAddress address; + private InetSocketAddress address; private ClientHandler handler; - private List queue = new ArrayList(); + private PrintWriter writer; private Timer authorized; private SubPlugin plugin; private Client instance; @@ -38,10 +37,11 @@ public class Client { * @param plugin SubPlugin * @param client Socket to Bind */ - public Client(SubPlugin plugin, Socket client) { + public Client(SubPlugin plugin, Socket client) throws IOException { this.plugin = plugin; socket = client; - address = client.getRemoteSocketAddress(); + writer = new PrintWriter(client.getOutputStream(), true); + address = new InetSocketAddress(client.getInetAddress(), client.getPort()); instance = this; authorized = new Timer("auth" + client.getRemoteSocketAddress().toString()); authorized.schedule(new TimerTask() { @@ -61,73 +61,41 @@ public class Client { * Network Loop */ protected void loop() { - new Thread() { - public void run() { - try { - BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - String input; - while ((input = in.readLine()) != null) { - try { - JSONObject json = new JSONObject(input); - PacketIn packet = plugin.subdata.decodePacket(json); - if (authorized == null || packet instanceof PacketAuthorization) { - try { - packet.execute(instance, (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(); - } - } + new Thread(() -> { + try { + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String input; + while ((input = in.readLine()) != null) { try { - plugin.subdata.removeClient(instance); - } catch (IOException e1) { - e1.printStackTrace(); - } - } catch (Exception e) { - if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace(); - try { - plugin.subdata.removeClient(instance); - } catch (IOException e1) { - e1.printStackTrace(); - } - } - } - }.start(); - new Thread() { - public void run() { - try { - PrintWriter out = new PrintWriter(socket.getOutputStream(), true); - while (!socket.isClosed()) { - while (queue.size() > 0) { + JSONObject json = new JSONObject(input); + PacketIn packet = SubDataServer.decodePacket(json); + if (authorized == null || packet instanceof PacketAuthorization) { try { - out.println(plugin.subdata.encodePacket(queue.get(0))); - queue.remove(0); - } catch (IllegalPacketException e) { - e.printStackTrace(); + packet.execute(instance, (json.keySet().contains("c")) ? json.getJSONObject("c") : null); + } catch (Exception e) { + new InvocationTargetException(e, "Exception while executing PacketIn").printStackTrace(); } } - sleep(100); - } - try { - plugin.subdata.removeClient(instance); - } catch (IOException e1) { - e1.printStackTrace(); - } - } catch (Exception e) { - if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace(); - try { - plugin.subdata.removeClient(instance); - } catch (IOException e1) { - e1.printStackTrace(); + } catch (IllegalPacketException e) { + e.printStackTrace(); + } catch (JSONException e) { + new IllegalPacketException("Unknown Packet Format: " + input).printStackTrace(); } } + try { + plugin.subdata.removeClient(instance); + } catch (IOException e1) { + e1.printStackTrace(); + } + } catch (Exception e) { + if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace(); + try { + plugin.subdata.removeClient(instance); + } catch (IOException e1) { + e1.printStackTrace(); + } } - }.start(); + }).start(); } /** @@ -147,7 +115,11 @@ public class Client { * @param packet Packet to send */ public void sendPacket(PacketOut packet) { - queue.add(packet); + try { + writer.println(SubDataServer.encodePacket(packet)); + } catch (IllegalPacketException e) { + e.printStackTrace(); + } } /** @@ -164,7 +136,7 @@ public class Client { * * @return Address */ - public SocketAddress getAddress() { + public InetSocketAddress getAddress() { return address; } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketAuthorization.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketAuthorization.java index 4f1af814..29601472 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketAuthorization.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketAuthorization.java @@ -1,6 +1,6 @@ package net.ME1312.SubServers.Proxy.Network.Packet; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import net.ME1312.SubServers.Proxy.Network.Client; import net.ME1312.SubServers.Proxy.Network.PacketIn; import net.ME1312.SubServers.Proxy.Network.PacketOut; @@ -23,7 +23,10 @@ public class PacketAuthorization implements PacketIn, PacketOut { @Override public JSONObject generate() { - return new JSONObject("{\"r\": " + response + ", \"" + message.replace("\"", "\\\"") + "\"}"); + JSONObject json = new JSONObject(); + json.put("r", response); + json.put("m", message); + return json; } @Override diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadBuildScript.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadBuildScript.java new file mode 100644 index 00000000..0bbecd16 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadBuildScript.java @@ -0,0 +1,55 @@ +package net.ME1312.SubServers.Proxy.Network.Packet; + +import net.ME1312.SubServers.Proxy.Library.UniversalFile; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Network.PacketIn; +import net.ME1312.SubServers.Proxy.Network.PacketOut; +import net.ME1312.SubServers.Proxy.SubPlugin; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.LinkedList; + +public class PacketDownloadBuildScript implements PacketIn, PacketOut { + private SubPlugin plugin; + private String id; + + public PacketDownloadBuildScript(SubPlugin plugin) { + this.plugin = plugin; + } + public PacketDownloadBuildScript(SubPlugin plugin, String id) { + this.plugin = plugin; + this.id = id; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + try { + LinkedList list = new LinkedList(); + BufferedReader script = new BufferedReader(new FileReader(new UniversalFile(plugin.dir, "SubServers:build.sh"))); + String line; + while ((line = script.readLine()) != null) { + list.add(line); + } + script.close(); + json.put("Script", list); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + + @Override + public void execute(Client client, JSONObject data) { + client.sendPacket(new PacketDownloadBuildScript(plugin, (data != null && data.keySet().contains("id"))?data.getString("id"):null)); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} \ No newline at end of file diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadHostInfo.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadHostInfo.java new file mode 100644 index 00000000..49fbf8c7 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadHostInfo.java @@ -0,0 +1,80 @@ +package net.ME1312.SubServers.Proxy.Network.Packet; + +import net.ME1312.SubServers.Proxy.Host.Host; +import net.ME1312.SubServers.Proxy.Host.SubServer; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Network.PacketIn; +import net.ME1312.SubServers.Proxy.Network.PacketOut; + +import net.ME1312.SubServers.Proxy.SubPlugin; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.json.JSONObject; + +public class PacketDownloadHostInfo implements PacketIn, PacketOut { + private SubPlugin plugin; + private Host host; + private String id; + + public PacketDownloadHostInfo(SubPlugin plugin) { + this.plugin = plugin; + } + public PacketDownloadHostInfo(SubPlugin plugin, Host host, String id) { + this.plugin = plugin; + this.host = host; + this.id = id; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + JSONObject info = new JSONObject(); + + if (host != null) { + json.put("valid", true); + + info.put("name", host.getName()); + info.put("enabled", host.isEnabled()); + info.put("editable", host.isEditable()); + info.put("address", host.getAddress().toString()); + info.put("dir", host.getDirectory()); + + JSONObject cinfo = new JSONObject(); + cinfo.put("busy", host.getCreator().isBusy()); + cinfo.put("git-bash", host.getCreator().getGitBashDirectory()); + info.put("creator", cinfo); + + JSONObject servers = new JSONObject(); + for (SubServer server : host.getSubServers().values()) { + JSONObject sinfo = new JSONObject(); + sinfo.put("enabled", server.isEnabled()); + sinfo.put("running", server.isRunning()); + sinfo.put("temp", server.isTemporary()); + JSONObject players = new JSONObject(); + for (ProxiedPlayer player : server.getPlayers()) { + JSONObject pinfo = new JSONObject(); + pinfo.put("name", player.getName()); + pinfo.put("nick", player.getDisplayName()); + players.put(player.getUniqueId().toString(), pinfo); + } + sinfo.put("players", players); + servers.put(server.getName(), sinfo); + } + info.put("servers", servers); + } else json.put("valid", false); + + json.put("host", info); + return json; + } + + @Override + public void execute(Client client, JSONObject data) { + client.sendPacket(new PacketDownloadHostInfo(plugin, plugin.api.getHost(data.getString("host")), (data.keySet().contains("id"))?data.getString("id"):null)); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadLang.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadLang.java new file mode 100644 index 00000000..6f26ce43 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadLang.java @@ -0,0 +1,39 @@ +package net.ME1312.SubServers.Proxy.Network.Packet; + +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Network.PacketIn; +import net.ME1312.SubServers.Proxy.Network.PacketOut; +import net.ME1312.SubServers.Proxy.SubPlugin; +import org.json.JSONObject; + +public class PacketDownloadLang implements PacketIn, PacketOut { + private SubPlugin plugin; + private String id; + + public PacketDownloadLang(SubPlugin plugin) { + this.plugin = plugin; + } + public PacketDownloadLang(SubPlugin plugin, String id) { + this.plugin = plugin; + this.id = id; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + json.put("Lang", plugin.lang.get().getSection("Lang").toJSON()); + return json; + } + + @Override + public void execute(Client client, JSONObject data) { + client.sendPacket(new PacketDownloadLang(plugin, (data != null && data.keySet().contains("id"))?data.getString("id"):null)); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadPlayerList.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadPlayerList.java new file mode 100644 index 00000000..ab04f145 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadPlayerList.java @@ -0,0 +1,48 @@ +package net.ME1312.SubServers.Proxy.Network.Packet; + +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Network.PacketIn; +import net.ME1312.SubServers.Proxy.Network.PacketOut; +import net.ME1312.SubServers.Proxy.SubPlugin; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.json.JSONObject; + +public class PacketDownloadPlayerList implements PacketIn, PacketOut { + private SubPlugin plugin; + private String id; + + public PacketDownloadPlayerList(SubPlugin plugin) { + this.plugin = plugin; + } + public PacketDownloadPlayerList(SubPlugin plugin, String id) { + this.plugin = plugin; + this.id = id; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + JSONObject players = new JSONObject(); + for (ProxiedPlayer player : plugin.getPlayers()) { + JSONObject pinfo = new JSONObject(); + pinfo.put("name", player.getName()); + pinfo.put("nick", player.getDisplayName()); + pinfo.put("server", player.getServer().getInfo().getName()); + players.put(player.getUniqueId().toString(), pinfo); + } + json.put("players", players); + return json; + } + + @Override + public void execute(Client client, JSONObject data) { + client.sendPacket(new PacketDownloadPlayerList(plugin, (data != null && data.keySet().contains("id"))?data.getString("id"):null)); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServerInfo.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java similarity index 67% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServerInfo.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java index 6e9f3654..149a1d32 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServerInfo.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerInfo.java @@ -2,34 +2,40 @@ package net.ME1312.SubServers.Proxy.Network.Packet; import net.ME1312.SubServers.Proxy.Host.Server; import net.ME1312.SubServers.Proxy.Host.SubServer; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import net.ME1312.SubServers.Proxy.Network.Client; import net.ME1312.SubServers.Proxy.Network.PacketIn; import net.ME1312.SubServers.Proxy.Network.PacketOut; import net.ME1312.SubServers.Proxy.SubPlugin; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.json.JSONArray; import org.json.JSONObject; -public class PacketRequestServerInfo implements PacketIn, PacketOut { +public class PacketDownloadServerInfo implements PacketIn, PacketOut { private SubPlugin plugin; private Server server; + private String id; - public PacketRequestServerInfo(SubPlugin plugin, Server server) { - this.server = server; - } - - public PacketRequestServerInfo(SubPlugin plugin) { + public PacketDownloadServerInfo(SubPlugin plugin) { this.plugin = plugin; } + public PacketDownloadServerInfo(SubPlugin plugin, Server server, String id) { + this.plugin = plugin; + this.server = server; + this.id = id; + } @Override public JSONObject generate() { JSONObject json = new JSONObject(); - JSONObject info = new JSONObject(); + json.put("id", id); json.put("type", (server == null)?"invalid":((server instanceof SubServer)?"subserver":"server")); + JSONObject info = new JSONObject(); if (server != null && server instanceof SubServer) { info.put("host", ((SubServer) server).getHost().getName()); info.put("enabled", ((SubServer) server).isEnabled()); + info.put("editable", ((SubServer) server).isEditable()); info.put("log", ((SubServer) server).isLogging()); info.put("dir", plugin.config.get().getSection("Servers").getSection(server.getName()).getString("Directory")); info.put("exec", plugin.config.get().getSection("Servers").getSection(server.getName()).getString("Executable")); @@ -44,6 +50,15 @@ public class PacketRequestServerInfo implements PacketIn, PacketOut { info.put("restricted", server.isRestricted()); info.put("motd", server.getMotd()); info.put("subdata", server.getSubDataClient() == null); + + JSONObject players = new JSONObject(); + for (ProxiedPlayer player : server.getPlayers()) { + JSONObject pinfo = new JSONObject(); + pinfo.put("name", player.getName()); + pinfo.put("nick", player.getDisplayName()); + players.put(player.getUniqueId().toString(), pinfo); + } + info.put("players", players); } json.put("server", info); @@ -52,7 +67,7 @@ public class PacketRequestServerInfo implements PacketIn, PacketOut { @Override public void execute(Client client, JSONObject data) { - client.sendPacket(new PacketRequestServerInfo(plugin, plugin.api.getServer(data.getString("server")))); + client.sendPacket(new PacketDownloadServerInfo(plugin, plugin.api.getServer(data.getString("server")), (data.keySet().contains("id"))?data.getString("id"):null)); } @Override diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerList.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerList.java new file mode 100644 index 00000000..b3bf1821 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketDownloadServerList.java @@ -0,0 +1,95 @@ +package net.ME1312.SubServers.Proxy.Network.Packet; + +import net.ME1312.SubServers.Proxy.Host.Host; +import net.ME1312.SubServers.Proxy.Host.Server; +import net.ME1312.SubServers.Proxy.Host.SubServer; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Network.PacketIn; +import net.ME1312.SubServers.Proxy.Network.PacketOut; +import net.ME1312.SubServers.Proxy.SubPlugin; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeMap; + +public class PacketDownloadServerList implements PacketIn, PacketOut { + private SubPlugin plugin; + private String host; + private String id; + + public PacketDownloadServerList(SubPlugin plugin) { + this.plugin = plugin; + } + public PacketDownloadServerList(SubPlugin plugin, String host, String id) { + this.plugin = plugin; + this.host = host; + this.id = id; + } + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("id", id); + if (host == null || host.equals("")) { + JSONObject exServers = new JSONObject(); + for (Server server : plugin.exServers.values()) { + JSONObject info = new JSONObject(); + JSONObject players = new JSONObject(); + for (ProxiedPlayer player : server.getPlayers()) { + JSONObject pinfo = new JSONObject(); + pinfo.put("name", player.getName()); + pinfo.put("nick", player.getDisplayName()); + players.put(player.getUniqueId().toString(), pinfo); + } + info.put("players", players); + exServers.put(server.getName(), info); + } + json.put("servers", exServers); + } + + if (this.host == null || !this.host.equals("")) { + JSONObject hosts = new JSONObject(); + for (Host host : plugin.api.getHosts().values()) { + if (this.host == null || this.host.equalsIgnoreCase(host.getName())) { + JSONObject hinfo = new JSONObject(); + hinfo.put("enabled", host.isEnabled()); + JSONObject servers = new JSONObject(); + for (SubServer server : host.getSubServers().values()) { + JSONObject sinfo = new JSONObject(); + sinfo.put("enabled", server.isEnabled()); + sinfo.put("running", server.isRunning()); + sinfo.put("temp", server.isTemporary()); + JSONObject players = new JSONObject(); + for (ProxiedPlayer player : server.getPlayers()) { + JSONObject pinfo = new JSONObject(); + pinfo.put("name", player.getName()); + pinfo.put("nick", player.getDisplayName()); + players.put(player.getUniqueId().toString(), pinfo); + } + sinfo.put("players", players); + servers.put(server.getName(), sinfo); + } + hinfo.put("servers", servers); + hosts.put(host.getName(), hinfo); + } + } + json.put("hosts", hosts); + } + + return json; + } + + @Override + public void execute(Client client, JSONObject data) { + client.sendPacket(new PacketDownloadServerList(plugin, (data.keySet().contains("host"))?data.getString("host"):null, (data.keySet().contains("id"))?data.getString("id"):null)); + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketInfoPassthrough.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketInfoPassthrough.java new file mode 100644 index 00000000..567c4ece --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketInfoPassthrough.java @@ -0,0 +1,73 @@ +package net.ME1312.SubServers.Proxy.Network.Packet; + +import net.ME1312.SubServers.Proxy.Event.SubDataRecieveGenericInfoEvent; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Network.ClientHandler; +import net.ME1312.SubServers.Proxy.Network.PacketIn; +import net.ME1312.SubServers.Proxy.Network.PacketOut; +import net.ME1312.SubServers.Proxy.SubPlugin; +import org.json.JSONObject; + +import java.net.InetSocketAddress; + +public class PacketInfoPassthrough implements PacketIn, PacketOut { + private SubPlugin plugin; + private String h; + private Version v; + private JSONObject c; + + public PacketInfoPassthrough(SubPlugin plugin) { + this.plugin = plugin; + } + public PacketInfoPassthrough(String handle, Version version, JSONObject content) { + this.h = handle; + this.v = version; + this.c = content; + } + + + @Override + public JSONObject generate() { + JSONObject json = new JSONObject(); + json.put("h", h); + json.put("v", v.toString()); + json.put("c", c); + return json; + } + + @Override + public void execute(Client client, JSONObject data) { + if (data.get("t") == null) { + plugin.getPluginManager().callEvent(new SubDataRecieveGenericInfoEvent(data.getString("h"), new Version(data.getString("v")), data.getJSONObject("c"))); + } else { + try { + switch (data.getJSONObject("t").getString("type").toLowerCase()) { + case "address": + if (plugin.subdata.getClient(new InetSocketAddress(data.getJSONObject("t").getString("id").split(":")[0], Integer.parseInt(data.getJSONObject("t").getString("id").split(":")[1]))) != null) + plugin.subdata.getClient(new InetSocketAddress(data.getJSONObject("t").getString("id").split(":")[0], Integer.parseInt(data.getJSONObject("t").getString("id").split(":")[1]))) + .sendPacket(new PacketInfoPassthrough(data.getString("h"), new Version(data.getString("v")), data.getJSONObject("c"))); + break; + case "host": + if (plugin.hosts.keySet().contains(data.getJSONObject("t").getString("id").toLowerCase()) && plugin.hosts.get(data.getJSONObject("t").getString("id").toLowerCase()) instanceof ClientHandler) + ((ClientHandler) plugin.hosts.get(data.getJSONObject("t").getString("id").toLowerCase())).getSubDataClient() + .sendPacket(new PacketInfoPassthrough(data.getString("h"), new Version(data.getString("v")), data.getJSONObject("c"))); + break; + case "server": + case "subserver": + if (plugin.api.getServers().keySet().contains(data.getJSONObject("t").getString("id").toLowerCase())) + plugin.api.getServers().get(data.getJSONObject("t").getString("id").toLowerCase()).getSubDataClient() + .sendPacket(new PacketInfoPassthrough(data.getString("h"), new Version(data.getString("v")), data.getJSONObject("c"))); + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public Version getVersion() { + return new Version("2.11.0a"); + } +} \ No newline at end of file diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketLinkServer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketLinkServer.java index 9b05b3ee..3eb21cf2 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketLinkServer.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketLinkServer.java @@ -2,7 +2,7 @@ package net.ME1312.SubServers.Proxy.Network.Packet; import net.ME1312.SubServers.Proxy.Host.Server; import net.ME1312.SubServers.Proxy.Host.SubServer; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import net.ME1312.SubServers.Proxy.Network.Client; import net.ME1312.SubServers.Proxy.Network.PacketIn; import net.ME1312.SubServers.Proxy.Network.PacketOut; @@ -28,7 +28,10 @@ public class PacketLinkServer implements PacketIn, PacketOut { @Override public JSONObject generate() { - return new JSONObject("{\"r\": " + response + ", \"" + message.replace("\"", "\\\"") + "\"}"); + JSONObject json = new JSONObject(); + json.put("r", response); + json.put("m", message); + return json; } @Override @@ -37,9 +40,13 @@ public class PacketLinkServer implements PacketIn, PacketOut { Map servers = plugin.api.getServers(); if (servers.keySet().contains(data.getString("name").toLowerCase())) { Server server = servers.get(data.getString("name").toLowerCase()); - server.linkSubDataClient(client); - System.out.println("SubData > " + client.getAddress().toString() + " has been defined as " + ((server instanceof SubServer)?"SubServer":"Server") + ": " + server.getName()); - client.sendPacket(new PacketLinkServer(true, "Definition Successful")); + if (server.getSubDataClient() == null) { + server.linkSubDataClient(client); + System.out.println("SubData > " + client.getAddress().toString() + " has been defined as " + ((server instanceof SubServer) ? "SubServer" : "Server") + ": " + server.getName()); + client.sendPacket(new PacketLinkServer(true, "Definition Successful")); + } else { + client.sendPacket(new PacketLinkServer(false, "Server already linked")); + } } else { client.sendPacket(new PacketLinkServer(false, "There is no server with that name")); } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServers.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServers.java deleted file mode 100644 index c47b0b80..00000000 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/Packet/PacketRequestServers.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.ME1312.SubServers.Proxy.Network.Packet; - -import net.ME1312.SubServers.Proxy.Host.Server; -import net.ME1312.SubServers.Proxy.Host.SubServer; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; -import net.ME1312.SubServers.Proxy.Network.Client; -import net.ME1312.SubServers.Proxy.Network.PacketIn; -import net.ME1312.SubServers.Proxy.Network.PacketOut; -import net.ME1312.SubServers.Proxy.SubPlugin; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.List; -import java.util.TreeMap; - -public class PacketRequestServers implements PacketIn, PacketOut { - private SubPlugin plugin; - - public PacketRequestServers(SubPlugin plugin) { - this.plugin = plugin; - } - - @Override - public JSONObject generate() { - JSONObject json = new JSONObject(); - - List exServers = new ArrayList(); - for (Server server : plugin.exServers.values()) { - exServers.add(server.getName()); - } - json.put("servers", exServers); - - TreeMap> hosts = new TreeMap>(); - for (SubServer server : plugin.api.getSubServers().values()) { - List servers = (hosts.keySet().contains(server.getHost().getName()))?hosts.get(server.getHost().getName()):new ArrayList(); - servers.add(server.getName()); - hosts.put(server.getHost().getName(), servers); - } - json.put("hosts", hosts); - - return json; - } - - @Override - public void execute(Client client, JSONObject data) { - client.sendPacket(this); - } - - @Override - public Version getVersion() { - return new Version("2.11.0a"); - } -} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketIn.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketIn.java index 21f5a8d7..bc47d0d9 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketIn.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketIn.java @@ -1,7 +1,6 @@ package net.ME1312.SubServers.Proxy.Network; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; -import net.ME1312.SubServers.Proxy.Network.Client; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import org.json.JSONObject; /** diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketOut.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketOut.java index ef9cdd10..9cc0342c 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketOut.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/PacketOut.java @@ -1,6 +1,6 @@ package net.ME1312.SubServers.Proxy.Network; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import org.json.JSONObject; /** diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/NetworkManager.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/SubDataServer.java similarity index 63% rename from SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/NetworkManager.java rename to SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/SubDataServer.java index c1bf665a..51f186c6 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/NetworkManager.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/Network/SubDataServer.java @@ -1,39 +1,34 @@ package net.ME1312.SubServers.Proxy.Network; -import net.ME1312.SubServers.Proxy.Libraries.Exception.IllegalPacketException; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; -import net.ME1312.SubServers.Proxy.Network.Packet.PacketAuthorization; -import net.ME1312.SubServers.Proxy.Network.Packet.PacketLinkServer; -import net.ME1312.SubServers.Proxy.Network.Packet.PacketRequestServerInfo; -import net.ME1312.SubServers.Proxy.Network.Packet.PacketRequestServers; +import net.ME1312.SubServers.Proxy.Library.Exception.IllegalPacketException; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.Packet.*; import net.ME1312.SubServers.Proxy.SubPlugin; import org.json.JSONObject; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketAddress; +import java.net.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * NetworkManager Class + * SubDataServer Class * * @author ME1312 */ -public final class NetworkManager { - private HashMap, String> pOut = new HashMap, String>(); - private HashMap pIn = new HashMap(); - private HashMap clients = new HashMap(); - private List allowedAddresses = new ArrayList(); +public final class SubDataServer { + private static HashMap, String> pOut = new HashMap, String>(); + private static HashMap pIn = new HashMap(); + private static List allowedAddresses = new ArrayList(); + private static boolean defaults = false; + private HashMap clients = new HashMap(); private ServerSocket server; private SubPlugin plugin; /** - * SubServers Network Manager + * SubData Server Instance * * @param plugin SubPlugin * @param port Port @@ -41,15 +36,16 @@ public final class NetworkManager { * @param address Bind Address * @throws IOException */ - public NetworkManager(SubPlugin plugin, int port, int backlog, InetAddress address) throws IOException { + public SubDataServer(SubPlugin plugin, int port, int backlog, InetAddress address) throws IOException { server = new ServerSocket(port, backlog, address); this.plugin = plugin; allowConnection(address); - loadDefaults(); + if (!defaults) loadDefaults(); } private void loadDefaults() { + defaults = true; for (String s : plugin.config.get().getSection("Settings").getSection("SubData").getStringList("Allowed-Connections")) { try { allowedAddresses.add(InetAddress.getByName(s)); @@ -59,14 +55,24 @@ public final class NetworkManager { } registerPacket(new PacketAuthorization(plugin), "Authorization"); + registerPacket(new PacketDownloadBuildScript(plugin), "DownloadBuildScript"); + registerPacket(new PacketDownloadHostInfo(plugin), "DownloadHostInfo"); + registerPacket(new PacketDownloadLang(plugin), "DownloadLang"); + registerPacket(new PacketDownloadPlayerList(plugin), "DownloadPlayerList"); + registerPacket(new PacketDownloadServerInfo(plugin), "DownloadServerInfo"); + registerPacket(new PacketDownloadServerList(plugin), "DownloadServerList"); + registerPacket(new PacketInfoPassthrough(plugin), "InfoPassthrough"); registerPacket(new PacketLinkServer(plugin), "LinkServer"); - registerPacket(new PacketRequestServerInfo(plugin), "RequestServerInfo"); - registerPacket(new PacketRequestServers(plugin), "RequestServers"); registerPacket(PacketAuthorization.class, "Authorization"); + registerPacket(PacketDownloadBuildScript.class, "DownloadBuildScript"); + registerPacket(PacketDownloadHostInfo.class, "DownloadHostInfo"); + registerPacket(PacketDownloadLang.class, "DownloadLang"); + registerPacket(PacketDownloadPlayerList.class, "DownloadPlayerList"); + registerPacket(PacketDownloadServerInfo.class, "DownloadServerInfo"); + registerPacket(PacketDownloadServerList.class, "DownloadServerList"); + registerPacket(PacketInfoPassthrough.class, "InfoPassthrough"); registerPacket(PacketLinkServer.class, "LinkServer"); - registerPacket(PacketRequestServerInfo.class, "RequestServerInfo"); - registerPacket(PacketRequestServers.class, "RequestServers"); } /** @@ -91,7 +97,7 @@ public final class NetworkManager { clients.put(client.getAddress(), client); return client; } else { - System.out.println("SubData > " + socket.getRemoteSocketAddress().toString() + " attempted to connect, but isn't whitelisted"); + System.out.println("SubData > " + socket.getInetAddress().toString() + ":" + socket.getPort() + " attempted to connect, but isn't whitelisted"); socket.close(); return null; } @@ -104,7 +110,7 @@ public final class NetworkManager { * @return Client */ public Client getClient(Socket socket) { - return clients.get(socket.getRemoteSocketAddress()); + return clients.get(new InetSocketAddress(socket.getInetAddress(), socket.getPort())); } /** @@ -113,7 +119,7 @@ public final class NetworkManager { * @param address Address to search * @return Client */ - public Client getClient(SocketAddress address) { + public Client getClient(InetSocketAddress address) { return clients.get(address); } @@ -138,7 +144,7 @@ public final class NetworkManager { * @param address Address to Kick * @throws IOException */ - public void removeClient(SocketAddress address) throws IOException { + public void removeClient(InetSocketAddress address) throws IOException { Client client = clients.get(address); if (clients.keySet().contains(address)) { clients.remove(address); @@ -148,23 +154,41 @@ public final class NetworkManager { } /** - * Register Packet to the Network + * Register PacketIn to the Network * * @param packet PacketIn to register * @param handle Handle to Bind */ - public void registerPacket(PacketIn packet, String handle) { - pIn.put(handle, packet); + public static void registerPacket(PacketIn packet, String handle) { + if (!pIn.keySet().contains(handle)) { + pIn.put(handle, packet); + } else { + throw new IllegalStateException("PacketIn Handle \"" + handle + "\" is already in use!"); + } } /** - * Register Packet to the Network + * Register PacketOut to the Network * * @param packet PacketOut to register * @param handle Handle to bind */ - public void registerPacket(Class packet, String handle) { - pOut.put(packet, handle); + public static void registerPacket(Class packet, String handle) { + if (!pOut.values().contains(handle)) { + pOut.put(packet, handle); + } else { + throw new IllegalStateException("PacketOut Handle \"" + handle + "\" is already in use!"); + } + } + + /** + * Grab PacketIn Instance via handle + * + * @param handle Handle + * @return PacketIn + */ + public static PacketIn getPacket(String handle) { + return pIn.get(handle); } /** @@ -184,7 +208,7 @@ public final class NetworkManager { * * @param address Address to allow */ - public void allowConnection(InetAddress address) { + public static void allowConnection(InetAddress address) { if (!allowedAddresses.contains(address)) allowedAddresses.add(address); } @@ -193,7 +217,7 @@ public final class NetworkManager { * * @param address Address to deny */ - public void denyConnection(InetAddress address) { + public static void denyConnection(InetAddress address) { allowedAddresses.remove(address); } @@ -204,7 +228,7 @@ public final class NetworkManager { * @return JSON Formatted Packet * @throws IllegalPacketException */ - protected JSONObject encodePacket(PacketOut 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()); @@ -225,7 +249,7 @@ public final class NetworkManager { * @throws IllegalPacketException * @throws InvocationTargetException */ - protected PacketIn decodePacket(JSONObject json) throws IllegalPacketException, 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")); diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubAPI.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubAPI.java index 7ffca944..2ab5b2fd 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubAPI.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubAPI.java @@ -1,14 +1,18 @@ package net.ME1312.SubServers.Proxy; +import net.ME1312.SubServers.Proxy.Event.SubAddServerEvent; import net.ME1312.SubServers.Proxy.Host.Server; import net.ME1312.SubServers.Proxy.Host.Host; import net.ME1312.SubServers.Proxy.Host.SubServer; -import net.ME1312.SubServers.Proxy.Libraries.UniversalFile; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; -import net.ME1312.SubServers.Proxy.Network.NetworkManager; +import net.ME1312.SubServers.Proxy.Library.UniversalFile; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.SubDataServer; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.Map; import java.util.TreeMap; +import java.util.UUID; /** * SubAPI Class @@ -49,7 +53,7 @@ public final class SubAPI { * * @return SubData Network Manager */ - public NetworkManager getSubDataNetwork() { + public SubDataServer getSubDataNetwork() { return plugin.subdata; } @@ -97,6 +101,43 @@ public final class SubAPI { return servers; } + /** + * Adds a Server to the Network + * + * @param name Name of the Server + * @param ip IP of the Server + * @param port Port of the Server + * @param motd MOTD of the Server + * @param restricted Players will need a permission to join if true + * @return The Server + */ + public Server addServer(String name, InetAddress ip, int port, String motd, boolean restricted) { + return addServer(null, name, ip, port, motd, restricted); + } + + /** + * Adds a Server to the Network + * + * @param player Player who added + * @param name Name of the Server + * @param ip IP of the Server + * @param port Port of the Server + * @param motd MOTD of the Server + * @param restricted Players will need a permission to join if true + * @return The Server + */ + public Server addServer(UUID player, String name, InetAddress ip, int port, String motd, boolean restricted) { + Server server = new Server(name, new InetSocketAddress(ip, port), motd, restricted); + SubAddServerEvent event = new SubAddServerEvent(player, null, server); + plugin.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + plugin.exServers.put(name.toLowerCase(), server); + return server; + } else { + return null; + } + } + /** * Gets a Server * diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java index 9ad2c386..8fee1fe1 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubCommand.java @@ -1,9 +1,14 @@ package net.ME1312.SubServers.Proxy; +import net.ME1312.SubServers.Proxy.Host.Server; +import net.ME1312.SubServers.Proxy.Host.SubCreator; import net.ME1312.SubServers.Proxy.Host.SubServer; +import net.ME1312.SubServers.Proxy.Library.Util; +import net.ME1312.SubServers.Proxy.Library.Version.Version; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.command.ConsoleCommandSender; @@ -18,7 +23,7 @@ public final class SubCommand extends Command { private SubPlugin plugin; public SubCommand(SubPlugin plugin) { - super("subserver", "subservers.console_only", "sub", "subservers"); + super("subserver", null, "sub", "subservers"); this.plugin = plugin; } @@ -36,18 +41,20 @@ public final class SubCommand extends Command { if (args[0].equalsIgnoreCase("help") || args[0].equalsIgnoreCase("?")) { sender.sendMessages(printHelp()); } else if (args[0].equalsIgnoreCase("version") || args[0].equalsIgnoreCase("ver")) { - sender.sendMessage("SubServers > SubServers.Proxy is running version " + plugin.version.toString()); + sender.sendMessage("SubServers > SubServers.Bungee is running version " + plugin.version.toString() + ((plugin.bversion != null)?" BETA "+plugin.bversion.toString():"")); } else if (args[0].equalsIgnoreCase("list")) { sender.sendMessages( "SubServers > Host List:", plugin.hosts.keySet().toString(), - "SubServers > Server List:", plugin.getServers().keySet().toString()); + "SubServers > Server List:", plugin.api.getServers().keySet().toString()); } else if (args[0].equalsIgnoreCase("start")) { if (args.length > 1) { - Map servers = plugin.getServers(); + Map servers = plugin.api.getServers(); if (!servers.keySet().contains(args[1].toLowerCase())) { sender.sendMessage("SubServers > There is no server with that name"); } else if (!(servers.get(args[1].toLowerCase()) instanceof SubServer)) { sender.sendMessage("SubServers > That Server is not a SubServer"); + } else if (!((SubServer) servers.get(args[1].toLowerCase())).getHost().isEnabled()) { + sender.sendMessage("SubServers > That SubServer's Host is not enabled"); } else if (!((SubServer) servers.get(args[1].toLowerCase())).isEnabled()) { sender.sendMessage("SubServers > That SubServer is not enabled"); } else if (((SubServer) servers.get(args[1].toLowerCase())).isRunning()) { @@ -60,7 +67,7 @@ public final class SubCommand extends Command { } } else if (args[0].equalsIgnoreCase("stop")) { if (args.length > 1) { - Map servers = plugin.getServers(); + Map servers = plugin.api.getServers(); if (!servers.keySet().contains(args[1].toLowerCase())) { sender.sendMessage("SubServers > There is no server with that name"); } else if (!(servers.get(args[1].toLowerCase()) instanceof SubServer)) { @@ -75,7 +82,7 @@ public final class SubCommand extends Command { } } else if (args[0].equalsIgnoreCase("kill") || args[0].equalsIgnoreCase("terminate")) { if (args.length > 1) { - Map servers = plugin.getServers(); + Map servers = plugin.api.getServers(); if (!servers.keySet().contains(args[1].toLowerCase())) { sender.sendMessage("SubServers > There is no server with that name"); } else if (!(servers.get(args[1].toLowerCase()) instanceof SubServer)) { @@ -90,7 +97,7 @@ public final class SubCommand extends Command { } } else if (args[0].equalsIgnoreCase("cmd") || args[0].equalsIgnoreCase("command")) { if (args.length > 2) { - Map servers = plugin.getServers(); + Map servers = plugin.api.getServers(); if (!servers.keySet().contains(args[1].toLowerCase())) { sender.sendMessage("SubServers > There is no server with that name"); } else if (!(servers.get(args[1].toLowerCase()) instanceof SubServer)) { @@ -112,13 +119,40 @@ public final class SubCommand extends Command { sender.sendMessage("SubServers > Usage: /sub cmd [Args...]"); } } else if (args[0].equalsIgnoreCase("create")) { - + if (args.length > 5) { + if (plugin.api.getServers().keySet().contains(args[1].toLowerCase())) { + sender.sendMessage("SubServers > There is already a server with that name"); + } else if (!plugin.hosts.keySet().contains(args[2].toLowerCase())) { + sender.sendMessage("SubServers > There is no host with that name"); + } else if (plugin.hosts.get(args[2].toLowerCase()).getCreator().isBusy()) { + sender.sendMessage("SubServers > The SubCreator instance on that host is already running"); + } else if (Util.isException(() -> SubCreator.ServerType.valueOf(args[3].toUpperCase()))) { + sender.sendMessage("SubServers > There is no server type with that name"); + } else if (new Version("1.8").compareTo(new Version(args[4])) > 0) { + sender.sendMessage("SubServers > SubCreator cannot create servers before Minecraft 1.8"); + } else if (Util.isException(() -> Integer.parseInt(args[5])) || Integer.parseInt(args[5]) <= 0 || Integer.parseInt(args[5]) > 65535) { + sender.sendMessage("SubServers > Invalid Port Number"); + } else if (args.length > 6 && (Util.isException(() -> Integer.parseInt(args[6])) || Integer.parseInt(args[6]) < 256)) { + sender.sendMessage("SubServers > Invalid Ram Amount"); + } else { + plugin.hosts.get(args[2].toLowerCase()).getCreator().create(args[1], SubCreator.ServerType.valueOf(args[3].toUpperCase()), new Version(args[4]), (args.length > 6)?Integer.parseInt(args[6]):1024, Integer.parseInt(args[5])); + } + } else { + sender.sendMessage("SubServers > Usage: /sub create [RAM]"); + } } } else { sender.sendMessages(printHelp()); } } else { - sender.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.lang.get().getSection("Lang").getString("Console-Only-Command"))); + String str = ""; + int i = -1; + while ((i + 1) != args.length) { + i++; + str = str + " " + args[i]; + } + System.out.println("/subserver" + str); + ((ProxiedPlayer) sender).chat("/subserver" + str); } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java index 7e62be86..1ee1539a 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Proxy/SubPlugin.java @@ -2,14 +2,15 @@ package net.ME1312.SubServers.Proxy; import net.ME1312.SubServers.Proxy.Host.Executable; import net.ME1312.SubServers.Proxy.Host.Server; -import net.ME1312.SubServers.Proxy.Libraries.Config.YAMLConfig; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidHostException; -import net.ME1312.SubServers.Proxy.Libraries.Exception.InvalidServerException; +import net.ME1312.SubServers.Proxy.Library.Config.YAMLConfig; +import net.ME1312.SubServers.Proxy.Library.Exception.InvalidHostException; +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.Libraries.UniversalFile; -import net.ME1312.SubServers.Proxy.Libraries.Version.Version; -import net.ME1312.SubServers.Proxy.Network.NetworkManager; +import net.ME1312.SubServers.Proxy.Library.UniversalFile; +import net.ME1312.SubServers.Proxy.Library.Util; +import net.ME1312.SubServers.Proxy.Library.Version.Version; +import net.ME1312.SubServers.Proxy.Network.SubDataServer; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.api.config.ServerInfo; @@ -29,11 +30,12 @@ public final class SubPlugin extends BungeeCord { public final HashMap exServers = new HashMap(); public final HashMap hosts = new HashMap(); - public final UniversalFile dir = new UniversalFile(new File("./")); + public final UniversalFile dir = new UniversalFile(new File(System.getProperty("user.dir"))); public YAMLConfig config; public YAMLConfig lang; - public NetworkManager subdata; + public SubDataServer subdata = null; public final Version version = new Version("2.11.0a"); + protected Version bversion = new Version(1); protected boolean running = false; public final SubAPI api = new SubAPI(this); @@ -49,31 +51,31 @@ public final class SubPlugin extends BungeeCord { */ protected void enable() throws IOException { if (running) throw new IllegalStateException("SubServers has already been loaded"); - System.out.println("SubServers > Loading SubServers v" + version.toString() + " Libraries... "); + System.out.println("SubServers > Loading SubServers v" + version.toString() + " Library... "); running = true; UniversalFile dir = new UniversalFile(this.dir, "SubServers"); dir.mkdir(); if (!(new UniversalFile(dir, "config.yml").exists())) { - copyFromJar("net/ME1312/SubServers/Proxy/Libraries/Files/config.yml", new UniversalFile(dir, "config.yml").getPath()); + Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Proxy/Library/Files/config.yml", new UniversalFile(dir, "config.yml").getPath()); System.out.println("SubServers > Created ~/SubServers/config.yml"); } else if ((new Version((new YAMLConfig(new UniversalFile(dir, "config.yml"))).get().getSection("Settings").getString("Version", "0")).compareTo(new Version("2.11.0a+"))) != 0) { Files.move(new UniversalFile(dir, "config.yml").toPath(), new UniversalFile(dir, "config.old" + Math.round(Math.random() * 100000) + ".yml").toPath()); - copyFromJar("net/ME1312/SubServers/Proxy/Libraries/Files/config.yml", new UniversalFile(dir, "config.yml").getPath()); + Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Proxy/Library/Files/config.yml", new UniversalFile(dir, "config.yml").getPath()); System.out.println("SubServers > Updated ~/SubServers/config.yml"); } if (!(new UniversalFile(dir, "lang.yml").exists())) { - copyFromJar("net/ME1312/SubServers/Proxy/Libraries/Files/lang.yml", new UniversalFile(dir, "lang.yml").getPath()); + Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Proxy/Library/Files/lang.yml", new UniversalFile(dir, "lang.yml").getPath()); System.out.println("SubServers > Created ~/SubServers/lang.yml"); } else if ((new Version((new YAMLConfig(new UniversalFile(dir, "lang.yml"))).get().getString("Version", "0")).compareTo(new Version("2.11.0a+"))) != 0) { Files.move(new UniversalFile(dir, "lang.yml").toPath(), new UniversalFile(dir, "lang.old" + Math.round(Math.random() * 100000) + ".yml").toPath()); - copyFromJar("net/ME1312/SubServers/Proxy/Libraries/Files/lang.yml", new UniversalFile(dir, "lang.yml").getPath()); + Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Proxy/Library/Files/lang.yml", new UniversalFile(dir, "lang.yml").getPath()); System.out.println("SubServers > Updated ~/SubServers/lang.yml"); } if (!(new UniversalFile(dir, "build.sh").exists())) { - copyFromJar("net/ME1312/SubServers/Proxy/Libraries/Files/build.sh", new UniversalFile(dir, "build.sh").getPath()); + Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Proxy/Library/Files/build.sh", new UniversalFile(dir, "build.sh").getPath()); System.out.println("SubServers > Created ~/SubServers/build.sh"); } else { String Version = "null"; @@ -85,14 +87,14 @@ public final class SubPlugin extends BungeeCord { if (!Version.equalsIgnoreCase("2.11.0a+")) { Files.move(new UniversalFile(dir, "build.sh").toPath(), new UniversalFile(dir, "build.old" + Math.round(Math.random() * 100000) + ".sh").toPath()); - copyFromJar("net/ME1312/SubServers/Proxy/Libraries/Files/build.sh", new UniversalFile(dir, "build.sh").getPath()); + Util.copyFromJar(SubPlugin.class.getClassLoader(), "net/ME1312/SubServers/Proxy/Library/Files/build.sh", new UniversalFile(dir, "build.sh").getPath()); System.out.println("SubServers > Updated ~/SubServers/build.sh"); } } hostDrivers.put("built-in", net.ME1312.SubServers.Proxy.Host.Internal.InternalHost.class); - System.out.println("SubServers > Loading BungeeCord Libraries..."); + System.out.println("SubServers > Loading BungeeCord Library..."); } /** @@ -103,8 +105,8 @@ public final class SubPlugin extends BungeeCord { try { config = new YAMLConfig(new UniversalFile(dir, "SubServers:config.yml")); lang = new YAMLConfig(new UniversalFile(dir, "SubServers:lang.yml")); - subdata = new NetworkManager(this, Integer.parseInt(config.get().getSection("Settings").getSection("SubData").getString("Address", "127.0.0.1:4391").split(":")[1]), 10, - InetAddress.getByName(config.get().getSection("Settings").getSection("SubData").getString("Address", "127.0.0.1:4391").split(":")[0])); + subdata = new SubDataServer(this, Integer.parseInt(config.get().getSection("Settings").getSection("SubData").getRawString("Address", "127.0.0.1:4391").split(":")[1]), 10, + InetAddress.getByName(config.get().getSection("Settings").getSection("SubData").getRawString("Address", "127.0.0.1:4391").split(":")[0])); System.out.println("SubServers > SubData Listening on " + subdata.getServer().getLocalSocketAddress().toString()); loop(); @@ -113,12 +115,12 @@ public final class SubPlugin extends BungeeCord { System.out.println("SubServers > Loading Hosts..."); for (String name : config.get().getSection("Hosts").getKeys()) { try { - if (name.contains(" ")) throw new InvalidHostException("Host names cannot have spaces: " + name); - if (!hostDrivers.keySet().contains(config.get().getSection("Hosts").getSection(name).getString("Driver").toLowerCase())) throw new InvalidHostException("Invalid Driver for host: " + name); - Host host = hostDrivers.get(config.get().getSection("Hosts").getSection(name).getString("Driver").toLowerCase()).getConstructor(SubPlugin.class, String.class, Boolean.class, InetAddress.class, UniversalFile.class).newInstance( - this, name, (Boolean) config.get().getSection("Hosts").getSection(name).getBoolean("Enabled"), InetAddress.getByName(config.get().getSection("Hosts").getSection(name).getString("Address")), new UniversalFile(new File(config.get().getSection("Hosts").getSection(name).getString("Directory")))); + if (!hostDrivers.keySet().contains(config.get().getSection("Hosts").getSection(name).getRawString("Driver").toLowerCase())) throw new InvalidHostException("Invalid Driver for host: " + name); + Host host = hostDrivers.get(config.get().getSection("Hosts").getSection(name).getRawString("Driver").toLowerCase()).getConstructor(SubPlugin.class, String.class, Boolean.class, InetAddress.class, String.class, String.class).newInstance( + this, name, (Boolean) config.get().getSection("Hosts").getSection(name).getBoolean("Enabled"), InetAddress.getByName(config.get().getSection("Hosts").getSection(name).getRawString("Address")), config.get().getSection("Hosts").getSection(name).getRawString("Directory"), + config.get().getSection("Hosts").getSection(name).getRawString("Git-Bash")); this.hosts.put(name.toLowerCase(), host); - subdata.allowConnection(host.getAddress()); + SubDataServer.allowConnection(host.getAddress()); hosts++; } catch (Exception e) { e.printStackTrace(); @@ -130,11 +132,11 @@ public final class SubPlugin extends BungeeCord { YAMLConfig bungee = new YAMLConfig(new UniversalFile(dir, "config.yml")); for (String name : bungee.get().getSection("servers").getKeys()) { try { - Server server = new Server(name, new InetSocketAddress(bungee.get().getSection("servers").getSection(name).getString("address").split(":")[0], - Integer.parseInt(bungee.get().getSection("servers").getSection(name).getString("address").split(":")[1])), bungee.get().getSection("servers").getSection(name).getString("motd"), + Server server = new Server(name, new InetSocketAddress(bungee.get().getSection("servers").getSection(name).getRawString("address").split(":")[0], + Integer.parseInt(bungee.get().getSection("servers").getSection(name).getRawString("address").split(":")[1])), bungee.get().getSection("servers").getSection(name).getColoredString("motd", '&'), bungee.get().getSection("servers").getSection(name).getBoolean("restricted")); exServers.put(name.toLowerCase(), server); - subdata.allowConnection(server.getAddress().getAddress()); + SubDataServer.allowConnection(server.getAddress().getAddress()); servers++; } catch (Exception e) { e.printStackTrace(); @@ -146,11 +148,14 @@ public final class SubPlugin extends BungeeCord { for (String name : config.get().getSection("Servers").getKeys()) { try { if (!this.hosts.keySet().contains(config.get().getSection("Servers").getSection(name).getString("Host").toLowerCase())) throw new InvalidServerException("There is no host with this name:" + name); + if (exServers.keySet().contains(name.toLowerCase())) { + exServers.remove(name.toLowerCase()); + servers--; + } SubServer server = this.hosts.get(config.get().getSection("Servers").getSection(name).getString("Host").toLowerCase()).addSubServer(name, config.get().getSection("Servers").getSection(name).getBoolean("Enabled"), - config.get().getSection("Servers").getSection(name).getInt("Port"), config.get().getSection("Servers").getSection(name).getString("Motd"), config.get().getSection("Servers").getSection(name).getBoolean("Log"), - config.get().getSection("Servers").getSection(name).getString("Directory"), new Executable(config.get().getSection("Servers").getSection(name).getString("Executable")), config.get().getSection("Servers").getSection(name).getString("Stop-Command"), - config.get().getSection("Servers").getSection(name).getBoolean("Run-On-Launch"), config.get().getSection("Servers").getSection(name).getBoolean("Auto-Restart"), false); - + config.get().getSection("Servers").getSection(name).getInt("Port"), config.get().getSection("Servers").getSection(name).getColoredString("Motd", '&'), config.get().getSection("Servers").getSection(name).getBoolean("Log"), + config.get().getSection("Servers").getSection(name).getRawString("Directory"), new Executable(config.get().getSection("Servers").getSection(name).getRawString("Executable")), config.get().getSection("Servers").getSection(name).getRawString("Stop-Command"), + config.get().getSection("Servers").getSection(name).getBoolean("Run-On-Launch"), config.get().getSection("Servers").getSection(name).getBoolean("Auto-Restart"), config.get().getSection("Servers").getSection(name).getBoolean("Restricted"), false); subservers++; } catch (Exception e) { e.printStackTrace(); @@ -167,35 +172,30 @@ public final class SubPlugin extends BungeeCord { } } - /** - * SubData Listener Loop - */ - public void loop() { - new Thread() { - public void run() { - while(running && subdata != null) { - try { - subdata.addClient(subdata.getServer().accept()); - } catch (IOException e) { - if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace(); - } + private void loop() { + new Thread(() -> { + while (running && subdata != null) { + try { + subdata.addClient(subdata.getServer().accept()); + } catch (IOException e) { + if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace(); } } - }.start(); + }).start(); } /** - * Override BungeeCord Servers + * Emulate BungeeCord's getServers() * * @see SubAPI#getServers() * @return Server Map */ @Override public Map getServers() { - TreeMap servers = new TreeMap(); - servers.putAll(this.exServers); + HashMap servers = new HashMap(); + for (ServerInfo server : exServers.values()) servers.put(server.getName(), server); for (Host host : this.hosts.values()) { - servers.putAll(host.getSubServers()); + for (ServerInfo server : host.getSubServers().values()) servers.put(server.getName(), server); } return servers; } @@ -261,22 +261,4 @@ public final class SubPlugin extends BungeeCord { disable(); super.stop(reason); } - - 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/src/plugin.yml b/SubServers.Client/src/plugin.yml deleted file mode 100644 index 2176d8c9..00000000 --- a/SubServers.Client/src/plugin.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: 'SubServers' -main: 'net.ME1312.SubServers.Client.SubPlugin' -version: '2.11.0a' -authors: [ME1312] -website: 'http://www.example.com/' -commands: - subservers: - description: All SubServer Commands - usage: /SubServers [Server] - subserver: - description: All SubServer Commands - usage: /SubServer [Server] - sub: - description: All SubServer Commands - usage: /Sub [Server] -permissions: - subserver.*: - description: All Subserver Commands - default: op - children: - subserver.command: - description: Subservers GUI - default: op - subserver.command.*: - description: 'Subserver Commands/Actions' - default: op - children: - subserver.command.create: - description: Creates a SubServer - default: op - subserver.command.start.*: - description: Starts a Subserver - default: op - subserver.command.kill.*: - description: Terminates a Subserver - default: op - subserver.command.stop.*: - description: Stops a Subserver - default: op - subserver.command.send.*: - description: Sends Commands to a Subserver - default: op - subserver.command.edit.*: - description: Edits a SubServer - default: op - subserver.command.teleport.*: - description: Teleport to SubServers - default: op - subserver.command.teleport.others.*: - description: Teleport Others to SubServers - default: op - subserver.command.reload: - description: Reload Subservers Configs - default: op \ No newline at end of file