goauth

Fabric plugin for enhanced whitelists
git clone git://git.bain.cz/goauth.git
Log | Files | Refs | README | LICENSE

commit cb5b2a51f6ba3034ac1f65608c54de85e3aacf32
parent ad8c8b9b91cac73e4661dce974b5838d45d9a106
Author: bain <bain@bain.cz>
Date:   Fri,  3 Dec 2021 18:36:02 +0100

less whitelist, more authentication

Diffstat:
MREADME | 12+++++++-----
Mgradle/wrapper/gradle-wrapper.properties | 2+-
Asrc/main/java/cz/bain/plugins/goauth/AuthStore.java | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/cz/bain/plugins/goauth/AuthUpdateRunner.java | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main/java/cz/bain/plugins/goauth/DummyServerPlayNetworkHandler.java | 2+-
Msrc/main/java/cz/bain/plugins/goauth/Goauth.java | 17++++++++---------
Msrc/main/java/cz/bain/plugins/goauth/OAuthUpdate.java | 27+++++++++++++++++----------
Msrc/main/java/cz/bain/plugins/goauth/StringRepository.java | 4++--
Dsrc/main/java/cz/bain/plugins/goauth/WhitelistUpdateRunner.java | 128-------------------------------------------------------------------------------
Dsrc/main/java/cz/bain/plugins/goauth/events/callbacks/OnWhitelistAddCallback.java | 26--------------------------
Msrc/main/java/cz/bain/plugins/goauth/events/listeners/OnPlayerConnectListener.java | 7++++---
Msrc/main/java/cz/bain/plugins/goauth/events/listeners/OnServerTickListener.java | 35+++++++++++++++--------------------
Dsrc/main/java/cz/bain/plugins/goauth/events/listeners/OnWhitelistAddListener.java | 34----------------------------------
Dsrc/main/java/cz/bain/plugins/goauth/mixin/UserCacheMixin.java | 37-------------------------------------
Dsrc/main/java/cz/bain/plugins/goauth/mixin/WhitelistCommandMixin.java | 23-----------------------
Msrc/main/resources/goauth.mixins.json | 4+---
16 files changed, 263 insertions(+), 302 deletions(-)

diff --git a/README b/README @@ -1,7 +1,8 @@ GOAuth GOAuth is a fabric plugin which adds an authentication limbo -for players that are not on the whitelist. +for players that are not registered or connecting from a new +IP address. The authentication limbo is a stripped down connection that lets the user join, sends him a fake empty world and a message @@ -14,11 +15,12 @@ A socket is open on a port specified in goauth.properties server> 0x00 if size is small enough, 0x01 if not client> sends 12 byte nonce for ChaCha20-Poly1305 encryption client> sends $size bytes of encrypted payload with pre-set key - ex. 1: [{"type": "add", "username": "bain"}] + ex. 1: [{"type": "update", "username": "bain"}] ex. 2: [{"type": "remove", "username": "bain"}] server> 0x01 if the payload is invalid, 0x00 if the transaction was successful -The socket allows a remote server to modify the whitelist. -Whitelist modification is stricter, it kicks the users if they are -removed from the whitelist (and from limbo when they are added). +The socket allows a remote server to authorize a player's IP. +This plugin can work as a whitelist since the remote server +can allow only certain people to register. The plugin itself +is not capable of authenticating users. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/cz/bain/plugins/goauth/AuthStore.java b/src/main/java/cz/bain/plugins/goauth/AuthStore.java @@ -0,0 +1,81 @@ +package cz.bain.plugins.goauth; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import net.minecraft.network.ClientConnection; +import net.minecraft.server.network.ServerPlayerEntity; +import org.apache.logging.log4j.Logger; + +import java.io.*; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.HashMap; + +public class AuthStore { + private final File file; + private HashMap<String, String> entries = new HashMap<>(); + private final Logger logger; + + public AuthStore(Logger logger, File file) { + this.file = file; + this.logger = logger; + } + + public void load() { + if (!this.file.exists()) { + save(); + return; + } + try (FileReader reader = new FileReader(this.file)) { + Gson gson = new Gson(); + Type type = new TypeToken<HashMap<String, String>>(){}.getType(); + entries = gson.fromJson(reader, type); + } catch (IOException e) { + logger.error("IOException while loading auth db!"); + } + } + + public void save() { + try (FileWriter writer = new FileWriter(this.file)) { + Gson gson = new Gson(); + gson.toJson(entries, writer); + } catch (IOException e) { + logger.error("IOException while saving auth db!"); + } + } + + public String hash(String ip) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(ip.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(hash); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return ""; + } + } + + public void put(ServerPlayerEntity player) { + String username = player.getGameProfile().getName(); + String ipHash = hash(player.getIp()); + entries.put(username, ipHash); + save(); + } + + public boolean remove(String name) { + String val = entries.remove(name); + return val != null; + } + + public boolean allowed(ServerPlayerEntity player, ClientConnection connection) { + String ipHash = entries.get(player.getGameProfile().getName()); + String ip = connection.getAddress().toString(); + ip = ip.substring(ip.indexOf("/") + 1); + ip = ip.substring(0, ip.indexOf(":")); + return ipHash != null && ipHash.equals(hash(ip)); + } + +} diff --git a/src/main/java/cz/bain/plugins/goauth/AuthUpdateRunner.java b/src/main/java/cz/bain/plugins/goauth/AuthUpdateRunner.java @@ -0,0 +1,126 @@ +package cz.bain.plugins.goauth; + +import com.google.gson.*; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; + +public class AuthUpdateRunner implements Runnable { + + private final SecretKeySpec key; + private final Goauth plugin; + + public AuthUpdateRunner(byte[] key, Goauth plugin) { + this.key = new SecretKeySpec(key, "ChaCha20"); + this.plugin = plugin; + } + + @Override + public void run() { + ServerSocket serverSocket; + try { + serverSocket = new ServerSocket(); + serverSocket.bind(new InetSocketAddress(Goauth.port), 2); + serverSocket.setSoTimeout(5); + + } catch (IOException e) { + Goauth.LOGGER.error("Failed to create socket for updates!"); + return; + } + while (this.plugin.running) { + try ( + Socket socket = serverSocket.accept(); + InputStream inputStream = socket.getInputStream(); + OutputStream outputStream = socket.getOutputStream() + ) { + // protecting ourselves from being bombarded with large amounts of data + byte[] sizeBytes = inputStream.readNBytes(4); + if (sizeBytes.length != 4) continue; + int size = fromByteArray(sizeBytes); + if (size > 2048 || size <= 0) { + outputStream.write(0x01); + outputStream.flush(); + Goauth.LOGGER.warn("Whitelist update rejected: payload size too big ({})", size); + continue; + } else { + outputStream.write(0x00); + outputStream.flush(); + } + byte[] iv = inputStream.readNBytes(12); + if (iv.length != 12) continue; + byte[] cipherText = inputStream.readNBytes(size); + if (cipherText.length != size) continue; + byte[] plainText; + try { + plainText = decryptMessage(cipherText, iv); + } catch (GeneralSecurityException e) { + Goauth.LOGGER.warn("Whitelist update rejected: failed to decrypt payload"); + outputStream.write(0x01); + outputStream.flush(); + continue; + } + JsonArray el = JsonParser.parseString(new String(plainText, StandardCharsets.UTF_8)).getAsJsonArray(); + Goauth.LOGGER.info("Got " + el.size() + " new whitelist updates"); + Gson gson = new Gson(); + synchronized (this.plugin.completed) { + for (JsonElement user : el) { + OAuthUpdate update; + try { + update = gson.fromJson(user, OAuthUpdate.class); + } catch (JsonSyntaxException ignored) { + Goauth.LOGGER.warn("Whitelist update rejected: bad update data"); + outputStream.write(0x01); + outputStream.flush(); + break; + } + this.plugin.completed.add(update); + outputStream.write(0x00); + } + } + } catch (SocketTimeoutException ignored) { + } catch (IOException | IllegalStateException e) { + Goauth.LOGGER.warn("Error while processing OAuth updates, dropping connection"); + e.printStackTrace(); + } + } + } + + /** + * Decrypts a message with the ChaCha20-Poly1305 cipher. + * + * @param cipherText cipher text with appended digest to the end + * @param iv unique nonce + * @return plain text + * @throws GeneralSecurityException when the decryption goes wrong + */ + private byte[] decryptMessage(byte[] cipherText, byte[] iv) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305"); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + cipher.init(Cipher.DECRYPT_MODE, this.key, ivSpec); + + return cipher.doFinal(cipherText); + } + + /** + * Little endian int from byte array + * + * @param bytes byte array + * @return int + */ + private int fromByteArray(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + (bytes[3] & 0xFF); + } +} diff --git a/src/main/java/cz/bain/plugins/goauth/DummyServerPlayNetworkHandler.java b/src/main/java/cz/bain/plugins/goauth/DummyServerPlayNetworkHandler.java @@ -70,7 +70,7 @@ public class DummyServerPlayNetworkHandler extends ServerPlayNetworkHandler { @Override public void onDisconnected(Text reason) { - Goauth.LOGGER.info("Player {} disconnected from limbo", this.player.getName().getString()); + Goauth.LOGGER.info("{} disconnected from limbo", this.player.getName().getString()); this.player.onDisconnect(); this.player.getTextStream().onDisconnect(); this.plugin.playersLimbo.remove(this.getPlayer().getGameProfile().getName()); diff --git a/src/main/java/cz/bain/plugins/goauth/Goauth.java b/src/main/java/cz/bain/plugins/goauth/Goauth.java @@ -2,14 +2,11 @@ package cz.bain.plugins.goauth; import cz.bain.plugins.goauth.events.callbacks.OnPlayerConnectCallback; import cz.bain.plugins.goauth.events.callbacks.OnServerTickCallback; -import cz.bain.plugins.goauth.events.callbacks.OnWhitelistAddCallback; import cz.bain.plugins.goauth.events.listeners.OnPlayerConnectListener; import cz.bain.plugins.goauth.events.listeners.OnServerTickListener; -import cz.bain.plugins.goauth.events.listeners.OnWhitelistAddListener; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.UserCache; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -29,16 +26,12 @@ public class Goauth implements ModInitializer { public static int port = 8000; public String authLink; public boolean running = true; + public AuthStore authStore; @Override public void onInitialize() { OnPlayerConnectCallback.EVENT.register(new OnPlayerConnectListener(this)); OnServerTickCallback.EVENT.register(new OnServerTickListener(this)); - OnWhitelistAddCallback.EVENT.register(new OnWhitelistAddListener(this)); - - ServerLifecycleEvents.SERVER_STARTED.register(server -> { - UserCache.setUseRemote(server.isOnlineMode()); - }); ServerLifecycleEvents.SERVER_STOPPED.register(server -> running = false); GoauthConfig config; @@ -64,7 +57,13 @@ public class Goauth implements ModInitializer { StringRepository.authLinkText = config.getRequired("auth-link-text"); authLink = Objects.requireNonNullElse(config.get("auth-link"), ""); - new Thread(new WhitelistUpdateRunner(key, this)).start(); + authStore = new AuthStore( + LOGGER, + new File(Objects.requireNonNullElse(config.get("db-location"), "authdb.json")) + ); + authStore.load(); + + new Thread(new AuthUpdateRunner(key, this)).start(); LOGGER.info("Initialized!"); } diff --git a/src/main/java/cz/bain/plugins/goauth/OAuthUpdate.java b/src/main/java/cz/bain/plugins/goauth/OAuthUpdate.java @@ -1,16 +1,23 @@ package cz.bain.plugins.goauth; -public record OAuthUpdate(cz.bain.plugins.goauth.OAuthUpdate.UpdateType type, String username) { +import com.google.gson.annotations.SerializedName; + +public class OAuthUpdate { public enum UpdateType { - ADD, - REMOVE; + @SerializedName("update") + UPDATE, + @SerializedName("remove") + REMOVE + } + + UpdateType type; + String username; + + public UpdateType getType() { + return type; + } - public static UpdateType fromString(String type) { - return switch (type) { - case "add" -> UpdateType.ADD; - case "remove" -> UpdateType.REMOVE; - default -> null; - }; - } + public String getUsername() { + return username; } } diff --git a/src/main/java/cz/bain/plugins/goauth/StringRepository.java b/src/main/java/cz/bain/plugins/goauth/StringRepository.java @@ -2,7 +2,7 @@ package cz.bain.plugins.goauth; public class StringRepository { public static String authLinkText; - public static String limboRemoveDisconnect = "You have been added to the whitelist, please reconnect"; + public static String limboRemoveDisconnect = "Successfully authenticated, please reconnect"; public static String limboExpiredDisconnect = "Authentication period expired"; - public static String playerWhitelistKick = "You have been removed from the whitelist"; + public static String playerUnregisterKick = "You have been unregistered"; } diff --git a/src/main/java/cz/bain/plugins/goauth/WhitelistUpdateRunner.java b/src/main/java/cz/bain/plugins/goauth/WhitelistUpdateRunner.java @@ -1,128 +0,0 @@ -package cz.bain.plugins.goauth; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketTimeoutException; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; - -public class WhitelistUpdateRunner implements Runnable { - - private final SecretKeySpec key; - private final Goauth plugin; - - public WhitelistUpdateRunner(byte[] key, Goauth plugin) { - this.key = new SecretKeySpec(key, "ChaCha20"); - this.plugin = plugin; - } - - @Override - public void run() { - ServerSocket serverSocket; - try { - serverSocket = new ServerSocket(); - serverSocket.bind(new InetSocketAddress(Goauth.port), 2); - serverSocket.setSoTimeout(5); - - } catch (IOException e) { - Goauth.LOGGER.error("Failed to create socket for updates!"); - return; - } - while (this.plugin.running) { - try ( - Socket socket = serverSocket.accept(); - InputStream inputStream = socket.getInputStream(); - OutputStream outputStream = socket.getOutputStream() - ) { - // protecting ourselves from being bombarded with large amounts of data - byte[] sizeBytes = inputStream.readNBytes(4); - if (sizeBytes.length != 4) continue; - int size = fromByteArray(sizeBytes); - if (size > 2048 || size <= 0) { - outputStream.write(0x01); - outputStream.flush(); - Goauth.LOGGER.warn("Whitelist update rejected: payload size too big ({})", size); - continue; - } else { - outputStream.write(0x00); - outputStream.flush(); - } - byte[] iv = inputStream.readNBytes(12); - if (iv.length != 12) continue; - byte[] cipherText = inputStream.readNBytes(size); - if (cipherText.length != size) continue; - byte[] plainText; - try { - plainText = decryptMessage(cipherText, iv); - } catch (GeneralSecurityException e) { - Goauth.LOGGER.warn("Whitelist update rejected: failed to decrypt payload"); - outputStream.write(0x01); - outputStream.flush(); - continue; - } - JsonArray el = JsonParser.parseString(new String(plainText, StandardCharsets.UTF_8)).getAsJsonArray(); - Goauth.LOGGER.info("Got " + el.size() + " new whitelist updates"); - synchronized (this.plugin.completed) { - for (JsonElement user : el) { - JsonObject userObject = user.getAsJsonObject(); - String username = userObject.get("username").getAsString(); - OAuthUpdate.UpdateType type = OAuthUpdate.UpdateType.fromString(userObject.get("type").getAsString()); - if (type == null) { - Goauth.LOGGER.warn("Whitelist update rejected: bad update data (type={})", userObject.get("type").getAsString()); - outputStream.write(0x01); - outputStream.flush(); - break; - } - this.plugin.completed.add(new OAuthUpdate(type, username)); - outputStream.write(0x00); - } - } - } catch (SocketTimeoutException ignored) { - } catch (IOException | IllegalStateException e) { - Goauth.LOGGER.warn("Error while processing OAuth updates, dropping connection"); - e.printStackTrace(); - } - } - } - - /** - * Decrypts a message with the ChaCha20-Poly1305 cipher. - * - * @param cipherText cipher text with appended digest to the end - * @param iv unique nonce - * @return plain text - * @throws GeneralSecurityException when the decryption goes wrong - */ - private byte[] decryptMessage(byte[] cipherText, byte[] iv) throws GeneralSecurityException { - Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305"); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - cipher.init(Cipher.DECRYPT_MODE, this.key, ivSpec); - - return cipher.doFinal(cipherText); - } - - /** - * Little endian int from byte array - * - * @param bytes byte array - * @return int - */ - private int fromByteArray(byte[] bytes) { - return ((bytes[0] & 0xFF) << 24) | - ((bytes[1] & 0xFF) << 16) | - ((bytes[2] & 0xFF) << 8) | - (bytes[3] & 0xFF); - } -} diff --git a/src/main/java/cz/bain/plugins/goauth/events/callbacks/OnWhitelistAddCallback.java b/src/main/java/cz/bain/plugins/goauth/events/callbacks/OnWhitelistAddCallback.java @@ -1,26 +0,0 @@ -package cz.bain.plugins.goauth.events.callbacks; - -import com.mojang.authlib.GameProfile; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.util.ActionResult; - -import java.util.Collection; - -public interface OnWhitelistAddCallback { - Event<OnWhitelistAddCallback> EVENT = EventFactory.createArrayBacked(OnWhitelistAddCallback.class, - (listeners) -> (source, targets) -> { - for (OnWhitelistAddCallback listener : listeners) { - ActionResult result = listener.interact(source, targets); - - if (result != ActionResult.PASS) { - return result; - } - } - - return ActionResult.PASS; - }); - - ActionResult interact(ServerCommandSource source, Collection<GameProfile> targets); -} diff --git a/src/main/java/cz/bain/plugins/goauth/events/listeners/OnPlayerConnectListener.java b/src/main/java/cz/bain/plugins/goauth/events/listeners/OnPlayerConnectListener.java @@ -35,16 +35,17 @@ public class OnPlayerConnectListener implements OnPlayerConnectCallback { } /** - * Here we fake everything if the player is not on the whitelist. Just send him nothing and a link to authenticate. + * Here we fake everything if the player is not registered or connecting from a new ip. + * Just send him nothing and a link to authenticate. */ @Override public ActionResult interact(ServerPlayerEntity player, ClientConnection connection) { MinecraftServer server = Objects.requireNonNull(player.getServer()); // the player is in the whitelist, let the server do its things - if (server.getPlayerManager().getWhitelist().isAllowed(player.getGameProfile())) return ActionResult.PASS; + if (this.plugin.authStore.allowed(player, connection)) return ActionResult.PASS; - Goauth.LOGGER.info("Player " + player.getGameProfile().getName() + " is not on the whitelist, putting him in limbo"); + Goauth.LOGGER.info(player.getGameProfile().getName() + " is connecting from a new ip - putting him into limbo"); // fake initial connection info, use DummyServerPlayNetworkHandler to override all events and ignore them ServerPlayNetworkHandler serverPlayNetworkHandler = new DummyServerPlayNetworkHandler(server, connection, player, plugin); diff --git a/src/main/java/cz/bain/plugins/goauth/events/listeners/OnServerTickListener.java b/src/main/java/cz/bain/plugins/goauth/events/listeners/OnServerTickListener.java @@ -1,18 +1,15 @@ package cz.bain.plugins.goauth.events.listeners; -import com.mojang.authlib.GameProfile; import cz.bain.plugins.goauth.Goauth; import cz.bain.plugins.goauth.OAuthUpdate; import cz.bain.plugins.goauth.StringRepository; import cz.bain.plugins.goauth.events.callbacks.OnServerTickCallback; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.PlayerManager; -import net.minecraft.server.Whitelist; -import net.minecraft.server.WhitelistEntry; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; +@SuppressWarnings("ClassCanBeRecord") public class OnServerTickListener implements OnServerTickCallback { private final Goauth plugin; @@ -24,27 +21,25 @@ public class OnServerTickListener implements OnServerTickCallback { @Override public ActionResult interact(PlayerManager playerManager, long ticks) { if (ticks % 20 == 0) { - Whitelist wl = playerManager.getWhitelist(); synchronized (this.plugin.completed) { for (OAuthUpdate update : this.plugin.completed) { - switch (update.type()) { - case ADD -> { - GameProfile profile = new GameProfile(PlayerEntity.getOfflinePlayerUuid(update.username()), update.username()); - if (!wl.isAllowed(profile)) wl.add(new WhitelistEntry(profile)); - Goauth.LOGGER.info("Added " + update.username() + " to the whitelist"); - ServerPlayerEntity player = this.plugin.playersLimbo.get(update.username()); - if (player != null) { - player.networkHandler.disconnect( - Text.of(StringRepository.limboRemoveDisconnect) - ); + switch (update.getType()) { + case UPDATE -> { + ServerPlayerEntity player = this.plugin.playersLimbo.get(update.getUsername()); + if (player == null) { + Goauth.LOGGER.info("Cannot authenticate an offline player! {}", update.getUsername()); + continue; } + this.plugin.authStore.put(player); + player.networkHandler.disconnect(Text.of(StringRepository.limboRemoveDisconnect)); } case REMOVE -> { - GameProfile profile = new GameProfile(PlayerEntity.getOfflinePlayerUuid(update.username()), update.username()); - if (wl.isAllowed(profile)) wl.remove(profile); - Goauth.LOGGER.info("Removed " + update.username() + " from the whitelist"); - ServerPlayerEntity player = playerManager.getPlayer(update.username()); - if (player != null) player.networkHandler.disconnect(Text.of(StringRepository.playerWhitelistKick)); + if (this.plugin.authStore.remove(update.getUsername())) { + Goauth.LOGGER.info("Removed " + update.getUsername() + " from authentication db"); + ServerPlayerEntity player = playerManager.getPlayer(update.getUsername()); + if (player != null) + player.networkHandler.disconnect(Text.of(StringRepository.playerUnregisterKick)); + } } } } diff --git a/src/main/java/cz/bain/plugins/goauth/events/listeners/OnWhitelistAddListener.java b/src/main/java/cz/bain/plugins/goauth/events/listeners/OnWhitelistAddListener.java @@ -1,34 +0,0 @@ -package cz.bain.plugins.goauth.events.listeners; - -import com.mojang.authlib.GameProfile; -import cz.bain.plugins.goauth.Goauth; -import cz.bain.plugins.goauth.StringRepository; -import cz.bain.plugins.goauth.events.callbacks.OnWhitelistAddCallback; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; - -import java.util.Collection; - -public class OnWhitelistAddListener implements OnWhitelistAddCallback { - - private final Goauth plugin; - - public OnWhitelistAddListener(Goauth plugin) { - this.plugin = plugin; - } - - @Override - public ActionResult interact(ServerCommandSource source, Collection<GameProfile> targets) { - - for (GameProfile target : targets) { - ServerPlayerEntity player = this.plugin.playersLimbo.get(target.getName()); - if (player != null) { - player.networkHandler.disconnect(Text.of(StringRepository.limboRemoveDisconnect)); - } - } - - return ActionResult.PASS; - } -} diff --git a/src/main/java/cz/bain/plugins/goauth/mixin/UserCacheMixin.java b/src/main/java/cz/bain/plugins/goauth/mixin/UserCacheMixin.java @@ -1,37 +0,0 @@ -package cz.bain.plugins.goauth.mixin; - -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.GameProfileRepository; -import cz.bain.plugins.goauth.Goauth; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.UserCache; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Optional; - -@Mixin(UserCache.class) -public abstract class UserCacheMixin { - - @Shadow - private static boolean shouldUseRemote() { - return false; - } - - /** - * Override UUIDs when server is in offline mode - */ - @Inject(at = @At(value = "RETURN"), method = "findProfileByName", cancellable = true) - private static void findProfileByNameInject(GameProfileRepository repository, String name, CallbackInfoReturnable<Optional<GameProfile>> cir) { - if (!shouldUseRemote() && cir.getReturnValue().isPresent()) { - GameProfile profile = cir.getReturnValue().get(); - Goauth.LOGGER.info("changin uuid"); - cir.setReturnValue(Optional.of( - new GameProfile(PlayerEntity.getUuidFromProfile(new GameProfile(null, profile.getName())), profile.getName()) - )); - } - } -} diff --git a/src/main/java/cz/bain/plugins/goauth/mixin/WhitelistCommandMixin.java b/src/main/java/cz/bain/plugins/goauth/mixin/WhitelistCommandMixin.java @@ -1,23 +0,0 @@ -package cz.bain.plugins.goauth.mixin; - -import com.mojang.authlib.GameProfile; -import cz.bain.plugins.goauth.events.callbacks.OnWhitelistAddCallback; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.dedicated.command.WhitelistCommand; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Collection; - -@Mixin(WhitelistCommand.class) -public class WhitelistCommandMixin { - - @Inject(at = @At(value = "RETURN"), method = "executeAdd") - private static void executeAdd(ServerCommandSource source, Collection<GameProfile> targets, CallbackInfoReturnable<Integer> cir) { - if (cir.getReturnValue() == 1) { - OnWhitelistAddCallback.EVENT.invoker().interact(source, targets); - } - } -} diff --git a/src/main/resources/goauth.mixins.json b/src/main/resources/goauth.mixins.json @@ -7,9 +7,7 @@ "DimensionTypeAccessor", "MinecraftServerMixin", "OnPlayerConnectMixin", - "PlayerManagerAccessor", - "UserCacheMixin", - "WhitelistCommandMixin" + "PlayerManagerAccessor" ], "client": [ ],