mirror of
https://github.com/ArthurDanjou/ArtTemplateMC.git
synced 2026-01-18 14:07:57 +01:00
Initial commit 🚀
This commit is contained in:
80
src/main/java/fr/arthurdanjou/template/Main.java
Normal file
80
src/main/java/fr/arthurdanjou/template/Main.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package fr.arthurdanjou.template;
|
||||
|
||||
import fr.arthurdanjou.template.game.Game;
|
||||
import fr.arthurdanjou.template.team.TeamManager;
|
||||
import fr.arthurdanjou.template.config.settings.Settings;
|
||||
import fr.arthurdanjou.template.listeners.PlayerListeners;
|
||||
import fr.arthurdanjou.template.listeners.ServerListeners;
|
||||
import fr.arthurdanjou.template.listeners.WorldListeners;
|
||||
import fr.arthurdanjou.template.config.FileManager;
|
||||
import fr.arthurdanjou.template.config.ConfigFiles;
|
||||
import fr.arthurdanjou.template.game.GameState;
|
||||
import fr.arthurdanjou.template.users.UserManager;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@Getter
|
||||
public class Main extends JavaPlugin {
|
||||
|
||||
@Getter
|
||||
private static Main instance;
|
||||
|
||||
private Game game;
|
||||
private FileManager fileManager;
|
||||
private TeamManager teamManager;
|
||||
private UserManager userManager;
|
||||
private Settings settings;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
this.getLogger().info("+------[ PROJET ]------+");
|
||||
this.getLogger().info("Initialisation en cours...");
|
||||
|
||||
this.fileManager = new FileManager(this, getClassLoader());
|
||||
this.teamManager = new TeamManager();
|
||||
this.userManager = new UserManager();
|
||||
this.fileManager.saveResourceAs(ConfigFiles.CONFIG.getFileName(), ConfigFiles.CONFIG.getFileName());
|
||||
|
||||
this.settings = this.fileManager.getSettings();
|
||||
|
||||
this.game = new Game(this);
|
||||
|
||||
this.registerCommands();
|
||||
this.registerListeners();
|
||||
|
||||
GameState.setState(GameState.LOBBY);
|
||||
|
||||
Bukkit.getWorlds().forEach(world -> {
|
||||
world.setDifficulty(Difficulty.PEACEFUL);
|
||||
world.setPVP(false);
|
||||
world.setTime(6000L);
|
||||
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
|
||||
world.setGameRule(GameRule.MOB_GRIEFING, false);
|
||||
world.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
|
||||
});
|
||||
|
||||
this.getLogger().info("+----------------------+");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
pluginManager.registerEvents(new PlayerListeners(this), this);
|
||||
pluginManager.registerEvents(new WorldListeners(this), this);
|
||||
pluginManager.registerEvents(new ServerListeners(this), this);
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package fr.arthurdanjou.template.config;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@AllArgsConstructor @Getter
|
||||
public enum ConfigFiles {
|
||||
|
||||
CONFIG("config.yml"),
|
||||
LANG("lang.yml"),
|
||||
|
||||
;
|
||||
|
||||
private final String fileName;
|
||||
|
||||
public File getDataFolder() {
|
||||
return Main.getInstance().getDataFolder();
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return new File(getDataFolder(), getFileName());
|
||||
}
|
||||
|
||||
public FileConfiguration getConfiguration() {
|
||||
return YamlConfiguration.loadConfiguration(getFile());
|
||||
}
|
||||
|
||||
public void save(FileConfiguration configuration) {
|
||||
try {
|
||||
configuration.save(getFile());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package fr.arthurdanjou.template.config;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import fr.arthurdanjou.template.config.settings.Settings;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor;
|
||||
import org.yaml.snakeyaml.introspector.BeanAccess;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class FileManager {
|
||||
|
||||
private final Main main;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public void saveResourceAs(String resource, String output) {
|
||||
if (resource == null || resource.isEmpty()) {
|
||||
throw new IllegalArgumentException("La ressource ne peut pas etre nulle !");
|
||||
}
|
||||
InputStream inputStream = main.getResource(resource);
|
||||
|
||||
if (inputStream == null) {
|
||||
throw new IllegalArgumentException("La ressource " + resource + " n'est pas presente dans le dossier !");
|
||||
}
|
||||
|
||||
if (!main.getDataFolder().exists() && !main.getDataFolder().mkdir()) {
|
||||
main.getLogger().severe("Permission insuffisante pour creer le dossier");
|
||||
}
|
||||
|
||||
File outputFile = new File(main.getDataFolder(), output);
|
||||
|
||||
try {
|
||||
if (!outputFile.exists()) {
|
||||
main.getLogger().info("La ressource est introuvable, creation en cours !");
|
||||
OutputStream outputStream = new FileOutputStream(outputFile);
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int n;
|
||||
while ((n = inputStream.read(buf)) >= 0) {
|
||||
outputStream.write(buf, 0, n);
|
||||
}
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
|
||||
if (!outputFile.exists()) {
|
||||
main.getLogger().severe("Impossible de creer le fichier !");
|
||||
}
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
Settings settings = null;
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(ConfigFiles.CONFIG.getFile().toPath(), StandardCharsets.UTF_8)) {
|
||||
Yaml yaml = new Yaml(new CustomClassLoaderConstructor(this.getClassLoader()));
|
||||
yaml.setBeanAccess(BeanAccess.FIELD);
|
||||
|
||||
settings = yaml.loadAs(reader, Settings.class);
|
||||
main.getLogger().info("Le fichier de configuration a ete lu correctement !");
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
}
|
||||
53
src/main/java/fr/arthurdanjou/template/config/lang/Lang.java
Normal file
53
src/main/java/fr/arthurdanjou/template/config/lang/Lang.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package fr.arthurdanjou.template.config.lang;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import fr.arthurdanjou.template.config.ConfigFiles;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum Lang {
|
||||
|
||||
PREFIX,
|
||||
|
||||
MOTD_LOBBY,
|
||||
MOTD_GAME,
|
||||
|
||||
GAME_START_COUNTDOWN,
|
||||
GAME_STOP_COUNTDOWN,
|
||||
;
|
||||
|
||||
@Getter
|
||||
private static final Map<Lang, String> VALUES = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Lang lang : values()) {
|
||||
VALUES.put(lang, lang.getFromFile());
|
||||
}
|
||||
Main.getInstance().getLogger().info("Lecture du fichier de langues !");
|
||||
}
|
||||
|
||||
public String get() {
|
||||
return VALUES.get(this);
|
||||
}
|
||||
|
||||
public static String getPrefix() {
|
||||
return PREFIX.get() + ChatColor.RESET + " ";
|
||||
}
|
||||
|
||||
private String getFromFile() {
|
||||
FileConfiguration configuration = ConfigFiles.LANG.getConfiguration();
|
||||
String key = name().toLowerCase().replace('_', '-');
|
||||
String value = configuration.getString(key);
|
||||
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
return ChatColor.translateAlternateColorCodes('&', value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package fr.arthurdanjou.template.config.lang;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
public enum PlaceHolders {
|
||||
|
||||
PLAYER("player"),
|
||||
SLOTS("slots"),
|
||||
COUNTDOWN("countdown"),
|
||||
|
||||
;
|
||||
|
||||
private final String placeholder;
|
||||
|
||||
public String getPlaceholder() {
|
||||
return "{" + placeholder + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package fr.arthurdanjou.template.config.settings;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter @Setter
|
||||
public class LocationConfig {
|
||||
|
||||
public final String world;
|
||||
public final double x, y, z;
|
||||
public final float yaw, pitch;
|
||||
|
||||
public Location toBukkitLocation() {
|
||||
return new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package fr.arthurdanjou.template.config.settings;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
|
||||
@Getter @Setter
|
||||
public class Settings {
|
||||
|
||||
public int slots;
|
||||
public boolean spectator;
|
||||
public LocationConfig spawnLocation;
|
||||
public int minimumPlayers;
|
||||
|
||||
public Location getSpawnLocation() {
|
||||
return spawnLocation.toBukkitLocation();
|
||||
}
|
||||
|
||||
}
|
||||
51
src/main/java/fr/arthurdanjou/template/game/Game.java
Normal file
51
src/main/java/fr/arthurdanjou/template/game/Game.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package fr.arthurdanjou.template.game;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@Getter
|
||||
public class Game {
|
||||
|
||||
private final Main main;
|
||||
|
||||
private StartRunnable startRunnable;
|
||||
private GameRunnable gameRunnable;
|
||||
|
||||
public Game(Main main) {
|
||||
this.main = main;
|
||||
this.startRunnable = new StartRunnable(this);
|
||||
this.gameRunnable = new GameRunnable();
|
||||
}
|
||||
|
||||
public void startCountDown() {
|
||||
this.startRunnable.runTaskTimer(main, 0, 20);
|
||||
this.startRunnable.setStarting(true);
|
||||
}
|
||||
|
||||
public void stopCountDown() {
|
||||
if (this.startRunnable.getCountdown() > 0) {
|
||||
this.startRunnable.cancel();
|
||||
this.startRunnable = new StartRunnable(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void startGame() {
|
||||
|
||||
}
|
||||
|
||||
public void checkWin() {
|
||||
|
||||
}
|
||||
|
||||
public void end() {
|
||||
|
||||
}
|
||||
|
||||
public void checkStart() {
|
||||
if (main.getTeamManager().areAllInTeam() && main.getSettings().getMinimumPlayers() <= Bukkit.getOnlinePlayers().size()) {
|
||||
this.startCountDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package fr.arthurdanjou.template.game;
|
||||
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class GameRunnable extends BukkitRunnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
}
|
||||
29
src/main/java/fr/arthurdanjou/template/game/GameState.java
Normal file
29
src/main/java/fr/arthurdanjou/template/game/GameState.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package fr.arthurdanjou.template.game;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public enum GameState {
|
||||
|
||||
LOBBY,
|
||||
GAME,
|
||||
END,
|
||||
;
|
||||
|
||||
public boolean isGame() {
|
||||
return this == GAME;
|
||||
}
|
||||
|
||||
public boolean isNotGame() {
|
||||
return this == LOBBY || this == END;
|
||||
}
|
||||
|
||||
@Getter @Setter
|
||||
private static GameState state;
|
||||
|
||||
public static boolean isState(GameState... states) {
|
||||
return Arrays.stream(states).anyMatch(gameState -> gameState == state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package fr.arthurdanjou.template.game;
|
||||
|
||||
import fr.arthurdanjou.template.config.lang.Lang;
|
||||
import fr.arthurdanjou.template.config.lang.PlaceHolders;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class StartRunnable extends BukkitRunnable {
|
||||
|
||||
private final Game game;
|
||||
@Getter @Setter
|
||||
private boolean starting;
|
||||
@Getter @Setter
|
||||
private int countdown;
|
||||
|
||||
public StartRunnable(Game game) {
|
||||
this.game = game;
|
||||
this.starting = false;
|
||||
this.countdown = 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.countdown == 30 || this.countdown == 20 || (this.countdown <= 5 && this.countdown >= 1)) {
|
||||
Bukkit.broadcastMessage(
|
||||
Lang.getPrefix() +
|
||||
Lang.GAME_START_COUNTDOWN.get()
|
||||
.replace(PlaceHolders.COUNTDOWN.getPlaceholder(), Integer.toString(this.countdown))
|
||||
);
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_HARP, 1f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.countdown == 0) {
|
||||
cancel();
|
||||
}
|
||||
|
||||
this.countdown--;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package fr.arthurdanjou.template.listeners;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import fr.arthurdanjou.template.game.GameState;
|
||||
import fr.arthurdanjou.template.team.TeamUnit;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerPickupArrowEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
@AllArgsConstructor @Getter
|
||||
public class PlayerListeners implements Listener {
|
||||
|
||||
private final Main main;
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (GameState.isState(GameState.LOBBY)) {
|
||||
preparePlayer(player, false);
|
||||
main.getTeamManager().joinTeam(player, TeamUnit.NONE);
|
||||
main.getUserManager().onLogin(player);
|
||||
main.getGame().checkStart();
|
||||
} else {
|
||||
preparePlayer(player, true);
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BELL, 1f, 1f);
|
||||
main.getTeamManager().joinTeam(player, TeamUnit.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void preparePlayer(Player player, boolean started) {
|
||||
player.setFoodLevel(20);
|
||||
player.setHealth(20);
|
||||
player.setGameMode(started ? GameMode.SPECTATOR : GameMode.ADVENTURE);
|
||||
player.getInventory().clear();
|
||||
player.setExp(0);
|
||||
player.setLevel(0);
|
||||
player.getActivePotionEffects().forEach(potionEffect -> player.removePotionEffect(potionEffect.getType()));
|
||||
player.teleport(main.getSettings().getSpawnLocation());
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BELL, 1f, 1f);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
main.getTeamManager().onLogout(player);
|
||||
main.getUserManager().delete(player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerPickupArrow(PlayerPickupArrowEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityPickupItem(EntityPickupItemEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
event.setCancelled(GameState.isState(GameState.GAME));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package fr.arthurdanjou.template.listeners;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import fr.arthurdanjou.template.game.GameState;
|
||||
import fr.arthurdanjou.template.config.lang.Lang;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerListPingEvent;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class ServerListeners implements Listener {
|
||||
|
||||
private final Main main;
|
||||
|
||||
@EventHandler
|
||||
public void onServerListPing(ServerListPingEvent event) {
|
||||
event.setMaxPlayers(main.getSettings().getSlots());
|
||||
|
||||
if (GameState.isState(GameState.GAME)) {
|
||||
event.setMotd(Lang.MOTD_GAME.get());
|
||||
} else {
|
||||
event.setMotd(Lang.MOTD_LOBBY.get());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package fr.arthurdanjou.template.listeners;
|
||||
|
||||
import fr.arthurdanjou.template.Main;
|
||||
import fr.arthurdanjou.template.game.GameState;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.event.weather.WeatherChangeEvent;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class WorldListeners implements Listener {
|
||||
|
||||
private final Main main;
|
||||
|
||||
@EventHandler
|
||||
public void onWeatherChange(WeatherChangeEvent event) {
|
||||
if (event.toWeatherState()) {
|
||||
event.getWorld().setStorm(false);
|
||||
event.getWorld().setThundering(false);
|
||||
event.getWorld().setWeatherDuration(0);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityExplode(EntityExplodeEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockExplode(BlockExplodeEvent event) {
|
||||
event.setCancelled(!GameState.isState(GameState.GAME));
|
||||
}
|
||||
|
||||
}
|
||||
77
src/main/java/fr/arthurdanjou/template/team/TeamManager.java
Normal file
77
src/main/java/fr/arthurdanjou/template/team/TeamManager.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package fr.arthurdanjou.template.team;
|
||||
|
||||
import fr.arthurdanjou.template.utils.team.Team;
|
||||
import fr.arthurdanjou.template.utils.team.TeamHandler;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TeamManager {
|
||||
|
||||
private final TeamHandler teamHandler;
|
||||
//todo set teams here
|
||||
|
||||
public TeamManager() {
|
||||
this.teamHandler = new TeamHandler();
|
||||
|
||||
for (TeamUnit team : TeamUnit.values()) {
|
||||
if (this.teamHandler.getTeam(team) != null) {
|
||||
continue;
|
||||
}
|
||||
TeamHandler.VTeam vTeam = this.teamHandler.createNewTeam(team.getName(), team.getColoredName());
|
||||
vTeam.setRealName(team.getName());
|
||||
vTeam.setPrefix(team.getColoredName());
|
||||
|
||||
this.teamHandler.addTeam(vTeam);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLogout(Player player) {
|
||||
this.teamHandler.removeReceiver(player);
|
||||
}
|
||||
|
||||
public void joinTeam(Player player, TeamUnit teamUnit) {
|
||||
this.leaveTeam(player);
|
||||
|
||||
Team team = getTeam(teamUnit);
|
||||
|
||||
if (team != null) {
|
||||
team.getPlayers().add(player.getUniqueId());
|
||||
}
|
||||
|
||||
this.teamHandler.addReceiver(player);
|
||||
this.teamHandler.addPlayerToTeam(player, this.teamHandler.getTeam(teamUnit));
|
||||
}
|
||||
|
||||
public void leaveTeam(Player player) {
|
||||
this.leaveTeam(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void leaveTeam(UUID uuid) {
|
||||
|
||||
}
|
||||
|
||||
public Team getTeam(TeamUnit teamUnit) {
|
||||
//todo if teamUnit == TEAM alors on retourne
|
||||
return null;
|
||||
}
|
||||
|
||||
public Team getPlayerTeam(Player player) {
|
||||
return this.getPlayerTeam(player.getUniqueId());
|
||||
}
|
||||
|
||||
public Team getPlayerTeam(UUID uuid) {
|
||||
//todo if teams.getPlayers.contains(uuid) alors on retourne
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean areAllInTeam() {
|
||||
int count = 0;
|
||||
for (TeamHandler.VTeam team : this.teamHandler.getTeams()) {
|
||||
count += team.getPlayers().size();
|
||||
}
|
||||
return count == Bukkit.getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/java/fr/arthurdanjou/template/team/TeamUnit.java
Normal file
29
src/main/java/fr/arthurdanjou/template/team/TeamUnit.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package fr.arthurdanjou.template.team;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum TeamUnit {
|
||||
|
||||
//todo set teams info here
|
||||
|
||||
NONE("none", "&f", "&f"),
|
||||
;
|
||||
|
||||
private final String name, prefix, color;
|
||||
|
||||
public String getColor() {
|
||||
return ChatColor.translateAlternateColorCodes('&', color);
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return ChatColor.translateAlternateColorCodes('&', prefix);
|
||||
}
|
||||
|
||||
public String getColoredName() {
|
||||
return getColor() + getName();
|
||||
}
|
||||
}
|
||||
34
src/main/java/fr/arthurdanjou/template/users/User.java
Normal file
34
src/main/java/fr/arthurdanjou/template/users/User.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package fr.arthurdanjou.template.users;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter @Setter
|
||||
public class User {
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
private final boolean alive;
|
||||
private int kills;
|
||||
private int deaths;
|
||||
|
||||
public User(Player player) {
|
||||
this.uuid = player.getUniqueId();
|
||||
this.name = player.getName();
|
||||
|
||||
this.alive = true;
|
||||
this.kills = 0;
|
||||
this.deaths = 0;
|
||||
}
|
||||
|
||||
public void addKill() {
|
||||
this.kills++;
|
||||
}
|
||||
|
||||
public void addDeath() {
|
||||
this.deaths++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package fr.arthurdanjou.template.users;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class UserManager {
|
||||
|
||||
private final Set<User> users = new HashSet<>();
|
||||
|
||||
public void onLogin(Player player) {
|
||||
users.add(new User(player));
|
||||
}
|
||||
|
||||
public Optional<User> getUser(Player player) {
|
||||
return getUser(player.getUniqueId());
|
||||
}
|
||||
|
||||
public Optional<User> getUser(UUID uuid) {
|
||||
return this.users.stream().filter(user -> user.getUuid().equals(uuid)).findFirst();
|
||||
}
|
||||
|
||||
public Set<User> getAliveUsers() {
|
||||
return this.users.stream().filter(User::isAlive).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public Set<User> getSpectators() {
|
||||
return this.users.stream().filter(user -> !user.isAlive()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public void delete(Player player) {
|
||||
this.delete(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void delete(UUID uuid) {
|
||||
this.getUser(uuid).ifPresent(users::remove);
|
||||
}
|
||||
|
||||
}
|
||||
188
src/main/java/fr/arthurdanjou/template/utils/ItemBuilder.java
Normal file
188
src/main/java/fr/arthurdanjou/template/utils/ItemBuilder.java
Normal file
@@ -0,0 +1,188 @@
|
||||
package fr.arthurdanjou.template.utils;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemBuilder {
|
||||
|
||||
private ItemStack is;
|
||||
|
||||
/**
|
||||
* Create a new ItemBuilder from scratch.
|
||||
* @param m The material to create the ItemBuilder with.
|
||||
*/
|
||||
public ItemBuilder(Material m) {
|
||||
this(m, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ItemBuilder over an existing itemstack.
|
||||
* @param is The itemstack to create the ItemBuilder over.
|
||||
*/
|
||||
public ItemBuilder(ItemStack is) {
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ItemBuilder from scratch.
|
||||
* @param m The material of the item.
|
||||
* @param amount The amount of the item.
|
||||
*/
|
||||
public ItemBuilder(Material m, int amount) {
|
||||
is = new ItemStack(m, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the ItemBuilder into a new one.
|
||||
* @return The cloned instance.
|
||||
*/
|
||||
@Override
|
||||
public ItemBuilder clone() {
|
||||
return new ItemBuilder(is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the displayname of the item.
|
||||
* @param name The name to change it to.
|
||||
*/
|
||||
public ItemBuilder setName(String name) {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
im.setDisplayName(name);
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the skull owner for the item. Works on skulls only.
|
||||
* @param owner The name of the skull's owner.
|
||||
*/
|
||||
public ItemBuilder setSkullOwner(final OfflinePlayer owner) {
|
||||
try {
|
||||
SkullMeta im = (SkullMeta) is.getItemMeta();
|
||||
assert im != null;
|
||||
im.setOwningPlayer(owner);
|
||||
is.setItemMeta(im);
|
||||
} catch (ClassCastException ignored) {}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets infinity durability on the item by setting the durability to
|
||||
* Short.MAX_VALUE.
|
||||
*/
|
||||
public ItemBuilder setInfinityDurability() {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
im.setUnbreakable(true);
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-sets the lore.
|
||||
* @param lore The lore to set it to.
|
||||
*/
|
||||
public ItemBuilder setLore(String... lore) {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
im.setLore(Arrays.asList(lore));
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemBuilder addNBTTag(String id, String value) {
|
||||
ItemStack nmsIs = CraftItemStack.asNMSCopy(is);
|
||||
NBTTagCompound nmsCompound = (nmsIs.hasTag()) ? nmsIs.getTag() : new NBTTagCompound();
|
||||
assert nmsCompound != null;
|
||||
nmsCompound.set(id, NBTTagString.a(value));
|
||||
nmsIs.setTag(nmsCompound);
|
||||
is = CraftItemStack.asBukkitCopy(nmsIs);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a lore line.
|
||||
* @param line The lore to remove.
|
||||
*/
|
||||
public ItemBuilder removeLoreLine(String line) {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
List<String> lore = new ArrayList<>(Objects.requireNonNull(im.getLore()));
|
||||
if(!lore.contains(line))
|
||||
return this;
|
||||
lore.remove(line);
|
||||
im.setLore(lore);
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a lore line.
|
||||
* @param index The index of the lore line to remove.
|
||||
*/
|
||||
public ItemBuilder removeLoreLine(int index) {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
List<String> lore = new ArrayList<>(Objects.requireNonNull(im.getLore()));
|
||||
if(index < 0 || index > lore.size())
|
||||
return this;
|
||||
lore.remove(index);
|
||||
im.setLore(lore);
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a lore line.
|
||||
* @param line The lore line to add.
|
||||
*/
|
||||
public ItemBuilder addLoreLine(String line) {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
List<String> lore = new ArrayList<>();
|
||||
assert im != null;
|
||||
if(im.hasLore())
|
||||
lore = new ArrayList<>(Objects.requireNonNull(im.getLore()));
|
||||
lore.add(line);
|
||||
im.setLore(lore);
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a lore line.
|
||||
* @param line The lore line to add.
|
||||
* @param pos The index of where to put it.
|
||||
*/
|
||||
public ItemBuilder addLoreLine(String line, int pos) {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
List<String> lore = new ArrayList<>(Objects.requireNonNull(im.getLore()));
|
||||
lore.set(pos, line);
|
||||
im.setLore(lore);
|
||||
is.setItemMeta(im);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void clearLoreLines() {
|
||||
ItemMeta im = is.getItemMeta();
|
||||
assert im != null;
|
||||
im.setLore(new ArrayList<>());
|
||||
is.setItemMeta(im);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the itemstack from the ItemBuilder.
|
||||
* @return The itemstack created/modified by the ItemBuilder instance.
|
||||
*/
|
||||
public ItemStack toItemStack() { return is; }
|
||||
|
||||
}
|
||||
549
src/main/java/fr/arthurdanjou/template/utils/ScoreBoard.java
Normal file
549
src/main/java/fr/arthurdanjou/template/utils/ScoreBoard.java
Normal file
@@ -0,0 +1,549 @@
|
||||
package fr.arthurdanjou.template.utils;
|
||||
|
||||
import fr.arthurdanjou.template.utils.reflection.ScoreBoardReflection;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public class ScoreBoard {
|
||||
|
||||
private static final VersionType VERSION_TYPE;
|
||||
|
||||
// Packets sending
|
||||
private static final Field PLAYER_CONNECTION;
|
||||
private static final Method SEND_PACKET;
|
||||
private static final Method PLAYER_GET_HANDLE;
|
||||
|
||||
// Chat components
|
||||
private static final Class<?> CHAT_COMPONENT_CLASS;
|
||||
private static final Method MESSAGE_FROM_STRING;
|
||||
|
||||
// Scoreboard packets
|
||||
private static final Constructor<?> PACKET_SB_OBJ;
|
||||
private static final Constructor<?> PACKET_SB_DISPLAY_OBJ;
|
||||
private static final Constructor<?> PACKET_SB_SCORE;
|
||||
private static final Constructor<?> PACKET_SB_TEAM;
|
||||
|
||||
// Scoreboard enums
|
||||
private static final Class<?> ENUM_SB_HEALTH_DISPLAY;
|
||||
private static final Class<?> ENUM_SB_ACTION;
|
||||
private static final Object ENUM_SB_HEALTH_DISPLAY_INTEGER;
|
||||
private static final Object ENUM_SB_ACTION_CHANGE;
|
||||
private static final Object ENUM_SB_ACTION_REMOVE;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (ScoreBoardReflection.nmsOptionalClass("ScoreboardServer$Action").isPresent()) {
|
||||
VERSION_TYPE = VersionType.V1_13;
|
||||
} else if (ScoreBoardReflection.nmsOptionalClass("IScoreboardCriteria$EnumScoreboardHealthDisplay").isPresent()) {
|
||||
VERSION_TYPE = VersionType.V1_8;
|
||||
} else {
|
||||
VERSION_TYPE = VersionType.V1_7;
|
||||
}
|
||||
|
||||
Class<?> craftChatMessageClass = ScoreBoardReflection.obcClass("util.CraftChatMessage");
|
||||
Class<?> entityPlayerClass = ScoreBoardReflection.nmsClass("EntityPlayer");
|
||||
Class<?> playerConnectionClass = ScoreBoardReflection.nmsClass("PlayerConnection");
|
||||
Class<?> craftPlayerClass = ScoreBoardReflection.obcClass("entity.CraftPlayer");
|
||||
|
||||
MESSAGE_FROM_STRING = craftChatMessageClass.getDeclaredMethod("fromString", String.class);
|
||||
CHAT_COMPONENT_CLASS = ScoreBoardReflection.nmsClass("IChatBaseComponent");
|
||||
|
||||
PLAYER_GET_HANDLE = craftPlayerClass.getDeclaredMethod("getHandle");
|
||||
PLAYER_CONNECTION = entityPlayerClass.getDeclaredField("playerConnection");
|
||||
SEND_PACKET = playerConnectionClass.getDeclaredMethod("sendPacket", ScoreBoardReflection.nmsClass("Packet"));
|
||||
|
||||
PACKET_SB_OBJ = ScoreBoardReflection.nmsClass("PacketPlayOutScoreboardObjective").getConstructor();
|
||||
PACKET_SB_DISPLAY_OBJ = ScoreBoardReflection.nmsClass("PacketPlayOutScoreboardDisplayObjective").getConstructor();
|
||||
PACKET_SB_SCORE = ScoreBoardReflection.nmsClass("PacketPlayOutScoreboardScore").getConstructor();
|
||||
PACKET_SB_TEAM = ScoreBoardReflection.nmsClass("PacketPlayOutScoreboardTeam").getConstructor();
|
||||
|
||||
if (VersionType.V1_8.isHigherOrEqual()) {
|
||||
ENUM_SB_HEALTH_DISPLAY = ScoreBoardReflection.nmsClass("IScoreboardCriteria$EnumScoreboardHealthDisplay");
|
||||
|
||||
if (VersionType.V1_13.isHigherOrEqual()) {
|
||||
ENUM_SB_ACTION = ScoreBoardReflection.nmsClass("ScoreboardServer$Action");
|
||||
} else {
|
||||
ENUM_SB_ACTION = ScoreBoardReflection.nmsClass("PacketPlayOutScoreboardScore$EnumScoreboardAction");
|
||||
}
|
||||
|
||||
ENUM_SB_HEALTH_DISPLAY_INTEGER = ScoreBoardReflection.enumValueOf(ENUM_SB_HEALTH_DISPLAY, "INTEGER");
|
||||
ENUM_SB_ACTION_CHANGE = ScoreBoardReflection.enumValueOf(ENUM_SB_ACTION, "CHANGE");
|
||||
ENUM_SB_ACTION_REMOVE = ScoreBoardReflection.enumValueOf(ENUM_SB_ACTION, "REMOVE");
|
||||
} else {
|
||||
ENUM_SB_HEALTH_DISPLAY = null;
|
||||
ENUM_SB_ACTION = null;
|
||||
|
||||
ENUM_SB_HEALTH_DISPLAY_INTEGER = null;
|
||||
ENUM_SB_ACTION_CHANGE = null;
|
||||
ENUM_SB_ACTION_REMOVE = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Player player;
|
||||
private final String id;
|
||||
|
||||
private String title = ChatColor.RESET.toString();
|
||||
private final List<String> lines = new ArrayList<>();
|
||||
|
||||
private boolean deleted = false;
|
||||
|
||||
/**
|
||||
* Creates a new FastBoard.
|
||||
*
|
||||
* @param player the player the scoreboard is for
|
||||
*/
|
||||
public ScoreBoard(Player player) {
|
||||
this.player = Objects.requireNonNull(player, "player");
|
||||
|
||||
id = "fb-" + Double.toString(Math.random()).substring(2, 10);
|
||||
|
||||
try {
|
||||
sendObjectivePacket(ObjectiveMode.CREATE);
|
||||
sendDisplayObjectivePacket();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard title.
|
||||
*
|
||||
* @return the scoreboard title
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scoreboard title.
|
||||
*
|
||||
* @param title the new scoreboard title
|
||||
* @throws IllegalArgumentException if the title is longer than 32 chars on 1.12 or lower
|
||||
* @throws IllegalStateException if {@link #delete()} was call before
|
||||
*/
|
||||
public void updateTitle(String title) {
|
||||
if (this.title.equals(Objects.requireNonNull(title, "title"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!VersionType.V1_13.isHigherOrEqual() && title.length() > 32) {
|
||||
throw new IllegalArgumentException("Title is longer than 32 chars");
|
||||
}
|
||||
|
||||
this.title = title;
|
||||
|
||||
try {
|
||||
sendObjectivePacket(ObjectiveMode.UPDATE);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard lines.
|
||||
*
|
||||
* @return the scoreboard lines
|
||||
*/
|
||||
public List<String> getLines() {
|
||||
return new ArrayList<>(lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified scoreboard line.
|
||||
*
|
||||
* @param line the line number
|
||||
* @return the line
|
||||
* @throws IndexOutOfBoundsException if the line is higher than {@code size}
|
||||
*/
|
||||
public String getLine(int line) {
|
||||
checkLineNumber(line, true);
|
||||
|
||||
return lines.get(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single scoreboard line.
|
||||
*
|
||||
* @param line the line number
|
||||
* @param text the new line text
|
||||
* @throws IndexOutOfBoundsException if the line is higher than {@code size} + 1
|
||||
*/
|
||||
public void updateLine(int line, String text) {
|
||||
checkLineNumber(line, false);
|
||||
|
||||
try {
|
||||
if (line < size()) {
|
||||
lines.set(line, text);
|
||||
|
||||
sendTeamPacket(getScoreByLine(line), TeamMode.UPDATE);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> newLines = new ArrayList<>(lines);
|
||||
|
||||
if (line > size()) {
|
||||
for (int i = size(); i < line; i++) {
|
||||
newLines.add("");
|
||||
}
|
||||
}
|
||||
|
||||
newLines.add(text);
|
||||
|
||||
updateLines(newLines);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a scoreboard line.
|
||||
*
|
||||
* @param line the line number
|
||||
*/
|
||||
public void removeLine(int line) {
|
||||
checkLineNumber(line, false);
|
||||
|
||||
if (line >= size()) {
|
||||
return; // The line don't exists
|
||||
}
|
||||
|
||||
List<String> lines = new ArrayList<>(this.lines);
|
||||
lines.remove(line);
|
||||
updateLines(lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all the scoreboard lines.
|
||||
*
|
||||
* @param lines the new lines
|
||||
* @throws IllegalArgumentException if one line is longer than 30 chars on 1.12 or lower
|
||||
* @throws IllegalStateException if {@link #delete()} was call before
|
||||
*/
|
||||
public void updateLines(String... lines) {
|
||||
updateLines(Arrays.asList(lines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the lines of the scoreboard
|
||||
*
|
||||
* @param lines the new scoreboard lines
|
||||
* @throws IllegalArgumentException if one line is longer than 30 chars on 1.12 or lower
|
||||
* @throws IllegalStateException if {@link #delete()} was call before
|
||||
*/
|
||||
public void updateLines(Collection<String> lines) {
|
||||
Objects.requireNonNull(lines, "lines");
|
||||
|
||||
if (!VersionType.V1_13.isHigherOrEqual()) {
|
||||
int lineCount = 0;
|
||||
for (String s : lines) {
|
||||
if (s != null && s.length() > 30) {
|
||||
throw new IllegalArgumentException("Line " + lineCount + " is longer than 30 chars");
|
||||
}
|
||||
lineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
List<String> oldLines = new ArrayList<>(this.lines);
|
||||
this.lines.clear();
|
||||
this.lines.addAll(lines);
|
||||
|
||||
int linesSize = this.lines.size();
|
||||
|
||||
try {
|
||||
if (oldLines.size() != linesSize) {
|
||||
List<String> oldLinesCopy = new ArrayList<>(oldLines);
|
||||
|
||||
if (oldLines.size() > linesSize) {
|
||||
for (int i = oldLinesCopy.size(); i > linesSize; i--) {
|
||||
sendTeamPacket(i - 1, TeamMode.REMOVE);
|
||||
|
||||
sendScorePacket(i - 1, ScoreboardAction.REMOVE);
|
||||
|
||||
oldLines.remove(0);
|
||||
}
|
||||
} else {
|
||||
for (int i = oldLinesCopy.size(); i < linesSize; i++) {
|
||||
sendScorePacket(i, ScoreboardAction.CHANGE);
|
||||
|
||||
sendTeamPacket(i, TeamMode.CREATE);
|
||||
|
||||
oldLines.add(oldLines.size() - i, getLineByScore(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < linesSize; i++) {
|
||||
if (!Objects.equals(getLineByScore(oldLines, i), getLineByScore(i))) {
|
||||
sendTeamPacket(i, TeamMode.UPDATE);
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player who has the scoreboard.
|
||||
*
|
||||
* @return current player for this FastBoard
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard id.
|
||||
*
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the scoreboard is deleted.
|
||||
*
|
||||
* @return true if the scoreboard is deleted
|
||||
*/
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard size (the number of lines).
|
||||
*
|
||||
* @return the size
|
||||
*/
|
||||
public int size() {
|
||||
return lines.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this FastBoard, and will remove the scoreboard for the associated player if he is online.
|
||||
* After this, all uses of {@link #updateLines} and {@link #updateTitle} will throws an {@link IllegalStateException}
|
||||
*
|
||||
* @throws IllegalStateException if this was already call before
|
||||
*/
|
||||
public void delete() {
|
||||
try {
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
sendTeamPacket(i, TeamMode.REMOVE);
|
||||
}
|
||||
|
||||
sendObjectivePacket(ObjectiveMode.REMOVE);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
deleted = true;
|
||||
}
|
||||
|
||||
private void checkLineNumber(int line, boolean checkMax) {
|
||||
if (line < 0) {
|
||||
throw new IllegalArgumentException("Line number must be positive");
|
||||
}
|
||||
|
||||
if (checkMax && line >= lines.size()) {
|
||||
throw new IllegalArgumentException("Line number must be under " + lines.size());
|
||||
}
|
||||
}
|
||||
|
||||
private int getScoreByLine(int line) {
|
||||
return lines.size() - line - 1;
|
||||
}
|
||||
|
||||
private String getLineByScore(int score) {
|
||||
return getLineByScore(lines, score);
|
||||
}
|
||||
|
||||
private String getLineByScore(List<String> lines, int score) {
|
||||
return lines.get(lines.size() - score - 1);
|
||||
}
|
||||
|
||||
private void sendObjectivePacket(ObjectiveMode mode) throws ReflectiveOperationException {
|
||||
Object packet = PACKET_SB_OBJ.newInstance();
|
||||
|
||||
setField(packet, String.class, id);
|
||||
setField(packet, int.class, mode.ordinal());
|
||||
|
||||
if (mode != ObjectiveMode.REMOVE) {
|
||||
setComponentField(packet, title, 1);
|
||||
|
||||
if (VersionType.V1_8.isHigherOrEqual()) {
|
||||
setField(packet, ENUM_SB_HEALTH_DISPLAY, ENUM_SB_HEALTH_DISPLAY_INTEGER);
|
||||
}
|
||||
} else if (VERSION_TYPE == VersionType.V1_7) {
|
||||
setField(packet, String.class, "", 1);
|
||||
}
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendDisplayObjectivePacket() throws ReflectiveOperationException {
|
||||
Object packet = PACKET_SB_DISPLAY_OBJ.newInstance();
|
||||
|
||||
setField(packet, int.class, 1);
|
||||
setField(packet, String.class, id);
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendScorePacket(int score, ScoreboardAction action) throws ReflectiveOperationException {
|
||||
Object packet = PACKET_SB_SCORE.newInstance();
|
||||
|
||||
setField(packet, String.class, getColorCode(score), 0);
|
||||
|
||||
if (VersionType.V1_8.isHigherOrEqual()) {
|
||||
setField(packet, ENUM_SB_ACTION, action == ScoreboardAction.REMOVE ? ENUM_SB_ACTION_REMOVE : ENUM_SB_ACTION_CHANGE);
|
||||
} else {
|
||||
setField(packet, int.class, action.ordinal(), 1);
|
||||
}
|
||||
|
||||
if (action == ScoreboardAction.CHANGE) {
|
||||
setField(packet, String.class, id, 1);
|
||||
setField(packet, int.class, score);
|
||||
}
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendTeamPacket(int score, TeamMode mode) throws ReflectiveOperationException {
|
||||
if (mode == TeamMode.ADD_PLAYERS || mode == TeamMode.REMOVE_PLAYERS) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
Object packet = PACKET_SB_TEAM.newInstance();
|
||||
|
||||
setField(packet, String.class, id + ':' + score); // Team name
|
||||
setField(packet, int.class, mode.ordinal(), VERSION_TYPE == VersionType.V1_8 ? 1 : 0); // Update mode
|
||||
|
||||
if (mode == TeamMode.CREATE || mode == TeamMode.UPDATE) {
|
||||
String line = getLineByScore(score);
|
||||
String prefix;
|
||||
String suffix = null;
|
||||
|
||||
if (line == null || line.isEmpty()) {
|
||||
prefix = getColorCode(score) + ChatColor.RESET;
|
||||
} else if (line.length() <= 16 || VersionType.V1_13.isHigherOrEqual()) {
|
||||
prefix = line;
|
||||
} else {
|
||||
// Prevent splitting color codes
|
||||
int index = line.charAt(15) == ChatColor.COLOR_CHAR ? 15 : 16;
|
||||
prefix = line.substring(0, index);
|
||||
String suffixTmp = line.substring(index);
|
||||
ChatColor chatColor = null;
|
||||
|
||||
if (suffixTmp.length() >= 2 && suffixTmp.charAt(0) == ChatColor.COLOR_CHAR) {
|
||||
chatColor = ChatColor.getByChar(suffixTmp.charAt(1));
|
||||
}
|
||||
|
||||
String color = ChatColor.getLastColors(prefix);
|
||||
boolean addColor = chatColor == null || chatColor.isFormat();
|
||||
|
||||
suffix = (addColor ? (color.isEmpty() ? ChatColor.RESET.toString() : color) : "") + suffixTmp;
|
||||
}
|
||||
|
||||
if (VERSION_TYPE != VersionType.V1_13) {
|
||||
if (prefix.length() > 16 || (suffix != null && suffix.length() > 16)) {
|
||||
// Something went wrong, just cut to prevent client crash/kick
|
||||
prefix = prefix.substring(0, 16);
|
||||
suffix = (suffix != null) ? suffix.substring(0, 16) : null;
|
||||
}
|
||||
}
|
||||
|
||||
setComponentField(packet, prefix, 2); // Prefix
|
||||
setComponentField(packet, suffix == null ? "" : suffix, 3); // Suffix
|
||||
setField(packet, String.class, "always", 4); // Visibility for 1.8+
|
||||
setField(packet, String.class, "always", 5); // Collisions for 1.9+
|
||||
|
||||
if (mode == TeamMode.CREATE) {
|
||||
setField(packet, Collection.class, Collections.singletonList(getColorCode(score))); // Players in the team
|
||||
}
|
||||
}
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private String getColorCode(int score) {
|
||||
return ChatColor.values()[score].toString();
|
||||
}
|
||||
|
||||
private void sendPacket(Object packet) throws ReflectiveOperationException {
|
||||
if (deleted) {
|
||||
throw new IllegalStateException("This FastBoard is deleted");
|
||||
}
|
||||
|
||||
if (player.isOnline()) {
|
||||
Object entityPlayer = PLAYER_GET_HANDLE.invoke(player);
|
||||
Object playerConnection = PLAYER_CONNECTION.get(entityPlayer);
|
||||
SEND_PACKET.invoke(playerConnection, packet);
|
||||
}
|
||||
}
|
||||
|
||||
private void setField(Object object, Class<?> fieldType, Object value) throws ReflectiveOperationException {
|
||||
setField(object, fieldType, value, 0);
|
||||
}
|
||||
|
||||
private void setField(Object object, Class<?> fieldType, Object value, int count) throws ReflectiveOperationException {
|
||||
int i = 0;
|
||||
|
||||
for (Field f : object.getClass().getDeclaredFields()) {
|
||||
if (f.getType() == fieldType && i++ == count) {
|
||||
f.setAccessible(true);
|
||||
f.set(object, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setComponentField(Object object, String value, int count) throws ReflectiveOperationException {
|
||||
if (VERSION_TYPE != VersionType.V1_13) {
|
||||
setField(object, String.class, value, count);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (Field f : object.getClass().getDeclaredFields()) {
|
||||
if ((f.getType() == String.class || f.getType() == CHAT_COMPONENT_CLASS) && i++ == count) {
|
||||
f.setAccessible(true);
|
||||
f.set(object, Array.get(MESSAGE_FROM_STRING.invoke(null, value), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ObjectiveMode {
|
||||
|
||||
CREATE, REMOVE, UPDATE
|
||||
|
||||
}
|
||||
|
||||
enum TeamMode {
|
||||
|
||||
CREATE, REMOVE, UPDATE, ADD_PLAYERS, REMOVE_PLAYERS
|
||||
|
||||
}
|
||||
|
||||
enum ScoreboardAction {
|
||||
|
||||
CHANGE, REMOVE
|
||||
|
||||
}
|
||||
|
||||
enum VersionType {
|
||||
|
||||
V1_7, V1_8, V1_13;
|
||||
|
||||
public boolean isHigherOrEqual() {
|
||||
return VERSION_TYPE.ordinal() >= ordinal();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,965 @@
|
||||
package fr.arthurdanjou.template.utils.reflection;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Reflection {
|
||||
|
||||
public static void playSound(Player player, Location location, String soundName, float volume, float pitch) {
|
||||
try {
|
||||
Class<?> soundClass = getClass("org.bukkit.Sound");
|
||||
Sound sound = (Sound) soundClass.getField(soundName).get(null);
|
||||
|
||||
Method playSoundMethod = getMethod(player.getClass(), "playSound", Location.class, Sound.class, float.class, float.class);
|
||||
playSoundMethod.invoke(player, location, sound, volume, pitch);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getNMSClass(String className) {
|
||||
try {
|
||||
return PackageType.MINECRAFT_SERVER.getClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getOBCClass(String className) {
|
||||
try {
|
||||
return PackageType.CRAFTBUKKIT.getClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacket(Player player, Object packet) {
|
||||
try {
|
||||
Class<?> packetClass = getNMSClass("Packet");
|
||||
Class<?> entityPlayerClass = getNMSClass("EntityPlayer");
|
||||
Field playerConnectionField = getField(entityPlayerClass, "playerConnection");
|
||||
Method sendPacketMethod = getMethod(playerConnectionField.getType(), "sendPacket", packetClass);
|
||||
|
||||
Object entityPlayer = getHandle(player);
|
||||
Object playerConnection = playerConnectionField.get(entityPlayer);
|
||||
|
||||
sendPacketMethod.invoke(playerConnection, packet);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Method makeMethod(Class<?> clazz, String methodName, Class<?>... paramaters) {
|
||||
try {
|
||||
return clazz.getDeclaredMethod(methodName, paramaters);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T callMethod(Method method, Object instance, Object... paramaters) {
|
||||
if (method == null) throw new RuntimeException("No such method");
|
||||
method.setAccessible(true);
|
||||
try {
|
||||
return (T) method.invoke(instance, paramaters);
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex.getCause());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Constructor<T> makeConstructor(Class<?> clazz, Class<?>... paramaterTypes) {
|
||||
try {
|
||||
return (Constructor<T>) clazz.getConstructor(paramaterTypes);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T callConstructor(Constructor<T> constructor, Object... paramaters) {
|
||||
if (constructor == null) throw new RuntimeException("No such constructor");
|
||||
constructor.setAccessible(true);
|
||||
try {
|
||||
return (T) constructor.newInstance(paramaters);
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex.getCause());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Field makeField(Class<?> clazz, String name) {
|
||||
try {
|
||||
return clazz.getDeclaredField(name);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
return null;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getField(Field field, Object instance) {
|
||||
if (field == null) throw new RuntimeException("No such field");
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
return (T) field.get(instance);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setField(Field field, Object instance, Object value) {
|
||||
if (field == null) throw new RuntimeException("No such field");
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.set(instance, value);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getClass(String name) {
|
||||
try {
|
||||
return Class.forName(name);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Class<? extends T> getClass(String name, Class<T> superClass) {
|
||||
try {
|
||||
return Class.forName(name).asSubclass(superClass);
|
||||
} catch (ClassCastException | ClassNotFoundException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getHandle(Object obj) {
|
||||
try {
|
||||
return getMethod(obj.getClass(), "getHandle").invoke(obj);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Reflection failed for getHandle Entity.");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Field getField(Class<?> clazz, String name) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean compareClassList(Class<?>[] l1, Class<?>[] l2) {
|
||||
boolean equal = true;
|
||||
if (l1.length != l2.length)
|
||||
return false;
|
||||
for (int i = 0; i < l1.length; i++)
|
||||
if (!Objects.equals(l1[i], l2[i])) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constructor of a given class with the given parameter types
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param parameterTypes Parameter types of the desired constructor
|
||||
* @return The constructor of the target class with the specified parameter types
|
||||
* @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found
|
||||
* @see DataType
|
||||
* @see DataType#getPrimitive(Class[])
|
||||
* @see DataType#compare(Class[], Class[])
|
||||
*/
|
||||
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
Class<?>[] primitiveTypes = DataType.getPrimitive(parameterTypes);
|
||||
for (Constructor<?> constructor : clazz.getConstructors()) {
|
||||
if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) {
|
||||
continue;
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constructor of a desired class with the given parameter types
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param parameterTypes Parameter types of the desired constructor
|
||||
* @return The constructor of the desired target class with the specified parameter types
|
||||
* @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found
|
||||
* @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #getConstructor(Class, Class...)
|
||||
*/
|
||||
public static Constructor<?> getConstructor(String className, PackageType packageType, Class<?>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
|
||||
return getConstructor(packageType.getClass(className), parameterTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a class with the given arguments
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param arguments Arguments which are used to construct an object of the target class
|
||||
* @return The instance of the target class with the specified arguments
|
||||
* @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances
|
||||
* @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments)
|
||||
* @throws InvocationTargetException If the desired constructor cannot be invoked
|
||||
* @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found
|
||||
*/
|
||||
public static Object instantiateObject(Class<?> clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
|
||||
return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a desired class with the given arguments
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param arguments Arguments which are used to construct an object of the desired target class
|
||||
* @return The instance of the desired target class with the specified arguments
|
||||
* @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances
|
||||
* @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments)
|
||||
* @throws InvocationTargetException If the desired constructor cannot be invoked
|
||||
* @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found
|
||||
* @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #instantiateObject(Class, Object...)
|
||||
*/
|
||||
public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
|
||||
return instantiateObject(packageType.getClass(className), arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a method of a class with the given parameter types
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param methodName Name of the desired method
|
||||
* @param parameterTypes Parameter types of the desired method
|
||||
* @return The method of the target class with the specified name and parameter types
|
||||
* @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found
|
||||
* @see DataType#getPrimitive(Class[])
|
||||
* @see DataType#compare(Class[], Class[])
|
||||
*/
|
||||
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
Class<?>[] primitiveTypes = DataType.getPrimitive(parameterTypes);
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) {
|
||||
continue;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a method of a desired class with the given parameter types
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param methodName Name of the desired method
|
||||
* @param parameterTypes Parameter types of the desired method
|
||||
* @return The method of the desired target class with the specified name and parameter types
|
||||
* @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found
|
||||
* @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #getMethod(Class, String, Class...)
|
||||
*/
|
||||
public static Method getMethod(String className, PackageType packageType, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
|
||||
return getMethod(packageType.getClass(className), methodName, parameterTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a method on an object with the given arguments
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param methodName Name of the desired method
|
||||
* @param arguments Arguments which are used to invoke the desired method
|
||||
* @return The result of invoking the desired method on the target object
|
||||
* @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments)
|
||||
* @throws InvocationTargetException If the desired method cannot be invoked on the target object
|
||||
* @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found
|
||||
* @see #getMethod(Class, String, Class...)
|
||||
* @see DataType#getPrimitive(Object[])
|
||||
*/
|
||||
public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
|
||||
return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a method of the target class on an object with the given arguments
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param clazz Target class
|
||||
* @param methodName Name of the desired method
|
||||
* @param arguments Arguments which are used to invoke the desired method
|
||||
* @return The result of invoking the desired method on the target object
|
||||
* @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments)
|
||||
* @throws InvocationTargetException If the desired method cannot be invoked on the target object
|
||||
* @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found
|
||||
* @see #getMethod(Class, String, Class...)
|
||||
* @see DataType#getPrimitive(Object[])
|
||||
*/
|
||||
public static Object invokeMethod(Object instance, Class<?> clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
|
||||
return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a method of a desired class on an object with the given arguments
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param methodName Name of the desired method
|
||||
* @param arguments Arguments which are used to invoke the desired method
|
||||
* @return The result of invoking the desired method on the target object
|
||||
* @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances
|
||||
* @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments)
|
||||
* @throws InvocationTargetException If the desired method cannot be invoked on the target object
|
||||
* @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found
|
||||
* @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #invokeMethod(Object, Class, String, Object...)
|
||||
*/
|
||||
public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
|
||||
return invokeMethod(instance, packageType.getClass(className), methodName, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field of the target class with the given name
|
||||
*
|
||||
* @param clazz Target class
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The field of the target class with the specified name
|
||||
* @throws NoSuchFieldException If the desired field of the given class cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
*/
|
||||
public static Field getField(Class<?> clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException {
|
||||
Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field of a desired class with the given name
|
||||
*
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The field of the desired target class with the specified name
|
||||
* @throws NoSuchFieldException If the desired field of the desired class cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #getField(Class, boolean, String)
|
||||
*/
|
||||
public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException {
|
||||
return getField(packageType.getClass(className), declared, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field of the given class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param clazz Target class
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The value of field of the target object
|
||||
* @throws IllegalArgumentException If the target object does not feature the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target class cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #getField(Class, boolean, String)
|
||||
*/
|
||||
public static Object getValue(Object instance, Class<?> clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
return getField(clazz, declared, fieldName).get(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field of a desired class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The value of field of the target object
|
||||
* @throws IllegalArgumentException If the target object does not feature the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the desired class cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #getValue(Object, Class, boolean, String)
|
||||
*/
|
||||
public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
|
||||
return getValue(instance, packageType.getClass(className), declared, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field with the given name of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @return The value of field of the target object
|
||||
* @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object)
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target object cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #getValue(Object, Class, boolean, String)
|
||||
*/
|
||||
public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
return getValue(instance, instance.getClass(), declared, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field of the given class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param clazz Target class
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @param value New value
|
||||
* @throws IllegalArgumentException If the type of the value does not match the type of the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target class cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #getField(Class, boolean, String)
|
||||
*/
|
||||
public static void setValue(Object instance, Class<?> clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
getField(clazz, declared, fieldName).set(instance, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field of a desired class of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param className Name of the desired target class
|
||||
* @param packageType Package where the desired target class is located
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @param value New value
|
||||
* @throws IllegalArgumentException If the type of the value does not match the type of the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the desired class cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
|
||||
* @see #setValue(Object, Class, boolean, String, Object)
|
||||
*/
|
||||
public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
|
||||
setValue(instance, packageType.getClass(className), declared, fieldName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field with the given name of an object
|
||||
*
|
||||
* @param instance Target object
|
||||
* @param declared Whether the desired field is declared or not
|
||||
* @param fieldName Name of the desired field
|
||||
* @param value New value
|
||||
* @throws IllegalArgumentException If the type of the value does not match the type of the desired field
|
||||
* @throws IllegalAccessException If the desired field cannot be accessed
|
||||
* @throws NoSuchFieldException If the desired field of the target object cannot be found
|
||||
* @throws SecurityException If the desired field cannot be made accessible
|
||||
* @see #setValue(Object, Class, boolean, String, Object)
|
||||
*/
|
||||
public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
||||
setValue(instance, instance.getClass(), declared, fieldName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value of an {@link Object} via reflection
|
||||
*
|
||||
* @param instance instance the class to use
|
||||
* @param fieldName the name of the {@link Field} to modify
|
||||
* @param value the value to set
|
||||
* @throws NoSuchFieldException, IllegalAccessException
|
||||
*/
|
||||
public static void setValue(Object instance, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
setValue(instance, true, fieldName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value of an {@link Object}'s {@link Field}
|
||||
*
|
||||
* @param instance the target {@link Object}
|
||||
* @param fieldName name of the {@link Field}
|
||||
* @return the value of {@link Object} instance's {@link Field} with the
|
||||
* name of fieldName
|
||||
* @throws NoSuchFieldException, IllegalAccessException
|
||||
*/
|
||||
public static Object getValue(Object instance, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getValue(instance, true, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a final static var
|
||||
* @param field The field object
|
||||
* @param value The new value
|
||||
* @throws ReflectiveOperationException
|
||||
*/
|
||||
public static void setFinalStatic(Field field, Object value) throws ReflectiveOperationException {
|
||||
field.setAccessible(true);
|
||||
Class.class.getModifiers();
|
||||
Field mf = Field.class.getDeclaredField("modifiers");
|
||||
mf.setAccessible(true);
|
||||
mf.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
field.set(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a final static var
|
||||
* @param field The field object
|
||||
* @param value The new value
|
||||
* @throws ReflectiveOperationException
|
||||
*/
|
||||
public static void setFinal(Object object, Field field, Object value) throws ReflectiveOperationException {
|
||||
field.setAccessible(true);
|
||||
Field mf = Field.class.getDeclaredField("modifiers");
|
||||
mf.setAccessible(true);
|
||||
mf.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
field.set(object, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an enumeration of dynamic packages of NMS and CraftBukkit
|
||||
* <p/>
|
||||
* This class is part of the <b>ReflectionUtils</b> and follows the same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum PackageType {
|
||||
MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()),
|
||||
CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()),
|
||||
CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"),
|
||||
CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"),
|
||||
CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"),
|
||||
CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"),
|
||||
CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"),
|
||||
CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"),
|
||||
CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"),
|
||||
CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"),
|
||||
CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"),
|
||||
CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"),
|
||||
CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"),
|
||||
CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"),
|
||||
CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"),
|
||||
CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"),
|
||||
CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"),
|
||||
CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"),
|
||||
CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"),
|
||||
CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"),
|
||||
BUKKIT("org.bukkit");
|
||||
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Construct a new package type
|
||||
*
|
||||
* @param path Path of the package
|
||||
*/
|
||||
private PackageType(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new package type
|
||||
*
|
||||
* @param parent Parent package of the package
|
||||
* @param path Path of the package
|
||||
*/
|
||||
private PackageType(PackageType parent, String path) {
|
||||
this(parent + "." + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of your server
|
||||
*
|
||||
* @return The server version
|
||||
*/
|
||||
public static String getServerVersion() {
|
||||
String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
return name.substring(name.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of this package type
|
||||
*
|
||||
* @return The path
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class with the given name
|
||||
*
|
||||
* @param className Name of the desired class
|
||||
* @return The class with the specified name
|
||||
* @throws ClassNotFoundException If the desired class with the specified name and package cannot be found
|
||||
*/
|
||||
public Class<?> getClass(String className) throws ClassNotFoundException {
|
||||
return Class.forName(this + "." + className);
|
||||
}
|
||||
|
||||
// Override for convenience
|
||||
@Override
|
||||
public String toString() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an enumeration of Java data types with corresponding classes
|
||||
* <p/>
|
||||
* This class is part of the <b>ReflectionUtils</b> and follows the same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum DataType {
|
||||
BYTE(byte.class, Byte.class),
|
||||
SHORT(short.class, Short.class),
|
||||
INTEGER(int.class, Integer.class),
|
||||
LONG(long.class, Long.class),
|
||||
CHARACTER(char.class, Character.class),
|
||||
FLOAT(float.class, Float.class),
|
||||
DOUBLE(double.class, Double.class),
|
||||
BOOLEAN(boolean.class, Boolean.class);
|
||||
|
||||
private static final Map<Class<?>, DataType> CLASS_MAP = new HashMap<>();
|
||||
private final Class<?> primitive;
|
||||
private final Class<?> reference;
|
||||
|
||||
// Initialize map for quick class lookup
|
||||
static {
|
||||
for (DataType type : values()) {
|
||||
CLASS_MAP.put(type.primitive, type);
|
||||
CLASS_MAP.put(type.reference, type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new data type
|
||||
*
|
||||
* @param primitive Primitive class of this data type
|
||||
* @param reference Reference class of this data type
|
||||
*/
|
||||
private DataType(Class<?> primitive, Class<?> reference) {
|
||||
this.primitive = primitive;
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data type with the given primitive/reference class
|
||||
*
|
||||
* @param clazz Primitive/Reference class of the data type
|
||||
* @return The data type
|
||||
*/
|
||||
public static DataType fromClass(Class<?> clazz) {
|
||||
return CLASS_MAP.get(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class of the data type with the given reference class
|
||||
*
|
||||
* @param clazz Reference class of the data type
|
||||
* @return The primitive class
|
||||
*/
|
||||
public static Class<?> getPrimitive(Class<?> clazz) {
|
||||
DataType type = fromClass(clazz);
|
||||
return type == null ? clazz : type.getPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class of the data type with the given primitive class
|
||||
*
|
||||
* @param clazz Primitive class of the data type
|
||||
* @return The reference class
|
||||
*/
|
||||
public static Class<?> getReference(Class<?> clazz) {
|
||||
DataType type = fromClass(clazz);
|
||||
return type == null ? clazz : type.getReference();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class array of the given class array
|
||||
*
|
||||
* @param classes Given class array
|
||||
* @return The primitive class array
|
||||
*/
|
||||
public static Class<?>[] getPrimitive(Class<?>[] classes) {
|
||||
int length = classes == null ? 0 : classes.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getPrimitive(classes[index]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class array of the given class array
|
||||
*
|
||||
* @param classes Given class array
|
||||
* @return The reference class array
|
||||
*/
|
||||
public static Class<?>[] getReference(Class<?>[] classes) {
|
||||
int length = classes == null ? 0 : classes.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getReference(classes[index]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class array of the given object array
|
||||
*
|
||||
* @param objects Given object array
|
||||
* @return The primitive class array
|
||||
*/
|
||||
public static Class<?>[] getPrimitive(Object[] objects) {
|
||||
int length = objects == null ? 0 : objects.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getPrimitive(objects[index].getClass());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class array of the given object array
|
||||
*
|
||||
* @param objects Given object array
|
||||
* @return The reference class array
|
||||
*/
|
||||
public static Class<?>[] getReference(Object[] objects) {
|
||||
int length = objects == null ? 0 : objects.length;
|
||||
Class<?>[] types = new Class<?>[length];
|
||||
for (int index = 0; index < length; index++) {
|
||||
types[index] = getReference(objects[index].getClass());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two class arrays on equivalence
|
||||
*
|
||||
* @param primary Primary class array
|
||||
* @param secondary Class array which is compared to the primary array
|
||||
* @return Whether these arrays are equal or not
|
||||
*/
|
||||
public static boolean compare(Class<?>[] primary, Class<?>[] secondary) {
|
||||
if (primary == null || secondary == null || primary.length != secondary.length) {
|
||||
return false;
|
||||
}
|
||||
for (int index = 0; index < primary.length; index++) {
|
||||
Class<?> primaryClass = primary[index];
|
||||
Class<?> secondaryClass = secondary[index];
|
||||
if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive class of this data type
|
||||
*
|
||||
* @return The primitive class
|
||||
*/
|
||||
public Class<?> getPrimitive() {
|
||||
return primitive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference class of this data type
|
||||
*
|
||||
* @return The reference class
|
||||
*/
|
||||
public Class<?> getReference() {
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an enumeration of all packet types that are featured in <b>Minecraft 1.7.10</b>
|
||||
* <p/>
|
||||
* If this enumeration is no longer up-to-date, please let me know in my <a href="http://forums.bukkit.org/threads/lib-1-7-particleeffect-v1-4.154406">forum post</a>
|
||||
* <p/>
|
||||
* This class is part of the <b>ReflectionUtils</b> and follows the same usage conditions
|
||||
*
|
||||
* @author DarkBlade12
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum PacketType {
|
||||
HANDSHAKING_IN_SET_PROTOCOL("PacketHandshakingInSetProtocol"),
|
||||
LOGIN_IN_ENCRYPTION_BEGIN("PacketLoginInEncryptionBegin"),
|
||||
LOGIN_IN_START("PacketLoginInStart"),
|
||||
LOGIN_OUT_DISCONNECT("PacketLoginOutDisconnect"),
|
||||
LOGIN_OUT_ENCRYPTION_BEGIN("PacketLoginOutEncryptionBegin"),
|
||||
LOGIN_OUT_SUCCESS("PacketLoginOutSuccess"),
|
||||
PLAY_IN_ABILITIES("PacketPlayInAbilities"),
|
||||
PLAY_IN_ARM_ANIMATION("PacketPlayInArmAnimation"),
|
||||
PLAY_IN_BLOCK_DIG("PacketPlayInBlockDig"),
|
||||
PLAY_IN_BLOCK_PLACE("PacketPlayInBlockPlace"),
|
||||
PLAY_IN_CHAT("PacketPlayInChat"),
|
||||
PLAY_IN_CLIENT_COMMAND("PacketPlayInClientCommand"),
|
||||
PLAY_IN_CLOSE_WINDOW("PacketPlayInCloseWindow"),
|
||||
PLAY_IN_CUSTOM_PAYLOAD("PacketPlayInCustomPayload"),
|
||||
PLAY_IN_ENCHANT_ITEM("PacketPlayInEnchantItem"),
|
||||
PLAY_IN_ENTITY_ACTION("PacketPlayInEntityAction"),
|
||||
PLAY_IN_FLYING("PacketPlayInFlying"),
|
||||
PLAY_IN_HELD_ITEM_SLOT("PacketPlayInHeldItemSlot"),
|
||||
PLAY_IN_KEEP_ALIVE("PacketPlayInKeepAlive"),
|
||||
PLAY_IN_LOOK("PacketPlayInLook"),
|
||||
PLAY_IN_POSITION("PacketPlayInPosition"),
|
||||
PLAY_IN_POSITION_LOOK("PacketPlayInPositionLook"),
|
||||
PLAY_IN_SET_CREATIVE_SLOT("PacketPlayInSetCreativeSlot "),
|
||||
PLAY_IN_SETTINGS("PacketPlayInSettings"),
|
||||
PLAY_IN_STEER_VEHICLE("PacketPlayInSteerVehicle"),
|
||||
PLAY_IN_TAB_COMPLETE("PacketPlayInTabComplete"),
|
||||
PLAY_IN_TRANSACTION("PacketPlayInTransaction"),
|
||||
PLAY_IN_UPDATE_SIGN("PacketPlayInUpdateSign"),
|
||||
PLAY_IN_USE_ENTITY("PacketPlayInUseEntity"),
|
||||
PLAY_IN_WINDOW_CLICK("PacketPlayInWindowClick"),
|
||||
PLAY_OUT_ABILITIES("PacketPlayOutAbilities"),
|
||||
PLAY_OUT_ANIMATION("PacketPlayOutAnimation"),
|
||||
PLAY_OUT_ATTACH_ENTITY("PacketPlayOutAttachEntity"),
|
||||
PLAY_OUT_BED("PacketPlayOutBed"),
|
||||
PLAY_OUT_BLOCK_ACTION("PacketPlayOutBlockAction"),
|
||||
PLAY_OUT_BLOCK_BREAK_ANIMATION("PacketPlayOutBlockBreakAnimation"),
|
||||
PLAY_OUT_BLOCK_CHANGE("PacketPlayOutBlockChange"),
|
||||
PLAY_OUT_CHAT("PacketPlayOutChat"),
|
||||
PLAY_OUT_CLOSE_WINDOW("PacketPlayOutCloseWindow"),
|
||||
PLAY_OUT_COLLECT("PacketPlayOutCollect"),
|
||||
PLAY_OUT_CRAFT_PROGRESS_BAR("PacketPlayOutCraftProgressBar"),
|
||||
PLAY_OUT_CUSTOM_PAYLOAD("PacketPlayOutCustomPayload"),
|
||||
PLAY_OUT_ENTITY("PacketPlayOutEntity"),
|
||||
PLAY_OUT_ENTITY_DESTROY("PacketPlayOutEntityDestroy"),
|
||||
PLAY_OUT_ENTITY_EFFECT("PacketPlayOutEntityEffect"),
|
||||
PLAY_OUT_ENTITY_EQUIPMENT("PacketPlayOutEntityEquipment"),
|
||||
PLAY_OUT_ENTITY_HEAD_ROTATION("PacketPlayOutEntityHeadRotation"),
|
||||
PLAY_OUT_ENTITY_LOOK("PacketPlayOutEntityLook"),
|
||||
PLAY_OUT_ENTITY_METADATA("PacketPlayOutEntityMetadata"),
|
||||
PLAY_OUT_ENTITY_STATUS("PacketPlayOutEntityStatus"),
|
||||
PLAY_OUT_ENTITY_TELEPORT("PacketPlayOutEntityTeleport"),
|
||||
PLAY_OUT_ENTITY_VELOCITY("PacketPlayOutEntityVelocity"),
|
||||
PLAY_OUT_EXPERIENCE("PacketPlayOutExperience"),
|
||||
PLAY_OUT_EXPLOSION("PacketPlayOutExplosion"),
|
||||
PLAY_OUT_GAME_STATE_CHANGE("PacketPlayOutGameStateChange"),
|
||||
PLAY_OUT_HELD_ITEM_SLOT("PacketPlayOutHeldItemSlot"),
|
||||
PLAY_OUT_KEEP_ALIVE("PacketPlayOutKeepAlive"),
|
||||
PLAY_OUT_KICK_DISCONNECT("PacketPlayOutKickDisconnect"),
|
||||
PLAY_OUT_LOGIN("PacketPlayOutLogin"),
|
||||
PLAY_OUT_MAP("PacketPlayOutMap"),
|
||||
PLAY_OUT_MAP_CHUNK("PacketPlayOutMapChunk"),
|
||||
PLAY_OUT_MAP_CHUNK_BULK("PacketPlayOutMapChunkBulk"),
|
||||
PLAY_OUT_MULTI_BLOCK_CHANGE("PacketPlayOutMultiBlockChange"),
|
||||
PLAY_OUT_NAMED_ENTITY_SPAWN("PacketPlayOutNamedEntitySpawn"),
|
||||
PLAY_OUT_NAMED_SOUND_EFFECT("PacketPlayOutNamedSoundEffect"),
|
||||
PLAY_OUT_OPEN_SIGN_EDITOR("PacketPlayOutOpenSignEditor"),
|
||||
PLAY_OUT_OPEN_WINDOW("PacketPlayOutOpenWindow"),
|
||||
PLAY_OUT_PLAYER_INFO("PacketPlayOutPlayerInfo"),
|
||||
PLAY_OUT_POSITION("PacketPlayOutPosition"),
|
||||
PLAY_OUT_REL_ENTITY_MOVE("PacketPlayOutRelEntityMove"),
|
||||
PLAY_OUT_REL_ENTITY_MOVE_LOOK("PacketPlayOutRelEntityMoveLook"),
|
||||
PLAY_OUT_REMOVE_ENTITY_EFFECT("PacketPlayOutRemoveEntityEffect"),
|
||||
PLAY_OUT_RESPAWN("PacketPlayOutRespawn"),
|
||||
PLAY_OUT_SCOREBOARD_DISPLAY_OBJECTIVE("PacketPlayOutScoreboardDisplayObjective"),
|
||||
PLAY_OUT_SCOREBOARD_OBJECTIVE("PacketPlayOutScoreboardObjective"),
|
||||
PLAY_OUT_SCOREBOARD_SCORE("PacketPlayOutScoreboardScore"),
|
||||
PLAY_OUT_SCOREBOARD_TEAM("PacketPlayOutScoreboardTeam"),
|
||||
PLAY_OUT_SET_SLOT("PacketPlayOutSetSlot"),
|
||||
PLAY_OUT_SPAWN_ENTITY("PacketPlayOutSpawnEntity"),
|
||||
PLAY_OUT_SPAWN_ENTITY_EXPERIENCE_ORB("PacketPlayOutSpawnEntityExperienceOrb"),
|
||||
PLAY_OUT_SPAWN_ENTITY_LIVING("PacketPlayOutSpawnEntityLiving"),
|
||||
PLAY_OUT_SPAWN_ENTITY_PAINTING("PacketPlayOutSpawnEntityPainting"),
|
||||
PLAY_OUT_SPAWN_ENTITY_WEATHER("PacketPlayOutSpawnEntityWeather"),
|
||||
PLAY_OUT_SPAWN_POSITION("PacketPlayOutSpawnPosition"),
|
||||
PLAY_OUT_STATISTIC("PacketPlayOutStatistic"),
|
||||
PLAY_OUT_TAB_COMPLETE("PacketPlayOutTabComplete"),
|
||||
PLAY_OUT_TILE_ENTITY_DATA("PacketPlayOutTileEntityData"),
|
||||
PLAY_OUT_TRANSACTION("PacketPlayOutTransaction"),
|
||||
PLAY_OUT_UPDATE_ATTRIBUTES("PacketPlayOutUpdateAttributes"),
|
||||
PLAY_OUT_UPDATE_HEALTH("PacketPlayOutUpdateHealth"),
|
||||
PLAY_OUT_UPDATE_SIGN("PacketPlayOutUpdateSign"),
|
||||
PLAY_OUT_UPDATE_TIME("PacketPlayOutUpdateTime"),
|
||||
PLAY_OUT_WINDOW_ITEMS("PacketPlayOutWindowItems"),
|
||||
PLAY_OUT_WORLD_EVENT("PacketPlayOutWorldEvent"),
|
||||
PLAY_OUT_WORLD_PARTICLES("PacketPlayOutWorldParticles"),
|
||||
STATUS_IN_PING("PacketStatusInPing"),
|
||||
STATUS_IN_START("PacketStatusInStart"),
|
||||
STATUS_OUT_PONG("PacketStatusOutPong"),
|
||||
STATUS_OUT_SERVER_INFO("PacketStatusOutServerInfo");
|
||||
|
||||
private static final Map<String, PacketType> NAME_MAP = new HashMap<>();
|
||||
private final String name;
|
||||
private Class<?> packet;
|
||||
|
||||
// Initialize map for quick name lookup
|
||||
static {
|
||||
for (PacketType type : values()) {
|
||||
NAME_MAP.put(type.name, type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new packet type
|
||||
*
|
||||
* @param name Name of this packet
|
||||
*/
|
||||
private PacketType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this packet type
|
||||
*
|
||||
* @return The name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class of this packet
|
||||
*
|
||||
* @return The packet class
|
||||
* @throws ClassNotFoundException If the packet class cannot be found (the name differs in your Bukkit version)
|
||||
*/
|
||||
public Class<?> getPacket() throws ClassNotFoundException {
|
||||
return packet == null ? (packet = PackageType.MINECRAFT_SERVER.getClass(name)) : packet;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package fr.arthurdanjou.template.utils.reflection;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ScoreBoardReflection {
|
||||
|
||||
public static final String OBC_PACKAGE = "org.bukkit.craftbukkit";
|
||||
public static final String NMS_PACKAGE = "net.minecraft.server";
|
||||
|
||||
public static final String VERSION = Bukkit.getServer().getClass().getPackage().getName().substring(OBC_PACKAGE.length() + 1);
|
||||
|
||||
private ScoreBoardReflection() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static String nmsClassName(String className) {
|
||||
return NMS_PACKAGE + '.' + VERSION + '.' + className;
|
||||
}
|
||||
|
||||
public static Class<?> nmsClass(String className) throws ClassNotFoundException {
|
||||
return Class.forName(nmsClassName(className));
|
||||
}
|
||||
|
||||
public static Optional<Class<?>> nmsOptionalClass(String className) {
|
||||
return optionalClass(nmsClassName(className));
|
||||
}
|
||||
|
||||
public static String obcClassName(String className) {
|
||||
return OBC_PACKAGE + '.' + VERSION + '.' + className;
|
||||
}
|
||||
|
||||
public static Class<?> obcClass(String className) throws ClassNotFoundException {
|
||||
return Class.forName(obcClassName(className));
|
||||
}
|
||||
|
||||
public static Optional<Class<?>> obcOptionalClass(String className) {
|
||||
return optionalClass(obcClassName(className));
|
||||
}
|
||||
|
||||
public static Optional<Class<?>> optionalClass(String className) {
|
||||
try {
|
||||
return Optional.of(Class.forName(className));
|
||||
} catch (ClassNotFoundException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E extends Enum<E>> E enumValueOf(Class<?> enumClass, String enumName) {
|
||||
return Enum.valueOf((Class<E>) enumClass, enumName.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/fr/arthurdanjou/template/utils/team/Team.java
Normal file
45
src/main/java/fr/arthurdanjou/template/utils/team/Team.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package fr.arthurdanjou.template.utils.team;
|
||||
|
||||
import fr.arthurdanjou.template.team.TeamUnit;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
public class Team {
|
||||
|
||||
private final TeamUnit teamUnit;
|
||||
private final Set<UUID> players;
|
||||
|
||||
public Team(TeamUnit teamUnit) {
|
||||
this.teamUnit = teamUnit;
|
||||
this.players = new HashSet<>();
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return this.teamUnit.getPrefix();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.teamUnit.getName();
|
||||
}
|
||||
|
||||
public String getColoredName() {
|
||||
return this.teamUnit.getColoredName();
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return this.teamUnit.getColor();
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return this.players.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.players.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,483 @@
|
||||
package fr.arthurdanjou.template.utils.team;
|
||||
|
||||
import fr.arthurdanjou.template.team.TeamUnit;
|
||||
import fr.arthurdanjou.template.utils.reflection.Reflection;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class TeamHandler {
|
||||
|
||||
@Getter
|
||||
private ConcurrentLinkedQueue<VTeam> teams;
|
||||
private List<OfflinePlayer> receivers;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TeamHandler() {
|
||||
this.teams = new ConcurrentLinkedQueue<>();
|
||||
this.receivers = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add receiver
|
||||
*
|
||||
* @param offlinePlayer Player
|
||||
*
|
||||
* @return {@code true} if success
|
||||
*/
|
||||
public boolean addReceiver(OfflinePlayer offlinePlayer) {
|
||||
if(!offlinePlayer.isOnline())
|
||||
return false;
|
||||
|
||||
this.removeFromAllTeams(offlinePlayer);
|
||||
|
||||
this.receivers.add(offlinePlayer);
|
||||
Player p = offlinePlayer.getPlayer();
|
||||
this.sendAllTeams(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove receiver
|
||||
*
|
||||
* @param offlinePlayer Player
|
||||
*
|
||||
* @return {@code true} if success
|
||||
*/
|
||||
public boolean removeReceiver(OfflinePlayer offlinePlayer) {
|
||||
this.receivers.remove(offlinePlayer);
|
||||
this.removeFromAllTeams(offlinePlayer);
|
||||
|
||||
if(offlinePlayer.isOnline())
|
||||
this.removeAllTeams(offlinePlayer.getPlayer());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new scoreboard team
|
||||
*
|
||||
* @param name Team name
|
||||
* @param display Team display name
|
||||
*
|
||||
* @return Team instance
|
||||
*/
|
||||
public VTeam createNewTeam(String name, String display) {
|
||||
return new VTeam(name, display);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a given player to the given team
|
||||
*
|
||||
* @param p Player
|
||||
* @param team Team
|
||||
*
|
||||
* @return {@code true} is success
|
||||
*/
|
||||
public boolean addPlayerToTeam(OfflinePlayer p, VTeam team) {
|
||||
return this.addPlayerToTeam(p.getName(), team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a given player to the given team
|
||||
*
|
||||
* @param p Player
|
||||
* @param team Team
|
||||
*
|
||||
* @return {@code true} is success
|
||||
*/
|
||||
public boolean addPlayerToTeam(String p, VTeam team) {
|
||||
team.addPlayer(p);
|
||||
|
||||
for(OfflinePlayer offlinePlayer : this.receivers) {
|
||||
if(!offlinePlayer.isOnline())
|
||||
continue;
|
||||
|
||||
RawTeam.addPlayerToTeam(offlinePlayer.getPlayer(), team, p);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given player from the given team
|
||||
*
|
||||
* @param offlinePlayer Player
|
||||
* @param team Team
|
||||
*
|
||||
* @return {@code true} is success
|
||||
*/
|
||||
public boolean removePlayerFromTeam(OfflinePlayer offlinePlayer, VTeam team) {
|
||||
team.removePlayer(offlinePlayer);
|
||||
|
||||
for(OfflinePlayer player : this.receivers) {
|
||||
if(!player.isOnline())
|
||||
continue;
|
||||
|
||||
RawTeam.removePlayerFromTeam(player.getPlayer(), team, player.getName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a team to the scoreboard
|
||||
*
|
||||
* @param vt Team
|
||||
*
|
||||
*/
|
||||
public void addTeam(VTeam vt) {
|
||||
this.teams.add(vt);
|
||||
this.sendToAllTeam(vt);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a team from the scoreboard
|
||||
*
|
||||
* @param teamName Team
|
||||
*
|
||||
* @return {@code true} is success
|
||||
*/
|
||||
public boolean removeTeam(String teamName) {
|
||||
VTeam vt = this.getTeamByName(teamName);
|
||||
|
||||
if(vt == null)
|
||||
return false;
|
||||
|
||||
this.removeToAllTeam(vt);
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Add a given player to all teams
|
||||
*
|
||||
* @param offlinePlayer Player
|
||||
*
|
||||
* @return {@code true} is success
|
||||
*/
|
||||
private boolean removeFromAllTeams(OfflinePlayer offlinePlayer) {
|
||||
return this.removeFromAllTeams(offlinePlayer.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a given player to all teams
|
||||
*
|
||||
* @param player Player
|
||||
*
|
||||
* @return {@code true} is success
|
||||
*/
|
||||
private boolean removeFromAllTeams(String player) {
|
||||
for (VTeam team : teams) {
|
||||
for (String op : team.getPlayers()) {
|
||||
if (player.equals(op)) {
|
||||
team.removePlayer(op);
|
||||
|
||||
for (OfflinePlayer p : this.receivers) {
|
||||
if(!p.isOnline())
|
||||
continue;
|
||||
|
||||
RawTeam.removePlayerFromTeam(p.getPlayer(), team, op);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send scoreboard's teams to a given player
|
||||
*
|
||||
* @param p Player
|
||||
*/
|
||||
private void sendAllTeams(Player p) {
|
||||
for (VTeam vt : this.teams)
|
||||
this.sendTeam(p, vt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove scoreboard's teams from a given player
|
||||
*
|
||||
* @param p Player
|
||||
*/
|
||||
private void removeAllTeams(Player p) {
|
||||
for (VTeam vt : this.teams)
|
||||
this.removeTeam(p, vt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a given scoreboard's team to all players
|
||||
*
|
||||
* @param vt Team
|
||||
*/
|
||||
private void sendToAllTeam(VTeam vt) {
|
||||
for(OfflinePlayer offlinePlayer : this.receivers) {
|
||||
if(!offlinePlayer.isOnline())
|
||||
continue;
|
||||
|
||||
this.sendTeam(offlinePlayer.getPlayer(), vt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given scoreboard's team from all players
|
||||
*
|
||||
* @param vt Team
|
||||
*/
|
||||
private void removeToAllTeam(VTeam vt) {
|
||||
for(OfflinePlayer offlinePlayer : this.receivers) {
|
||||
if(!offlinePlayer.isOnline())
|
||||
continue;
|
||||
|
||||
this.removeTeam(offlinePlayer.getPlayer(), vt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a given team to the given player
|
||||
*
|
||||
* @param p Player
|
||||
* @param vt Team
|
||||
*/
|
||||
private void sendTeam(Player p, VTeam vt) {
|
||||
RawTeam.createTeam(p, vt);
|
||||
RawTeam.sendTeam(p, vt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given team from the given player
|
||||
*
|
||||
* @param p Player
|
||||
* @param vt Team
|
||||
*/
|
||||
private void removeTeam(Player p, VTeam vt) {
|
||||
RawTeam.removeTeam(p, vt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player's scoreboard team
|
||||
*
|
||||
* @param p Player
|
||||
*
|
||||
* @return Team
|
||||
*/
|
||||
public VTeam getTeamByPlayer(Player p) {
|
||||
for (VTeam n : this.teams)
|
||||
if (n.contains(p.getName()))
|
||||
return n;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a scoreboard team by it's name
|
||||
*
|
||||
* @param name Team's name
|
||||
*
|
||||
* @return Team
|
||||
*/
|
||||
public VTeam getTeamByName(String name) {
|
||||
for (VTeam n : this.teams)
|
||||
if (n.getName().equals(name))
|
||||
return n;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public VTeam getTeam(TeamUnit team) {
|
||||
return getTeamByName(team.getName());
|
||||
}
|
||||
|
||||
public static class RawTeam {
|
||||
public static void createTeam(Player player, VTeam team) {
|
||||
Reflection.sendPacket(player, makePacket(team, new ArrayList<>(), 0));
|
||||
}
|
||||
|
||||
public static void sendTeam(Player player, VTeam team) {
|
||||
Reflection.sendPacket(player, makePacket(team, 3));
|
||||
}
|
||||
|
||||
public static void removeTeam(Player player, VTeam team) {
|
||||
Reflection.sendPacket(player, makePacket(team, new ArrayList<>(), 1));
|
||||
}
|
||||
|
||||
public static void changeTeam(Player player, VTeam team) {
|
||||
Reflection.sendPacket(player, makePacket(team, new ArrayList<>(), 2));
|
||||
}
|
||||
|
||||
public static void addPlayerToTeam(Player receiver, VTeam team, Player toadd) {
|
||||
addPlayerToTeam(receiver, team, toadd.getName());
|
||||
}
|
||||
|
||||
public static void addPlayerToTeam(Player receiver, VTeam team, String toadd) {
|
||||
Reflection.sendPacket(receiver, makePacket(team, Collections.singletonList(toadd), 3));
|
||||
}
|
||||
|
||||
public static void removePlayerFromTeam(Player receiver, VTeam team, Player toremove) {
|
||||
removePlayerFromTeam(receiver, team, toremove.getName());
|
||||
}
|
||||
|
||||
public static void removePlayerFromTeam(Player receiver, VTeam team, String toremove) {
|
||||
if (team.players.contains(toremove))
|
||||
Reflection.sendPacket(receiver, makePacket(team, Collections.singletonList(toremove), 4));
|
||||
}
|
||||
|
||||
private static Object makePacket(VTeam team, List<String> news, int n) {
|
||||
//0: Création de team
|
||||
//1: Suppression de team
|
||||
//2: Changements infos de la team
|
||||
//3: Ajout d'un joueur
|
||||
//4: Suppression d'un joueur
|
||||
|
||||
if (news == null)
|
||||
news = new ArrayList<>();
|
||||
|
||||
try {
|
||||
PacketPlayOutScoreboardTeam packet = new PacketPlayOutScoreboardTeam();
|
||||
|
||||
Reflection.setValue(packet, "a", team.getRealName()); // Team display name
|
||||
Reflection.setValue(packet, "b", new ChatComponentText(team.getDisplayName())); // Team display name
|
||||
Reflection.setValue(packet, "c", new ChatComponentText(team.getPrefix())); // Team prefix
|
||||
Reflection.setValue(packet, "d", new ChatComponentText(team.getSuffix())); // Team suffix
|
||||
Reflection.setValue(packet, "e", team.getHideToOtherTeams() ? "hideForOtherTeams" : "always"); // Name tag visible
|
||||
Reflection.setValue(packet, "f", "never"); // Collision rule
|
||||
// Reflection.setValue(packet, "g", news.size()); // Player count
|
||||
Reflection.setValue(packet, "h", news); // Players
|
||||
// Reflection.setValue(packet, "i", n); // Action id
|
||||
// Reflection.setValue(packet, "j", 0); // Friendly fire
|
||||
Reflection.setValue(packet, "i", n); // Action id
|
||||
Reflection.setValue(packet, "j", 0); // Friendly fire
|
||||
|
||||
return packet;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object makePacket(VTeam team, int n)
|
||||
{
|
||||
return makePacket(team, team.getPlayers(), n);
|
||||
}
|
||||
}
|
||||
|
||||
public class VTeam {
|
||||
private String name = "";
|
||||
private String realName = "";
|
||||
private String display = "";
|
||||
private String prefix = ChatColor.GRAY + "";
|
||||
private String suffix = "";
|
||||
private boolean hideToOtherTeams = false;
|
||||
|
||||
private final CopyOnWriteArrayList<String> players = new CopyOnWriteArrayList<>();
|
||||
|
||||
public VTeam(String name, String display) {
|
||||
this.name = name;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public VTeam(String name, String realName, String display, String prefix, String suffix) {
|
||||
this.name = name;
|
||||
this.realName = realName;
|
||||
this.display = display;
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return this.display;
|
||||
}
|
||||
|
||||
public void setDisplayName(String dn) {
|
||||
this.display = dn;
|
||||
}
|
||||
|
||||
public String getPrefix()
|
||||
{
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String p)
|
||||
{
|
||||
this.prefix = p.substring(0, Math.min(p.length(), 16));
|
||||
}
|
||||
|
||||
public String getSuffix()
|
||||
{
|
||||
return this.suffix;
|
||||
}
|
||||
|
||||
public void setSuffix(String s)
|
||||
{
|
||||
this.suffix = s.substring(0, Math.min(s.length(), 16));
|
||||
}
|
||||
|
||||
public boolean contains(OfflinePlayer op)
|
||||
{
|
||||
return this.players.contains(op.getName());
|
||||
}
|
||||
|
||||
public boolean contains(String op) {
|
||||
return this.players.contains(op);
|
||||
}
|
||||
|
||||
public List<String> getPlayers() {
|
||||
return this.players;
|
||||
}
|
||||
|
||||
public void addPlayer(OfflinePlayer op) {
|
||||
this.players.add(op.getName());
|
||||
}
|
||||
|
||||
public void addPlayer(String op) {
|
||||
this.players.add(op);
|
||||
}
|
||||
|
||||
public void removePlayer(OfflinePlayer op) {
|
||||
if (this.contains(op))
|
||||
this.players.remove(op.getName());
|
||||
}
|
||||
|
||||
public void removePlayer(String op) {
|
||||
this.players.remove(op);
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return this.players.size();
|
||||
}
|
||||
|
||||
public String getRealName() {
|
||||
return this.realName;
|
||||
}
|
||||
|
||||
public void setRealName(String realName) {
|
||||
this.realName = realName;
|
||||
}
|
||||
|
||||
public void setHideToOtherTeams(boolean hideToOtherTeams) {
|
||||
this.hideToOtherTeams = hideToOtherTeams;
|
||||
}
|
||||
|
||||
public boolean getHideToOtherTeams() {
|
||||
return this.hideToOtherTeams;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user