diff --git a/pom.xml b/pom.xml index c17bff7..c1395e9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.v4guard v4guard-plugin - 1.1.3c + 1.1.4 jar diff --git a/src/main/java/io/v4guard/plugin/bungee/accounts/BungeeMessageReceiver.java b/src/main/java/io/v4guard/plugin/bungee/accounts/BungeeMessageReceiver.java index fb94b5f..5810253 100644 --- a/src/main/java/io/v4guard/plugin/bungee/accounts/BungeeMessageReceiver.java +++ b/src/main/java/io/v4guard/plugin/bungee/accounts/BungeeMessageReceiver.java @@ -46,7 +46,7 @@ public void onPostLogin(PostLoginEvent e) { if(!v4GuardCore.getInstance().isAccountShieldFound()) { ProxiedPlayer player = e.getPlayer(); if (player.getPendingConnection().isOnlineMode()) { - Authentication auth = new Authentication(player.getName(), AuthType.MOJANG); + Authentication auth = new Authentication(player.getName(), AuthType.MOJANG, player.hasPermission("v4guard.accshield")); v4GuardCore.getInstance().getAccountShieldManager().sendSocketMessage(auth); } } diff --git a/src/main/java/io/v4guard/plugin/bungee/listener/PluginMessagingListener.java b/src/main/java/io/v4guard/plugin/bungee/listener/PluginMessagingListener.java index fa9bce2..16496a0 100644 --- a/src/main/java/io/v4guard/plugin/bungee/listener/PluginMessagingListener.java +++ b/src/main/java/io/v4guard/plugin/bungee/listener/PluginMessagingListener.java @@ -1,6 +1,10 @@ package io.v4guard.plugin.bungee.listener; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.v4guard.plugin.bungee.v4GuardBungee; +import io.v4guard.plugin.core.tasks.types.CompletableMCBrandTask; +import io.v4guard.plugin.core.utils.StringUtils; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.api.plugin.Listener; @@ -15,22 +19,29 @@ public PluginMessagingListener() { @EventHandler public void onChannelMessage(PluginMessageEvent e){ + Document privacySettings = (Document) v4GuardBungee.getCoreInstance().getBackendConnector().getSettings().getOrDefault("privacy", new Document()); boolean invalidatedCache = (boolean) v4GuardBungee.getCoreInstance().getBackendConnector().getSettings().getOrDefault("invalidateCache", false); if(!invalidatedCache && privacySettings.getBoolean("collectMCBrand", true)){ if(e.getSender() instanceof ProxiedPlayer){ if(e.getTag().equals("MC|Brand") || e.getTag().equals("minecraft:brand")){ ProxiedPlayer player = (ProxiedPlayer) e.getSender(); - Document data = new Document(); - data.put("username", player.getName()); - data.put("brand", new String(e.getData())); - v4GuardBungee.getCoreInstance().getBackendConnector().getSocket().emit("mc:brand", data.toJson()); + CompletableMCBrandTask task = v4GuardBungee.getCoreInstance().getCompletableTaskManager().getBrandTask(player.getName()); + if(task == null) task = new CompletableMCBrandTask(player.getName()); + task.addData(new String(e.getData())); } else if (e.getTag().equals("LMC") || e.getTag().equals("labymod3:main")){ ProxiedPlayer player = (ProxiedPlayer) e.getSender(); - Document data = new Document(); - data.put("username", player.getName()); - data.put("brand", "labymod"); - v4GuardBungee.getCoreInstance().getBackendConnector().getSocket().emit("mc:brand", data.toJson()); + CompletableMCBrandTask task = v4GuardBungee.getCoreInstance().getCompletableTaskManager().getBrandTask(player.getName()); + if(task == null) task = new CompletableMCBrandTask(player.getName()); + ByteBuf buf = Unpooled.wrappedBuffer(e.getData()); + String key = StringUtils.readString(buf, Short.MAX_VALUE); + if(!key.equals("INFO")){ + return; + } + String json = StringUtils.readString(buf, Short.MAX_VALUE); + Document data = Document.parse(json); + String version = data == null ? "unknown" : (String) data.getOrDefault("version", "unknown"); + task.addData("labymod:" + version); } } } diff --git a/src/main/java/io/v4guard/plugin/core/accounts/AccountShieldManager.java b/src/main/java/io/v4guard/plugin/core/accounts/AccountShieldManager.java index 369a653..febe6a4 100644 --- a/src/main/java/io/v4guard/plugin/core/accounts/AccountShieldManager.java +++ b/src/main/java/io/v4guard/plugin/core/accounts/AccountShieldManager.java @@ -23,8 +23,7 @@ public void sendSocketMessage(Authentication auth){ boolean shieldEnabled = (boolean) shieldSettings.getOrDefault("accshield", false); if(!shieldEnabled) return; - Document finalDocument = new Document("username", auth.getUsername()) - .append("type", auth.getAuthType().toString()); + Document finalDocument = auth.serialize(); v4GuardCore.getInstance().getBackendConnector().getSocket().emit("accshield:login", finalDocument.toJson()); } } diff --git a/src/main/java/io/v4guard/plugin/core/accounts/auth/Authentication.java b/src/main/java/io/v4guard/plugin/core/accounts/auth/Authentication.java index 4c3872f..018e96d 100644 --- a/src/main/java/io/v4guard/plugin/core/accounts/auth/Authentication.java +++ b/src/main/java/io/v4guard/plugin/core/accounts/auth/Authentication.java @@ -6,10 +6,12 @@ public class Authentication { private final String username; private final AuthType authType; + private boolean hasPermission; - public Authentication(String username, AuthType authType) { + public Authentication(String username, AuthType authType, boolean hasPermission) { this.username = username; this.authType = authType; + this.hasPermission = hasPermission; } public String getUsername() { @@ -22,10 +24,11 @@ public AuthType getAuthType() { public Document serialize(){ return new Document("username", username) - .append("authType", authType.toString()); + .append("authType", authType.toString()) + .append("hasPermission", hasPermission); } public static Authentication deserialize(Document doc){ - return new Authentication(doc.getString("username"), AuthType.valueOf(doc.getString("authType"))); + return new Authentication(doc.getString("username"), AuthType.valueOf(doc.getString("authType")), doc.getBoolean("hasPermission")); } } diff --git a/src/main/java/io/v4guard/plugin/core/socket/listener/MessageListener.java b/src/main/java/io/v4guard/plugin/core/socket/listener/MessageListener.java index 5574c58..40ab045 100644 --- a/src/main/java/io/v4guard/plugin/core/socket/listener/MessageListener.java +++ b/src/main/java/io/v4guard/plugin/core/socket/listener/MessageListener.java @@ -21,13 +21,15 @@ public MessageListener(BackendConnector backendConnector) { @Override public void call(Object... args) { Document doc = Document.parse(args[0].toString()); - String permission = doc.getOrDefault("permission", "*").toString(); + String permission = doc.getOrDefault("permission", "no-permission").toString(); List players = (List) doc.getOrDefault("players", new ArrayList<>()); String message = (String) doc.getOrDefault("message", "Disconnected"); switch (v4GuardCore.getInstance().getPluginMode()){ case BUNGEE: { - List broadcasted = v4GuardBungee.getV4Guard().getMessager().broadcastWithPermission(message, permission); - players.removeAll(broadcasted); + if(!permission.equals("no-permission")){ + List broadcasted = v4GuardBungee.getV4Guard().getMessager().broadcastWithPermission(message, permission); + players.removeAll(broadcasted); + } for(String player : players){ v4GuardBungee.getV4Guard().getMessager().sendToPlayer(message, player); } @@ -35,8 +37,10 @@ public void call(Object... args) { } case VELOCITY: { - List broadcasted = v4GuardVelocity.getV4Guard().getMessager().broadcastWithPermission(message, permission); - players.removeAll(broadcasted); + if(!permission.equals("no-permission")) { + List broadcasted = v4GuardVelocity.getV4Guard().getMessager().broadcastWithPermission(message, permission); + players.removeAll(broadcasted); + } for(String player : players){ v4GuardVelocity.getV4Guard().getMessager().sendToPlayer(message, player); } diff --git a/src/main/java/io/v4guard/plugin/core/tasks/CompletableTaskManager.java b/src/main/java/io/v4guard/plugin/core/tasks/CompletableTaskManager.java index 1694899..b264312 100644 --- a/src/main/java/io/v4guard/plugin/core/tasks/CompletableTaskManager.java +++ b/src/main/java/io/v4guard/plugin/core/tasks/CompletableTaskManager.java @@ -1,6 +1,7 @@ package io.v4guard.plugin.core.tasks; import io.v4guard.plugin.core.tasks.common.CompletableTask; +import io.v4guard.plugin.core.tasks.types.CompletableMCBrandTask; import java.util.HashMap; @@ -12,4 +13,16 @@ public HashMap getTasks() { return this.tasks; } + public CompletableMCBrandTask getBrandTask(String username){ + for(CompletableTask task : this.tasks.values()){ + if(task instanceof CompletableMCBrandTask){ + CompletableMCBrandTask brandTask = (CompletableMCBrandTask) task; + if(brandTask.getUsername().equals(username)){ + return brandTask; + } + } + } + return null; + } + } \ No newline at end of file diff --git a/src/main/java/io/v4guard/plugin/core/tasks/types/CompletableMCBrandTask.java b/src/main/java/io/v4guard/plugin/core/tasks/types/CompletableMCBrandTask.java new file mode 100644 index 0000000..20e41fc --- /dev/null +++ b/src/main/java/io/v4guard/plugin/core/tasks/types/CompletableMCBrandTask.java @@ -0,0 +1,51 @@ +package io.v4guard.plugin.core.tasks.types; + +import io.v4guard.plugin.bungee.v4GuardBungee; +import io.v4guard.plugin.core.tasks.common.CompletableTask; +import io.v4guard.plugin.core.v4GuardCore; +import org.bson.Document; + +import java.util.*; + +public class CompletableMCBrandTask implements CompletableTask { + + private final String taskID; + private final String username; + private final List brands; + + public CompletableMCBrandTask(String username) { + this.username = username; + this.brands = new ArrayList<>(); + this.taskID = UUID.randomUUID().toString(); + v4GuardCore.getInstance().getCompletableTaskManager().getTasks().put(this.taskID, this); + new Timer().schedule(new TimerTask(){ + @Override + public void run() { + complete(); + } + }, 1000L); + } + + @Override + public void complete() { + Document data = new Document(); + data.put("username", username); + data.put("brand", brands); + v4GuardBungee.getCoreInstance().getBackendConnector().getSocket().emit("mc:brand", data.toJson()); + v4GuardCore.getInstance().getCompletableTaskManager().getTasks().remove(taskID); + } + + @Override + public String getTaskID() { + return this.taskID; + } + + public void addData(String brand) { + if(!this.brands.contains(brand)) this.brands.add(brand); + } + + public String getUsername() { + return this.username; + } + +} diff --git a/src/main/java/io/v4guard/plugin/core/utils/StringUtils.java b/src/main/java/io/v4guard/plugin/core/utils/StringUtils.java index 5d6df52..b80c0df 100644 --- a/src/main/java/io/v4guard/plugin/core/utils/StringUtils.java +++ b/src/main/java/io/v4guard/plugin/core/utils/StringUtils.java @@ -1,7 +1,10 @@ package io.v4guard.plugin.core.utils; +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.DecoderException; import org.bson.Document; +import java.nio.charset.Charset; import java.util.List; import java.util.StringJoiner; @@ -25,4 +28,54 @@ public static String buildMultilineString(List lines) { return message.toString(); } + /** + * Reads a varint from the given byte buffer + * + * @param buf the byte buffer the varint should be read from + * @return the int read + */ + public static int readVarIntFromBuffer( ByteBuf buf ) { + int i = 0; + int j = 0; + + byte b0; + do { + b0 = buf.readByte(); + i |= (b0 & 127) << j++ * 7; + if ( j > 5 ) { + throw new RuntimeException( "VarInt too big" ); + } + } while ( (b0 & 128) == 128 ); + + return i; + } + + /** + * Reads a string from the given byte buffer + * + * @param buf the byte buffer the string should be read from + * @param maxLength the string's max-length + * @return the string read + */ + public static String readString(ByteBuf buf, int maxLength ) { + int i = readVarIntFromBuffer( buf ); + + if ( i > maxLength * 4 ) { + throw new DecoderException( "The received encoded string buffer length is longer than maximum allowed (" + i + " > " + maxLength * 4 + ")" ); + } else if ( i < 0 ) { + throw new DecoderException( "The received encoded string buffer length is less than zero! Weird string!" ); + } else { + byte[] bytes = new byte[i]; + buf.readBytes( bytes ); + + String s = new String( bytes, Charset.forName( "UTF-8" ) ); + if ( s.length() > maxLength ) { + throw new DecoderException( "The received string length is longer than maximum allowed (" + i + " > " + maxLength + ")" ); + } else { + return s; + } + } + } + + } diff --git a/src/main/java/io/v4guard/plugin/core/v4GuardCore.java b/src/main/java/io/v4guard/plugin/core/v4GuardCore.java index c42fb05..d26d27b 100644 --- a/src/main/java/io/v4guard/plugin/core/v4GuardCore.java +++ b/src/main/java/io/v4guard/plugin/core/v4GuardCore.java @@ -24,7 +24,7 @@ public class v4GuardCore { private AccountShieldManager accountShieldManager; private ChatFilterManager chatFilterManager; - public static final String pluginVersion = "1.1.3c"; + public static final String pluginVersion = "1.1.4"; private boolean debug = false; private boolean accountShieldFound = false; diff --git a/src/main/java/io/v4guard/plugin/velocity/accounts/VelocityMessageReceiver.java b/src/main/java/io/v4guard/plugin/velocity/accounts/VelocityMessageReceiver.java index b55f7bc..4c086c5 100644 --- a/src/main/java/io/v4guard/plugin/velocity/accounts/VelocityMessageReceiver.java +++ b/src/main/java/io/v4guard/plugin/velocity/accounts/VelocityMessageReceiver.java @@ -48,7 +48,7 @@ public void onPostLogin(PostLoginEvent e) { if(!v4GuardCore.getInstance().isAccountShieldFound()) { Player player = e.getPlayer(); if (player.isOnlineMode()) { - Authentication auth = new Authentication(player.getUsername(), AuthType.MOJANG); + Authentication auth = new Authentication(player.getUsername(), AuthType.MOJANG, player.hasPermission("v4guard.accshield")); v4GuardCore.getInstance().getAccountShieldManager().sendSocketMessage(auth); } } diff --git a/src/main/java/io/v4guard/plugin/velocity/listener/PluginMessagingListener.java b/src/main/java/io/v4guard/plugin/velocity/listener/PluginMessagingListener.java index 8291b7d..b4c566f 100644 --- a/src/main/java/io/v4guard/plugin/velocity/listener/PluginMessagingListener.java +++ b/src/main/java/io/v4guard/plugin/velocity/listener/PluginMessagingListener.java @@ -4,6 +4,11 @@ import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.proxy.Player; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.v4guard.plugin.bungee.v4GuardBungee; +import io.v4guard.plugin.core.tasks.types.CompletableMCBrandTask; +import io.v4guard.plugin.core.utils.StringUtils; import io.v4guard.plugin.velocity.v4GuardVelocity; import net.md_5.bungee.api.plugin.Listener; import org.bson.Document; @@ -18,18 +23,26 @@ public void onMessage(PluginMessageEvent e){ if(e.getSource() instanceof Player){ if(e.getIdentifier().getId().equals("MC|Brand") || e.getIdentifier().getId().equals("minecraft:brand")){ Player player = (Player) e.getSource(); - Document data = new Document(); - data.put("username", player.getUsername()); - data.put("brand", new String(e.getData())); - v4GuardVelocity.getCoreInstance().getBackendConnector().getSocket().emit("mc:brand", data.toJson()); + CompletableMCBrandTask task = v4GuardBungee.getCoreInstance().getCompletableTaskManager().getBrandTask(player.getUsername()); + if(task == null) task = new CompletableMCBrandTask(player.getUsername()); + task.addData(new String(e.getData())); } else if (e.getIdentifier().getId().equals("LMC") || e.getIdentifier().getId().equals("labymod3:main")){ Player player = (Player) e.getSource(); - Document data = new Document(); - data.put("username", player.getUsername()); - data.put("brand", "labymod"); - v4GuardVelocity.getCoreInstance().getBackendConnector().getSocket().emit("mc:brand", data.toJson()); + CompletableMCBrandTask task = v4GuardBungee.getCoreInstance().getCompletableTaskManager().getBrandTask(player.getUsername()); + if(task == null) task = new CompletableMCBrandTask(player.getUsername()); + ByteBuf buf = Unpooled.wrappedBuffer(e.getData()); + String key = StringUtils.readString(buf, Short.MAX_VALUE); + if(!key.equals("INFO")){ + return; + } + String json = StringUtils.readString(buf, Short.MAX_VALUE); + Document data = Document.parse(json); + String version = data == null ? "unknown" : (String) data.getOrDefault("version", "unknown"); + task.addData("labymod:" + version); } } } } + + }