v4.6.5-OG release
This commit is contained in:
1 parent
c51fd2bd97
commit
7afb98e35c
15 files changed
+629
-20
No files matched your search
@@ -1,3 +1,8 @@
|
||||
4.6.5-OG:
|
||||
- Hide cosmetics while a player is in a Duels-OG match and restore them when it ends
|
||||
- Hide cosmetics while a player is combat tagged by EternalCombat-OG and restore them on untag
|
||||
- Add enabled-worlds whitelist, defaulting to world, world_nether and world_the_end
|
||||
|
||||
4.6.2-OG:
|
||||
- Use TrueOG Network live config files
|
||||
- Bundle default particles.yml into .jar
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ kotlin { jvmToolchain(17) }
|
||||
/* ----------------------------- Metadata ------------------------------ */
|
||||
group = "net.trueog.cosmetics-og" // Declare bundle identifier.
|
||||
|
||||
version = "4.6.4" // Declare plugin version (will be in .jar).
|
||||
version = "4.6.5" // Declare plugin version (will be in .jar).
|
||||
|
||||
val apiVersion = "1.19" // Declare minecraft server target version.
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
package cosmeticsOG.hooks;
|
||||
|
||||
import cosmeticsOG.CosmeticsOG;
|
||||
import cosmeticsOG.player.EntityState;
|
||||
import cosmeticsOG.player.SuppressionSource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.EventExecutor;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
// Hides cosmetics while a player is in a Duels-OG match and restores them when it ends.
|
||||
// Talks to the Duels-OG API through reflection so Duels-OG stays an optional dependency.
|
||||
public class DuelsHook implements Listener {
|
||||
|
||||
private static final String DUELS_API_CLASS = "me.realized.duels.api.Duels";
|
||||
private static final String MATCH_START_EVENT_CLASS = "me.realized.duels.api.event.match.MatchStartEvent";
|
||||
private static final String MATCH_END_EVENT_CLASS = "me.realized.duels.api.event.match.MatchEndEvent";
|
||||
|
||||
private final CosmeticsOG core;
|
||||
private final Plugin duelsPlugin;
|
||||
|
||||
private final Method getArenaManagerMethod;
|
||||
private final Method isInMatchMethod;
|
||||
private final Method getStartPlayersMethod;
|
||||
private final Method getMatchMethod;
|
||||
private final Method getStartingPlayersMethod;
|
||||
|
||||
public DuelsHook(final CosmeticsOG core, final Plugin duelsPlugin) throws ReflectiveOperationException {
|
||||
|
||||
this.core = core;
|
||||
this.duelsPlugin = duelsPlugin;
|
||||
|
||||
final ClassLoader loader = duelsPlugin.getClass().getClassLoader();
|
||||
|
||||
final Class<?> duelsApiClass = Class.forName(DUELS_API_CLASS, false, loader);
|
||||
if (!duelsApiClass.isInstance(duelsPlugin)) {
|
||||
|
||||
throw new ClassNotFoundException(duelsPlugin.getName() + " does not implement " + DUELS_API_CLASS);
|
||||
|
||||
}
|
||||
|
||||
getArenaManagerMethod = duelsApiClass.getMethod("getArenaManager");
|
||||
isInMatchMethod = getArenaManagerMethod.getReturnType().getMethod("isInMatch", Player.class);
|
||||
|
||||
final Class<?> startEventClass = Class.forName(MATCH_START_EVENT_CLASS, false, loader);
|
||||
getStartPlayersMethod = startEventClass.getMethod("getPlayers");
|
||||
|
||||
final Class<?> endEventClass = Class.forName(MATCH_END_EVENT_CLASS, false, loader);
|
||||
getMatchMethod = endEventClass.getMethod("getMatch");
|
||||
getStartingPlayersMethod = getMatchMethod.getReturnType().getMethod("getStartingPlayers");
|
||||
|
||||
registerMatchEvent(startEventClass.asSubclass(Event.class), true);
|
||||
registerMatchEvent(endEventClass.asSubclass(Event.class), false);
|
||||
|
||||
syncOnlinePlayers();
|
||||
|
||||
}
|
||||
|
||||
// Returns true if Duels-OG currently has this player in a match.
|
||||
public boolean isInMatch(Player player) {
|
||||
|
||||
if (!duelsPlugin.isEnabled()) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
final Object arenaManager = getArenaManagerMethod.invoke(duelsPlugin);
|
||||
return arenaManager != null && Boolean.TRUE.equals(isInMatchMethod.invoke(arenaManager, player));
|
||||
|
||||
} catch (ReflectiveOperationException | RuntimeException ignored) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Unregisters the match listeners and restores cosmetics for everyone still
|
||||
// suppressed.
|
||||
public void unregister() {
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
|
||||
for (EntityState entityState : core.getEntityStates()) {
|
||||
|
||||
entityState.setSuppressed(SuppressionSource.DUEL, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void registerMatchEvent(Class<? extends Event> eventClass, boolean matchStarted) {
|
||||
|
||||
final EventExecutor executor = (listener, event) -> handleMatchEvent(event, matchStarted);
|
||||
core.getServer().getPluginManager().registerEvent(eventClass, this, EventPriority.MONITOR, executor, core,
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
private void handleMatchEvent(Event event, boolean matchStarted) {
|
||||
|
||||
try {
|
||||
|
||||
if (matchStarted) {
|
||||
|
||||
final Object players = getStartPlayersMethod.invoke(event);
|
||||
if (players instanceof Player[]) {
|
||||
|
||||
for (Player player : (Player[]) players) {
|
||||
|
||||
setSuppressed(player, true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// The end event carries UUIDs only, so read both starting players from the
|
||||
// match.
|
||||
final Object match = getMatchMethod.invoke(event);
|
||||
if (match == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
final Object players = getStartingPlayersMethod.invoke(match);
|
||||
if (players instanceof Collection) {
|
||||
|
||||
for (Object player : (Collection<?>) players) {
|
||||
|
||||
if (player instanceof Player) {
|
||||
|
||||
setSuppressed((Player) player, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (ReflectiveOperationException | RuntimeException ignored) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void syncOnlinePlayers() {
|
||||
|
||||
for (Player player : core.getServer().getOnlinePlayers()) {
|
||||
|
||||
setSuppressed(player, isInMatch(player));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setSuppressed(Player player, boolean suppressed) {
|
||||
|
||||
if (player == null || !core.hasEntityState(player)) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
core.getPlayerState(player).setSuppressed(SuppressionSource.DUEL, suppressed);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package cosmeticsOG.hooks;
|
||||
|
||||
import cosmeticsOG.CosmeticsOG;
|
||||
import cosmeticsOG.player.EntityState;
|
||||
import cosmeticsOG.player.SuppressionSource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.plugin.EventExecutor;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
// Hides cosmetics while EternalCombat-OG has a player combat tagged, restores on untag.
|
||||
// Talks to the EternalCombat-OG API through reflection so it stays an optional dependency.
|
||||
public class EternalCombatHook implements Listener {
|
||||
|
||||
private static final String API_CLASS = "com.eternalcode.combat.EternalCombatApi";
|
||||
private static final String TAG_EVENT_CLASS = "com.eternalcode.combat.fight.event.FightTagEvent";
|
||||
private static final String UNTAG_EVENT_CLASS = "com.eternalcode.combat.fight.event.FightUntagEvent";
|
||||
|
||||
private final CosmeticsOG core;
|
||||
private final Plugin combatPlugin;
|
||||
|
||||
private final Method getFightManagerMethod;
|
||||
private final Method isInCombatMethod;
|
||||
private final Method getTagPlayerMethod;
|
||||
private final Method getUntagPlayerMethod;
|
||||
|
||||
public EternalCombatHook(final CosmeticsOG core, final Plugin combatPlugin) throws ReflectiveOperationException {
|
||||
|
||||
this.core = core;
|
||||
this.combatPlugin = combatPlugin;
|
||||
|
||||
final ClassLoader loader = combatPlugin.getClass().getClassLoader();
|
||||
|
||||
final Class<?> apiClass = Class.forName(API_CLASS, false, loader);
|
||||
if (!apiClass.isInstance(combatPlugin)) {
|
||||
|
||||
throw new ClassNotFoundException(combatPlugin.getName() + " does not implement " + API_CLASS);
|
||||
|
||||
}
|
||||
|
||||
getFightManagerMethod = apiClass.getMethod("getFightManager");
|
||||
isInCombatMethod = getFightManagerMethod.getReturnType().getMethod("isInCombat", UUID.class);
|
||||
|
||||
final Class<?> tagEventClass = Class.forName(TAG_EVENT_CLASS, false, loader);
|
||||
getTagPlayerMethod = tagEventClass.getMethod("getPlayer");
|
||||
|
||||
final Class<?> untagEventClass = Class.forName(UNTAG_EVENT_CLASS, false, loader);
|
||||
getUntagPlayerMethod = untagEventClass.getMethod("getPlayer");
|
||||
|
||||
registerTagEvent(tagEventClass.asSubclass(Event.class), getTagPlayerMethod, true);
|
||||
registerTagEvent(untagEventClass.asSubclass(Event.class), getUntagPlayerMethod, false);
|
||||
core.getServer().getPluginManager().registerEvents(this, core);
|
||||
|
||||
syncOnlinePlayers();
|
||||
|
||||
}
|
||||
|
||||
// Returns true if EternalCombat-OG currently has this player combat tagged.
|
||||
public boolean isInCombat(Player player) {
|
||||
|
||||
if (!combatPlugin.isEnabled()) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
final Object fightManager = getFightManagerMethod.invoke(combatPlugin);
|
||||
return fightManager != null
|
||||
&& Boolean.TRUE.equals(isInCombatMethod.invoke(fightManager, player.getUniqueId()));
|
||||
|
||||
} catch (ReflectiveOperationException | RuntimeException ignored) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Unregisters the listeners and restores cosmetics for everyone still tagged.
|
||||
public void unregister() {
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
clearAll();
|
||||
|
||||
}
|
||||
|
||||
// Tags never get released once the plugin is gone, so drop them here.
|
||||
@EventHandler
|
||||
public void onPluginDisable(PluginDisableEvent event) {
|
||||
|
||||
if (event.getPlugin().equals(combatPlugin)) {
|
||||
|
||||
clearAll();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void registerTagEvent(Class<? extends Event> eventClass, Method getPlayerMethod, boolean tagged) {
|
||||
|
||||
// Cancelled tag or untag events leave the combat state unchanged, so skip them.
|
||||
final EventExecutor executor = (listener, event) -> handleTagEvent(event, getPlayerMethod, tagged);
|
||||
core.getServer().getPluginManager().registerEvent(eventClass, this, EventPriority.MONITOR, executor, core,
|
||||
true);
|
||||
|
||||
}
|
||||
|
||||
private void handleTagEvent(Event event, Method getPlayerMethod, boolean tagged) {
|
||||
|
||||
try {
|
||||
|
||||
final Object playerId = getPlayerMethod.invoke(event);
|
||||
if (playerId instanceof UUID) {
|
||||
|
||||
setSuppressed(core.getServer().getPlayer((UUID) playerId), tagged);
|
||||
|
||||
}
|
||||
|
||||
} catch (ReflectiveOperationException | RuntimeException ignored) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void syncOnlinePlayers() {
|
||||
|
||||
for (Player player : core.getServer().getOnlinePlayers()) {
|
||||
|
||||
setSuppressed(player, isInCombat(player));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void clearAll() {
|
||||
|
||||
for (EntityState entityState : core.getEntityStates()) {
|
||||
|
||||
entityState.setSuppressed(SuppressionSource.COMBAT, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setSuppressed(Player player, boolean suppressed) {
|
||||
|
||||
if (player == null || !core.hasEntityState(player)) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
core.getPlayerState(player).setSuppressed(SuppressionSource.COMBAT, suppressed);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,11 +3,14 @@ package cosmeticsOG.listeners;
|
||||
import cosmeticsOG.CosmeticsOG;
|
||||
import cosmeticsOG.database.type.DatabaseType;
|
||||
import cosmeticsOG.database.type.yaml.YamlDatabase;
|
||||
import cosmeticsOG.hooks.DuelsHook;
|
||||
import cosmeticsOG.hooks.EternalCombatHook;
|
||||
import cosmeticsOG.hooks.VanishHook;
|
||||
import cosmeticsOG.managers.SettingsManager;
|
||||
import cosmeticsOG.particles.Hat;
|
||||
import cosmeticsOG.particles.HatReference;
|
||||
import cosmeticsOG.player.PlayerState;
|
||||
import cosmeticsOG.player.SuppressionSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -38,6 +41,12 @@ public class ConnectionListener implements Listener {
|
||||
VanishHook vanishHook = core.getHookManager().getVanishHook();
|
||||
boolean isVanished = vanishHook != null && vanishHook.isVanished(player);
|
||||
|
||||
// Keep cosmetics hidden if the player is already mid-duel or combat tagged.
|
||||
DuelsHook duelsHook = core.getHookManager().getDuelsHook();
|
||||
playerState.setSuppressed(SuppressionSource.DUEL, duelsHook != null && duelsHook.isInMatch(player));
|
||||
EternalCombatHook combatHook = core.getHookManager().getEternalCombatHook();
|
||||
playerState.setSuppressed(SuppressionSource.COMBAT, combatHook != null && combatHook.isInCombat(player));
|
||||
|
||||
// Load equipped hats
|
||||
core.getDatabase().loadPlayerEquippedHats(id, (loadedHats) -> {
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import cosmeticsOG.CosmeticsOG;
|
||||
import cosmeticsOG.hooks.DuelsHook;
|
||||
import cosmeticsOG.hooks.EternalCombatHook;
|
||||
import cosmeticsOG.hooks.VanishHook;
|
||||
import cosmeticsOG.hooks.vanish.SuperVanishHook;
|
||||
import net.trueog.utilitiesog.UtilitiesOG;
|
||||
@@ -12,10 +14,14 @@ public class HookManager {
|
||||
|
||||
private static final String[] VANISH_PLUGIN_NAMES = { "Vanish-OG", "SuperVanish", "PremiumVanish",
|
||||
"VanishNoPacket" };
|
||||
private static final String DUELS_PLUGIN_NAME = "Duels-OG";
|
||||
private static final String ETERNALCOMBAT_PLUGIN_NAME = "EternalCombat-OG";
|
||||
|
||||
private final CosmeticsOG core;
|
||||
|
||||
private VanishHook vanishHook;
|
||||
private DuelsHook duelsHook;
|
||||
private EternalCombatHook eternalCombatHook;
|
||||
|
||||
public HookManager(final CosmeticsOG core) {
|
||||
|
||||
@@ -42,6 +48,21 @@ public class HookManager {
|
||||
|
||||
}
|
||||
|
||||
// Returns the Duels-OG hook, or null when Duels-OG is absent or the flag is
|
||||
// off.
|
||||
public DuelsHook getDuelsHook() {
|
||||
|
||||
return duelsHook;
|
||||
|
||||
}
|
||||
|
||||
// Returns the EternalCombat-OG hook, or null when absent or the flag is off.
|
||||
public EternalCombatHook getEternalCombatHook() {
|
||||
|
||||
return eternalCombatHook;
|
||||
|
||||
}
|
||||
|
||||
private void loadHooks() {
|
||||
|
||||
final PluginManager pluginManager = core.getServer().getPluginManager();
|
||||
@@ -88,6 +109,121 @@ public class HookManager {
|
||||
|
||||
}
|
||||
|
||||
loadDuelsHook(pluginManager);
|
||||
loadEternalCombatHook(pluginManager);
|
||||
|
||||
}
|
||||
|
||||
// Hides cosmetics during Duels-OG matches while the flag is on and Duels-OG is
|
||||
// loaded.
|
||||
private void loadDuelsHook(PluginManager pluginManager) {
|
||||
|
||||
if (!SettingsManager.FLAG_DUELS.getBoolean()) {
|
||||
|
||||
if (duelsHook != null) {
|
||||
|
||||
duelsHook.unregister();
|
||||
duelsHook = null;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (duelsHook != null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
final Plugin duelsPlugin = getEnabledPlugin(pluginManager, DUELS_PLUGIN_NAME);
|
||||
if (duelsPlugin == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
duelsHook = new DuelsHook(core, duelsPlugin);
|
||||
|
||||
UtilitiesOG.logToConsole(CosmeticsOG.getPrefix(), "Hooking into " + DUELS_PLUGIN_NAME + "...");
|
||||
|
||||
} catch (ReflectiveOperationException | RuntimeException exception) {
|
||||
|
||||
logUnsupported(DUELS_PLUGIN_NAME, exception);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Hides cosmetics while EternalCombat-OG combat tags a player, if the flag is
|
||||
// on.
|
||||
private void loadEternalCombatHook(PluginManager pluginManager) {
|
||||
|
||||
if (!SettingsManager.FLAG_ETERNALCOMBAT.getBoolean()) {
|
||||
|
||||
if (eternalCombatHook != null) {
|
||||
|
||||
eternalCombatHook.unregister();
|
||||
eternalCombatHook = null;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (eternalCombatHook != null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
final Plugin combatPlugin = getEnabledPlugin(pluginManager, ETERNALCOMBAT_PLUGIN_NAME);
|
||||
if (combatPlugin == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
eternalCombatHook = new EternalCombatHook(core, combatPlugin);
|
||||
|
||||
UtilitiesOG.logToConsole(CosmeticsOG.getPrefix(), "Hooking into " + ETERNALCOMBAT_PLUGIN_NAME + "...");
|
||||
|
||||
} catch (ReflectiveOperationException | RuntimeException exception) {
|
||||
|
||||
logUnsupported(ETERNALCOMBAT_PLUGIN_NAME, exception);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Returns the named plugin if it is enabled, otherwise warns and returns null.
|
||||
private Plugin getEnabledPlugin(PluginManager pluginManager, String pluginName) {
|
||||
|
||||
final Plugin plugin = pluginManager.getPlugin(pluginName);
|
||||
if (plugin == null || !plugin.isEnabled()) {
|
||||
|
||||
UtilitiesOG.logToConsole(CosmeticsOG.getPrefix(),
|
||||
"WARNING: Could not find " + pluginName + ", disabling its cosmetics hook!");
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
return plugin;
|
||||
|
||||
}
|
||||
|
||||
private void logUnsupported(String pluginName, Exception exception) {
|
||||
|
||||
UtilitiesOG.logToConsole(CosmeticsOG.getPrefix(), "WARNING: Unsupported " + pluginName + " version ("
|
||||
+ exception.getMessage() + "), disabling its cosmetics hook!");
|
||||
|
||||
}
|
||||
|
||||
private Plugin getEnabledVanishPlugin(PluginManager pluginManager) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cosmeticsOG.managers;
|
||||
|
||||
import cosmeticsOG.util.WorldUtil;
|
||||
import cosmeticsOG.CosmeticsOG;
|
||||
import cosmeticsOG.hooks.VanishHook;
|
||||
import cosmeticsOG.locale.Message;
|
||||
@@ -14,7 +15,6 @@ import cosmeticsOG.ui.StaticMenuManager;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -115,10 +115,9 @@ public class ParticleManager {
|
||||
|
||||
PlayerState playerState = core.getPlayerState(player);
|
||||
String worldName = player.getWorld().getName().toLowerCase();
|
||||
List<String> disabledWorlds = SettingsManager.DISABLED_WORLDS.getList();
|
||||
|
||||
// Disabled World.
|
||||
if (disabledWorlds.contains(worldName)) {
|
||||
// World not allowed by the whitelist or blacklist.
|
||||
if (!WorldUtil.isEnabled(worldName)) {
|
||||
|
||||
CosmeticsOG.chatMessage(player, Message.WORLD_DISABLED.getValue());
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import cosmeticsOG.util.ItemUtil;
|
||||
import cosmeticsOG.util.MathUtil;
|
||||
import cosmeticsOG.util.ResourceUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Material;
|
||||
@@ -22,6 +23,8 @@ public enum SettingsManager {
|
||||
LOAD_INCLUDED_MENUS("load-included-menus", Type.BOOLEAN, true),
|
||||
LOAD_INCLUDED_CUSTOM_TYPES("load-included-custom-types", Type.BOOLEAN, true),
|
||||
DISABLED_WORLDS("disabled-worlds", Type.STRING_LIST, new ArrayList<String>()),
|
||||
ENABLED_WORLDS("enabled-worlds", Type.STRING_LIST,
|
||||
new ArrayList<String>(Arrays.asList("world", "world_nether", "world_the_end"))),
|
||||
CHECK_WORLD_PERMISSION("check-world-permission", Type.BOOLEAN, true),
|
||||
CLOSE_MENU_ON_EQUIP("close-menu-on-equip", Type.BOOLEAN, true), CURRENCY("currency", Type.STRING, "&bShards"),
|
||||
LIVE_MENUS("live-menus", Type.BOOLEAN, true), LIVE_MENU_UPDATE_FREQUENCY("live-menu-update-frequency", Type.INT, 5),
|
||||
@@ -47,6 +50,7 @@ public enum SettingsManager {
|
||||
FLAG_EXPERIENCE("flags.experience", Type.BOOLEAN, false), FLAG_PERMISSION("flags.permission", Type.BOOLEAN, true),
|
||||
FLAG_VANISH("flags.vanish", Type.BOOLEAN, false),
|
||||
FLAG_ESSENTIALS_VANISH("flags.essentials-vanish", Type.BOOLEAN, false),
|
||||
FLAG_DUELS("flags.duels", Type.BOOLEAN, true), FLAG_ETERNALCOMBAT("flags.eternalcombat", Type.BOOLEAN, true),
|
||||
|
||||
/**
|
||||
* Afk / Combat cooldown and flags
|
||||
|
||||
@@ -8,7 +8,9 @@ import cosmeticsOG.player.PlayerState.PVPState;
|
||||
import cosmeticsOG.tasks.HatTask;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -24,6 +26,9 @@ public class EntityState {
|
||||
private AFKState afkState = AFKState.ACTIVE;
|
||||
private PVPState pvpState = PVPState.PEACEFUL;
|
||||
|
||||
// Read from the async HatTask, so keep it a concurrent set.
|
||||
private final Set<SuppressionSource> suppressors = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private Location afkLocation;
|
||||
private Location lastLocation;
|
||||
|
||||
@@ -251,6 +256,28 @@ public class EntityState {
|
||||
|
||||
}
|
||||
|
||||
// Suppressed hats stay equipped but stop rendering, e.g. while the owner duels.
|
||||
public void setSuppressed(SuppressionSource source, boolean suppressed) {
|
||||
|
||||
if (suppressed) {
|
||||
|
||||
suppressors.add(source);
|
||||
|
||||
} else {
|
||||
|
||||
suppressors.remove(source);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// True while any source is still hiding this entity's hats.
|
||||
public boolean isSuppressed() {
|
||||
|
||||
return !suppressors.isEmpty();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the entities AFKState
|
||||
*
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package cosmeticsOG.player;
|
||||
|
||||
// Reasons another plugin can hide a player's cosmetics; each is tracked separately.
|
||||
public enum SuppressionSource {
|
||||
|
||||
DUEL, COMBAT;
|
||||
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import cosmeticsOG.managers.SettingsManager;
|
||||
import cosmeticsOG.player.EntityState;
|
||||
import cosmeticsOG.player.PlayerState.AFKState;
|
||||
import cosmeticsOG.player.PlayerState.PVPState;
|
||||
import cosmeticsOG.util.WorldUtil;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
@@ -20,12 +20,9 @@ public class EntityTask extends BukkitRunnable {
|
||||
private int afkCooldown = SettingsManager.AFK_COOLDOWN.getInt() * 1000;
|
||||
private int pvpCooldown = SettingsManager.COMBAT_COOLDOWN.getInt() * 1000;
|
||||
|
||||
private List<String> disabledWorlds;
|
||||
|
||||
public EntityTask(CosmeticsOG core) {
|
||||
|
||||
this.core = core;
|
||||
disabledWorlds = SettingsManager.DISABLED_WORLDS.getList();
|
||||
|
||||
}
|
||||
|
||||
@@ -52,9 +49,9 @@ public class EntityTask extends BukkitRunnable {
|
||||
|
||||
}
|
||||
|
||||
// Skip this world if it is disabled
|
||||
// Skip entities outside the allowed worlds.
|
||||
World world = entity.getWorld();
|
||||
if (disabledWorlds.contains(world.getName())) {
|
||||
if (!WorldUtil.isEnabled(world)) {
|
||||
|
||||
continue;
|
||||
|
||||
@@ -74,9 +71,6 @@ public class EntityTask extends BukkitRunnable {
|
||||
afkCooldown = SettingsManager.AFK_COOLDOWN.getInt() * 1000;
|
||||
pvpCooldown = SettingsManager.COMBAT_COOLDOWN.getInt() * 1000;
|
||||
|
||||
disabledWorlds.clear();
|
||||
disabledWorlds = SettingsManager.DISABLED_WORLDS.getList();
|
||||
|
||||
}
|
||||
|
||||
private void checkMode(UUID id, EntityState entityState) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import cosmeticsOG.permission.Permission;
|
||||
import cosmeticsOG.player.EntityState;
|
||||
import cosmeticsOG.player.PlayerState;
|
||||
import cosmeticsOG.util.PlayerUtil;
|
||||
import cosmeticsOG.util.WorldUtil;
|
||||
import java.util.List;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
@@ -25,7 +26,6 @@ public class HatTask extends BukkitRunnable {
|
||||
private final Entity entity;
|
||||
private final Hat hat;
|
||||
|
||||
private List<String> disabledWorlds;
|
||||
private boolean checkWorldPermission;
|
||||
private boolean essentialsVanishFlag;
|
||||
|
||||
@@ -37,7 +37,6 @@ public class HatTask extends BukkitRunnable {
|
||||
this.entity = entity;
|
||||
this.hat = hat;
|
||||
|
||||
disabledWorlds = SettingsManager.DISABLED_WORLDS.getList();
|
||||
checkWorldPermission = SettingsManager.CHECK_WORLD_PERMISSION.getBoolean();
|
||||
essentialsVanishFlag = SettingsManager.FLAG_ESSENTIALS_VANISH.getBoolean();
|
||||
|
||||
@@ -53,7 +52,6 @@ public class HatTask extends BukkitRunnable {
|
||||
|
||||
public void reload() {
|
||||
|
||||
disabledWorlds = SettingsManager.DISABLED_WORLDS.getList();
|
||||
checkWorldPermission = SettingsManager.CHECK_WORLD_PERMISSION.getBoolean();
|
||||
essentialsVanishFlag = SettingsManager.FLAG_ESSENTIALS_VANISH.getBoolean();
|
||||
|
||||
@@ -62,9 +60,15 @@ public class HatTask extends BukkitRunnable {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
// Skip this world if it is disabled
|
||||
// Outside the allowed worlds hats stay equipped but stop rendering.
|
||||
World world = entity.getWorld();
|
||||
if (disabledWorlds.contains(world.getName())) {
|
||||
if (!WorldUtil.isEnabled(world)) {
|
||||
|
||||
if (hat.isDisplaying()) {
|
||||
|
||||
hat.setIsDisplaying(false, entity);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -106,6 +110,19 @@ public class HatTask extends BukkitRunnable {
|
||||
|
||||
}
|
||||
|
||||
// Suppressed hats (e.g. owner in a duel) stop rendering until the flag clears.
|
||||
if (entityState.isSuppressed()) {
|
||||
|
||||
if (hat.isDisplaying()) {
|
||||
|
||||
hat.setIsDisplaying(false, entity);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (hat.isVanished() || hat.isHidden()) {
|
||||
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package cosmeticsOG.util;
|
||||
|
||||
import cosmeticsOG.managers.SettingsManager;
|
||||
import java.util.List;
|
||||
import org.bukkit.World;
|
||||
|
||||
// Decides whether cosmetics may run in a world: the whitelist gates first, then the blacklist.
|
||||
public final class WorldUtil {
|
||||
|
||||
private WorldUtil() {
|
||||
|
||||
}
|
||||
|
||||
public static boolean isEnabled(World world) {
|
||||
|
||||
return isEnabled(world.getName());
|
||||
|
||||
}
|
||||
|
||||
// An empty whitelist allows every world that the disabled-worlds list does not
|
||||
// name.
|
||||
public static boolean isEnabled(String worldName) {
|
||||
|
||||
final List<String> enabledWorlds = SettingsManager.ENABLED_WORLDS.getList();
|
||||
if (!enabledWorlds.isEmpty() && !containsIgnoreCase(enabledWorlds, worldName)) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return !containsIgnoreCase(SettingsManager.DISABLED_WORLDS.getList(), worldName);
|
||||
|
||||
}
|
||||
|
||||
private static boolean containsIgnoreCase(List<String> worlds, String worldName) {
|
||||
|
||||
for (String world : worlds) {
|
||||
|
||||
if (world.equalsIgnoreCase(worldName)) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,12 @@ load-included-custom-types: false
|
||||
# Choose which worlds this plugin should ignore
|
||||
disabled-worlds: []
|
||||
#
|
||||
# Only run cosmetics in these worlds, an empty list allows every world not ignored above
|
||||
enabled-worlds:
|
||||
- world
|
||||
- world_nether
|
||||
- world_the_end
|
||||
#
|
||||
# Checks to see if a player has permission to use particles for the world they're in.
|
||||
check-world-permission: false
|
||||
#
|
||||
@@ -99,6 +105,12 @@ flags:
|
||||
#
|
||||
# Disable particle effects when a player has a potion of invisibility effect
|
||||
essentials-vanish: true
|
||||
#
|
||||
# Hide cosmetics while a player is in a Duels-OG match and restore them when it ends
|
||||
duels: true
|
||||
#
|
||||
# Hide cosmetics while EternalCombat-OG has a player combat tagged and restore them on untag
|
||||
eternalcombat: true
|
||||
#
|
||||
afk:
|
||||
# Set how many seconds the plugin will wait before marking a player as AFK
|
||||
|
||||
@@ -4,7 +4,7 @@ version: '${version}'
|
||||
api-version: '${apiVersion}'
|
||||
authors: [MediusEcho, NotAlexNoyle]
|
||||
depend: [DiamondBank-OG]
|
||||
softdepend: [Vanish-OG, SuperVanish, PremiumVanish, VanishNoPacket, Citizens]
|
||||
softdepend: [Duels-OG, EternalCombat-OG, Vanish-OG, SuperVanish, PremiumVanish, VanishNoPacket, Citizens]
|
||||
commands:
|
||||
cosmetics:
|
||||
description: Main command for Cosmetics-OG
|
||||
|
||||
Reference in new issue
Block a user