Made break listener safer, Duels started, Task scheduling reduced and streamlined, many other improvements that I cant remember

This commit is contained in:
DroppingAnvil 2020-02-29 20:23:57 -06:00 committed by droppinganvil
parent dfbfbf9981
commit 43c567ee02
29 changed files with 800 additions and 61 deletions

@ -12,8 +12,10 @@ import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
@ -44,6 +46,30 @@ public interface FPlayer extends EconomyParticipator {
*/ */
void setEnemiesNearby(Boolean b); void setEnemiesNearby(Boolean b);
/**
* Get this players inventory prior to entering the duel (Will be set to null after duel!)
* @return Map of old inventory contents
*/
Map<Integer, ItemStack> getOldInv();
/**
* Set this players stored inventory, this inventory will be retrieved after a duel is complete
* @param inv Map of inventory contents
*/
void setOldInv(Map<Integer, ItemStack> inv);
/**
* Used to check if player has entered a duel and has not proceeded
* @return boolean determining if the player is in a duel
*/
boolean isInDuel();
/**
* Used before and after duels to set the inDuel status of the FPlayer
* @param b Desired status
*/
void setInDuel(Boolean b);
/** /**
* Get if a player has setup their Discord before * Get if a player has setup their Discord before
* @return if the player setup Discord as a boolean * @return if the player setup Discord as a boolean

@ -23,6 +23,8 @@ import java.util.concurrent.ConcurrentHashMap;
public interface Faction extends EconomyParticipator { public interface Faction extends EconomyParticipator {
void broadcast(String s);
String getMemberRoleId(); String getMemberRoleId();
void setMemberRoleId(String roleId); void setMemberRoleId(String roleId);

@ -26,6 +26,7 @@ import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.*; import com.massivecraft.factions.util.*;
import com.massivecraft.factions.util.Particles.ReflectionUtils; import com.massivecraft.factions.util.Particles.ReflectionUtils;
import com.massivecraft.factions.util.Sync.SyncExecutor;
import com.massivecraft.factions.zcore.CommandVisibility; import com.massivecraft.factions.zcore.CommandVisibility;
import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.MPlugin;
import com.massivecraft.factions.zcore.fperms.Access; import com.massivecraft.factions.zcore.fperms.Access;
@ -181,6 +182,8 @@ public class FactionsPlugin extends MPlugin {
this.saveResource("config.yml", false); this.saveResource("config.yml", false);
this.reloadConfig(); this.reloadConfig();
} }
//Start synctask
SyncExecutor.startTask();
//Attempt to generate a permission list //Attempt to generate a permission list
PermissionList.generateFile(); PermissionList.generateFile();
// Load Conf from disk // Load Conf from disk

@ -6,10 +6,10 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
public class Aliases {
/** /**
* @author DroppingAnvil * @author DroppingAnvil
*/ */
public class Aliases {
public static ArrayList<String> alts_alts = new ArrayList<>(Arrays.asList("alts", "alt")); public static ArrayList<String> alts_alts = new ArrayList<>(Arrays.asList("alts", "alt"));
public static ArrayList<String> alts_list = new ArrayList<>(Arrays.asList("list", "l")); public static ArrayList<String> alts_list = new ArrayList<>(Arrays.asList("list", "l"));
public static ArrayList<String> alts_invite = new ArrayList<>(Collections.singletonList("invite")); public static ArrayList<String> alts_invite = new ArrayList<>(Collections.singletonList("invite"));

@ -6,6 +6,9 @@ import com.massivecraft.factions.zcore.util.TL;
import java.util.Random; import java.util.Random;
/**
* @author droppinganvil
*/
public class CmdDiscord extends FCommand { public class CmdDiscord extends FCommand {
public CmdDiscord() { public CmdDiscord() {
super(); super();

@ -3,6 +3,7 @@ package com.massivecraft.factions.cmd;
import com.massivecraft.factions.Conf; import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FactionsPlugin; import com.massivecraft.factions.FactionsPlugin;
import com.massivecraft.factions.discord.Discord; import com.massivecraft.factions.discord.Discord;
import com.massivecraft.factions.duels.RequestGUI;
import com.massivecraft.factions.listeners.FactionsPlayerListener; import com.massivecraft.factions.listeners.FactionsPlayerListener;
import com.massivecraft.factions.shop.ShopConfig; import com.massivecraft.factions.shop.ShopConfig;
import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Permission;
@ -44,6 +45,9 @@ public class CmdReload extends FCommand {
FCmdRoot.instance.addVariableCommands(); FCmdRoot.instance.addVariableCommands();
FCmdRoot.instance.rebuild(); FCmdRoot.instance.rebuild();
long timeReload = (System.currentTimeMillis() - timeInitStart); long timeReload = (System.currentTimeMillis() - timeInitStart);
//Duels
RequestGUI.inv = null;
RequestGUI.responseMap.clear();
context.msg(TL.COMMAND_RELOAD_TIME, timeReload); context.msg(TL.COMMAND_RELOAD_TIME, timeReload);
} }

@ -17,6 +17,9 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
/**
* @author droppinganvil
*/
public class ConvertConfigHandler { public class ConvertConfigHandler {
static File savageConfigFile = new File("plugins/Factions/SavageFactions/config.yml"); static File savageConfigFile = new File("plugins/Factions/SavageFactions/config.yml");

@ -10,6 +10,7 @@ import com.massivecraft.factions.cmd.CommandContext;
import com.massivecraft.factions.cmd.CommandRequirements; import com.massivecraft.factions.cmd.CommandRequirements;
import com.massivecraft.factions.cmd.FCommand; import com.massivecraft.factions.cmd.FCommand;
import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Permission;
import com.massivecraft.factions.util.Wait.WaitedTask;
import com.massivecraft.factions.zcore.util.TL; import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -23,18 +24,21 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Random; import java.util.Random;
public class CmdWild extends FCommand { /**
public static HashMap<Player, Integer> waitingTeleport; * @author droppinganvil
*/
public class CmdWild extends FCommand implements WaitedTask {
public static HashMap<Player, String> teleportRange; public static HashMap<Player, String> teleportRange;
public static HashSet<Player> teleporting; public static HashSet<Player> teleporting;
public static CmdWild instance;
public CmdWild() { public CmdWild() {
super(); super();
if (this.instance == null) instance = this;
this.aliases.addAll(Aliases.wild); this.aliases.addAll(Aliases.wild);
this.requirements = new CommandRequirements.Builder(Permission.WILD) this.requirements = new CommandRequirements.Builder(Permission.WILD)
.playerOnly() .playerOnly()
.build(); .build();
waitingTeleport = new HashMap<>();
teleporting = new HashSet<>(); teleporting = new HashSet<>();
teleportRange = new HashMap<>(); teleportRange = new HashMap<>();
startWild(); startWild();
@ -42,7 +46,7 @@ public class CmdWild extends FCommand {
@Override @Override
public void perform(CommandContext context) { public void perform(CommandContext context) {
if (!waitingTeleport.containsKey(context.player)) { if (!teleportRange.containsKey(context.player)) {
context.player.openInventory(new WildGUI(context.player, context.fPlayer).getInventory()); context.player.openInventory(new WildGUI(context.player, context.fPlayer).getInventory());
} else { } else {
context.fPlayer.msg(TL.COMMAND_WILD_WAIT); context.fPlayer.msg(TL.COMMAND_WILD_WAIT);
@ -50,23 +54,6 @@ public class CmdWild extends FCommand {
} }
public void startWild() { public void startWild() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(FactionsPlugin.instance, () -> {
for (Player p : waitingTeleport.keySet()) {
int i = waitingTeleport.get(p) - 1;
if (i > 0) {
if (i != 1) {
p.sendMessage(TL.COMMAND_WILD_WAIT.format((i + " Seconds")));
} else {
p.sendMessage(TL.COMMAND_WILD_WAIT.format((i + " Second")));
}
waitingTeleport.replace(p, i);
} else {
p.sendMessage(TL.COMMAND_WILD_SUCCESS.toString());
waitingTeleport.remove(p);
attemptTeleport(p);
}
}
}, 0L, 20L);
} }
public void attemptTeleport(Player p) { public void attemptTeleport(Player p) {
@ -121,4 +108,14 @@ public class CmdWild extends FCommand {
public TL getUsageTranslation() { public TL getUsageTranslation() {
return TL.COMMAND_WILD_DESCRIPTION; return TL.COMMAND_WILD_DESCRIPTION;
} }
@Override
public void handleSuccess(Player player) {
attemptTeleport(player);
}
@Override
public void handleFailure(Player player) {
player.sendMessage(TL.COMMAND_WILD_INTERUPTED.toString());
}
} }

@ -3,6 +3,8 @@ package com.massivecraft.factions.cmd.wild;
import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.FactionsPlugin; import com.massivecraft.factions.FactionsPlugin;
import com.massivecraft.factions.util.FactionGUI; import com.massivecraft.factions.util.FactionGUI;
import com.massivecraft.factions.util.Wait.WaitExecutor;
import com.massivecraft.factions.util.Wait.WaitTask;
import com.massivecraft.factions.util.XMaterial; import com.massivecraft.factions.util.XMaterial;
import com.massivecraft.factions.zcore.util.TL; import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -18,6 +20,10 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/**
* @author droppinganvil
*/
//TODO StaticGUI
public class WildGUI implements FactionGUI { public class WildGUI implements FactionGUI {
Player player; Player player;
FPlayer fplayer; FPlayer fplayer;
@ -35,7 +41,7 @@ public class WildGUI implements FactionGUI {
if (map.containsKey(slot)) { if (map.containsKey(slot)) {
String zone = map.get(slot); String zone = map.get(slot);
if (fplayer.hasMoney(FactionsPlugin.getInstance().getConfig().getInt("Wild.Zones." + zone + ".Cost"))) { if (fplayer.hasMoney(FactionsPlugin.getInstance().getConfig().getInt("Wild.Zones." + zone + ".Cost"))) {
CmdWild.waitingTeleport.put(player, FactionsPlugin.getInstance().getConfig().getInt("Wild.Wait")); WaitExecutor.taskMap.put(player, new WaitTask(FactionsPlugin.getInstance().getConfig().getInt("Wild.Wait"), TL.COMMAND_WILD_INPROGRESS, player, CmdWild.instance));
CmdWild.teleportRange.put(player, zone); CmdWild.teleportRange.put(player, zone);
fplayer.msg(TL.COMMAND_WILD_WAIT, FactionsPlugin.getInstance().getConfig().getInt("Wild.Wait") + " Seconds"); fplayer.msg(TL.COMMAND_WILD_WAIT, FactionsPlugin.getInstance().getConfig().getInt("Wild.Wait") + " Seconds");
player.closeInventory(); player.closeInventory();

@ -19,6 +19,9 @@ import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
/**
* @author droppinganvil
*/
public class Discord { public class Discord {
//We dont want waitingLink to reset during reload so we are going to set it here //We dont want waitingLink to reset during reload so we are going to set it here
public static HashMap<Integer, FPlayer> waitingLink; public static HashMap<Integer, FPlayer> waitingLink;

@ -1,5 +1,8 @@
package com.massivecraft.factions.discord; package com.massivecraft.factions.discord;
/**
* @author droppinganvil
*/
public class DiscordSetupAttempt { public class DiscordSetupAttempt {
private Boolean success; private Boolean success;
private String reason; private String reason;

@ -0,0 +1,164 @@
package com.massivecraft.factions.duels;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.FactionsPlugin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author droppinganvil
*/
public class Duel {
private Faction faction1;
private Faction faction2;
private HashMap<FPlayer, Boolean> eliminationMap;
private HashMap<FPlayer, Location> oldLocMap;
public Duel(Faction faction1, Faction faction2) {
this.faction1 = faction1;
this.faction2 = faction2;
this.eliminationMap = new HashMap<>();
this.oldLocMap = new HashMap<>();
}
public Faction getFaction1() {
return faction1;
}
public Faction getFaction2() {
return faction2;
}
public Set<FPlayer> getEliminated() {
Set<FPlayer> list = new HashSet<>();
for (Map.Entry<FPlayer, Boolean> entry : eliminationMap.entrySet()) {
if (entry.getValue()) list.add(entry.getKey());
}
return list;
}
public Set<FPlayer> getEliminated(Faction faction) {
Set<FPlayer> list = new HashSet<>();
for (Map.Entry<FPlayer, Boolean> entry : eliminationMap.entrySet()) {
if (entry.getValue() && entry.getKey().getFaction().equals(faction)) list.add(entry.getKey());
}
return list;
}
public Set<FPlayer> getRemaining() {
Set<FPlayer> list = new HashSet<>();
for (Map.Entry<FPlayer, Boolean> entry : eliminationMap.entrySet()) {
if (!entry.getValue()) list.add(entry.getKey());
}
return list;
}
public Set<FPlayer> getRemaining(Faction faction) {
Set<FPlayer> list = new HashSet<>();
for (Map.Entry<FPlayer, Boolean> entry : eliminationMap.entrySet()) {
if (!entry.getValue() && entry.getKey().getFaction().equals(faction)) list.add(entry.getKey());
}
return list;
}
public void handleExit(FPlayer fplayer, Boolean death) {
if (death) {
eliminationMap.replace(fplayer, false, true);
fplayer.getPlayer().spigot().respawn();
}
fplayer.getPlayer().teleport(oldLocMap.get(fplayer), PlayerTeleportEvent.TeleportCause.PLUGIN);
for (Map.Entry<Integer, ItemStack> entry : fplayer.getOldInv().entrySet()) {
fplayer.getPlayer().getInventory().setItem(entry.getKey(), entry.getValue());
}
fplayer.setOldInv(null);
fplayer.setInDuel(false);
if (getClearWinner() != null) {
handleEnd();
}
}
public void handleEnd() {
if (FactionsPlugin.getInstance().getConfig().getBoolean("Duels.Broadcast.BroadcastResult.Enabled")) {
Bukkit.broadcastMessage(getEndMessage());
}
for (FPlayer fp : getRemaining()) {
handleExit(fp, false);
}
Map.Entry<Faction, Faction> fvf = (Map.Entry<Faction, Faction>) Duels.duelQueue.entrySet().toArray()[0];
if (fvf != null) {
Duels.duel = new Duel(fvf.getKey(), fvf.getValue());
Duels.preparingDuel = true;
Duels.acceptedDuel.clear();
}
}
public Faction getClearWinner() {
Set<FPlayer> team1r = getRemaining(faction1);
Set<FPlayer> team2r = getRemaining(faction2);
if (team1r.isEmpty() && !team2r.isEmpty()) return faction2;
if (team2r.isEmpty() && !team1r.isEmpty()) return faction1;
return null;
}
private Faction getWinning(Set<FPlayer> s1, Set<FPlayer> s2) {
if (s1.size() > s2.size()) return faction1;
return faction2;
}
public String getEndMessage() {
String temp;
Set<FPlayer> team1r = getRemaining(faction1);
Set<FPlayer> team2r = getRemaining(faction2);
if (team1r.size() == team2r.size()) {
//Tied
temp = FactionsPlugin.getInstance().getConfig().getString("Duels.Broadcast.BroadcastResult.FormatTie");
} else {
temp = FactionsPlugin.getInstance().getConfig().getString("Duels.Broadcast.BroadcastResult.Format");
}
Faction winner = getWinning(team1r, team2r);
return ChatColor.translateAlternateColorCodes('&', temp
.replace("{team1_tag}", faction1.getTag())
.replace("{team2_tag}", faction2.getTag())
.replace("{remaining}", String.valueOf(getRemaining(winner).size()))
.replace("{tag}", winner.getTag())
.replace("{losers_tag}", winner == faction1 ? faction2.getTag() : faction1.getTag()));
}
public String getDeathMessage(Player player) {
return ChatColor.translateAlternateColorCodes('&',
FactionsPlugin.getInstance().getConfig().getString("Duels.Broadcast.BroadcastKill.Format")
.replace("{team1_remaining}", String.valueOf(getRemaining(getFaction1()).size()))
.replace("{team2_remaining}", String.valueOf(getRemaining(getFaction2()).size()))
.replace("{team1_eliminated}", String.valueOf(getEliminated(getFaction1()).size()))
.replace("{team2_eliminated}", String.valueOf(getEliminated(getFaction2()).size()))
.replace("{team1_tag}", faction1.getTag())
.replace("{team2_tag}", faction2.getTag())
.replace("{eliminated_name}", player.getName()));
}
public HashMap<FPlayer, Location> getLocMap() {
return oldLocMap;
}
public void addFPlayer(FPlayer fp) {
oldLocMap.put(fp, fp.getPlayer().getLocation());
eliminationMap.put(fp, false);
}
public void start() {
Duels.preparingDuel = false;
for (FPlayer fplayer : Duels.acceptedDuel) {
}
}
}

@ -0,0 +1,73 @@
package com.massivecraft.factions.duels;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.FactionsPlugin;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author droppinganvil
*/
public class Duels {
public static boolean enabled = true;
public static long targetTimeout = Integer.toUnsignedLong(FactionsPlugin.getInstance().getConfig().getInt("Duels.WaitTime")) * 1000;
public static ConcurrentHashMap<FPlayer, Long> guiMap = new ConcurrentHashMap<>();
public static HashSet<FPlayer> acceptedDuel = new HashSet<>();
public static HashMap<Faction, Faction> duelQueue = new HashMap<>();
public static Boolean preparingDuel = false;
public static Duel duel;
public static HashSet<SpawnPoint> spawnPoints = new HashSet<>();
private static void startGUITask() {
Bukkit.getScheduler().scheduleAsyncRepeatingTask(FactionsPlugin.instance, () -> {
for (Map.Entry<FPlayer, Long> entry : guiMap.entrySet()) {
if (System.currentTimeMillis() - entry.getValue() <= targetTimeout) RequestGUI.closeSync(true, entry.getKey());
}
}, 0L, 20L);
}
public void setup() {
enabled = FactionsPlugin.getInstance().getConfig().getBoolean("Duels.Enabled", true);
if (enabled) startGUITask();
loadSpawnPoints();
}
public void loadSpawnPoints() {
spawnPoints.clear();
loadTeamSpawnPoints(1);
loadTeamSpawnPoints(2);
}
public void loadTeamSpawnPoints(Integer i) {
FileConfiguration config = FactionsPlugin.getInstance().getConfig();
String team = "Team" + i;
for (String key : config.getConfigurationSection("Duels.SpawnPoints." + team).getKeys(false)) {
spawnPoints.add(new SpawnPoint (i, getSpawnPointLocation(team, key, config), Integer.parseInt(key)));
}
}
public Location getSpawnPointLocation(String team, String key, FileConfiguration config) {
String[] locKeyArray = config.getString("Duels.SpawnPoints." + team + "." + key).split(",");
return new Location(Bukkit.getWorld(locKeyArray[0]), Double.parseDouble(locKeyArray[1]), Double.parseDouble(locKeyArray[2]), Double.parseDouble(locKeyArray[3]));
}
public void sendRequests() {
for (FPlayer fplayer : duel.getFaction1().getFPlayers()) {
if (fplayer.isOnline()) {
fplayer.getPlayer().openInventory(RequestGUI.inv);
guiMap.put(fplayer, System.currentTimeMillis());
}
}
}
}

@ -0,0 +1,121 @@
package com.massivecraft.factions.duels;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.FPlayers;
import com.massivecraft.factions.FactionsPlugin;
import com.massivecraft.factions.util.StaticGUI;
import com.massivecraft.factions.util.Sync.SyncExecutor;
import com.massivecraft.factions.util.Sync.SyncTask;
import com.massivecraft.factions.util.XMaterial;
import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
/**
* @author droppinganvil
*/
public class RequestGUI implements StaticGUI {
private static ItemStack fillItem;
private static RequestResponse fallback;
FileConfiguration config = FactionsPlugin.getInstance().getConfig();
public static HashMap<Integer, RequestResponse> responseMap = new HashMap<>();
public static Inventory inv;
private static RequestGUI instance;
public static RequestGUI getInstance() {
return instance;
}
public RequestGUI() {
if (instance == null) {
instance = this;
}
if (fillItem == null) {
fillItem = XMaterial.matchXMaterial(config.getString("Duels.GUI.Fill-Item.Material")).get().parseItem();
ItemMeta fillMeta = fillItem.getItemMeta();
fillMeta.setDisplayName(" ");
fillItem.setItemMeta(fillMeta);
}
if (fallback == null) {
try {
fallback = RequestResponse.valueOf(config.getString("Duels.GUI.Fill-Item.Response"));
} catch (EnumConstantNotPresentException e) {
FactionsPlugin.getInstance().getLogger().log(Level.WARNING, "FallbackResponse is invalid! Using Ignored");
fallback = RequestResponse.Ignored;
}
}
if (inv == null) {
inv = Bukkit.createInventory(this, 27, "Join Faction Duel");
int fi = 0;
while (fi != 26) {
inv.setItem(fi, fillItem);
fi++;
}
for (String key : config.getConfigurationSection("Duels.GUI.Items").getKeys(false)) {
ItemStack item = XMaterial.matchXMaterial(config.getString("Duels.GUI.Items." + key + ".Material")).get().parseItem();
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString("Duels.GUI.Items." + key + ".Name")));
List<String> lore = new ArrayList<>();
for (String loreEntry : config.getStringList("Duels.GUI.Items." + key + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', loreEntry));
}
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
int slot = Integer.parseInt(key);
responseMap.put(slot, RequestResponse.valueOf(config.getString("Duels.GUI.Items." + key + ".Response")));
inv.setItem(slot, item);
}
}
}
@Override
public void click(int slot, ClickType action, Player player) {
FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player);
if (action != ClickType.LEFT) {
processResponse(fallback, fPlayer);
} else {
processResponse(responseMap.get(slot), fPlayer);
}
}
public static void processResponse(RequestResponse response, FPlayer fPlayer) {
switch (response) {
case Accepted:
fPlayer.getFaction().broadcast(TL.DUEL_REQUEST_ACCEPTED_PLAYER.format(fPlayer.getNameAndTitle()));
Duels.acceptedDuel.add(fPlayer);
close(false, fPlayer);
break;
case Rejected:
fPlayer.getFaction().broadcast(TL.DUEL_REQUEST_REJECTED_PLAYER.format(fPlayer.getNameAndTitle()));
close(false, fPlayer);
break;
}
}
public static void close(Boolean reject, FPlayer fPlayer) {
if (reject) {
processResponse(RequestResponse.Rejected, fPlayer);
}
fPlayer.getPlayer().closeInventory();
Duels.guiMap.remove(fPlayer);
}
public static void closeSync(Boolean reject, FPlayer fPlayer) {
SyncExecutor.taskQueue.add(new SyncTask(RequestGUI.getInstance(), "close", reject, fPlayer));
}
@Override
public Inventory getInventory() {
return inv;
}
}

@ -0,0 +1,10 @@
package com.massivecraft.factions.duels;
/**
* @author droppinganvil
*/
public enum RequestResponse {
Accepted,
Rejected,
Ignored,
}

@ -0,0 +1,27 @@
package com.massivecraft.factions.duels;
import org.bukkit.Location;
public class SpawnPoint {
private Integer team;
private Integer id;
private Location location;
public SpawnPoint(Integer team, Location location, Integer id) {
this.team = team;
this.location = location;
this.id = id;
}
public Integer getTeam() {
return team;
}
public Location getLocation() {
return location;
}
public Integer getID() {
return id;
}
}

@ -493,6 +493,8 @@ public class FactionsBlockListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
//If there is an error its much safer to not allow the block to be broken
try {
Block block = event.getBlock(); Block block = event.getBlock();
Faction at = Board.getInstance().getFactionAt(new FLocation(block)); Faction at = Board.getInstance().getFactionAt(new FLocation(block));
@ -527,6 +529,10 @@ public class FactionsBlockListener implements Listener {
} }
} }
} }
} catch (Exception e) {
event.setCancelled(true);
e.printStackTrace();
}
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)

@ -21,6 +21,7 @@ import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.CC; import com.massivecraft.factions.util.CC;
import com.massivecraft.factions.util.FactionGUI; import com.massivecraft.factions.util.FactionGUI;
import com.massivecraft.factions.util.VisualizeUtil; import com.massivecraft.factions.util.VisualizeUtil;
import com.massivecraft.factions.util.Wait.WaitExecutor;
import com.massivecraft.factions.util.XMaterial; import com.massivecraft.factions.util.XMaterial;
import com.massivecraft.factions.zcore.fperms.Access; import com.massivecraft.factions.zcore.fperms.Access;
import com.massivecraft.factions.zcore.fperms.PermissableAction; import com.massivecraft.factions.zcore.fperms.PermissableAction;
@ -935,11 +936,7 @@ public class FactionsPlayerListener implements Listener {
handler.cancelLogout(e.getPlayer()); handler.cancelLogout(e.getPlayer());
e.getPlayer().sendMessage(String.valueOf(TL.COMMAND_LOGOUT_MOVED)); e.getPlayer().sendMessage(String.valueOf(TL.COMMAND_LOGOUT_MOVED));
} }
WaitExecutor.handleAction(e.getPlayer());
if (CmdWild.waitingTeleport.containsKey(e.getPlayer())) {
CmdWild.waitingTeleport.remove(e.getPlayer());
FPlayers.getInstance().getByPlayer(e.getPlayer()).msg(TL.COMMAND_WILD_INTERUPTED);
}
} }
@EventHandler @EventHandler
@ -951,10 +948,7 @@ public class FactionsPlayerListener implements Listener {
handler.cancelLogout(player); handler.cancelLogout(player);
player.sendMessage(String.valueOf(TL.COMMAND_LOGOUT_DAMAGE_TAKEN)); player.sendMessage(String.valueOf(TL.COMMAND_LOGOUT_DAMAGE_TAKEN));
} }
if (CmdWild.waitingTeleport.containsKey(player)) { WaitExecutor.handleAction(player);
CmdWild.waitingTeleport.remove(player);
FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_WILD_INTERUPTED);
}
if (CmdWild.teleporting.contains(player)) { if (CmdWild.teleporting.contains(player)) {
if (!FactionsPlugin.getInstance().getConfig().getBoolean("Wild.FallDamage") && e.getCause() == EntityDamageEvent.DamageCause.FALL) { if (!FactionsPlugin.getInstance().getConfig().getBoolean("Wild.FallDamage") && e.getCause() == EntityDamageEvent.DamageCause.FALL) {
e.setCancelled(true); e.setCancelled(true);

@ -8,6 +8,9 @@ import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
/**
* @author droppinganvil
*/
public class PermissionList { public class PermissionList {
public static void generateFile() { public static void generateFile() {
File file = new File(FactionsPlugin.getInstance().getDataFolder().toString() + "/" + "permissions.yml"); File file = new File(FactionsPlugin.getInstance().getDataFolder().toString() + "/" + "permissions.yml");

@ -0,0 +1,15 @@
package com.massivecraft.factions.util;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.InventoryHolder;
/**
* @author droppinganvil
* Inspired by FactionGUI with the difference being that this should be used for GUIs that will not differ between players
* Using StaticGUI and only generating one will not require generating one object per player unlike FactionGUI this will save many resources from being used.
* @see FactionGUI
*/
public interface StaticGUI extends InventoryHolder {
void click(int slot, ClickType action, Player player);
}

@ -0,0 +1,35 @@
package com.massivecraft.factions.util.Sync;
import com.massivecraft.factions.FactionsPlugin;
import org.bukkit.Bukkit;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Level;
/**
* @author droppinganvil
*/
public class SyncExecutor {
private static boolean started = false;
/**
* This queue is used to collect task that need to happen async rather than scheduling for every action.
*/
public static Queue<SyncTask> taskQueue = new LinkedList<>();
public static void startTask() {
if (started) return;
Bukkit.getScheduler().scheduleSyncRepeatingTask(FactionsPlugin.instance, () -> {
SyncTask syncTask = taskQueue.poll();
if (syncTask != null) {
try {
syncTask.call();
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
FactionsPlugin.getInstance().getLogger().log(Level.SEVERE, "A task was not able to execute successfully! Please provide this stacktrace to the Saber team at Discord.Saber.pw");
}
}
}, 0L, 2L);
}
}

@ -0,0 +1,63 @@
package com.massivecraft.factions.util.Sync;
import com.massivecraft.factions.FactionsPlugin;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
/**
* @author droppinganvil
*/
public class SyncTask {
private Object o;
private Method m;
private Object[] arguments;
private Collection<Class<?>> params;
public SyncTask(Object target, Method method, Object... arguments) {
this.o = target;
this.m = method;
this.arguments = arguments;
}
/**
* Generate sync task without the ability to specify the Method object, made for easy typing
* @param target Object the method is on
* @param method Method name
* @param arguments Objects needed to call method
*/
public SyncTask(Object target, String method, Object... arguments) {
this.o = target;
this.arguments = arguments;
this.params = new ArrayList<>();
for (Object o : this.arguments) {
this.params.add(o.getClass());
}
try {
this.m = o.getClass().getMethod(method, (Class<?>[]) params.toArray());
} catch (NoSuchMethodException e) {
e.printStackTrace();
FactionsPlugin.getInstance().getLogger().log(Level.SEVERE, "A Method could not be located! This means a task that was supposed to happen did not, this may be a very serious issue");
}
}
/**
* Generate sync task without the ability to specify the Method object or arguments, made for easy typing
*/
public SyncTask(Object target, String method) {
this.o = target;
try {
this.m = o.getClass().getMethod(method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
FactionsPlugin.getInstance().getLogger().log(Level.SEVERE, "A Method could not be located! This means a task that was supposed to happen did not, this may be a very serious issue");
}
}
public void call() throws InvocationTargetException, IllegalAccessException {
m.invoke(o, arguments);
}
}

@ -0,0 +1,41 @@
package com.massivecraft.factions.util.Wait;
import com.massivecraft.factions.FactionsPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author droppinganvil
*/
public class WaitExecutor {
private static boolean enabled = false;
public static ConcurrentHashMap<Player, WaitTask> taskMap = new ConcurrentHashMap<>();
public static void startTask() {
if (enabled) return;
Bukkit.getScheduler().scheduleSyncRepeatingTask(FactionsPlugin.instance, () ->
{
for (WaitTask task : taskMap.values()) {
int i = task.getWait() - 1;
if (i > 0) {
if (i != 1) {
task.getPlayer().sendMessage(task.getMessage().format((i + " Seconds")));
} else {
task.getPlayer().sendMessage(task.getMessage().format((i + " Second")));
}
task.setWait(i);
} else {
task.success();
taskMap.remove(task.getPlayer());
}
}
},0L,20L);
enabled = true;
}
public static void handleAction(Player player) {
if (!taskMap.containsKey(player)) return;
taskMap.get(player).fail();
taskMap.remove(player);
}
}

@ -0,0 +1,47 @@
package com.massivecraft.factions.util.Wait;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.entity.Player;
/**
* @author droppinganvil
*/
public class WaitTask {
private Integer wait;
private TL msg;
//Using player as to not have to convert every event
private Player player;
private WaitedTask origin;
public WaitTask(Integer wait, TL message, Player player, WaitedTask waitedTask) {
this.wait = wait;
this.msg = message;
this.player = player;
this.origin = waitedTask;
}
public Integer getWait() {
return wait;
}
public TL getMessage() {
return msg;
}
public Player getPlayer() {
return player;
}
public void setWait(Integer i) {
wait = i;
}
public void success() {
origin.handleSuccess(player);
}
public void fail() {
origin.handleFailure(player);
}
}

@ -0,0 +1,11 @@
package com.massivecraft.factions.util.Wait;
import org.bukkit.entity.Player;
/**
* @author droppinganvil
*/
public interface WaitedTask {
void handleSuccess(Player player);
void handleFailure(Player player);
}

@ -32,6 +32,8 @@ import org.bukkit.*;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.*; import java.util.*;
@ -47,6 +49,8 @@ import java.util.*;
*/ */
public abstract class MemoryFPlayer implements FPlayer { public abstract class MemoryFPlayer implements FPlayer {
public boolean inDuel = false;
public Map<Integer, ItemStack> oldInv = null;
public boolean enemiesNearby = false; public boolean enemiesNearby = false;
public boolean inChest = false; public boolean inChest = false;
public boolean discordSetup = false; public boolean discordSetup = false;
@ -226,6 +230,14 @@ public abstract class MemoryFPlayer implements FPlayer {
public void setEnemiesNearby(Boolean b) {this.enemiesNearby = b;} public void setEnemiesNearby(Boolean b) {this.enemiesNearby = b;}
public Map<Integer, ItemStack> getOldInv() {return this.oldInv;}
public void setOldInv(Map<Integer, ItemStack> inv) {this.oldInv = inv;}
public void setInDuel(Boolean b) {this.inDuel = b;}
public boolean isInDuel() {return this.inDuel;}
public boolean discordSetup() {return this.discordSetup;} public boolean discordSetup() {return this.discordSetup;}
public String discordUserID() {return this.discordUserID;} public String discordUserID() {return this.discordUserID;}

@ -1429,4 +1429,10 @@ public abstract class MemoryFaction implements Faction, EconomyParticipator {
public Set<FLocation> getAllClaims() { public Set<FLocation> getAllClaims() {
return Board.getInstance().getAllClaims(this); return Board.getInstance().getAllClaims(this);
} }
public void broadcast(String s) {
for (FPlayer fPlayer : getFPlayersWhereOnline(true)) {
fPlayer.sendMessage(s);
}
}
} }

@ -355,6 +355,12 @@ public enum TL {
DISCORD_CODE_INVALID_KEY("That code is invalid, verify the code is correct."), DISCORD_CODE_INVALID_KEY("That code is invalid, verify the code is correct."),
DISCORD_CODE_INVALID_FORMAT("If you are submitting a code please only type the code. Example message: 0000"), DISCORD_CODE_INVALID_FORMAT("If you are submitting a code please only type the code. Example message: 0000"),
//Duels
DUEL_REQUEST_REJECTED_FACTION("&c&l[!]&7 %1$s has rejected your duel request"),
DUEL_REQUEST_REJECTED_PLAYER("&c&l[!]&7 %1$s has exited the duel queue"),
DUEL_REQUEST_ACCEPTED_FACTION("&c&l[!]&7 %1$s has accepted your duel request"),
DUEL_REQUEST_ACCEPTED_PLAYER("&c&l[!]&7 %1$s has entered the duel queue"),
COMMAND_DEINVITE_CANDEINVITE("&c&l[!]&7 Players you can &cdeinvite: "), COMMAND_DEINVITE_CANDEINVITE("&c&l[!]&7 Players you can &cdeinvite: "),
COMMAND_DEINVITE_CLICKTODEINVITE("&c&l[!]&7 Click to &crevoke&7 invite for &c%1$s"), COMMAND_DEINVITE_CLICKTODEINVITE("&c&l[!]&7 Click to &crevoke&7 invite for &c%1$s"),

@ -1439,6 +1439,61 @@ Wild:
SpawnAboveBlocks: 10 SpawnAboveBlocks: 10
Effects: Effects:
- 'NIGHT_VISION' - 'NIGHT_VISION'
Duels:
Enabled: true
# Cooldown before a faction can request another faction to duel after dueling
Cooldown: 0
# In minutes
Time: 3
# After individual players receive the request for the duel how long should it take to start in seconds
WaitTime: 60
Broadcast:
BroadcastKill:
Enabled: true
# {team1_remaining} {team2_remaining} {team1_eliminated} {team2_eliminated} {team1_tag} {team2_tag} {eliminated_name}
Format: '&c&lFaction Duels&r &7{eliminated} has been eliminated. {team1_tag} &d{team1_remaining} &7| {team2_tag} &d{team2_remaining}'
BroadcastResult:
Enabled: true
# These placeholders are all for the winning team unless specified otherwise
# {remaining} {tag} {losers_tag}
Format: '&c&lFaction Duels&r &d{tag}&7 has defeated &d{losers_tag}&7 with {remaining} players remaining'
FormatTie: '&c&lFaction Duels&r &d{team1_tag} &7has tied with &d{team2_tag}'
SpawnPoints:
# Please change these to your arena
Team1:
# Make sure each player has somewhere to spawn if max faction size is 10 you need 10 spawn points for each team!
# SpawnPoint format: World,X,Y,Z
1: Duel,0,60,0
2: Duel,5,60,5
3: Duel,10,60,10
Team2:
1: Duel,50,50,50
2: Duel,55,50,55
3: Duel,60,50,60
GUI:
# Responses #
# Accepted: This player is queued for the duel, GUI closes
# Rejected: This player is not included in the duel, GUI closes
# Ignored: This player remains in GUI and no action is taken on their entry in the duel
# This happens when the click type is not left click
FallbackResponse: Ignored
Fill-Item:
Material: GRAY_STAINED_GLASS_PANE
Response: Ignored
Items:
12:
Material: GREEN_STAINED_GLASS_PANE
Name: '&2Accept'
Lore:
- '&2Join your faction''s duel'
Response: Accepted
13:
Material: RED_STAINED_GLASS_PANE
Name: '&cReject'
Lore:
- '&cLeave your faction''s duels'
Response: Rejected
############################################################ ############################################################
# +------------------------------------------------------+ # # +------------------------------------------------------+ #