Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1 from CherryCraftMC/scoreboard-system
Browse files Browse the repository at this point in the history
Implement Scoreboard system and utilities
  • Loading branch information
mathiasclari authored Dec 27, 2023
2 parents fd17349 + 3962810 commit 7a1893b
Show file tree
Hide file tree
Showing 7 changed files with 1,091 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/main/java/net/cherrycraft/cherrycore/CherryCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public void onEnable() {
languageManager.loadAllLanguages();
Loader.registerCommands(this);
Loader.registerListeners(this);
Loader.registerTasks(this);
Loader.loadWorlds(this);
logger.info("ReefCore has been enabled.");
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/net/cherrycraft/cherrycore/Loader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.cherrycraft.cherrycore.languageSystem.command.LanguageCommand;
import net.cherrycraft.cherrycore.manager.CommandManager;
import net.cherrycraft.cherrycore.manager.LanguageManager;
import net.cherrycraft.cherrycore.scoreboard.Scoreboard;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;

Expand All @@ -27,6 +28,12 @@ public static void registerListeners(CherryCore plugin) {
Bukkit.getPluginManager().registerEvents(new ChatHistoryLogger(), plugin);
Bukkit.getPluginManager().registerEvents(new LanguageManager(), plugin);
Bukkit.getPluginManager().registerEvents(new ChatSystem(), plugin);
Bukkit.getPluginManager().registerEvents(new Scoreboard(), plugin);
}

public static void registerTasks(CherryCore plugin) {
Scoreboard scoreboard = new Scoreboard();

}

public static void loadWorlds(CherryCore plugin) {
Expand Down
124 changes: 124 additions & 0 deletions src/main/java/net/cherrycraft/cherrycore/scoreboard/Scoreboard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package net.cherrycraft.cherrycore.scoreboard;

import me.clip.placeholderapi.PlaceholderAPI;
import net.cherrycraft.cherrycore.CherryCore;
import net.cherrycraft.cherrycore.utils.scoreboard.adventure.ScoreboardSystem;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Scoreboard implements Listener {

private final Map<UUID, ScoreboardSystem> boards = new HashMap<>();
MiniMessage miniMessage = MiniMessage.builder().build();
LegacyComponentSerializer serializer = LegacyComponentSerializer.legacySection();

private String serverType;

@EventHandler
public void playerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();

ScoreboardSystem board = this.boards.remove(player.getUniqueId());

if (board != null) {
board.delete();
}

}

@EventHandler(priority = EventPriority.HIGHEST)
public void playerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
String serverType = CherryCore.getInstance().getConfig().getString("server-type");

if (serverType == null) {
serverType = CherryCore.getInstance().getConfig().getString("server-type");

if (serverType == null) {
Bukkit.getLogger().severe("Server type is not set in the config file.");
return;
}
}

switch (serverType) {
case "skypvp":
setupSkyPVPScoreboard(player);
System.out.println("SkyPVP scoreboard set up for " + player.getName());
break;
case "lobby":
setupLobbyScoreboard(player);
System.out.println("Lobby scoreboard set up for " + player.getName());
break;
default:
Bukkit.getLogger().severe("Unknown server type: " + serverType);
break;
}
}


private void setupSkyPVPScoreboard(Player player) {
ScoreboardSystem scoreboard = new ScoreboardSystem(player);
scoreboard.updateTitle(miniMessage.deserialize("<#C81F3B><bold>Cherry<#31AF14><bold>Craft"));
updateBoardSkyPVP(scoreboard);
Bukkit.getScheduler().runTaskTimerAsynchronously(CherryCore.getInstance(), () -> {
for (ScoreboardSystem board : this.boards.values()) {
updateBoardSkyPVP(board);
}
}, 0L, 20L);

this.boards.put(player.getUniqueId(), scoreboard);
}

private void setupLobbyScoreboard(Player player) {
ScoreboardSystem scoreboard = new ScoreboardSystem(player);
scoreboard.updateTitle(miniMessage.deserialize("<#C81F3B><bold>Cherry<#31AF14><bold>Craft"));
updateBoardLobby(scoreboard);
Bukkit.getScheduler().runTaskTimerAsynchronously(CherryCore.getInstance(), () -> {
for (ScoreboardSystem board : this.boards.values()) {
updateBoardLobby(board);
}
}, 0L, 20L);
this.boards.put(player.getUniqueId(), scoreboard);
}

private void updateBoardSkyPVP(ScoreboardSystem board) {
board.updateLines(

miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Level <#31AF14>%reefrealmskypvp_level%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Progress: <#31AF14>%reefrealmskypvp_required_score%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<gray>[%reefrealmskypvp_progress%<gray>]")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Coins: <#31AF14>%reefrealmskypvp_coins%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>K/D: <#31AF14>%reefrealmskypvp_kd%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Kills: <#31AF14>%reefrealmskypvp_kills%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Deaths: <#31AF14>%reefrealmskypvp_deaths%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Killstreak: <#31AF14>%reefrealmskypvp_killstreak%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<#C81F3B>cherrycraft.net"))
);
}

private void updateBoardLobby(ScoreboardSystem board) {
board.updateLines(

miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<white>Rank %luckperms_prefix%")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "")),
miniMessage.deserialize(PlaceholderAPI.setPlaceholders(board.getPlayer(), "<#C81F3B>cherrycraft.net"))
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package net.cherrycraft.cherrycore.utils.scoreboard;

import org.bukkit.Bukkit;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
import java.util.Optional;
import java.util.function.Predicate;

/**
* Small reflection utility class to use CraftBukkit and NMS.
*
* @author MrMicky
*/
public final class FastReflection {

public static final String OBC_PACKAGE = "org.bukkit.craftbukkit";
public static final String VERSION = Bukkit.getServer().getClass().getPackage().getName().substring(OBC_PACKAGE.length() + 1);
private static final String NM_PACKAGE = "net.minecraft";
public static final String NMS_PACKAGE = NM_PACKAGE + ".server";
private static final MethodType VOID_METHOD_TYPE = MethodType.methodType(void.class);
private static final boolean NMS_REPACKAGED = optionalClass(NM_PACKAGE + ".network.protocol.Packet").isPresent();

private static volatile Object theUnsafe;

private FastReflection() {
throw new UnsupportedOperationException();
}

public static boolean isRepackaged() {
return NMS_REPACKAGED;
}

public static String nmsClassName(String post1_17package, String className) {
if (NMS_REPACKAGED) {
String classPackage = post1_17package == null ? NM_PACKAGE : NM_PACKAGE + '.' + post1_17package;
return classPackage + '.' + className;
}
return NMS_PACKAGE + '.' + VERSION + '.' + className;
}

public static Class<?> nmsClass(String post1_17package, String className) throws ClassNotFoundException {
return Class.forName(nmsClassName(post1_17package, className));
}

public static Optional<Class<?>> nmsOptionalClass(String post1_17package, String className) {
return optionalClass(nmsClassName(post1_17package, 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();
}
}

public static Object enumValueOf(Class<?> enumClass, String enumName) {
return Enum.valueOf(enumClass.asSubclass(Enum.class), enumName);
}

public static Object enumValueOf(Class<?> enumClass, String enumName, int fallbackOrdinal) {
try {
return enumValueOf(enumClass, enumName);
} catch (IllegalArgumentException e) {
Object[] constants = enumClass.getEnumConstants();
if (constants.length > fallbackOrdinal) {
return constants[fallbackOrdinal];
}
throw e;
}
}

static Class<?> innerClass(Class<?> parentClass, Predicate<Class<?>> classPredicate) throws ClassNotFoundException {
for (Class<?> innerClass : parentClass.getDeclaredClasses()) {
if (classPredicate.test(innerClass)) {
return innerClass;
}
}
throw new ClassNotFoundException("No class in " + parentClass.getCanonicalName() + " matches the predicate.");
}

public static PacketConstructor findPacketConstructor(Class<?> packetClass, MethodHandles.Lookup lookup) throws Exception {
try {
MethodHandle constructor = lookup.findConstructor(packetClass, VOID_METHOD_TYPE);
return constructor::invoke;
} catch (NoSuchMethodException | IllegalAccessException e) {
// try below with Unsafe
}

if (theUnsafe == null) {
synchronized (FastReflection.class) {
if (theUnsafe == null) {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
Field theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
theUnsafe = theUnsafeField.get(null);
}
}
}

MethodType allocateMethodType = MethodType.methodType(Object.class, Class.class);
MethodHandle allocateMethod = lookup.findVirtual(theUnsafe.getClass(), "allocateInstance", allocateMethodType);
return () -> allocateMethod.invoke(theUnsafe, packetClass);
}

@FunctionalInterface
interface PacketConstructor {
Object invoke() throws Throwable;
}
}
Loading

0 comments on commit 7a1893b

Please sign in to comment.