private void handleFirstJoin(Player p) { if (!NameLayerPlugin.createGroupOnFirstJoin()) { return; } if (NameLayerPlugin.getDefaultGroupHandler().getDefaultGroup(p) != null) { // assume something went wrong, feel free to chose a random civcraft dev to blame return; } final UUID uuid = p.getUniqueId(); final String name = p.getName(); new NewfriendCreate(name, uuid).bootstrap(); }
private void changePlayerRank(UUID toChange, PlayerType newRank) { if (gm.hasAccess(g, p.getUniqueId(), getAccordingPermission(g.getCurrentRank(toChange)))) { if (!g.isMember(toChange)) { p.sendMessage( ChatColor.RED + "This player is no longer on the group and can't be " + demoteOrPromote(g.getCurrentRank(toChange), newRank, false) + "d"); return; } if (g.isOwner(toChange)) { p.sendMessage(ChatColor.RED + "This player owns the group and can't be demoted"); } OfflinePlayer prom = Bukkit.getOfflinePlayer(toChange); NameLayerPlugin.log( Level.INFO, p.getName() + " changed player rank for " + NameAPI.getCurrentName(toChange) + " from " + g.getCurrentRank(toChange).toString() + " to " + newRank.toString() + " for group " + g.getName() + "via gui"); if (prom.isOnline()) { Player oProm = (Player) prom; PromotePlayerEvent event = new PromotePlayerEvent(oProm, g, g.getCurrentRank(toChange), newRank); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { p.sendMessage( ChatColor.RED + "Could not change player rank, you should complain about this"); return; } g.removeMember(toChange); g.addMember(toChange, newRank); oProm.sendMessage( ChatColor.GREEN + "You have been promoted to " + getRankName(toChange) + " in (Group) " + g.getName()); } else { // player is offline change their perms g.removeMember(toChange); g.addMember(toChange, newRank); } p.sendMessage( ChatColor.GREEN + NameAPI.getCurrentName(toChange) + " has been " + demoteOrPromote(g.getCurrentRank(toChange), newRank, false) + "d to " + getRankName(toChange)); } else { p.sendMessage(ChatColor.RED + "You have lost permission to remove this player"); } }
@EventHandler(priority = EventPriority.LOWEST) public void playerJoinEvent(PlayerJoinEvent event) { Player p = event.getPlayer(); UUID uuid = p.getUniqueId(); if (!p.hasPlayedBefore()) { handleFirstJoin(p); } if (!notifications.containsKey(uuid) || notifications.get(uuid).isEmpty()) return; String x = null; boolean shouldAutoAccept = NameLayerPlugin.getAutoAcceptHandler().getAutoAccept(uuid); if (shouldAutoAccept) { x = "You have auto-accepted invitation from the following groups while you were away: "; } else { x = "You have been invited to the following groups while you were away. You can accept each invitation by using the command: /nlag [groupname]. "; } for (Group g : notifications.get(uuid)) { x += g.getName() + ", "; } x = x.substring(0, x.length() - 2); x += "."; p.sendMessage(ChatColor.YELLOW + x); }
public void setAutoAccept(UUID player, boolean accept, boolean persistToDb) { if (accept && !autoAccepts.contains(player)) { autoAccepts.add(player); if (persistToDb) { NameLayerPlugin.getGroupManagerDao().autoAcceptGroupsAsync(player); Mercury.addAutoAccept(player); } } else { if (autoAccepts.contains(player)) { autoAccepts.remove(player); if (persistToDb) { NameLayerPlugin.getGroupManagerDao().removeAutoAcceptGroupAsync(player); Mercury.removeAutoAccept(player); } } } }
@Override public void run() { Group g = getGroup(); if (g.getGroupId() == -1) { // now try + num NameLayerPlugin.log( Level.WARNING, "Newfriend automatic group creation failed for " + g.getName() + " " + uuid); GroupManager gm = NameAPI.getGroupManager(); if (inc == null) { inc = 0; } else { inc++; } if (inc < 20) { String newName = name + String.valueOf(inc); gm.createGroupAsync(new Group(newName, uuid, false, null, -1), this, true); } } else { NameLayerPlugin.log( Level.WARNING, "Newfriend automatic group creation succeeded for " + g.getName() + " " + uuid); g.setDefaultGroup(uuid); } }
private void removeMember(UUID toRemove) { if (gm.hasAccess(g, p.getUniqueId(), getAccordingPermission(g.getCurrentRank(toRemove)))) { if (!g.isMember(toRemove)) { p.sendMessage(ChatColor.RED + "This player is no longer on the group and can't be removed"); return; } if (g.isOwner(toRemove)) { p.sendMessage(ChatColor.RED + "This player owns the group and can't be removed"); } NameLayerPlugin.log( Level.INFO, p.getName() + " kicked " + NameAPI.getCurrentName(toRemove) + " from " + g.getName() + "via gui"); g.removeMember(toRemove); p.sendMessage( ChatColor.GREEN + NameAPI.getCurrentName(toRemove) + " has been removed from the group"); } else { p.sendMessage(ChatColor.RED + "You have lost permission to remove this player"); } }
/** * Creates a list of all Clickables representing members, invitees and blacklisted players, if * they are supposed to be displayed. This is whats directly fed into the middle of the gui */ private List<Clickable> constructClickables() { List<Clickable> clicks = new ArrayList<Clickable>(); if (showInheritedMembers) { if (g.hasSuperGroup()) { clicks.addAll(getRecursiveInheritedMembers(g.getSuperGroup())); } } if (showBlacklist) { final BlackList black = NameLayerPlugin.getBlackList(); for (final UUID uuid : black.getBlacklist(g)) { ItemStack is = new ItemStack(Material.LEATHER_CHESTPLATE); LeatherArmorMeta meta = (LeatherArmorMeta) is.getItemMeta(); meta.setColor(Color.BLACK); meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); is.setItemMeta(meta); ISUtils.setName(is, NameAPI.getCurrentName(uuid)); Clickable c; if (gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("BLACKLIST"))) { ISUtils.addLore( is, ChatColor.GREEN + "Click to remove " + NameAPI.getCurrentName(uuid), ChatColor.GREEN + "from the blacklist"); c = new Clickable(is) { @Override public void clicked(Player arg0) { if (gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("BLACKLIST"))) { NameLayerPlugin.log( Level.INFO, arg0.getName() + " removed " + NameAPI.getCurrentName(uuid) + " from the blacklist of " + g.getName() + "via gui"); black.removeBlacklistMember(g, uuid, true); p.sendMessage( ChatColor.GREEN + "You removed " + NameAPI.getCurrentName(uuid) + " from the blacklist"); } else { p.sendMessage( ChatColor.RED + "You lost permission to remove this player from the blacklist"); } showScreen(); } }; } else { ISUtils.addLore( is, ChatColor.RED + "You dont have permission to remove", ChatColor.RED + NameAPI.getCurrentName(uuid) + "from the blacklist"); c = new DecorationStack(is); } clicks.add(c); } } if (showInvites) { Map<UUID, PlayerType> invites = NameLayerPlugin.getGroupManagerDao().getInvitesForGroup(g.getName()); for (Entry<UUID, PlayerType> entry : invites.entrySet()) { ItemStack is = new ItemStack(Material.CHAINMAIL_CHESTPLATE); ItemMeta im = is.getItemMeta(); im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); is.setItemMeta(im); final String playerName = NameAPI.getCurrentName(entry.getKey()); ISUtils.setName(is, ChatColor.GOLD + playerName); boolean canRevoke = false; switch (entry.getValue()) { case MEMBERS: ISUtils.addLore(is, ChatColor.AQUA + "Invited as: Member"); if (gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("MEMBERS"))) { canRevoke = true; } break; case MODS: ISUtils.addLore(is, ChatColor.AQUA + "Invited as: Mod"); if (gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("MODS"))) { canRevoke = true; } break; case ADMINS: ISUtils.addLore(is, ChatColor.AQUA + "Invited as: Admin"); if (gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("ADMINS"))) { canRevoke = true; } break; case OWNER: ISUtils.addLore(is, ChatColor.AQUA + "Invited as: Owner"); if (gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("OWNER"))) { canRevoke = true; } break; default: continue; } Clickable c = null; if (canRevoke) { ISUtils.addLore(is, ChatColor.GREEN + "Click to revoke this invite"); c = new Clickable(is) { @Override public void clicked(Player arg0) { UUID invitedUUID = NameAPI.getUUID(playerName); PlayerType pType = g.getInvite(invitedUUID); if (pType == null) { p.sendMessage( ChatColor.RED + "Failed to revoke invite for " + playerName + ". This player isn't invited currently."); showScreen(); } // make sure the player still has permission to do // this boolean allowed = false; switch (pType) { case MEMBERS: allowed = gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("MEMBERS")); break; case MODS: allowed = gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("MODS")); break; case ADMINS: allowed = gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("ADMINS")); break; case OWNER: allowed = gm.hasAccess(g, p.getUniqueId(), PermissionType.getPermission("OWNER")); break; default: allowed = false; break; } if (!allowed) { p.sendMessage( ChatColor.RED + "You don't have permission to revoke this invite"); } else { NameLayerPlugin.log( Level.INFO, arg0.getName() + " revoked an invite for " + NameAPI.getCurrentName(invitedUUID) + " for group " + g.getName() + "via gui"); g.removeInvite(invitedUUID, true); PlayerListener.removeNotification(invitedUUID, g); Mercury.remInvite(g.getGroupId(), invitedUUID); p.sendMessage(ChatColor.GREEN + playerName + "'s invitation has been revoked."); } showScreen(); } }; } else { ISUtils.addLore(is, ChatColor.RED + "You don't have permission to revoke this invite"); c = new DecorationStack(is); } if (c != null) { clicks.add(c); } } } for (UUID uuid : g.getAllMembers()) { Clickable c = null; switch (g.getPlayerType(uuid)) { case MEMBERS: if (showMembers) { c = constructMemberClickable(Material.LEATHER_CHESTPLATE, uuid, PlayerType.MEMBERS); } break; case MODS: if (showMods) { c = constructMemberClickable(Material.GOLD_CHESTPLATE, uuid, PlayerType.MODS); } break; case ADMINS: if (showAdmins) { c = constructMemberClickable(Material.IRON_CHESTPLATE, uuid, PlayerType.ADMINS); } break; case OWNER: if (showOwners) { c = constructMemberClickable(Material.DIAMOND_CHESTPLATE, uuid, PlayerType.OWNER); } break; default: // should never happen } if (c != null) { clicks.add(c); } } return clicks; }
/** Creates the required mysql tables and updates the db if needed. */ private void createTables() { int ver = NameLayerPlugin.getVersionNum(plugin.getName()); long begin_time = System.currentTimeMillis(); if (ver == 0) { db.execute( String.format( "update db_version set plugin_name = '%s' " + "where plugin_name is null", plugin.getName())); ver = NameLayerPlugin.getVersionNum(plugin.getName()); if (ver == 0) { Citadel.Log("Creating tables from scratch, this is a new " + "instance of citadel."); } else { Citadel.Log( "Detected previous version of Citadel, " + "updating to new db.\n" + "You should have backed up your data, " + "if you havent already you have ten seconds to" + " shut down the server and perform a backup."); try { Thread.sleep(10000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } long first_time = System.currentTimeMillis(); db.execute( "alter table reinforcement drop security_level, drop version, add group_id int not null;"); /* Citadel.Log("Remapping from material id to material name " + "in process."); db.execute("create table if not exists material_mapping(" + "" + "material varchar(40) not null," + "material_id int not null);"); db.execute("create index x on material_mapping (material_id);"); for (Material mat: Material.values()){ PreparedStatement insert = db.prepareStatement ("insert into material_mapping(" + "material, material_id) values(?,?);"); try { insert.setString(1, mat.name()); insert.setInt(2, mat.getId()); insert.execute(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } db.execute("alter table reinforcement add " + "material varchar(10)"); db.execute("update reinforcement r " + "inner join material_mapping m on m.material_id = r.material_id " + "set r.material = m.material;"); db.execute("alter table reinforcement drop material_id;"); db.execute("drop table material_mapping;"); */ db.execute( "insert into faction_id (group_name) values (null);"); // For natural reinforcements db.execute("delete from reinforcement where `name` is null;"); db.execute( "update ignore reinforcement r inner join faction_id f on f.group_name = r.`name` " + "set r.group_id = f.group_id;"); db.execute( "alter table reinforcement drop `name`, add rein_type_id int not null default 1, " + "add lore varchar(255);"); db.execute("drop table citadel_account_id_map;"); Citadel.Log( "The update to new format took " + (System.currentTimeMillis() - first_time) / 1000 + " seconds."); } } if (ver == 5 || ver == 0) { long first_time = System.currentTimeMillis(); Citadel.Log("Updating to Citadel Version 6."); db.execute( "create table if not exists reinforcement(" + "x int not null," + "y int not null," + "z int not null," + "world varchar(10) not null," + "material_id int not null," + "durability varchar(10) not null," + "chunk_id varchar(255) not null," + "insecure tinyint(1) not null," + "group_id int not null," + "maturation_time int not null," + "rein_type_id int not null," + "lore varchar(255)," + "primary key (x,y,z,world));"); db.execute( "create table if not exists reinforcement_type(" + "rein_type_id int not null auto_increment," + "rein_type varchar(30) not null," + "primary key rein_type_key (rein_type_id));"); String[] types = {"PlayerReinforcement", "NaturalReinforcement", "MultiBlockReinforcement"}; for (String x : types) db.execute(String.format("insert into reinforcement_type(rein_type)" + "values('%s');", x)); NameLayerPlugin.insertVersionNum(5, plugin.getName()); ver = NameLayerPlugin.getVersionNum(plugin.getName()); Citadel.Log( "The update to Version 6 took " + (System.currentTimeMillis() - first_time) / 1000 + " seconds."); } if (ver == 6) { long first_time = System.currentTimeMillis(); Citadel.Log("Updating to version 7. No fun message for you :("); db.execute( "create table if not exists reinforcement_id(" + "rein_id int not null auto_increment," + "x int not null," + "y int not null," + "z int not null," + "chunk_id varchar(255)," + "world varchar (255) not null," + "primary key rein_id_key (rein_id)," + "unique key x_y_z_world(x,y,z,world));-- Your mother is a w***e and sleeps with banjos"); // I like turtles mother f****r. Never program because then you get turtles. db.execute( "insert into reinforcement_id (x, y, z, chunk_id, world) select x, y, z, chunk_id, world from reinforcement;"); // populate that bitch. db.execute("alter table reinforcement add rein_id int not null, drop chunk_id;"); db.execute( "update reinforcement r inner join reinforcement_id ri on " + "ri.x = r.x and ri.y = r.y and ri.z = r.z and ri.world = r.world " + "set r.rein_id = ri.rein_id"); db.execute( "alter table reinforcement DROP PRIMARY KEY, " + "add primary key rein_id_key(rein_id), " + "drop x," + "drop y," + "drop z," + "drop world;"); db.execute("alter table reinforcement_id add index `chunk_id_index` (chunk_id);"); NameLayerPlugin.insertVersionNum(ver, plugin.getName()); ver = NameLayerPlugin.getVersionNum(plugin.getName()); Citadel.Log( "The update to Version 7 took " + (System.currentTimeMillis() / first_time) / 1000 + " seconds."); } Citadel.Log( "The total time it took Citadel to update was " + (System.currentTimeMillis() - begin_time) / 1000 + " seconds."); }
/** * Inserts a reinforcement into the Database. Should only be called from SaveManager. * * @param The Reinforcement to save. */ public void insertReinforcement(Reinforcement rein) { reconnectAndReinitialize(); if (rein instanceof PlayerReinforcement) { Location loc = rein.getLocation(); int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); String world = loc.getWorld().getName(); Material mat = rein.getMaterial(); int dur = rein.getDurability(); int maturationTime = rein.getMaturationTime(); boolean insecure = false; String group = null; String reinType = ""; String lore = ""; PlayerReinforcement pRein = (PlayerReinforcement) rein; insecure = pRein.isInsecure(); ItemMeta meta = pRein.getStackRepresentation().getItemMeta(); if (meta.hasLore()) for (String xx : meta.getLore()) lore += xx + "\n"; else lore = null; group = pRein.getGroup().getName(); reinType = "PlayerReinforcement"; try { PreparedStatement insertReinID = db.prepareStatement(this.insertReinID); insertReinID.setInt(1, x); insertReinID.setInt(2, y); insertReinID.setInt(3, z); String formatChunk = formatChunk(loc); insertReinID.setString(4, formatChunk); insertReinID.setString(5, world); insertReinID.execute(); int id = getLastReinId(); PreparedStatement addRein = db.prepareStatement(this.addRein); addRein.setInt(1, mat.getId()); addRein.setInt(2, dur); addRein.setBoolean(3, insecure); addRein.setInt(4, maturationTime); addRein.setString(5, lore); addRein.setInt(6, id); addRein.setString(7, reinType); addRein.setString(8, group); addRein.execute(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (rein instanceof NaturalReinforcement) { Location loc = rein.getLocation(); int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); String world = loc.getWorld().getName(); Material mat = rein.getMaterial(); int dur = rein.getDurability(); String chunk_id = loc.getChunk().toString(); int maturationTime = rein.getMaturationTime(); boolean insecure = false; String group = NameLayerPlugin.getSpecialAdminGroup(); String reinType = "NaturalReinforcement"; String lore = ""; lore = null; try { PreparedStatement insertReinID = db.prepareStatement(this.insertReinID); insertReinID.setInt(1, x); insertReinID.setInt(2, y); insertReinID.setInt(3, z); String formatChunk = formatChunk(loc); insertReinID.setString(4, formatChunk); insertReinID.setString(5, world); insertReinID.execute(); int id = getLastReinId(); PreparedStatement addRein = db.prepareStatement(this.addRein); addRein.setInt(1, mat.getId()); addRein.setInt(2, dur); addRein.setBoolean(3, insecure); addRein.setInt(4, maturationTime); addRein.setString(5, lore); addRein.setInt(6, id); addRein.setString(7, reinType); addRein.setString(8, group); addRein.execute(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (rein instanceof MultiBlockReinforcement) { MultiBlockReinforcement mbRein = (MultiBlockReinforcement) rein; Location loc = mbRein.getLocation(); try { PreparedStatement insertReinID = db.prepareStatement(this.insertReinID); // add all the locations into the db. for (Location lo : mbRein.getLocations()) { insertReinID.setInt(1, lo.getBlockX()); insertReinID.setInt(2, lo.getBlockY()); insertReinID.setInt(3, lo.getBlockZ()); String formatChunk = formatChunk(lo); insertReinID.setString(4, formatChunk); insertReinID.setString(5, lo.getWorld().getName()); insertReinID.addBatch(); } insertReinID.executeBatch(); int id = getLastReinId(); PreparedStatement addRein = db.prepareStatement(this.addRein); addRein.setInt(1, -1); addRein.setInt(2, mbRein.getDurability()); addRein.setBoolean(3, false); addRein.setInt(4, mbRein.getMaturationTime()); addRein.setString(5, null); addRein.setInt(6, id); addRein.setString(7, "MultiBlockReinforcement"); addRein.setString(8, mbRein.getGroup().getName()); addRein.execute(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
public class InvitePlayer extends PlayerCommandMiddle { private GroupManagerDao db = NameLayerPlugin.getGroupManagerDao(); public InvitePlayer(String name) { super(name); setIdentifier("nlip"); setDescription( "Invite a player to the PlayerType " + PlayerType.toStringName() + " of a group."); setUsage("/nlip <group> <player> (PlayerType- default MEMBERS)"); setArguments(2, 3); } @Override public boolean execute(CommandSender sender, String[] args) { if (!(sender instanceof Player)) { sender.sendMessage(ChatColor.RED + "I'm sorry baby, please run this as a player :)"); return true; } Player p = (Player) sender; Group group = gm.getGroup(args[0]); if (group == null) { p.sendMessage(ChatColor.RED + "That group does not exist."); return true; } if (group.isDisciplined()) { p.sendMessage(ChatColor.RED + "This group is disiplined."); return true; } UUID executor = NameAPI.getUUID(p.getName()); PlayerType pType = PlayerType.MEMBERS; if (args.length == 3) pType = PlayerType.getPlayerType(args[2]); if (pType == null) { PlayerType.displayPlayerTypes(p); return true; } UUID uuid = NameAPI.getUUID(args[1]); if (uuid == null) { p.sendMessage(ChatColor.RED + "The player has never played before."); return true; } GroupPermission perm = gm.getPermissionforGroup(group); PlayerType t = group.getPlayerType(executor); // playertype for the player running the command. if (t == null) { p.sendMessage(ChatColor.RED + "You are not on that group."); return true; } boolean allowed = false; switch (pType) { // depending on the type the executor wants to add the player to case MEMBERS: allowed = perm.isAccessible(t, PermissionType.MEMBERS); break; case MODS: allowed = perm.isAccessible(t, PermissionType.MODS); break; case ADMINS: allowed = perm.isAccessible(t, PermissionType.ADMINS); break; case OWNER: allowed = perm.isAccessible(t, PermissionType.OWNER); break; default: allowed = false; break; } if (!allowed) { p.sendMessage(ChatColor.RED + "You do not have permissions to modify this group."); return true; } if (group.isMember(uuid)) { // So a player can't demote someone who is above them. p.sendMessage( ChatColor.RED + "Player is already a member." + "Use /nlpp to change their PlayerType."); return true; } group.addInvite(uuid, pType); OfflinePlayer invitee = Bukkit.getOfflinePlayer(uuid); boolean shouldAutoAccept = db.shouldAutoAcceptGroups(uuid); if (invitee.isOnline()) { // invitee is online make them a player Player oInvitee = (Player) invitee; if (shouldAutoAccept) { // player auto accepts invite group.addMember(uuid, pType); group.removeRemoveInvite(uuid); if (group instanceof PrivateGroup) { PrivateGroup priv = (PrivateGroup) group; List<Group> groups = priv.getSubGroups(); for (Group g : groups) { g.addMember(uuid, PlayerType.SUBGROUP); } } p.sendMessage( ChatColor.GREEN + "The invitation has been sent." + "\n Use /nlri to Revoke an invite."); oInvitee.sendMessage( ChatColor.GREEN + " You have auto-accepted invite to the group: " + group.getName()); } else { PlayerListener.addNotification(uuid, group); oInvitee.sendMessage( ChatColor.GREEN + "You have been invited to the group " + group.getName() + " by " + p.getName() + ".\n" + "Use the command /nlag <group> to accept.\n" + "If you wish to toggle invites so they always are accepted please run /nltaai"); p.sendMessage( ChatColor.GREEN + "The invitation has been sent." + "\n Use /nlri to Revoke an invite."); } } else { // invitee is offline if (shouldAutoAccept) { group.addMember(uuid, pType); group.removeRemoveInvite(uuid); PlayerListener.addNotification(uuid, group); p.sendMessage( ChatColor.GREEN + "The invitation has been sent." + "\n Use /nlri to Revoke an invite."); } else { // Player did not auto accept PlayerListener.addNotification(uuid, group); p.sendMessage( ChatColor.GREEN + "The invitation has been sent." + "\n Use /nlri to Revoke an invite."); } } return true; } @Override public List<String> tabComplete(CommandSender sender, String[] args) { if (!(sender instanceof Player)) { sender.sendMessage(ChatColor.RED + "I'm sorry baby, please run this as a player :)"); return null; } if (args.length < 2) { if (args.length == 0) return GroupTabCompleter.complete(null, null, (Player) sender); else return GroupTabCompleter.complete(args[0], null, (Player) sender); } else if (args.length == 2) return null; else if (args.length == 3) return MemberTypeCompleter.complete(args[2]); else return null; } }