mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
commit
073b00c58e
33 changed files with 226 additions and 149 deletions
|
@ -33,6 +33,7 @@
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
||||||
import org.bouncycastle.operator.OperatorCreationException;
|
import org.bouncycastle.operator.OperatorCreationException;
|
||||||
|
|
||||||
|
@ -359,7 +360,7 @@ public static void main(String... args) throws Throwable {
|
||||||
LogHelper.printLicense("LaunchServer");
|
LogHelper.printLicense("LaunchServer");
|
||||||
if (!StarterAgent.isAgentStarted()) {
|
if (!StarterAgent.isAgentStarted()) {
|
||||||
LogHelper.error("StarterAgent is not started!");
|
LogHelper.error("StarterAgent is not started!");
|
||||||
LogHelper.error("Your should add to JVM options this option: `-javaagent:LaunchServer.jar`");
|
LogHelper.error("You should add to JVM options this option: `-javaagent:LaunchServer.jar`");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start LaunchServer
|
// Start LaunchServer
|
||||||
|
@ -810,7 +811,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
newConfig.netty.fileServerEnabled = true;
|
newConfig.netty.fileServerEnabled = true;
|
||||||
newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)};
|
newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)};
|
||||||
newConfig.netty.performance = new NettyPerformanceConfig();
|
newConfig.netty.performance = new NettyPerformanceConfig();
|
||||||
newConfig.netty.performance.usingEpoll = JVMHelper.OS_TYPE == JVMHelper.OS.LINUX; //Only linux
|
newConfig.netty.performance.usingEpoll = Epoll.isAvailable();
|
||||||
newConfig.netty.performance.bossThread = 2;
|
newConfig.netty.performance.bossThread = 2;
|
||||||
newConfig.netty.performance.workerThread = 8;
|
newConfig.netty.performance.workerThread = 8;
|
||||||
|
|
||||||
|
|
|
@ -153,13 +153,17 @@ public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWI
|
||||||
db_hwid.HWDiskSerial = set.getString(hwidFieldHWDiskSerial);
|
db_hwid.HWDiskSerial = set.getString(hwidFieldHWDiskSerial);
|
||||||
db_hwid.totalMemory = Long.valueOf(set.getString(hwidFieldTotalMemory));
|
db_hwid.totalMemory = Long.valueOf(set.getString(hwidFieldTotalMemory));
|
||||||
db_hwid.macAddr = set.getString(hwidFieldMAC);
|
db_hwid.macAddr = set.getString(hwidFieldMAC);
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Compare HWID: %s vs %s", hwid.getSerializeString(), db_hwid.getSerializeString());
|
LogHelper.dev("Compare HWID: %s vs %s", hwid.getSerializeString(), db_hwid.getSerializeString());
|
||||||
|
}
|
||||||
int compare_point = hwid.compare(db_hwid);
|
int compare_point = hwid.compare(db_hwid);
|
||||||
if (compare_point < compare) continue;
|
if (compare_point < compare) continue;
|
||||||
else {
|
else {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.debug("User %s hwid check: found compare %d in %d", username, compare_point, set.getInt("id"));
|
LogHelper.debug("User %s hwid check: found compare %d in %d", username, compare_point, set.getInt("id"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (oneCompareMode) isOne = true;
|
if (oneCompareMode) isOne = true;
|
||||||
boolean isBanned = set.getBoolean(hwidFieldBanned);
|
boolean isBanned = set.getBoolean(hwidFieldBanned);
|
||||||
if (isBanned) {
|
if (isBanned) {
|
||||||
|
@ -175,7 +179,9 @@ public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWI
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIsBanned(HWID hwid, boolean isBanned) {
|
public void setIsBanned(HWID hwid, boolean isBanned) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("%s Request HWID: %s", isBanned ? "Ban" : "UnBan", hwid.toString());
|
LogHelper.debug("%s Request HWID: %s", isBanned ? "Ban" : "UnBan", hwid.toString());
|
||||||
|
}
|
||||||
if (hwid instanceof OshiHWID) {
|
if (hwid instanceof OshiHWID) {
|
||||||
OshiHWID oshiHWID = (OshiHWID) hwid;
|
OshiHWID oshiHWID = (OshiHWID) hwid;
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
try (Connection c = mySQLHolder.getConnection()) {
|
||||||
|
@ -214,7 +220,9 @@ public void unban(List<HWID> list) {
|
||||||
public List<HWID> getHwid(String username) {
|
public List<HWID> getHwid(String username) {
|
||||||
ArrayList<HWID> list = new ArrayList<>();
|
ArrayList<HWID> list = new ArrayList<>();
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
try (Connection c = mySQLHolder.getConnection()) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Try find HWID from username %s", username);
|
LogHelper.debug("Try find HWID from username %s", username);
|
||||||
|
}
|
||||||
PreparedStatement s = c.prepareStatement(String.format("SELECT %s, %s FROM `%s` WHERE `%s` = ? LIMIT 1", userFieldHwid, userFieldLogin, tableUsers, userFieldLogin));
|
PreparedStatement s = c.prepareStatement(String.format("SELECT %s, %s FROM `%s` WHERE `%s` = ? LIMIT 1", userFieldHwid, userFieldLogin, tableUsers, userFieldLogin));
|
||||||
s.setString(1, username);
|
s.setString(1, username);
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,15 @@ public RequestTextureProvider(String skinURL, String cloakURL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Texture getTexture(String url, boolean cloak) throws IOException {
|
private static Texture getTexture(String url, boolean cloak) throws IOException {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Getting texture: '%s'", url);
|
LogHelper.debug("Getting texture: '%s'", url);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return new Texture(url, cloak);
|
return new Texture(url, cloak);
|
||||||
} catch (FileNotFoundException ignored) {
|
} catch (FileNotFoundException ignored) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.subDebug("Texture not found :(");
|
LogHelper.subDebug("Texture not found :(");
|
||||||
|
}
|
||||||
return null; // Simply not found
|
return null; // Simply not found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ public void invoke(String... args) throws Exception {
|
||||||
public void invoke(String... args) throws Exception {
|
public void invoke(String... args) throws Exception {
|
||||||
verifyArgs(args, 1);
|
verifyArgs(args, 1);
|
||||||
LogHelper.info("Sessions write to %s", args[0]);
|
LogHelper.info("Sessions write to %s", args[0]);
|
||||||
Set<Client> clientSet = server.sessionManager.getSessions();
|
Collection<Client> clientSet = server.sessionManager.getSessions();
|
||||||
try (Writer writer = IOHelper.newWriter(Paths.get(args[0]))) {
|
try (Writer writer = IOHelper.newWriter(Paths.get(args[0]))) {
|
||||||
Launcher.gsonManager.configGson.toJson(clientSet, writer);
|
Launcher.gsonManager.configGson.toJson(clientSet, writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package pro.gravit.launchserver.manangers;
|
package pro.gravit.launchserver.manangers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import pro.gravit.launcher.NeedGarbageCollection;
|
import pro.gravit.launcher.NeedGarbageCollection;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
@ -10,53 +14,50 @@ public class SessionManager implements NeedGarbageCollection {
|
||||||
|
|
||||||
public static final long SESSION_TIMEOUT = 3 * 60 * 60 * 1000; // 3 часа
|
public static final long SESSION_TIMEOUT = 3 * 60 * 60 * 1000; // 3 часа
|
||||||
public static final boolean GARBAGE_SERVER = Boolean.parseBoolean(System.getProperty("launcher.garbageSessionsServer", "false"));
|
public static final boolean GARBAGE_SERVER = Boolean.parseBoolean(System.getProperty("launcher.garbageSessionsServer", "false"));
|
||||||
private HashSet<Client> clientSet = new HashSet<>(128);
|
private Map<Long, Client> clientSet = new HashMap<>(128);
|
||||||
|
|
||||||
|
|
||||||
public boolean addClient(Client client) {
|
public boolean addClient(Client client) {
|
||||||
clientSet.add(client);
|
clientSet.put(client.session, client);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void garbageCollection() {
|
public void garbageCollection() {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
clientSet.removeIf(c -> (c.timestamp + SESSION_TIMEOUT < time) && ((c.type == Client.Type.USER) || ((c.type == Client.Type.SERVER) && GARBAGE_SERVER)));
|
clientSet.entrySet().removeIf(entry -> {
|
||||||
|
Client c = entry.getValue();
|
||||||
|
return (c.timestamp + SESSION_TIMEOUT < time) && ((c.type == Client.Type.USER) || ((c.type == Client.Type.SERVER) && GARBAGE_SERVER));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Client getClient(long session) {
|
public Client getClient(long session) {
|
||||||
for (Client c : clientSet)
|
return clientSet.get(session);
|
||||||
if (c.session == session) return c;
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Client getOrNewClient(long session) {
|
public Client getOrNewClient(long session) {
|
||||||
for (Client c : clientSet)
|
return clientSet.computeIfAbsent(session, Client::new);
|
||||||
if (c.session == session) return c;
|
|
||||||
Client newClient = new Client(session);
|
|
||||||
clientSet.add(newClient);
|
|
||||||
return newClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateClient(long session) {
|
public void updateClient(long session) {
|
||||||
for (Client c : clientSet) {
|
Client c = clientSet.get(session);
|
||||||
if (c.session == session) {
|
if (c != null) {
|
||||||
c.up();
|
c.up();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Client newClient = new Client(session);
|
Client newClient = new Client(session);
|
||||||
clientSet.add(newClient);
|
clientSet.put(session, newClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Client> getSessions() {
|
public Set<Client> getSessions() {
|
||||||
return clientSet;
|
// TODO: removeme
|
||||||
|
return new HashSet<>(clientSet.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSessions(Set<Client> set) {
|
public void loadSessions(Set<Client> set) {
|
||||||
clientSet.addAll(set);
|
clientSet.putAll(set.stream().collect(Collectors.toMap(c -> c.session, Function.identity())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
import io.netty.channel.group.DefaultChannelGroup;
|
import io.netty.channel.group.DefaultChannelGroup;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||||
|
@ -20,7 +21,6 @@
|
||||||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||||
import pro.gravit.launchserver.socket.handlers.fileserver.FileServerHandler;
|
import pro.gravit.launchserver.socket.handlers.fileserver.FileServerHandler;
|
||||||
import pro.gravit.utils.BiHookSet;
|
import pro.gravit.utils.BiHookSet;
|
||||||
import pro.gravit.utils.helper.JVMHelper;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
public class LauncherNettyServer implements AutoCloseable {
|
public class LauncherNettyServer implements AutoCloseable {
|
||||||
|
@ -38,16 +38,16 @@ public LauncherNettyServer(LaunchServer server) {
|
||||||
{
|
{
|
||||||
LogHelper.debug("Netty: Epoll enabled");
|
LogHelper.debug("Netty: Epoll enabled");
|
||||||
}
|
}
|
||||||
if(config.performance.usingEpoll && JVMHelper.OS_TYPE != JVMHelper.OS.LINUX)
|
if(config.performance.usingEpoll && !Epoll.isAvailable())
|
||||||
{
|
{
|
||||||
LogHelper.error("netty,perfomance.usingEpoll work only Linux systems");
|
LogHelper.error("Epoll is not available: (netty,perfomance.usingEpoll configured wrongly)", Epoll.unavailabilityCause());
|
||||||
}
|
}
|
||||||
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread);
|
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread);
|
||||||
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread);
|
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread);
|
||||||
serverBootstrap = new ServerBootstrap();
|
serverBootstrap = new ServerBootstrap();
|
||||||
service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), server);
|
service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), server);
|
||||||
serverBootstrap.group(bossGroup, workerGroup)
|
serverBootstrap.group(bossGroup, workerGroup)
|
||||||
.channel(NettyObjectFactory.getServerSocketChannelClass())
|
.channelFactory(NettyObjectFactory.getServerSocketChannelFactory())
|
||||||
.handler(new LoggingHandler(config.logLevel))
|
.handler(new LoggingHandler(config.logLevel))
|
||||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package pro.gravit.launchserver.socket;
|
package pro.gravit.launchserver.socket;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelFactory;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.ServerChannel;
|
import io.netty.channel.ServerChannel;
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
|
@ -20,12 +21,12 @@ public static EventLoopGroup newEventLoopGroup(int threads)
|
||||||
else
|
else
|
||||||
return new NioEventLoopGroup(threads);
|
return new NioEventLoopGroup(threads);
|
||||||
}
|
}
|
||||||
public static Class<? extends ServerChannel> getServerSocketChannelClass()
|
public static ChannelFactory<? extends ServerChannel> getServerSocketChannelFactory()
|
||||||
{
|
{
|
||||||
if(epoll)
|
if(epoll)
|
||||||
return EpollServerSocketChannel.class;
|
return EpollServerSocketChannel::new;
|
||||||
else
|
else
|
||||||
return NioServerSocketChannel.class;
|
return NioServerSocketChannel::new;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.group.ChannelGroup;
|
import io.netty.channel.group.ChannelGroup;
|
||||||
|
import io.netty.channel.group.ChannelMatchers;
|
||||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.events.ExceptionEvent;
|
import pro.gravit.launcher.events.ExceptionEvent;
|
||||||
|
@ -120,22 +121,22 @@ public static void registerResponses() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)));
|
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), ctx.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ctx.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAll(Object obj) {
|
public void sendObjectAll(Object obj) {
|
||||||
for (Channel ch : channels) {
|
for (Channel ch : channels) {
|
||||||
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)));
|
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), ch.voidPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAll(Object obj, Type type) {
|
public void sendObjectAll(Object obj, Type type) {
|
||||||
for (Channel ch : channels) {
|
for (Channel ch : channels) {
|
||||||
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ch.voidPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendEvent(EventResult obj) {
|
public void sendEvent(EventResult obj) {
|
||||||
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)));
|
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)), ChannelMatchers.all(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EventResult implements WebSocketEvent {
|
public static class EventResult implements WebSocketEvent {
|
||||||
|
|
|
@ -36,7 +36,9 @@ protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> o
|
||||||
realIP = headers.get("X-Real-IP");
|
realIP = headers.get("X-Real-IP");
|
||||||
}
|
}
|
||||||
if (realIP != null) {
|
if (realIP != null) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Real IP address %s", realIP);
|
LogHelper.dev("Real IP address %s", realIP);
|
||||||
|
}
|
||||||
context.ip = realIP;
|
context.ip = realIP;
|
||||||
} else LogHelper.error("IpForwarding error. Headers not found");
|
} else LogHelper.error("IpForwarding error. Headers not found");
|
||||||
out.add(msg);
|
out.add(msg);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||||
|
@ -40,11 +41,14 @@ public void setClient(Client client) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(ChannelHandlerContext ctx) {
|
public void channelActive(ChannelHandlerContext ctx) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("New client %s", IOHelper.getIP(ctx.channel().remoteAddress()));
|
LogHelper.dev("New client %s", IOHelper.getIP(ctx.channel().remoteAddress()));
|
||||||
|
}
|
||||||
client = new Client(0);
|
client = new Client(0);
|
||||||
service.registerClient(ctx.channel());
|
Channel ch = ctx.channel();
|
||||||
|
service.registerClient(ch);
|
||||||
ctx.executor().schedule(() -> {
|
ctx.executor().schedule(() -> {
|
||||||
ctx.channel().writeAndFlush(new PingWebSocketFrame());
|
ch.writeAndFlush(new PingWebSocketFrame(), ch.voidPromise());
|
||||||
}, 30L, TimeUnit.SECONDS);
|
}, 30L, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +62,9 @@ protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
||||||
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
|
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
|
||||||
//return;
|
//return;
|
||||||
} else if ((frame instanceof PongWebSocketFrame)) {
|
} else if ((frame instanceof PongWebSocketFrame)) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("WebSocket Client received pong");
|
LogHelper.dev("WebSocket Client received pong");
|
||||||
|
}
|
||||||
} else if ((frame instanceof CloseWebSocketFrame)) {
|
} else if ((frame instanceof CloseWebSocketFrame)) {
|
||||||
ctx.channel().close();
|
ctx.channel().close();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -112,6 +112,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
result.permissions = clientData.permissions;
|
result.permissions = clientData.permissions;
|
||||||
if (authType == ConnectTypes.SERVER && !clientData.permissions.canServer) {
|
if (authType == ConnectTypes.SERVER && !clientData.permissions.canServer) {
|
||||||
AuthProvider.authError("authType: SERVER not allowed for this account");
|
AuthProvider.authError("authType: SERVER not allowed for this account");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (getSession) {
|
if (getSession) {
|
||||||
if (clientData.session == 0) {
|
if (clientData.session == 0) {
|
||||||
|
@ -123,8 +124,10 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
if (authType != ConnectTypes.API && server.config.protectHandler.allowGetAccessToken(context)) {
|
if (authType != ConnectTypes.API && server.config.protectHandler.allowGetAccessToken(context)) {
|
||||||
UUID uuid = pair.handler.auth(aresult);
|
UUID uuid = pair.handler.auth(aresult);
|
||||||
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, aresult.username, client, clientData.auth.textureProvider);
|
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, aresult.username, client, clientData.auth.textureProvider);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sendResult(result);
|
sendResult(result);
|
||||||
} catch (AuthException | HWIDException | HookException e) {
|
} catch (AuthException | HWIDException | HookException e) {
|
||||||
sendError(e.getMessage());
|
sendError(e.getMessage());
|
||||||
|
|
|
@ -27,7 +27,9 @@ public void execute(ChannelHandlerContext ctx, Client pClient) {
|
||||||
result.uuid = pClient.auth.handler.checkServer(username, serverID);
|
result.uuid = pClient.auth.handler.checkServer(username, serverID);
|
||||||
if (result.uuid != null)
|
if (result.uuid != null)
|
||||||
result.playerProfile = ProfileByUUIDResponse.getProfile(result.uuid, username, client, pClient.auth.textureProvider);
|
result.playerProfile = ProfileByUUIDResponse.getProfile(result.uuid, username, client, pClient.auth.textureProvider);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("checkServer: %s uuid: %s serverID: %s", result.playerProfile.username, result.uuid.toString(), serverID);
|
LogHelper.debug("checkServer: %s uuid: %s serverID: %s", result.playerProfile.username, result.uuid.toString(), serverID);
|
||||||
|
}
|
||||||
} catch (AuthException | HookException e) {
|
} catch (AuthException | HookException e) {
|
||||||
sendError(e.getMessage());
|
sendError(e.getMessage());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -27,7 +27,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
LogHelper.warning("Client auth is null. Using default.");
|
LogHelper.warning("Client auth is null. Using default.");
|
||||||
success = server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID);
|
success = server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID);
|
||||||
} else success = client.auth.handler.joinServer(username, accessToken, serverID);
|
} else success = client.auth.handler.joinServer(username, accessToken, serverID);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("joinServer: %s accessToken: %s serverID: %s", username, accessToken, serverID);
|
LogHelper.debug("joinServer: %s accessToken: %s serverID: %s", username, accessToken, serverID);
|
||||||
|
}
|
||||||
} catch (AuthException | HookException e) {
|
} catch (AuthException | HookException e) {
|
||||||
sendError(e.getMessage());
|
sendError(e.getMessage());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
import cpw.mods.fml.SafeExitJVMLegacy;
|
import cpw.mods.fml.SafeExitJVMLegacy;
|
||||||
import net.minecraftforge.fml.SafeExitJVM;
|
import net.minecraftforge.fml.SafeExitJVM;
|
||||||
import pro.gravit.launcher.utils.NativeJVMHalt;
|
import pro.gravit.launcher.utils.NativeJVMHalt;
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -46,6 +47,9 @@ public static void premain(String agentArgument, Instrumentation instrumentation
|
||||||
NativeJVMHalt.class.getName();
|
NativeJVMHalt.class.getName();
|
||||||
NativeJVMHalt.initFunc();
|
NativeJVMHalt.initFunc();
|
||||||
isAgentStarted = true;
|
isAgentStarted = true;
|
||||||
|
if (System.getProperty("java.vm.name").toUpperCase(Locale.US).contains("HOTSPOT"))
|
||||||
|
try {
|
||||||
|
if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
|
||||||
boolean pb = true;
|
boolean pb = true;
|
||||||
boolean rt = true;
|
boolean rt = true;
|
||||||
if (agentArgument != null) {
|
if (agentArgument != null) {
|
||||||
|
@ -55,10 +59,8 @@ public static void premain(String agentArgument, Instrumentation instrumentation
|
||||||
if (trimmedArg.contains("r")) rt = false;
|
if (trimmedArg.contains("r")) rt = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (System.getProperty("java.vm.name").toUpperCase(Locale.US).contains("HOTSPOT"))
|
replaceClasses(pb, rt);
|
||||||
try {
|
} else replaceClasses(false, false);
|
||||||
if (ManagementFactory.getOperatingSystemMXBean().getName().startsWith("Windows")) replaceClasses(pb, rt);
|
|
||||||
else replaceClasses(false, false);
|
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
NativeJVMHalt.haltA(294);
|
NativeJVMHalt.haltA(294);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -14,11 +14,15 @@
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.nio.file.attribute.PosixFilePermission;
|
import java.nio.file.attribute.PosixFilePermission;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
@ -55,16 +59,16 @@
|
||||||
|
|
||||||
public final class ClientLauncher {
|
public final class ClientLauncher {
|
||||||
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
private final Collection<Path> result;
|
private final Stream.Builder<Path> result;
|
||||||
|
|
||||||
private ClassPathFileVisitor(Collection<Path> result) {
|
private ClassPathFileVisitor(Stream.Builder<Path> result) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
if (IOHelper.hasExtension(file, "jar") || IOHelper.hasExtension(file, "zip"))
|
if (IOHelper.hasExtension(file, "jar") || IOHelper.hasExtension(file, "zip"))
|
||||||
result.add(file);
|
result.accept(file);
|
||||||
return super.visitFile(file, attrs);
|
return super.visitFile(file, attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,10 +286,17 @@ private static void launch(ClientProfile profile, Params params) throws Throwabl
|
||||||
System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString());
|
System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString());
|
||||||
}
|
}
|
||||||
Collections.addAll(args, profile.getClientArgs());
|
Collections.addAll(args, profile.getClientArgs());
|
||||||
LogHelper.debug("Args: " + args);
|
List<String> copy = new ArrayList<>(args);
|
||||||
|
for (int i = 0, l = copy.size(); i < l; i++) {
|
||||||
|
String s = copy.get(i);
|
||||||
|
if ( i + 1 < l && ("--accessToken".equals(s) || "--session".equals(s))) {
|
||||||
|
copy.set(i + 1, "censored");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogHelper.debug("Args: " + copy);
|
||||||
// Resolve main class and method
|
// Resolve main class and method
|
||||||
Class<?> mainClass = classLoader.loadClass(profile.getMainClass());
|
Class<?> mainClass = classLoader.loadClass(profile.getMainClass());
|
||||||
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)).asFixedArity();
|
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
Launcher.LAUNCHED.set(true);
|
Launcher.LAUNCHED.set(true);
|
||||||
JVMHelper.fullGC();
|
JVMHelper.fullGC();
|
||||||
// Invoke main method
|
// Invoke main method
|
||||||
|
@ -407,7 +418,7 @@ public static Process launch(
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
}
|
}
|
||||||
if (!clientStarted) {
|
if (!clientStarted) {
|
||||||
LogHelper.error("Write Client Params not successful. Using debug mode for more information");
|
LogHelper.error("Client did not start properly. Enable debug mode for more information");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clientStarted = false;
|
clientStarted = false;
|
||||||
|
@ -515,32 +526,27 @@ public static void main(String... args) throws Throwable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URL[] resolveClassPath(Path clientDir, String... classPath) throws IOException {
|
private static URL[] resolveClassPath(Path clientDir, String... classPath) throws IOException {
|
||||||
Collection<Path> result = new LinkedList<>();
|
return resolveClassPathStream(clientDir, classPath).map(IOHelper::toURL).toArray(URL[]::new);
|
||||||
for (String classPathEntry : classPath) {
|
|
||||||
Path path = clientDir.resolve(IOHelper.toPath(classPathEntry));
|
|
||||||
if (IOHelper.isDir(path)) { // Recursive walking and adding
|
|
||||||
IOHelper.walk(path, new ClassPathFileVisitor(result), false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.add(path);
|
|
||||||
}
|
|
||||||
return result.stream().map(IOHelper::toURL).toArray(URL[]::new);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
|
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
|
||||||
LinkedList<Path> result = new LinkedList<>();
|
return resolveClassPathStream(clientDir, classPath).collect(Collectors.toCollection(LinkedList::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Path> resolveClassPathStream(Path clientDir, String... classPath) throws IOException {
|
||||||
|
Stream.Builder<Path> builder = Stream.builder();
|
||||||
for (String classPathEntry : classPath) {
|
for (String classPathEntry : classPath) {
|
||||||
Path path = clientDir.resolve(IOHelper.toPath(classPathEntry));
|
Path path = clientDir.resolve(IOHelper.toPath(classPathEntry));
|
||||||
if (IOHelper.isDir(path)) { // Recursive walking and adding
|
if (IOHelper.isDir(path)) { // Recursive walking and adding
|
||||||
IOHelper.walk(path, new ClassPathFileVisitor(result), false);
|
IOHelper.walk(path, new ClassPathFileVisitor(builder), false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.add(path);
|
builder.accept(path);
|
||||||
}
|
}
|
||||||
return result;
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initGson() {
|
private static void initGson() {
|
||||||
Launcher.gsonManager = new ClientGsonManager();
|
Launcher.gsonManager = new ClientGsonManager();
|
||||||
Launcher.gsonManager.initGson();
|
Launcher.gsonManager.initGson();
|
||||||
}
|
}
|
||||||
|
@ -552,8 +558,8 @@ public static void setProfile(ClientProfile profile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException {
|
public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException {
|
||||||
if (matcher != null)
|
//if (matcher != null)
|
||||||
matcher = matcher.verifyOnly();
|
// matcher = matcher.verifyOnly();
|
||||||
|
|
||||||
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
||||||
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
||||||
|
|
|
@ -72,7 +72,9 @@ public void postDiff(UpdateRequest request, UpdateRequestEvent e, HashedDir.Diff
|
||||||
//if(file.isSame(ret, true))
|
//if(file.isSame(ret, true))
|
||||||
{
|
{
|
||||||
Path source = request.getDir().resolve(path);
|
Path source = request.getDir().resolve(path);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Copy file %s to %s", ret.toAbsolutePath().toString(), source.toAbsolutePath().toString());
|
LogHelper.debug("Copy file %s to %s", ret.toAbsolutePath().toString(), source.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
//Let's go!
|
//Let's go!
|
||||||
Files.copy(ret, source);
|
Files.copy(ret, source);
|
||||||
try (InputStream input = IOHelper.newInput(ret)) {
|
try (InputStream input = IOHelper.newInput(ret)) {
|
||||||
|
@ -93,11 +95,15 @@ public Path tryFind(NewLauncherSettings.HashedStoreEntry en, HashedFile file) th
|
||||||
if (entry.getType() == HashedEntry.Type.DIR) return HashedDir.WalkAction.CONTINUE;
|
if (entry.getType() == HashedEntry.Type.DIR) return HashedDir.WalkAction.CONTINUE;
|
||||||
HashedFile tfile = (HashedFile) entry;
|
HashedFile tfile = (HashedFile) entry;
|
||||||
if (tfile.isSame(file)) {
|
if (tfile.isSame(file)) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("[DIR:%s] Found file %s in %s", en.name, name, path);
|
LogHelper.dev("[DIR:%s] Found file %s in %s", en.name, name, path);
|
||||||
|
}
|
||||||
Path tdir = Paths.get(en.fullPath).resolve(path);
|
Path tdir = Paths.get(en.fullPath).resolve(path);
|
||||||
try {
|
try {
|
||||||
if (tfile.isSame(tdir, true)) {
|
if (tfile.isSame(tdir, true)) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("[DIR:%s] Confirmed file %s in %s", en.name, name, path);
|
LogHelper.dev("[DIR:%s] Confirmed file %s in %s", en.name, name, path);
|
||||||
|
}
|
||||||
ret.set(tdir);
|
ret.set(tdir);
|
||||||
return HashedDir.WalkAction.STOP;
|
return HashedDir.WalkAction.STOP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ public String getHWDisk() {
|
||||||
|
|
||||||
public String getMacAddr() {
|
public String getMacAddr() {
|
||||||
for (NetworkIF networkIF : hardware.getNetworkIFs()) {
|
for (NetworkIF networkIF : hardware.getNetworkIFs()) {
|
||||||
|
if (networkIF.getNetworkInterface().isVirtual()) continue;
|
||||||
for (String ipv4 : networkIF.getIPv4addr()) {
|
for (String ipv4 : networkIF.getIPv4addr()) {
|
||||||
if (ipv4.startsWith("127.")) continue;
|
if (ipv4.startsWith("127.")) continue;
|
||||||
if (ipv4.startsWith("10.")) continue;
|
if (ipv4.startsWith("10.")) continue;
|
||||||
|
|
|
@ -27,15 +27,6 @@
|
||||||
|
|
||||||
public final class DirWatcher implements Runnable, AutoCloseable {
|
public final class DirWatcher implements Runnable, AutoCloseable {
|
||||||
private final class RegisterFileVisitor extends SimpleFileVisitor<Path> {
|
private final class RegisterFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
private final Deque<String> path = new LinkedList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
|
||||||
FileVisitResult result = super.postVisitDirectory(dir, exc);
|
|
||||||
if (!DirWatcher.this.dir.equals(dir))
|
|
||||||
path.removeLast();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
|
@ -46,7 +37,6 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maybe it's unnecessary to go deeper
|
// Maybe it's unnecessary to go deeper
|
||||||
path.add(IOHelper.getFileName(dir));
|
|
||||||
//if (matcher != null && !matcher.shouldVerify(path)) {
|
//if (matcher != null && !matcher.shouldVerify(path)) {
|
||||||
// return FileVisitResult.SKIP_SUBTREE;
|
// return FileVisitResult.SKIP_SUBTREE;
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -60,7 +60,9 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
|
||||||
URI u = new URI(scheme, host, path + apply.apply, "", "");
|
URI u = new URI(scheme, host, path + apply.apply, "", "");
|
||||||
callback.stateChanged(apply.apply, 0L, apply.size);
|
callback.stateChanged(apply.apply, 0L, apply.size);
|
||||||
Path targetPath = dstDirFile.resolve(apply.apply);
|
Path targetPath = dstDirFile.resolve(apply.apply);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Download URL: %s to file %s dir: %s", u.toString(), targetPath.toAbsolutePath().toString(), dstDirFile.toAbsolutePath().toString());
|
LogHelper.debug("Download URL: %s to file %s dir: %s", u.toString(), targetPath.toAbsolutePath().toString(), dstDirFile.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
if (get == null) get = new HttpGet(u);
|
if (get == null) get = new HttpGet(u);
|
||||||
else {
|
else {
|
||||||
get.reset();
|
get.reset();
|
||||||
|
@ -104,7 +106,9 @@ public void downloadOne(String url, Path target) throws IOException, URISyntaxEx
|
||||||
|
|
||||||
HttpGet get;
|
HttpGet get;
|
||||||
URI u = new URL(url).toURI();
|
URI u = new URL(url).toURI();
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Download URL: %s", u.toString());
|
LogHelper.debug("Download URL: %s", u.toString());
|
||||||
|
}
|
||||||
get = new HttpGet(u);
|
get = new HttpGet(u);
|
||||||
httpclient.execute(get, new FileDownloadResponseHandler(target.toAbsolutePath()));
|
httpclient.execute(get, new FileDownloadResponseHandler(target.toAbsolutePath()));
|
||||||
}
|
}
|
||||||
|
@ -168,7 +172,9 @@ public Path handleResponse(HttpResponse response) throws IOException {
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.stateChanged(entry.getName(), 0, entry.getSize());
|
callback.stateChanged(entry.getName(), 0, entry.getSize());
|
||||||
}
|
}
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
|
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
transfer(source, target, filename, size, callback, totalCallback);
|
transfer(source, target, filename, size, callback, totalCallback);
|
||||||
entry = input.getNextEntry();
|
entry = input.getNextEntry();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
||||||
public void autoload(Path dir) throws IOException {
|
public void autoload(Path dir) throws IOException {
|
||||||
LogHelper.info("Load modules");
|
LogHelper.info("Load modules");
|
||||||
if (Files.notExists(dir)) Files.createDirectory(dir);
|
if (Files.notExists(dir)) Files.createDirectory(dir);
|
||||||
|
else {
|
||||||
IOHelper.walk(dir, new ModulesVisitor(), true);
|
IOHelper.walk(dir, new ModulesVisitor(), true);
|
||||||
|
}
|
||||||
sort();
|
sort();
|
||||||
LogHelper.info("Loaded %d modules", modules.size());
|
LogHelper.info("Loaded %d modules", modules.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ public void open() throws Exception {
|
||||||
|
|
||||||
public ChannelFuture send(String text) {
|
public ChannelFuture send(String text) {
|
||||||
LogHelper.dev("Send: %s", text);
|
LogHelper.dev("Send: %s", text);
|
||||||
return ch.writeAndFlush(new TextWebSocketFrame(text));
|
return ch.writeAndFlush(new TextWebSocketFrame(text), ch.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void onMessage(String message) throws Exception;
|
abstract void onMessage(String message) throws Exception;
|
||||||
|
@ -98,7 +98,7 @@ public void close() throws InterruptedException {
|
||||||
//System.out.println("WebSocket Client sending close");
|
//System.out.println("WebSocket Client sending close");
|
||||||
isClosed = true;
|
isClosed = true;
|
||||||
if (ch != null && ch.isActive()) {
|
if (ch != null && ch.isActive()) {
|
||||||
ch.writeAndFlush(new CloseWebSocketFrame());
|
ch.writeAndFlush(new CloseWebSocketFrame(), ch.voidPromise());
|
||||||
ch.closeFuture().sync();
|
ch.closeFuture().sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public void close() throws InterruptedException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void eval(final String text) throws IOException {
|
public void eval(final String text) throws IOException {
|
||||||
ch.writeAndFlush(new TextWebSocketFrame(text));
|
ch.writeAndFlush(new TextWebSocketFrame(text), ch.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -56,8 +56,8 @@ public boolean isDone() {
|
||||||
@Override
|
@Override
|
||||||
public WebSocketEvent get() throws InterruptedException, ExecutionException {
|
public WebSocketEvent get() throws InterruptedException, ExecutionException {
|
||||||
if (isCanceled) return null;
|
if (isCanceled) return null;
|
||||||
while (!event.ready) {
|
|
||||||
synchronized (event) {
|
synchronized (event) {
|
||||||
|
while (!event.ready) {
|
||||||
event.wait();
|
event.wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,8 +73,8 @@ public WebSocketEvent get() throws InterruptedException, ExecutionException {
|
||||||
@Override
|
@Override
|
||||||
public WebSocketEvent get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException {
|
public WebSocketEvent get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException {
|
||||||
if (isCanceled) return null;
|
if (isCanceled) return null;
|
||||||
while (!event.ready) {
|
|
||||||
synchronized (event) {
|
synchronized (event) {
|
||||||
|
while (!event.ready) {
|
||||||
event.wait(timeout);
|
event.wait(timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,14 @@ protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Except
|
||||||
if (frame instanceof TextWebSocketFrame) {
|
if (frame instanceof TextWebSocketFrame) {
|
||||||
final TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
final TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
||||||
clientJSONPoint.onMessage(textFrame.text());
|
clientJSONPoint.onMessage(textFrame.text());
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Message: %s", textFrame.text());
|
LogHelper.dev("Message: %s", textFrame.text());
|
||||||
|
}
|
||||||
// uncomment to print request
|
// uncomment to print request
|
||||||
// logger.info(textFrame.text());
|
// logger.info(textFrame.text());
|
||||||
} else if ((frame instanceof PingWebSocketFrame)) {
|
} else if ((frame instanceof PingWebSocketFrame)) {
|
||||||
frame.content().retain();
|
frame.content().retain();
|
||||||
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
|
ch.writeAndFlush(new PongWebSocketFrame(frame.content()), ch.voidPromise());
|
||||||
//return;
|
//return;
|
||||||
} else if (frame instanceof PongWebSocketFrame) {
|
} else if (frame instanceof PongWebSocketFrame) {
|
||||||
} else if (frame instanceof CloseWebSocketFrame)
|
} else if (frame instanceof CloseWebSocketFrame)
|
||||||
|
|
|
@ -46,8 +46,11 @@ public void findProfilesByNames(String[] usernames, Agent agent, ProfileLookupCa
|
||||||
try {
|
try {
|
||||||
sliceProfiles = new BatchProfileByUsernameRequest(sliceUsernames).request().playerProfiles;
|
sliceProfiles = new BatchProfileByUsernameRequest(sliceUsernames).request().playerProfiles;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
boolean debug = LogHelper.isDebugEnabled();
|
||||||
for (String username : sliceUsernames) {
|
for (String username : sliceUsernames) {
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("Couldn't find profile '%s': %s", username, e);
|
LogHelper.debug("Couldn't find profile '%s': %s", username, e);
|
||||||
|
}
|
||||||
callback.onProfileLookupFailed(new GameProfile((UUID) null, username), e);
|
callback.onProfileLookupFailed(new GameProfile((UUID) null, username), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,17 +60,23 @@ public void findProfilesByNames(String[] usernames, Agent agent, ProfileLookupCa
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request succeeded!
|
// Request succeeded!
|
||||||
for (int i = 0; i < sliceProfiles.length; i++) {
|
int len = sliceProfiles.length;
|
||||||
|
boolean debug = len > 0 && LogHelper.isDebugEnabled();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
PlayerProfile pp = sliceProfiles[i];
|
PlayerProfile pp = sliceProfiles[i];
|
||||||
if (pp == null) {
|
if (pp == null) {
|
||||||
String username = sliceUsernames[i];
|
String username = sliceUsernames[i];
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("Couldn't find profile '%s'", username);
|
LogHelper.debug("Couldn't find profile '%s'", username);
|
||||||
|
}
|
||||||
callback.onProfileLookupFailed(new GameProfile((UUID) null, username), new ProfileNotFoundException("Server did not find the requested profile"));
|
callback.onProfileLookupFailed(new GameProfile((UUID) null, username), new ProfileNotFoundException("Server did not find the requested profile"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report as looked up
|
// Report as looked up
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("Successfully looked up profile '%s'", pp.username);
|
LogHelper.debug("Successfully looked up profile '%s'", pp.username);
|
||||||
|
}
|
||||||
callback.onProfileLookupSucceeded(YggdrasilMinecraftSessionService.toGameProfile(pp));
|
callback.onProfileLookupSucceeded(YggdrasilMinecraftSessionService.toGameProfile(pp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,10 @@ public final class YggdrasilMinecraftSessionService extends BaseMinecraftSession
|
||||||
public static final boolean NO_TEXTURES = Boolean.parseBoolean("launcher.com.mojang.authlib.noTextures");
|
public static final boolean NO_TEXTURES = Boolean.parseBoolean("launcher.com.mojang.authlib.noTextures");
|
||||||
|
|
||||||
public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) {
|
public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) {
|
||||||
|
boolean debug = LogHelper.isDebugEnabled();
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("fillTextureProperties, Username: '%s'", profile.getName());
|
LogHelper.debug("fillTextureProperties, Username: '%s'", profile.getName());
|
||||||
|
}
|
||||||
if (NO_TEXTURES)
|
if (NO_TEXTURES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -42,14 +45,18 @@ public static void fillTextureProperties(GameProfile profile, PlayerProfile pp)
|
||||||
if (pp.skin != null) {
|
if (pp.skin != null) {
|
||||||
properties.put(Launcher.SKIN_URL_PROPERTY, new Property(Launcher.SKIN_URL_PROPERTY, pp.skin.url, ""));
|
properties.put(Launcher.SKIN_URL_PROPERTY, new Property(Launcher.SKIN_URL_PROPERTY, pp.skin.url, ""));
|
||||||
properties.put(Launcher.SKIN_DIGEST_PROPERTY, new Property(Launcher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest), ""));
|
properties.put(Launcher.SKIN_DIGEST_PROPERTY, new Property(Launcher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest), ""));
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("fillTextureProperties, Has skin texture for username '%s'", profile.getName());
|
LogHelper.debug("fillTextureProperties, Has skin texture for username '%s'", profile.getName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (pp.cloak != null) {
|
if (pp.cloak != null) {
|
||||||
properties.put(Launcher.CLOAK_URL_PROPERTY, new Property(Launcher.CLOAK_URL_PROPERTY, pp.cloak.url, ""));
|
properties.put(Launcher.CLOAK_URL_PROPERTY, new Property(Launcher.CLOAK_URL_PROPERTY, pp.cloak.url, ""));
|
||||||
properties.put(Launcher.CLOAK_DIGEST_PROPERTY, new Property(Launcher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest), ""));
|
properties.put(Launcher.CLOAK_DIGEST_PROPERTY, new Property(Launcher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest), ""));
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("fillTextureProperties, Has cloak texture for username '%s'", profile.getName());
|
LogHelper.debug("fillTextureProperties, Has cloak texture for username '%s'", profile.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void getTexturesMojang(Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures, String texturesBase64, GameProfile profile) {
|
private static void getTexturesMojang(Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures, String texturesBase64, GameProfile profile) {
|
||||||
// Decode textures payload
|
// Decode textures payload
|
||||||
|
@ -92,7 +99,10 @@ public YggdrasilMinecraftSessionService(AuthenticationService service) {
|
||||||
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
|
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
|
||||||
// Verify has UUID
|
// Verify has UUID
|
||||||
UUID uuid = profile.getUUID();
|
UUID uuid = profile.getUUID();
|
||||||
|
boolean debug = LogHelper.isDebugEnabled();
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("fillProfileProperties, UUID: %s", uuid);
|
LogHelper.debug("fillProfileProperties, UUID: %s", uuid);
|
||||||
|
}
|
||||||
if (uuid == null)
|
if (uuid == null)
|
||||||
return profile;
|
return profile;
|
||||||
|
|
||||||
|
@ -101,25 +111,33 @@ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSec
|
||||||
try {
|
try {
|
||||||
pp = new ProfileByUUIDRequest(uuid).request().playerProfile;
|
pp = new ProfileByUUIDRequest(uuid).request().playerProfile;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("Couldn't fetch profile properties for '%s': %s", profile, e);
|
LogHelper.debug("Couldn't fetch profile properties for '%s': %s", profile, e);
|
||||||
|
}
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify is found
|
// Verify is found
|
||||||
if (pp == null) {
|
if (pp == null) {
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("Couldn't fetch profile properties for '%s' as the profile does not exist", profile);
|
LogHelper.debug("Couldn't fetch profile properties for '%s' as the profile does not exist", profile);
|
||||||
|
}
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new game profile from player profile
|
// Create new game profile from player profile
|
||||||
|
if (debug) {
|
||||||
LogHelper.debug("Successfully fetched profile properties for '%s'", profile);
|
LogHelper.debug("Successfully fetched profile properties for '%s'", profile);
|
||||||
|
}
|
||||||
fillTextureProperties(profile, pp);
|
fillTextureProperties(profile, pp);
|
||||||
return toGameProfile(pp);
|
return toGameProfile(pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
|
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("getTextures, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID());
|
LogHelper.debug("getTextures, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID());
|
||||||
|
}
|
||||||
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = new EnumMap<>(MinecraftProfileTexture.Type.class);
|
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = new EnumMap<>(MinecraftProfileTexture.Type.class);
|
||||||
|
|
||||||
// Add textures
|
// Add textures
|
||||||
|
@ -151,7 +169,9 @@ public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(Ga
|
||||||
@Override
|
@Override
|
||||||
public GameProfile hasJoinedServer(GameProfile profile, String serverID) throws AuthenticationUnavailableException {
|
public GameProfile hasJoinedServer(GameProfile profile, String serverID) throws AuthenticationUnavailableException {
|
||||||
String username = profile.getName();
|
String username = profile.getName();
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("checkServer, Username: '%s', Server ID: %s", username, serverID);
|
LogHelper.debug("checkServer, Username: '%s', Server ID: %s", username, serverID);
|
||||||
|
}
|
||||||
|
|
||||||
// Make checkServer request
|
// Make checkServer request
|
||||||
PlayerProfile pp;
|
PlayerProfile pp;
|
||||||
|
@ -180,7 +200,9 @@ public void joinServer(GameProfile profile, String accessToken, String serverID)
|
||||||
|
|
||||||
// Join server
|
// Join server
|
||||||
String username = profile.getName();
|
String username = profile.getName();
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
|
LogHelper.debug("joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
|
||||||
|
}
|
||||||
|
|
||||||
// Make joinServer request
|
// Make joinServer request
|
||||||
boolean success;
|
boolean success;
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
// Не входящих в пакеты самого Forge
|
// Не входящих в пакеты самого Forge
|
||||||
public class SafeExitJVMLegacy {
|
public class SafeExitJVMLegacy {
|
||||||
public static void exit(int code) {
|
public static void exit(int code) {
|
||||||
try {
|
|
||||||
JVMHelper.RUNTIME.halt(code);
|
JVMHelper.RUNTIME.halt(code);
|
||||||
} catch (Throwable e) {
|
|
||||||
System.exit(code);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
// Не входящих в пакеты самого Forge
|
// Не входящих в пакеты самого Forge
|
||||||
public class SafeExitJVM {
|
public class SafeExitJVM {
|
||||||
public static void exit(int code) {
|
public static void exit(int code) {
|
||||||
try {
|
|
||||||
JVMHelper.RUNTIME.halt(code);
|
JVMHelper.RUNTIME.halt(code);
|
||||||
} catch (Throwable e) {
|
|
||||||
System.exit(code);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,16 +173,24 @@ public void removeR(String name) {
|
||||||
for (String s : dirs) {
|
for (String s : dirs) {
|
||||||
HashedEntry e = current.get(s);
|
HashedEntry e = current.get(s);
|
||||||
if (e == null) {
|
if (e == null) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Null %s", s);
|
LogHelper.debug("Null %s", s);
|
||||||
|
}
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
for (String x : current.keySet()) LogHelper.debug("Contains %s", x);
|
for (String x : current.keySet()) LogHelper.debug("Contains %s", x);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e.getType() == Type.DIR) {
|
if (e.getType() == Type.DIR) {
|
||||||
current = ((HashedDir) e).map;
|
current = ((HashedDir) e).map;
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Found dir %s", s);
|
LogHelper.debug("Found dir %s", s);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
current.remove(s);
|
current.remove(s);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Found filename %s", s);
|
LogHelper.debug("Found filename %s", s);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ public HashedEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializati
|
||||||
if (typename.equals("dir")) cls = HashedDir.class;
|
if (typename.equals("dir")) cls = HashedDir.class;
|
||||||
if (typename.equals("file")) cls = HashedFile.class;
|
if (typename.equals("file")) cls = HashedFile.class;
|
||||||
|
|
||||||
|
|
||||||
return (HashedEntry) context.deserialize(json, cls);
|
return (HashedEntry) context.deserialize(json, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package pro.gravit.launcher.managers;
|
package pro.gravit.launcher.managers;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ public Entry(NeedGarbageCollection invoke, long timer) {
|
||||||
|
|
||||||
private static final Timer timer = new Timer("GarbageTimer");
|
private static final Timer timer = new Timer("GarbageTimer");
|
||||||
|
|
||||||
private static final ArrayList<Entry> NEED_GARBARE_COLLECTION = new ArrayList<>();
|
private static final Set<Entry> NEED_GARBARE_COLLECTION = new HashSet<>();
|
||||||
|
|
||||||
public static void gc() {
|
public static void gc() {
|
||||||
for (Entry gc : NEED_GARBARE_COLLECTION)
|
for (Entry gc : NEED_GARBARE_COLLECTION)
|
||||||
|
|
|
@ -624,7 +624,11 @@ public static void setSocketFlags(Socket socket) throws SocketException {
|
||||||
|
|
||||||
// Set socket options
|
// Set socket options
|
||||||
socket.setSoTimeout(SOCKET_TIMEOUT);
|
socket.setSoTimeout(SOCKET_TIMEOUT);
|
||||||
|
try {
|
||||||
socket.setTrafficClass(0b11100);
|
socket.setTrafficClass(0b11100);
|
||||||
|
} catch (SocketException ignored) {
|
||||||
|
// Windows XP has no support for that
|
||||||
|
}
|
||||||
socket.setPerformancePreferences(1, 0, 2);
|
socket.setPerformancePreferences(1, 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,14 +345,9 @@ public static void subWarning(String format, Object... args) {
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static String toString(Throwable exc) {
|
public static String toString(Throwable exc) {
|
||||||
try (StringWriter sw = new StringWriter()) {
|
StringWriter sw = new StringWriter();
|
||||||
try (PrintWriter pw = new PrintWriter(sw)) {
|
exc.printStackTrace(new PrintWriter(sw));
|
||||||
exc.printStackTrace(pw);
|
|
||||||
}
|
|
||||||
return sw.toString();
|
return sw.toString();
|
||||||
} catch (IOException e) {
|
|
||||||
throw new InternalError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
|
|
@ -105,7 +105,7 @@ public void run(String... args) throws Throwable {
|
||||||
loadConfig();
|
loadConfig();
|
||||||
ServerWrapperSetup setup = new ServerWrapperSetup();
|
ServerWrapperSetup setup = new ServerWrapperSetup();
|
||||||
setup.run();
|
setup.run();
|
||||||
System.exit(0);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
modulesManager = new ModulesManager(wrapper);
|
modulesManager = new ModulesManager(wrapper);
|
||||||
modulesManager.autoload(modulesDir);
|
modulesManager.autoload(modulesDir);
|
||||||
|
|
Loading…
Reference in a new issue