public static class ScoreAPI { private static Class<?> CRAFT_SCORE = NMSUtil.getClassBukkit("scoreboard.CraftScore"); private static Class<?> CRAFT_OBJECTIVE = NMSUtil.getClassBukkit("scoreboard.CraftObjective"); private static Class<?> CRAFT_SCOREBOARD = NMSUtil.getClassBukkit("scoreboard.CraftScoreboard"); private static Class<?> CRAFT_SCOREBOARD_COMPONENT = NMSUtil.getClassBukkit("scoreboard.CraftScoreboardComponent"); private static Class<?> SCOREBOARD = NMSUtil.getClassNMS("Scoreboard"); private static Class<?> SCOREBOARD_SCORE = NMSUtil.getClassNMS("ScoreboardScore"); private static Class<?> SCOREBOARD_OBJECTIVE = NMSUtil.getClassNMS("ScoreboardObjective"); public static boolean isSet(Score score) { try { return isSetException(score); } catch (Exception e) { e.printStackTrace(); return false; } } private static boolean isSetException(Score score) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { Object craftScore = CRAFT_SCORE.cast(score); Object craftObjective = CRAFT_OBJECTIVE.cast(score.getObjective()); Method craftHandle = CRAFT_OBJECTIVE.getDeclaredMethod("getHandle"); craftHandle.setAccessible(true); Object craftObjectiveHandle = craftHandle.invoke(craftObjective); Field objective = CRAFT_SCORE.getDeclaredField("objective"); objective.setAccessible(true); Object craftScoreboard = checkState(objective.get(craftScore)); Field craftBoard = CRAFT_SCOREBOARD.getDeclaredField("board"); craftBoard.setAccessible(true); Object scoreboard = craftBoard.get(craftScoreboard); Method playerObjectives = SCOREBOARD.getDeclaredMethod("getPlayerObjectives", String.class); playerObjectives.setAccessible(true); Field playerField = CRAFT_SCORE.getDeclaredField("entry"); playerField.setAccessible(true); String playerName = (String) playerField.get(craftScore); Map map = (Map) playerObjectives.invoke(scoreboard, playerName); // return // objective.checkState().board.getPlayerObjectives(playerName).containsKey(objective.getHandle()); return map.containsKey(craftObjectiveHandle); } public static void reset(Score score) { try { resetException(score); } catch (Exception e) { e.printStackTrace(); } } private static void resetException(Score score) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { Object craftScore = CRAFT_SCORE.cast(score); Object craftObjective = CRAFT_OBJECTIVE.cast(score.getObjective()); Method craftHandle = CRAFT_OBJECTIVE.getDeclaredMethod("getHandle"); craftHandle.setAccessible(true); Object craftObjectiveHandle = craftHandle.invoke(craftObjective); Field objective = CRAFT_SCORE.getDeclaredField("objective"); objective.setAccessible(true); Object craftScoreboard = checkState(objective.get(craftScore)); /* Method checkState = CRAFT_OBJECTIVE.getDeclaredMethod("checkState"); checkState.setAccessible(true); craftScoreboard = checkState.invoke(CRAFT_SCORE.getDeclaredField("objective").get(craftScore)); */ Field scoreboardField = CRAFT_SCOREBOARD.getDeclaredField("board"); scoreboardField.setAccessible(true); Object scoreboard = scoreboardField.get(craftScoreboard); Method playerObjectives = SCOREBOARD.getDeclaredMethod("getPlayerObjectives", String.class); playerObjectives.setAccessible(true); Field playerField = CRAFT_SCORE.getDeclaredField("playerName"); playerField.setAccessible(true); String playerName = (String) playerField.get(craftScore); Map map = (Map) playerObjectives.invoke(scoreboard, playerName); if (map.remove(craftObjectiveHandle) == null) { // If they don't have a score to delete, don't delete it. return; } Method resetScores = SCOREBOARD.getDeclaredMethod("resetPlayerScores", String.class); resetScores.setAccessible(true); resetScores.invoke(scoreboard, playerName); for (Object key : map.keySet()) { Object value = map.get(key); Method playerScoreMethod = SCOREBOARD.getDeclaredMethod( "getPlayerScoreForObjective", String.class, SCOREBOARD_OBJECTIVE); playerScoreMethod.setAccessible(true); Object scoreboardScore = playerScoreMethod.invoke(scoreboard, playerName, key); Method getScore = SCOREBOARD_SCORE.getDeclaredMethod("getScore"); getScore.setAccessible(true); int setScoreTo = (int) getScore.invoke(value); Method setScore = SCOREBOARD_SCORE.getDeclaredMethod("setScore", int.class); setScore.setAccessible(true); setScore.invoke(scoreboardScore, setScoreTo); } /* CraftScoreboard myBoard = objective.checkState(); Map<ScoreboardObjective, ScoreboardScore> savedScores = myBoard.board.getPlayerObjectives(playerName); if(savedScores.remove(objective.getHandle()) == null) { // If they don't have a score to delete, don't delete it. return; } myBoard.board.resetPlayerScores(playerName); for(Map.Entry<ScoreboardObjective, ScoreboardScore> e : savedScores.entrySet()) { myBoard.board.getPlayerScoreForObjective(playerName, e.getKey()).setScore(e.getValue().getScore()); } */ } public static Object checkState(Object craftObjective) { try { return checkStateException(craftObjective); } catch (Exception e) { e.printStackTrace(); } return null; } public static Object checkStateException(Object craftObjective) throws NoSuchFieldException, IllegalAccessException { Object boardComponent = CRAFT_SCOREBOARD_COMPONENT.cast(craftObjective); Field scoreboard = CRAFT_SCOREBOARD_COMPONENT.getDeclaredField("scoreboard"); scoreboard.setAccessible(true); Object craftBoard = scoreboard.get(boardComponent); if (craftBoard == null) { throw new IllegalStateException("Unregistered scoreboard component"); } return craftBoard; /* CraftScoreboard scoreboard = this.scoreboard; if(scoreboard == null) { throw new IllegalStateException("Unregistered scoreboard component"); } return scoreboard; */ } }
@Override public void run() { if (complete) return; // Log.debug((NumberUtil.randomBoolean() ? "tick" : "tock")); Rotation rotation = Rotation.get(); RotationSlot next = rotation.getNext(); rotation.setRestart(); if (!rotation.isRestarting()) { next.load(true); } this.next = next; String what = getMessage(); ChatColor colour = ChatColor.GRAY; if (next != null) { colour = ChatColor.DARK_AQUA; } try { List<User> players = match.getMap().getWinner().getPlayers(); if (players.size() > 0 && isFullSecond()) { // check for more than 1 player User player = players.get(NumberUtil.getRandom(0, players.size() - 1)); Location location = player.getPlayer().getLocation(); Firework firework = (Firework) location.getWorld().spawnEntity(location, EntityType.FIREWORK); FireworkMeta meta = firework.getFireworkMeta(); meta.clearEffects(); meta.addEffect(getFirework()); firework.setFireworkMeta(meta); try { firework.detonate(); } catch (Exception e) { Log.warning( "Server isn't running a version of Bukkit which allows the use of Firework.detonate() - resorting to manual detonation."); try { Object craft = NMSUtil.getClassBukkit("entity.CraftFirework").cast(firework); Method method = craft.getClass().getMethod("getHandle"); method.setAccessible(true); Object handle = method.invoke(craft); handle.getClass().getField("expectedLifespan").set(handle, 0); } catch (Exception e2) { e2.printStackTrace(); } } } } catch (NullPointerException ignored) { } if (duration <= 0 && next == null) { for (User player : User.getUsers()) { player.getPlayer().kickPlayer(ChatColor.GREEN + "Server restarting!"); } complete = true; Bukkit.getServer().shutdown(); return; } if (duration <= 0) { broadcast(what + "!"); match.stop(); complete = true; rotation.cycle(); return; } boolean show = false; if (getTicks() % 20 == 0) { if (getSeconds() % 30 == 0) show = true; else if (getSeconds() < 30 && getSeconds() % 15 == 0) show = true; else if (getSeconds() < 15 && getSeconds() % 5 == 0) show = true; else if (getSeconds() < 5) show = true; } if (show) broadcast( what + " in " + ChatColor.RED + getSeconds() + " second" + (getSeconds() != 1 ? "s" : "") + colour + "!"); setTicks(getTicks() - 1); }