diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 493fb0a..705601a 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -3,6 +3,7 @@ repositories { maven { url 'https://repo.papermc.io/repository/maven-public/' } maven { url 'https://repo.codemc.io/repository/maven-public/' } maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' } + maven { url 'https://repo.nickuc.com/maven-releases/' } } dependencies { @@ -10,6 +11,7 @@ dependencies { compileOnly 'dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT' compileOnly 'io.netty:netty-all:4.1.25.Final' compileOnly 'fr.xephi:authme:5.6.0-beta2' + compileOnly 'com.nickuc.login:nlogin-api:10.2' compileOnly 'me.clip:placeholderapi:2.11.1' } diff --git a/bukkit/src/main/java/com/azuriom/azlink/bukkit/AzLinkBukkitPlugin.java b/bukkit/src/main/java/com/azuriom/azlink/bukkit/AzLinkBukkitPlugin.java index ec80b15..040c666 100644 --- a/bukkit/src/main/java/com/azuriom/azlink/bukkit/AzLinkBukkitPlugin.java +++ b/bukkit/src/main/java/com/azuriom/azlink/bukkit/AzLinkBukkitPlugin.java @@ -8,6 +8,7 @@ import com.azuriom.azlink.bukkit.integrations.FoliaSchedulerAdapter; import com.azuriom.azlink.bukkit.integrations.MoneyPlaceholderExpansion; import com.azuriom.azlink.bukkit.integrations.SkinsRestorerIntegration; +import com.azuriom.azlink.bukkit.integrations.NLoginIntegration; import com.azuriom.azlink.common.AzLinkPlatform; import com.azuriom.azlink.common.AzLinkPlugin; import com.azuriom.azlink.common.command.CommandSender; @@ -20,6 +21,7 @@ import com.azuriom.azlink.common.scheduler.JavaSchedulerAdapter; import com.azuriom.azlink.common.scheduler.SchedulerAdapter; import com.azuriom.azlink.common.tasks.TpsTask; +import com.nickuc.login.api.nLoginAPI; import org.bukkit.entity.Player; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.java.JavaPlugin; @@ -85,6 +87,15 @@ && getServer().getPluginManager().getPlugin("AuthMe") != null) { getServer().getPluginManager().registerEvents(new AuthMeIntegration(this), this); } + if (getConfig().getBoolean("nlogin-integration") + && getServer().getPluginManager().getPlugin("nLogin") != null) { + if (nLoginAPI.getApi().getApiVersion() >= 5) { + getServer().getPluginManager().registerEvents(new NLoginIntegration(this), this); + } else { + this.plugin.getLogger().warn("nLogin integration requires API version v5 or higher"); + } + } + if (getConfig().getBoolean("skinrestorer-integration") && getServer().getPluginManager().getPlugin("SkinsRestorer") != null) { try { diff --git a/bukkit/src/main/java/com/azuriom/azlink/bukkit/injector/InjectedHttpServer.java b/bukkit/src/main/java/com/azuriom/azlink/bukkit/injector/InjectedHttpServer.java index 96ef8fb..eea1fbe 100644 --- a/bukkit/src/main/java/com/azuriom/azlink/bukkit/injector/InjectedHttpServer.java +++ b/bukkit/src/main/java/com/azuriom/azlink/bukkit/injector/InjectedHttpServer.java @@ -2,13 +2,7 @@ import com.azuriom.azlink.bukkit.AzLinkBukkitPlugin; import com.azuriom.azlink.common.http.server.HttpServer; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandler; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; +import io.netty.channel.*; import org.bukkit.Bukkit; import java.lang.reflect.Field; diff --git a/bukkit/src/main/java/com/azuriom/azlink/bukkit/integrations/NLoginIntegration.java b/bukkit/src/main/java/com/azuriom/azlink/bukkit/integrations/NLoginIntegration.java new file mode 100644 index 0000000..b0b81b7 --- /dev/null +++ b/bukkit/src/main/java/com/azuriom/azlink/bukkit/integrations/NLoginIntegration.java @@ -0,0 +1,37 @@ +package com.azuriom.azlink.bukkit.integrations; + +import com.azuriom.azlink.bukkit.AzLinkBukkitPlugin; +import com.azuriom.azlink.common.integrations.BaseNLogin; +import com.nickuc.login.api.enums.TwoFactorType; +import com.nickuc.login.api.event.bukkit.auth.RegisterEvent; +import com.nickuc.login.api.event.bungee.twofactor.TwoFactorAddEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.net.InetSocketAddress; + +public class NLoginIntegration + extends BaseNLogin implements Listener { + + public NLoginIntegration(AzLinkBukkitPlugin plugin) { + super(plugin.getPlugin()); + } + + @EventHandler + public void onEmailAdded(TwoFactorAddEvent event) { + if (event.getType() != TwoFactorType.EMAIL) { + return; + } + + handleEmailUpdated(event.getPlayerId(), event.getPlayerName(), event.getAccount()); + } + + @EventHandler + public void onRegister(RegisterEvent event) { + Player player = event.getPlayer(); + InetSocketAddress ip = player.getAddress(); + + handleRegister(player.getUniqueId(), player.getName(), event.getPassword(), ip != null ? ip.getAddress() : null); + } +} diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml index ab2ac00..07bed4f 100644 --- a/bukkit/src/main/resources/config.yml +++ b/bukkit/src/main/resources/config.yml @@ -13,6 +13,12 @@ ignore-vanished-players: false # from registering multiple times authme-integration: false +# When enabled, new users registered with the nLogin plugin will automatically be registered on the website +# WARNING: You need nLogin version 10.2.43 or newer! +# If you are using multiples serves, you should use the same database for nLogin to prevent users +# from registering multiple times +nlogin-integration: false + # When enabled, if SkinsRestorer is installed, and the SkinAPI plugin is present on the website, # the player's skin will be updated to the website's skin skinrestorer-integration: false diff --git a/bungee/build.gradle b/bungee/build.gradle index 881368e..44bae0d 100644 --- a/bungee/build.gradle +++ b/bungee/build.gradle @@ -1,10 +1,12 @@ repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } + maven { url 'https://repo.nickuc.com/maven-releases/' } } dependencies { implementation project(':azlink-common') compileOnly 'net.md-5:bungeecord-api:1.16-R0.4' + compileOnly 'com.nickuc.login:nlogin-api:10.2' } processResources { diff --git a/bungee/src/main/java/com/azuriom/azlink/bungee/AzLinkBungeePlugin.java b/bungee/src/main/java/com/azuriom/azlink/bungee/AzLinkBungeePlugin.java index e02b6d2..b49ba99 100644 --- a/bungee/src/main/java/com/azuriom/azlink/bungee/AzLinkBungeePlugin.java +++ b/bungee/src/main/java/com/azuriom/azlink/bungee/AzLinkBungeePlugin.java @@ -2,6 +2,7 @@ import com.azuriom.azlink.bungee.command.BungeeCommandExecutor; import com.azuriom.azlink.bungee.command.BungeeCommandSender; +import com.azuriom.azlink.bungee.integrations.NLoginIntegration; import com.azuriom.azlink.bungee.integrations.SkinsRestorerIntegration; import com.azuriom.azlink.common.AzLinkPlatform; import com.azuriom.azlink.common.AzLinkPlugin; @@ -11,6 +12,7 @@ import com.azuriom.azlink.common.platform.PlatformInfo; import com.azuriom.azlink.common.platform.PlatformType; import com.azuriom.azlink.common.scheduler.SchedulerAdapter; +import com.nickuc.login.api.nLoginAPI; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.ConfigurationProvider; @@ -43,6 +45,15 @@ public void onEnable() { loadConfig(); + if (this.config.getBoolean("nlogin-integration") + && getProxy().getPluginManager().getPlugin("nLogin") != null) { + if (nLoginAPI.getApi().getApiVersion() >= 5) { + getProxy().getPluginManager().registerListener(this, new NLoginIntegration(this)); + } else { + this.plugin.getLogger().warn("nLogin integration requires API version v5 or higher"); + } + } + if (this.config.getBoolean("skinsrestorer-integration") && getProxy().getPluginManager().getPlugin("SkinsRestorer") != null) { getProxy().getPluginManager().registerListener(this, new SkinsRestorerIntegration(this)); diff --git a/bungee/src/main/java/com/azuriom/azlink/bungee/integrations/NLoginIntegration.java b/bungee/src/main/java/com/azuriom/azlink/bungee/integrations/NLoginIntegration.java new file mode 100644 index 0000000..c77536b --- /dev/null +++ b/bungee/src/main/java/com/azuriom/azlink/bungee/integrations/NLoginIntegration.java @@ -0,0 +1,40 @@ +package com.azuriom.azlink.bungee.integrations; + +import com.azuriom.azlink.bungee.AzLinkBungeePlugin; +import com.azuriom.azlink.common.integrations.BaseNLogin; +import com.nickuc.login.api.enums.TwoFactorType; +import com.nickuc.login.api.event.bungee.auth.RegisterEvent; +import com.nickuc.login.api.event.bungee.twofactor.TwoFactorAddEvent; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +public class NLoginIntegration + extends BaseNLogin implements Listener { + + public NLoginIntegration(AzLinkBungeePlugin plugin) { + super(plugin.getPlugin()); + } + + @EventHandler + public void onEmailAdded(TwoFactorAddEvent event) { + if (event.getType() != TwoFactorType.EMAIL) { + return; + } + + handleEmailUpdated(event.getPlayerId(), event.getPlayerName(), event.getAccount()); + } + + @EventHandler + public void onRegister(RegisterEvent event) { + ProxiedPlayer player = event.getPlayer(); + SocketAddress socketAddress = player.getSocketAddress(); + InetAddress ip = socketAddress instanceof InetSocketAddress ? ((InetSocketAddress) socketAddress).getAddress() : null; + + handleRegister(player.getUniqueId(), player.getName(), event.getPassword(), ip); + } +} diff --git a/bungee/src/main/resources/bungee-config.yml b/bungee/src/main/resources/bungee-config.yml index 6ad455c..838c3db 100644 --- a/bungee/src/main/resources/bungee-config.yml +++ b/bungee/src/main/resources/bungee-config.yml @@ -1,3 +1,9 @@ +# When enabled, new users registered with the nLogin plugin will automatically be registered on the website +# WARNING: You need nLogin version 10.2.43 or newer! +# If you are using multiples serves, you should use the same database for nLogin to prevent users +# from registering multiple times +nlogin-integration: false + # When enabled, if SkinsRestorer is installed, and the SkinAPI plugin is present on the website, # the player's skin will be updated to the website's skin skinsrestorer-integration: false diff --git a/common/build.gradle b/common/build.gradle index 8b7455f..d79e81d 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,5 +1,6 @@ repositories { maven { url 'https://repo.codemc.io/repository/maven-public/' } + maven { url 'https://repo.nickuc.com/maven-releases/' } } dependencies { @@ -7,6 +8,7 @@ dependencies { compileOnly 'com.google.code.gson:gson:2.10.1' compileOnly 'io.netty:netty-all:4.1.42.Final' compileOnly 'net.skinsrestorer:skinsrestorer-api:15.0.2' + compileOnly 'com.nickuc.login:nlogin-api:10.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.1' testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.1' diff --git a/common/src/main/java/com/azuriom/azlink/common/AzLinkPlugin.java b/common/src/main/java/com/azuriom/azlink/common/AzLinkPlugin.java index 00e4463..ad16e6d 100644 --- a/common/src/main/java/com/azuriom/azlink/common/AzLinkPlugin.java +++ b/common/src/main/java/com/azuriom/azlink/common/AzLinkPlugin.java @@ -3,11 +3,7 @@ import com.azuriom.azlink.common.command.AzLinkCommand; import com.azuriom.azlink.common.command.CommandSender; import com.azuriom.azlink.common.config.PluginConfig; -import com.azuriom.azlink.common.data.PlatformData; -import com.azuriom.azlink.common.data.PlayerData; -import com.azuriom.azlink.common.data.ServerData; -import com.azuriom.azlink.common.data.SystemData; -import com.azuriom.azlink.common.data.WorldData; +import com.azuriom.azlink.common.data.*; import com.azuriom.azlink.common.http.client.HttpClient; import com.azuriom.azlink.common.http.server.HttpServer; import com.azuriom.azlink.common.http.server.NettyHttpServer; diff --git a/common/src/main/java/com/azuriom/azlink/common/http/server/HttpHandler.java b/common/src/main/java/com/azuriom/azlink/common/http/server/HttpHandler.java index 8a50c19..62baed9 100644 --- a/common/src/main/java/com/azuriom/azlink/common/http/server/HttpHandler.java +++ b/common/src/main/java/com/azuriom/azlink/common/http/server/HttpHandler.java @@ -5,12 +5,7 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.*; import java.nio.charset.StandardCharsets; diff --git a/common/src/main/java/com/azuriom/azlink/common/integrations/BaseNLogin.java b/common/src/main/java/com/azuriom/azlink/common/integrations/BaseNLogin.java new file mode 100644 index 0000000..f5bab98 --- /dev/null +++ b/common/src/main/java/com/azuriom/azlink/common/integrations/BaseNLogin.java @@ -0,0 +1,39 @@ +package com.azuriom.azlink.common.integrations; + +import com.azuriom.azlink.common.AzLinkPlugin; + +import java.net.InetAddress; +import java.util.UUID; + +public class BaseNLogin { + + protected final AzLinkPlugin plugin; + + public BaseNLogin(AzLinkPlugin plugin) { + this.plugin = plugin; + + this.plugin.getLogger().info("nLogin integration enabled."); + } + + protected void handleEmailUpdated(UUID playerId, String playerName, String newEmail) { + this.plugin + .getHttpClient() + .updateEmail(playerId, newEmail) + .exceptionally(ex -> { + this.plugin.getLogger().error("Unable to update email for " + playerName, ex); + + return null; + }); + } + + protected void handleRegister(UUID playerId, String playerName, String password, InetAddress ip) { + this.plugin + .getHttpClient() + .registerUser(playerName, null, playerId, password, ip) + .exceptionally(ex -> { + this.plugin.getLogger().error("Unable to register " + playerName, ex); + + return null; + }); + } +} diff --git a/common/src/main/java/com/azuriom/azlink/common/scheduler/JavaSchedulerAdapter.java b/common/src/main/java/com/azuriom/azlink/common/scheduler/JavaSchedulerAdapter.java index 64da2cc..ce694ce 100644 --- a/common/src/main/java/com/azuriom/azlink/common/scheduler/JavaSchedulerAdapter.java +++ b/common/src/main/java/com/azuriom/azlink/common/scheduler/JavaSchedulerAdapter.java @@ -1,10 +1,6 @@ package com.azuriom.azlink.common.scheduler; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; public class JavaSchedulerAdapter implements SchedulerAdapter { diff --git a/velocity/build.gradle b/velocity/build.gradle index 284d2e7..546b771 100644 --- a/velocity/build.gradle +++ b/velocity/build.gradle @@ -5,6 +5,7 @@ plugins { repositories { maven { url 'https://nexus.velocitypowered.com/repository/maven-public/' } maven { url 'https://maven.elytrium.net/repo/' } + maven { url 'https://repo.nickuc.com/maven-releases/' } } dependencies { @@ -12,6 +13,7 @@ dependencies { compileOnly 'com.velocitypowered:velocity-api:3.1.1' compileOnly 'net.elytrium.limboapi:api:1.1.13' compileOnly 'net.elytrium:limboauth:1.1.1' + compileOnly 'com.nickuc.login:nlogin-api:10.2' annotationProcessor 'com.velocitypowered:velocity-api:3.1.1' } diff --git a/velocity/src/main/java/com/azuriom/azlink/velocity/AzLinkVelocityPlugin.java b/velocity/src/main/java/com/azuriom/azlink/velocity/AzLinkVelocityPlugin.java index 39e0f92..dc84f87 100644 --- a/velocity/src/main/java/com/azuriom/azlink/velocity/AzLinkVelocityPlugin.java +++ b/velocity/src/main/java/com/azuriom/azlink/velocity/AzLinkVelocityPlugin.java @@ -11,8 +11,10 @@ import com.azuriom.azlink.velocity.command.VelocityCommandExecutor; import com.azuriom.azlink.velocity.command.VelocityCommandSender; import com.azuriom.azlink.velocity.integrations.LimboAuthIntegration; +import com.azuriom.azlink.velocity.integrations.NLoginIntegration; import com.azuriom.azlink.velocity.integrations.SkinsRestorerIntegration; import com.google.inject.Inject; +import com.nickuc.login.api.nLoginAPI; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; @@ -81,6 +83,14 @@ public void onProxyInitialization(ProxyInitializeEvent event) { this.proxy.getEventManager().register(this, new LimboAuthIntegration(this)); } + if (this.proxy.getPluginManager().getPlugin("nlogin").isPresent()) { + if (nLoginAPI.getApi().getApiVersion() >= 5) { + this.proxy.getEventManager().register(this, new NLoginIntegration(this)); + } else { + this.plugin.getLogger().warn("nLogin integration requires API version v5 or higher"); + } + } + if (this.proxy.getPluginManager().getPlugin("skinsrestorer").isPresent() && this.config.getNode("skinsrestorer-integration").getBoolean()) { this.proxy.getEventManager().register(this, new SkinsRestorerIntegration(this)); diff --git a/velocity/src/main/java/com/azuriom/azlink/velocity/integrations/NLoginIntegration.java b/velocity/src/main/java/com/azuriom/azlink/velocity/integrations/NLoginIntegration.java new file mode 100644 index 0000000..74ef05d --- /dev/null +++ b/velocity/src/main/java/com/azuriom/azlink/velocity/integrations/NLoginIntegration.java @@ -0,0 +1,32 @@ +package com.azuriom.azlink.velocity.integrations; + +import com.azuriom.azlink.common.integrations.BaseNLogin; +import com.azuriom.azlink.velocity.AzLinkVelocityPlugin; +import com.nickuc.login.api.enums.TwoFactorType; +import com.nickuc.login.api.event.bungee.twofactor.TwoFactorAddEvent; +import com.nickuc.login.api.event.velocity.auth.RegisterEvent; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.proxy.Player; + +public class NLoginIntegration extends BaseNLogin { + + public NLoginIntegration(AzLinkVelocityPlugin plugin) { + super(plugin.getPlugin()); + } + + @Subscribe + public void onEmailAdded(TwoFactorAddEvent event) { + if (event.getType() != TwoFactorType.EMAIL) { + return; + } + + handleEmailUpdated(event.getPlayerId(), event.getPlayerName(), event.getAccount()); + } + + @Subscribe + public void onRegister(RegisterEvent event) { + Player player = event.getPlayer(); + + handleRegister(player.getUniqueId(), player.getUsername(), event.getPassword(), player.getRemoteAddress().getAddress()); + } +}