diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/player/PlayerModule.java b/src/main/java/org/skriptlang/skript/bukkit/entity/player/PlayerModule.java index 938a676b539..40f302215a5 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/entity/player/PlayerModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/player/PlayerModule.java @@ -1,22 +1,37 @@ package org.skriptlang.skript.bukkit.entity.player; import ch.njol.skript.Skript; +import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.lang.util.SimpleEvent; +import ch.njol.skript.registrations.Classes; +import com.destroystokyo.paper.profile.PlayerProfile; +import io.papermc.paper.connection.PlayerLoginConnection; import io.papermc.paper.event.player.AsyncChatEvent; import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; -import org.skriptlang.skript.bukkit.entity.player.elements.events.*; +import org.skriptlang.skript.bukkit.entity.player.elements.events.EvtPlayerLogin; +import org.skriptlang.skript.bukkit.entity.player.elements.events.EvtPlayerPickItem; import org.skriptlang.skript.bukkit.entity.player.elements.expressions.*; import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.lang.properties.Property; +import org.skriptlang.skript.lang.properties.handlers.base.ExpressionPropertyHandler; import org.skriptlang.skript.registration.SyntaxRegistry; +/** + * @noinspection UnstableApiUsage + */ public class PlayerModule extends HierarchicalAddonModule { public PlayerModule(AddonModule parentModule) { super(parentModule); } + @Override + protected void initSelf(SkriptAddon addon) { + registerConnectionTypes(addon); + } + @Override protected void loadSelf(SkriptAddon addon) { register(addon, @@ -28,7 +43,9 @@ protected void loadSelf(SkriptAddon addon) { ExprOnScreenKickMessage::register, ExprPlayerListHeaderFooter::register, ExprPlayerListName::register, - ExprQuitMessage::register + ExprQuitMessage::register, + + EvtPlayerLogin::register ); if (Skript.classExists("io.papermc.paper.event.player.PlayerPickBlockEvent")) { register(addon, @@ -62,4 +79,26 @@ public String name() { return "player"; } + private void registerConnectionTypes(SkriptAddon addon) { + Classes.registerClass(new ClassInfo<>(PlayerLoginConnection.class, "playerloginconnection") + .user("player ?login ?connections?") + .name("Player Login Connection") + .description("Represents a player's connection during the login process. This will have the player's IP address, UUID, and name.") + .since("INSERT VERSION") + .property(Property.NAME, + "The username of the player trying to log in.", + addon, + ExpressionPropertyHandler.of(connection -> { + PlayerProfile profile = connection.getAuthenticatedProfile(); + if (profile != null) + return profile.getName(); + profile = connection.getUnsafeProfile(); + if (profile != null) + return profile.getName(); + return null; + }, String.class)) + .property(Property.) + ); + } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/player/elements/events/EvtPlayerLogin.java b/src/main/java/org/skriptlang/skript/bukkit/entity/player/elements/events/EvtPlayerLogin.java new file mode 100644 index 00000000000..9d902e9f4fb --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/player/elements/events/EvtPlayerLogin.java @@ -0,0 +1,84 @@ +package org.skriptlang.skript.bukkit.entity.player.elements.events; + +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import io.papermc.paper.connection.PlayerConfigurationConnection; +import io.papermc.paper.connection.PlayerLoginConnection; +import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent; +import org.bukkit.event.Event; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; +import org.skriptlang.skript.registration.SyntaxRegistry; + +@SuppressWarnings("UnstableApiUsage") +public class EvtPlayerLogin extends SkriptEvent { + // on connection/player init: - when connection is PaperPlayerLoginConnection + // on connection/player configuration: - when connection is PaperPlayerConfigurationConnection + + public static void register(@NotNull SyntaxRegistry registry) { + registry.register( + BukkitSyntaxInfos.Event.KEY, + BukkitSyntaxInfos.Event.builder(EvtPlayerLogin.class, "Player Login") + .addEvent(PlayerConnectionValidateLoginEvent.class) + .addPatterns( + "player [connection] beginning login", // this pattern sucks + "player [connection] [finishing|completing] login" + ) + .addDescription(""" + Called when a player initially connects to a server. + At the beginning stage, the player information may or may not be available. Only the IP address is guaranteed. + At the finishing stage, player information is available and things like dialogs may be sent to the user. + Neither stage has a player object yet, just the player profile. If you need the player + """) + .addExample(""" + on player beginning login: + if {banned_ips::*} contains connection's ip: + refuse the connection due to "Your IP is banned!" + """) + .addExample(""" + on player finishing login: + if connection's name is "Jeb": + send "Welcome back, Jeb!" to connection + """) + .addSince("INSERT VERSION") + .build()); + } + + private enum ConnectStage { + BEGINNING, + FINISHING + } + + private ConnectStage stage; + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + stage = switch (matchedPattern) { + case 0 -> ConnectStage.BEGINNING; + case 1 -> ConnectStage.FINISHING; + default -> throw new IllegalStateException("Unexpected pattern index: " + matchedPattern); + }; + return true; + } + + @Override + public boolean check(Event event) { + if (!(event instanceof PlayerConnectionValidateLoginEvent loginEvent)) + return false; + return switch (stage) { + case BEGINNING -> loginEvent.getConnection() instanceof PlayerLoginConnection; + case FINISHING -> loginEvent.getConnection() instanceof PlayerConfigurationConnection; + }; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return switch (stage) { + case BEGINNING -> "player beginning login"; + case FINISHING -> "player finishing login"; + }; + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/entity/player/elements/expressions/ExprPlayerConnection.java b/src/main/java/org/skriptlang/skript/bukkit/entity/player/elements/expressions/ExprPlayerConnection.java new file mode 100644 index 00000000000..40fc6caac21 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/entity/player/elements/expressions/ExprPlayerConnection.java @@ -0,0 +1,4 @@ +package org.skriptlang.skript.bukkit.entity.player.elements.expressions; + +public class ExprPlayerConnection { +}