├── .gitignore
├── .idea
└── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── LICENSE
├── bukkit
├── api
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── java
│ │ └── nz
│ │ └── pactifylauncher
│ │ └── plugin
│ │ └── bukkit
│ │ └── api
│ │ ├── PactifyAPI.java
│ │ └── player
│ │ ├── PactifyPlayer.java
│ │ └── PlayersService.java
└── plugin
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── nz
│ │ └── pactifylauncher
│ │ └── plugin
│ │ └── bukkit
│ │ ├── PLSPMessenger.java
│ │ ├── PactifyPlugin.java
│ │ ├── command
│ │ ├── CheckCommand.java
│ │ ├── ListCommand.java
│ │ └── StatsCommand.java
│ │ ├── conf
│ │ ├── Conf.java
│ │ └── YamlConfProvider.java
│ │ ├── player
│ │ ├── PPactifyPlayer.java
│ │ └── PPlayersService.java
│ │ └── util
│ │ ├── BukkitUtil.java
│ │ ├── PacketOutBuffer.java
│ │ └── SchedulerUtil.java
│ └── resources
│ └── plugin.yml
├── bungee
└── plugin
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── nz
│ │ └── pactifylauncher
│ │ └── plugin
│ │ └── bungee
│ │ ├── HandshakeFix.java
│ │ └── PactifyPlugin.java
│ └── resources
│ └── bungee.yml
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Maven template
2 | target/
3 | pom.xml.tag
4 | pom.xml.releaseBackup
5 | pom.xml.versionsBackup
6 | pom.xml.next
7 | release.properties
8 | dependency-reduced-pom.xml
9 | buildNumber.properties
10 | .mvn/timing.properties
11 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
12 | .mvn/wrapper/maven-wrapper.jar
13 |
14 | ### JetBrains template
15 | *.iml
16 | .idea/*
17 | !.idea/codeStyles
18 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/bukkit/api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.github.pactifylauncherexamples
8 | pactify-plugin
9 | 1.0-SNAPSHOT
10 | ../../pom.xml
11 |
12 | pactify-plugin-bukkit-api
13 |
14 |
15 | ../
16 |
17 |
18 |
19 |
20 | org.spigotmc
21 | spigot-api
22 | 1.8.8-R0.1-SNAPSHOT
23 | provided
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/bukkit/api/src/main/java/nz/pactifylauncher/plugin/bukkit/api/PactifyAPI.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.api;
2 |
3 | import lombok.experimental.UtilityClass;
4 | import nz.pactifylauncher.plugin.bukkit.api.player.PlayersService;
5 |
6 | /**
7 | * Pactify Launcher API for Bukkit.
8 | */
9 | @UtilityClass
10 | public class PactifyAPI {
11 | private static Impl implementation;
12 |
13 | /**
14 | * @deprecated You certainly don't want to use this method.
15 | */
16 | @Deprecated
17 | public static void setImplementation(Impl implementation) {
18 | PactifyAPI.implementation = implementation;
19 | }
20 |
21 | /**
22 | * Returns the {@linkplain PlayersService players service}; containing players-related API methods.
23 | *
24 | * @return Returns the {@linkplain PlayersService players service}
25 | */
26 | public static PlayersService players() {
27 | return implementation.getPlayersService();
28 | }
29 |
30 | public interface Impl {
31 | PlayersService getPlayersService();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/bukkit/api/src/main/java/nz/pactifylauncher/plugin/bukkit/api/player/PactifyPlayer.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.api.player;
2 |
3 | import org.bukkit.entity.Player;
4 |
5 | /**
6 | * Class which represents a {@link Player} with the additional Pactify Plugin methods!
7 | */
8 | public interface PactifyPlayer {
9 | /**
10 | * Returns the {@linkplain Player Bukkit Player} (cannot be null).
11 | *
12 | * @return the {@linkplain Player Bukkit Player}
13 | */
14 | Player getPlayer();
15 |
16 | /**
17 | * Check whether this player is using the Pactify Launcher.
18 | *
19 | * @return {@code true} if this player uses the Pactify Launcher; {@code false} otherwise
20 | */
21 | boolean hasLauncher();
22 |
23 | /**
24 | * Returns the used Pactify Launcher protocol version.
25 | *
26 | * @return the protocol version; or zero if this player does not use the Pactify Launcher
27 | */
28 | int getLauncherProtocolVersion();
29 | }
30 |
--------------------------------------------------------------------------------
/bukkit/api/src/main/java/nz/pactifylauncher/plugin/bukkit/api/player/PlayersService.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.api.player;
2 |
3 | import org.bukkit.entity.Player;
4 | import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
5 | import org.bukkit.event.player.PlayerLoginEvent;
6 |
7 | import java.util.UUID;
8 |
9 | /**
10 | * Note: All of these players-related methods only work from the {@link PlayerLoginEvent} (after the LOWEST priority).
11 | * So don't try to call them during the {@link AsyncPlayerPreLoginEvent}!
12 | */
13 | public interface PlayersService {
14 | /**
15 | * Returns the {@link PactifyPlayer} related to a player.
16 | *
17 | * @param playerUid UUID of the player
18 | * @return the {@link PactifyPlayer} related to the player online with this UUID; or {@code null} if no player is
19 | * online with this UUID
20 | */
21 | PactifyPlayer getPlayer(UUID playerUid);
22 |
23 | /**
24 | * Returns the {@link PactifyPlayer} related to a player.
25 | *
26 | * @param player player
27 | * @return the {@link PactifyPlayer} related to this player; or {@code null} if this player is not online
28 | */
29 | PactifyPlayer getPlayer(Player player);
30 |
31 | /**
32 | * Check whether a player is using the Pactify launcher.
33 | *
34 | * @param playerUid UUID of the player to check
35 | * @return {@code true} if a player is online with this UUID and uses the Pactify Launcher; {@code false} otherwise
36 | */
37 | boolean hasLauncher(UUID playerUid);
38 |
39 | /**
40 | * Check whether a player is using the Pactify launcher.
41 | *
42 | * @param player player to check
43 | * @return {@code true} if the player is online and uses the Pactify Launcher; {@code false} otherwise
44 | */
45 | boolean hasLauncher(Player player);
46 | }
47 |
--------------------------------------------------------------------------------
/bukkit/plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.github.pactifylauncherexamples
8 | pactify-plugin
9 | 1.0-SNAPSHOT
10 | ../../pom.xml
11 |
12 | pactify-plugin-bukkit
13 |
14 |
15 | ../../
16 |
17 |
18 |
19 |
20 | ${project.groupId}
21 | pactify-plugin-bukkit-api
22 | ${project.version}
23 | compile
24 |
25 |
26 | pactify.client.api
27 | plsp-protocol
28 | 20200201
29 | compile
30 |
31 |
32 | org.spigotmc
33 | spigot-api
34 | 1.8.8-R0.1-SNAPSHOT
35 | provided
36 |
37 |
38 |
39 |
40 | PactifyPlugin-Bukkit-${project.version}
41 |
42 |
43 |
44 | org.apache.maven.plugins
45 | maven-shade-plugin
46 |
47 |
48 | package
49 |
50 | shade
51 |
52 |
53 |
54 |
55 | *:*
56 |
57 | META-INF/*.SF
58 | META-INF/*.DSA
59 | META-INF/*.RSA
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | true
72 | src/main/resources
73 |
74 | plugin.yml
75 |
76 |
77 |
78 | src/main/resources
79 |
80 | **
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/PLSPMessenger.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import nz.pactifylauncher.plugin.bukkit.util.PacketOutBuffer;
5 | import org.bukkit.entity.Player;
6 | import pactify.client.api.mcprotocol.util.NotchianPacketUtil;
7 | import pactify.client.api.plsp.PLSPPacket;
8 | import pactify.client.api.plsp.PLSPPacketHandler;
9 | import pactify.client.api.plsp.PLSPProtocol;
10 |
11 | import java.util.logging.Level;
12 |
13 | @RequiredArgsConstructor
14 | public class PLSPMessenger {
15 | private static final String PLSP_CHANNEL = "PLSP";
16 |
17 | private final PactifyPlugin plugin;
18 |
19 | public void enable() {
20 | plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, PLSP_CHANNEL);
21 | }
22 |
23 | public void disable() {
24 | plugin.getServer().getMessenger().unregisterOutgoingPluginChannel(plugin, PLSP_CHANNEL);
25 | }
26 |
27 | public void sendPLSPMessage(Player player, PLSPPacket message) {
28 | try {
29 | PacketOutBuffer buf = new PacketOutBuffer();
30 | PLSPProtocol.PacketData> packetData = PLSPProtocol.getClientPacketByClass(message.getClass());
31 | NotchianPacketUtil.writeString(buf, packetData.getId(), Short.MAX_VALUE);
32 | message.write(buf);
33 | player.sendPluginMessage(plugin, PLSP_CHANNEL, buf.toBytes());
34 | } catch (Exception e) {
35 | plugin.getLogger().log(Level.WARNING, "Exception sending PLSP message to "
36 | + (player != null ? player.getName() : "null") + ":", e);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/PactifyPlugin.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit;
2 |
3 | import lombok.Getter;
4 | import nz.pactifylauncher.plugin.bukkit.api.PactifyAPI;
5 | import nz.pactifylauncher.plugin.bukkit.command.CheckCommand;
6 | import nz.pactifylauncher.plugin.bukkit.command.ListCommand;
7 | import nz.pactifylauncher.plugin.bukkit.command.StatsCommand;
8 | import nz.pactifylauncher.plugin.bukkit.conf.Conf;
9 | import nz.pactifylauncher.plugin.bukkit.conf.YamlConfProvider;
10 | import nz.pactifylauncher.plugin.bukkit.player.PPlayersService;
11 | import nz.pactifylauncher.plugin.bukkit.util.BukkitUtil;
12 | import org.bukkit.plugin.java.JavaPlugin;
13 |
14 | public class PactifyPlugin extends JavaPlugin implements PactifyAPI.Impl {
15 | private @Getter Conf conf;
16 | private final @Getter PLSPMessenger plspMessenger = new PLSPMessenger(this);
17 | private final @Getter PPlayersService playersService = new PPlayersService(this);
18 | private @Getter int serverVersion;
19 |
20 | @Override
21 | public void onLoad() {
22 | // Initialize unsafe utilities (those with reflection)
23 | try {
24 | Class.forName(BukkitUtil.class.getName(), true, getClass().getClassLoader());
25 | } catch (ClassNotFoundException e) {
26 | throw new RuntimeException(e);
27 | }
28 |
29 | // Read configuration
30 | serverVersion = BukkitUtil.findServerVersion();
31 | conf = YamlConfProvider.load(this);
32 | // TODO: Dump configuration values?
33 |
34 | PactifyAPI.setImplementation(this);
35 | }
36 |
37 | @Override
38 | public void onEnable() {
39 | plspMessenger.enable();
40 | playersService.enable();
41 | registerCommands();
42 | getLogger().info("Enabled!");
43 | }
44 |
45 | @Override
46 | public void onDisable() {
47 | playersService.disable();
48 | plspMessenger.disable();
49 | getLogger().info("Disabled!");
50 | }
51 |
52 | private void registerCommands() {
53 | getCommand("pactifycheck").setExecutor(new CheckCommand(this));
54 | getCommand("pactifylist").setExecutor(new ListCommand(this));
55 | getCommand("pactifystats").setExecutor(new StatsCommand(this));
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/command/CheckCommand.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.command;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import nz.pactifylauncher.plugin.bukkit.PactifyPlugin;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 | import org.bukkit.entity.Player;
10 |
11 | import java.util.UUID;
12 |
13 | @RequiredArgsConstructor
14 | public class CheckCommand implements CommandExecutor {
15 | private final PactifyPlugin plugin;
16 |
17 | @Override
18 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
19 | if (args.length == 0) {
20 | sender.sendMessage(ChatColor.RED + "Usage: /pacheck ");
21 | return true;
22 | }
23 |
24 | Player player;
25 | try {
26 | player = plugin.getServer().getPlayer(UUID.fromString(args[0]));
27 | } catch (IllegalArgumentException ignored) {
28 | player = plugin.getServer().getPlayer(args[0]);
29 | }
30 | if (player == null) {
31 | sender.sendMessage(ChatColor.RED + "Player " + args[0] + " is not online");
32 | return true;
33 | }
34 |
35 | sender.sendMessage(ChatColor.YELLOW + "Player " + player.getName() + " is "
36 | + (plugin.getPlayersService().hasLauncher(player) ? ChatColor.GREEN + "using" : ChatColor.RED + "not using")
37 | + ChatColor.YELLOW + " the Pactify Launcher");
38 | return true;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/command/ListCommand.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.command;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import nz.pactifylauncher.plugin.bukkit.PactifyPlugin;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 | import org.bukkit.entity.Player;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | @RequiredArgsConstructor
15 | public class ListCommand implements CommandExecutor {
16 | private final PactifyPlugin plugin;
17 |
18 | @Override
19 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
20 | List pactifyList = new ArrayList<>();
21 | List vanillaList = new ArrayList<>();
22 | for (Player player : plugin.getServer().getOnlinePlayers()) {
23 | if (plugin.getPlayersService().hasLauncher(player)) {
24 | pactifyList.add(player.getName());
25 | } else {
26 | vanillaList.add(player.getName());
27 | }
28 | }
29 | pactifyList.sort(String::compareToIgnoreCase);
30 | vanillaList.sort(String::compareToIgnoreCase);
31 |
32 | sender.sendMessage(ChatColor.YELLOW + "Players using the Pactify Launcher: "
33 | + (pactifyList.isEmpty() ? ChatColor.GRAY + "(none)" : ChatColor.GREEN + String.join(", ", pactifyList)));
34 | sender.sendMessage(ChatColor.YELLOW + "Players not using the Pactify Launcher: "
35 | + (vanillaList.isEmpty() ? ChatColor.GRAY + "(none)" : ChatColor.RED + String.join(", ", vanillaList)));
36 | return true;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/command/StatsCommand.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.command;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import nz.pactifylauncher.plugin.bukkit.PactifyPlugin;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 | import org.bukkit.entity.Player;
10 |
11 | @RequiredArgsConstructor
12 | public class StatsCommand implements CommandExecutor {
13 | private final PactifyPlugin plugin;
14 |
15 | @Override
16 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
17 | int onlineCnt = 0;
18 | int pactifyCnt = 0;
19 | for (Player player : plugin.getServer().getOnlinePlayers()) {
20 | ++onlineCnt;
21 | if (plugin.getPlayersService().hasLauncher(player)) {
22 | ++pactifyCnt;
23 | }
24 | }
25 |
26 | sender.sendMessage(ChatColor.YELLOW + "Players using the Pactify Launcher: "
27 | + ChatColor.GREEN + pactifyCnt + ChatColor.YELLOW + "/" + onlineCnt);
28 | return true;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/conf/Conf.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.conf;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.Singular;
7 |
8 | import java.util.List;
9 |
10 | @lombok.Builder(builderClassName = "Builder")
11 | @Data
12 | public class Conf {
13 | private JoinActions loginWithPactify;
14 | private JoinActions loginWithoutPactify;
15 |
16 | @lombok.Builder(builderClassName = "Builder")
17 | @Data
18 | public static class JoinActions {
19 | private @Singular("message") List messages;
20 | private @Singular("command") List commands;
21 | }
22 |
23 | @RequiredArgsConstructor
24 | @Data
25 | public static class Action {
26 | private final @NonNull String value;
27 | private final int delay;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bukkit/plugin/src/main/java/nz/pactifylauncher/plugin/bukkit/conf/YamlConfProvider.java:
--------------------------------------------------------------------------------
1 | package nz.pactifylauncher.plugin.bukkit.conf;
2 |
3 | import com.google.common.collect.ImmutableMap;
4 | import lombok.AccessLevel;
5 | import lombok.RequiredArgsConstructor;
6 | import nz.pactifylauncher.plugin.bukkit.PactifyPlugin;
7 | import org.bukkit.ChatColor;
8 | import org.yaml.snakeyaml.DumperOptions;
9 | import org.yaml.snakeyaml.Yaml;
10 | import org.yaml.snakeyaml.constructor.SafeConstructor;
11 | import org.yaml.snakeyaml.nodes.Node;
12 | import org.yaml.snakeyaml.representer.BaseRepresenter;
13 | import org.yaml.snakeyaml.representer.Representer;
14 |
15 | import java.io.*;
16 | import java.lang.reflect.Field;
17 | import java.lang.reflect.Modifier;
18 | import java.nio.charset.StandardCharsets;
19 | import java.util.*;
20 | import java.util.function.Function;
21 | import java.util.logging.Level;
22 | import java.util.stream.Collectors;
23 |
24 | @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
25 | public class YamlConfProvider {
26 | private static final ThreadLocal YAML = ThreadLocal.withInitial(() -> {
27 | DumperOptions options = new DumperOptions();
28 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
29 | options.setPrettyFlow(false);
30 | options.setIndent(2);
31 | return new Yaml(new SafeConstructor(), new NoAnchorRepresenter(), options);
32 | });
33 |
34 | private static final String HEADER = "# This is the main configuration file for the Pactify Plugin on Bukkit.\n"
35 | + "# For a reference for any variable inside this file, check out the Pactify Plugin\n"
36 | + "# README: https://github.com/PactifyLauncherExamples/PactifyPlugin\n\n";
37 |
38 | public static Conf load(PactifyPlugin plugin) {
39 | return new YamlConfProvider(plugin, new File(plugin.getDataFolder(), "config.yml")).loadConfig();
40 | }
41 |
42 | private final PactifyPlugin plugin;
43 | private final File file;
44 | private final Map root = new LinkedHashMap<>();
45 |
46 | private Conf loadConfig() {
47 | readValues();
48 | Conf conf = Conf.builder()
49 | .loginWithPactify(getJoinActions("join.with-pactify",
50 | Collections.singletonList(ImmutableMap.of("delay", 0, "value", "&eYou are connected with the &cPactify Launcher&e!")),
51 | Collections.singletonList(ImmutableMap.of("delay", 20, "value", "/minecraft:effect {{name}} speed 15"))))
52 | .loginWithoutPactify(getJoinActions("join.without-pactify",
53 | Collections.emptyList(),
54 | Collections.emptyList()))
55 | .build();
56 | writeValues();
57 | return conf;
58 | }
59 |
60 | private Conf.JoinActions getJoinActions(String path, List