Improve track functionality. Resolves #39

This commit is contained in:
Luck 2016-11-01 21:34:54 +00:00
parent 80570717f9
commit 79f24a5944
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
9 changed files with 198 additions and 144 deletions

View File

@ -83,7 +83,7 @@ public class ParentSet extends SecondarySubCommand {
if (args.size() == 2) {
holder.clearParents(server);
holder.clearParents(server, null);
holder.setInheritGroup(group, server);
Message.SET_PARENT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server);
@ -103,7 +103,7 @@ public class ParentSet extends SecondarySubCommand {
}
} else {
holder.clearParents();
holder.clearParents(null, null);
holder.setInheritGroup(group);
if (holder instanceof User) {
((User) holder).setPrimaryGroup(group.getName());

View File

@ -48,7 +48,6 @@ public class UserMainCommand extends MainCommand<User> {
.add(new CommandMeta<>(true))
.add(new UserGetUUID())
.add(new UserSetPrimaryGroup())
.add(new UserShowTracks())
.add(new UserPromote())
.add(new UserDemote())
.add(new UserShowPos())

View File

@ -22,6 +22,8 @@
package me.lucko.luckperms.common.commands.user.subcommands;
import com.google.common.base.Objects;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.events.UserDemoteEvent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.internal.TrackLink;
@ -29,6 +31,7 @@ import me.lucko.luckperms.common.api.internal.UserLink;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.tracks.Track;
@ -37,12 +40,20 @@ import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class UserDemote extends SubCommand<User> {
public UserDemote() {
super("demote", "Demotes the user down a track", Permission.USER_DEMOTE, Predicate.not(1),
Arg.list(Arg.create("track", true, "the track to demote the user down"))
super("demote", "Demotes the user down a track", Permission.USER_DEMOTE, Predicate.notInRange(1, 3),
Arg.list(
Arg.create("track", true, "the track to demote the user down"),
Arg.create("server", false, "the server to promote on"),
Arg.create("world", false, "the world to promote on")
)
);
}
@ -70,13 +81,68 @@ public class UserDemote extends SubCommand<User> {
return CommandResult.STATE_ERROR;
}
final String old = user.getPrimaryGroup();
String server = null;
String world = null;
if (args.size() > 1) {
server = args.get(1);
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() > 2) {
world = args.get(2);
}
}
// Load applicable groups
Set<Node> nodes = new HashSet<>();
for (Node node : user.getNodes()) {
if (!node.isGroupNode()) {
continue;
}
if (!node.getValue()) {
continue;
}
String s = node.getServer().orElse(null);
if (!Objects.equal(s, server)) {
continue;
}
String w = node.getWorld().orElse(null);
if (!Objects.equal(w, world)) {
continue;
}
nodes.add(node);
}
Iterator<Node> it = nodes.iterator();
while (it.hasNext()) {
Node g = it.next();
if (!track.containsGroup(g.getGroupName())) {
it.remove();
}
}
if (nodes.isEmpty()) {
Message.USER_TRACK_ERROR_NOT_CONTAIN_GROUP.send(sender);
return CommandResult.FAILURE;
}
if (nodes.size() != 1) {
Message.TRACK_AMBIGUOUS_CALL.send(sender);
return CommandResult.FAILURE;
}
final String old = nodes.stream().findAny().get().getGroupName();
final String previous;
try {
previous = track.getPrevious(old);
} catch (ObjectLacksException e) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old);
Message.USER_DEMOTE_ERROR_NOT_CONTAIN_GROUP.send(sender);
return CommandResult.STATE_ERROR;
}
@ -96,19 +162,28 @@ public class UserDemote extends SubCommand<User> {
return CommandResult.LOADING_ERROR;
}
user.clearParents(server, world);
try {
user.unsetPermission("group." + old);
} catch (ObjectLacksException ignored) {}
try {
user.setInheritGroup(previousGroup);
user.setPermission(NodeFactory.newBuilder("group." + previousGroup.getName()).setServer(server).setWorld(world).build());
} catch (ObjectAlreadyHasException ignored) {}
user.setPrimaryGroup(previousGroup.getName());
Message.USER_DEMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, previousGroup.getDisplayName());
Message.USER_DEMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, previousGroup.getDisplayName(), previousGroup.getDisplayName());
if (server == null && world == null) {
user.setPrimaryGroup(previousGroup.getName());
}
if (server == null) {
Message.USER_DEMOTE_SUCCESS.send(sender, track.getName(), old, previousGroup.getDisplayName());
} else {
if (world == null) {
Message.USER_DEMOTE_SUCCESS_SERVER.send(sender, track.getName(), old, previousGroup.getDisplayName(), server);
} else {
Message.USER_DEMOTE_SUCCESS_SERVER_WORLD.send(sender, track.getName(), old, previousGroup.getDisplayName(), server, world);
}
}
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), previousGroup.getDisplayName(), old, true));
LogEntry.build().actor(sender).acted(user)
.action("demote " + track.getName() + "(from " + old + " to " + previousGroup.getName() + ")")
.action("demote " + args.stream().collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(user, sender, plugin);
plugin.getApiProvider().fireEventAsync(new UserDemoteEvent(new TrackLink(track), new UserLink(user), old, previousGroup.getName()));

View File

@ -22,6 +22,8 @@
package me.lucko.luckperms.common.commands.user.subcommands;
import com.google.common.base.Objects;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.events.UserPromoteEvent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.internal.TrackLink;
@ -29,6 +31,7 @@ import me.lucko.luckperms.common.api.internal.UserLink;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.tracks.Track;
@ -37,12 +40,20 @@ import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class UserPromote extends SubCommand<User> {
public UserPromote() {
super("promote", "Promotes the user up a track", Permission.USER_PROMOTE, Predicate.not(1),
Arg.list(Arg.create("track", true, "the track to promote the user up"))
super("promote", "Promotes the user up a track", Permission.USER_PROMOTE, Predicate.notInRange(1, 3),
Arg.list(
Arg.create("track", true, "the track to promote the user up"),
Arg.create("server", false, "the server to promote on"),
Arg.create("world", false, "the world to promote on")
)
);
}
@ -70,13 +81,68 @@ public class UserPromote extends SubCommand<User> {
return CommandResult.STATE_ERROR;
}
final String old = user.getPrimaryGroup();
String server = null;
String world = null;
if (args.size() > 1) {
server = args.get(1);
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() > 2) {
world = args.get(2);
}
}
// Load applicable groups
Set<Node> nodes = new HashSet<>();
for (Node node : user.getNodes()) {
if (!node.isGroupNode()) {
continue;
}
if (!node.getValue()) {
continue;
}
String s = node.getServer().orElse(null);
if (!Objects.equal(s, server)) {
continue;
}
String w = node.getWorld().orElse(null);
if (!Objects.equal(w, world)) {
continue;
}
nodes.add(node);
}
Iterator<Node> it = nodes.iterator();
while (it.hasNext()) {
Node g = it.next();
if (!track.containsGroup(g.getGroupName())) {
it.remove();
}
}
if (nodes.isEmpty()) {
Message.USER_TRACK_ERROR_NOT_CONTAIN_GROUP.send(sender);
return CommandResult.FAILURE;
}
if (nodes.size() != 1) {
Message.TRACK_AMBIGUOUS_CALL.send(sender);
return CommandResult.FAILURE;
}
final String old = nodes.stream().findAny().get().getGroupName();
final String next;
try {
next = track.getNext(old);
} catch (ObjectLacksException e) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old);
Message.USER_PROMOTE_ERROR_NOT_CONTAIN_GROUP.send(sender);
return CommandResult.STATE_ERROR;
}
@ -96,19 +162,28 @@ public class UserPromote extends SubCommand<User> {
return CommandResult.LOADING_ERROR;
}
user.clearParents(server, world);
try {
user.unsetPermission("group." + old);
} catch (ObjectLacksException ignored) {}
try {
user.setInheritGroup(nextGroup);
user.setPermission(NodeFactory.newBuilder("group." + nextGroup.getName()).setServer(server).setWorld(world).build());
} catch (ObjectAlreadyHasException ignored) {}
user.setPrimaryGroup(nextGroup.getName());
Message.USER_PROMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, nextGroup.getDisplayName());
Message.USER_PROMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, nextGroup.getDisplayName(), nextGroup.getDisplayName());
if (server == null && world == null) {
user.setPrimaryGroup(nextGroup.getName());
}
if (server == null) {
Message.USER_PROMOTE_SUCCESS.send(sender, track.getName(), old, nextGroup.getDisplayName());
} else {
if (world == null) {
Message.USER_PROMOTE_SUCCESS_SERVER.send(sender, track.getName(), old, nextGroup.getDisplayName(), server);
} else {
Message.USER_PROMOTE_SUCCESS_SERVER_WORLD.send(sender, track.getName(), old, nextGroup.getDisplayName(), server, world);
}
}
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), old, nextGroup.getDisplayName(), false));
LogEntry.build().actor(sender).acted(user)
.action("promote " + track.getName() + "(from " + old + " to " + nextGroup.getName() + ")")
.action("promote " + args.stream().collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(user, sender, plugin);
plugin.getApiProvider().fireEventAsync(new UserPromoteEvent(new TrackLink(track), new UserLink(user), old, nextGroup.getName()));

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.user.subcommands;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User;
import java.util.List;
import java.util.stream.Collectors;
public class UserShowTracks extends SubCommand<User> {
public UserShowTracks() {
super("showtracks", "Lists the tracks that the user's primary group features on", Permission.USER_SHOWTRACKS,
Predicate.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
if (!plugin.getDatastore().loadAllTracks().getUnchecked()) {
Message.TRACKS_LOAD_ERROR.send(sender);
return CommandResult.LOADING_ERROR;
}
Message.USER_SHOWTRACKS_INFO.send(sender, user.getPrimaryGroup(), user.getName());
Message.TRACKS_LIST.send(sender,
Util.listToCommaSep(plugin.getTrackManager().getApplicableTracks(user.getPrimaryGroup()).stream()
.map(Track::getName)
.collect(Collectors.toList())
)
);
return CommandResult.SUCCESS;
}
}

View File

@ -100,6 +100,7 @@ public enum Message {
TRACK_ALREADY_CONTAINS("Track {0} already contains the group '{1}'.", true),
TRACK_DOES_NOT_CONTAIN("Track {0} does not contain the group '{1}'.", true),
TRACK_AMBIGUOUS_CALL("The user specified is a member of multiple groups on this track. Unable to determine their location.", true),
GROUP_ALREADY_EXISTS("That group already exists!", true),
GROUP_DOES_NOT_EXIST("That group does not exist!", true),
@ -268,25 +269,25 @@ public enum Message {
USER_PRIMARYGROUP_SUCCESS("&b{0}&a's primary group was set to &b{1}&a.", true),
USER_PRIMARYGROUP_ERROR_ALREADYHAS("The user already has this group set as their primary group.", true),
USER_PRIMARYGROUP_ERROR_NOTMEMBER("&b{0}&a was not already a member of &b{1}&a, adding them now.", true),
USER_SHOWTRACKS_INFO("&aShowing tracks that contain the group '&b{0}&a' ({1}'s primary group)", true),
USER_PROMOTE_SUCCESS_PROMOTE("&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a.", true),
USER_PROMOTE_SUCCESS_REMOVE("&b{0}&a was removed from &b{1}&a, added to &b{2}&a, and their primary group was set to &b{3}&a.", true),
USER_TRACK_ERROR_NOT_CONTAIN_GROUP("The user specified isn't already in any groups on this track.", true),
USER_PROMOTE_SUCCESS("&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a.", true),
USER_PROMOTE_SUCCESS_SERVER("&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a.", true),
USER_PROMOTE_SUCCESS_SERVER_WORLD("&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a, world &b{4}&a.", true),
USER_PROMOTE_ERROR_ENDOFTRACK("The end of track &4{0}&c was reached. Unable to promote user.", true),
USER_PROMOTE_ERROR_MALFORMED(
"{PREFIX}The next group on the track, {0}, no longer exists. Unable to promote user." + "\n" +
"{PREFIX}Either create the group, or remove it from the track and try again.",
false
),
USER_PROMOTE_ERROR_NOT_CONTAIN_GROUP("Promotions are done based on primary groups. The users primary group is not on the track specified.", true),
USER_DEMOTE_SUCCESS_PROMOTE("&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a.", true),
USER_DEMOTE_SUCCESS_REMOVE("&b{0}&a was removed from &b{1}&a, added to &b{2}&a, and their primary group was set to &b{3}&a.", true),
USER_DEMOTE_SUCCESS("&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a.", true),
USER_DEMOTE_SUCCESS_SERVER("&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a.", true),
USER_DEMOTE_SUCCESS_SERVER_WORLD("&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a, world &b{4}&a.", true),
USER_DEMOTE_ERROR_ENDOFTRACK("The end of track &4{0}&c was reached. Unable to demote user.", true),
USER_DEMOTE_ERROR_MALFORMED(
"{PREFIX}The previous group on the track, {0}, no longer exists. Unable to demote user." + "\n" +
"{PREFIX}Either create the group, or remove it from the track and try again.",
false
),
USER_DEMOTE_ERROR_NOT_CONTAIN_GROUP("Demotions are done based on primary groups. The users primary group is not on the track specified.", true),
USER_SHOWPOS("&aShowing &b{0}&a's position on track &b{1}&a.\n{2}", true),
GROUP_INFO(
@ -298,7 +299,7 @@ public enum Message {
),
TRACK_INFO(
"{PREFIX}&b&l> Showing Track: &f{0}" + "\n" +
"{PREFIX}&b&l> &bShowing Track: &f{0}" + "\n" +
"{PREFIX}&f- &7Path: &f{1}",
false
),

View File

@ -56,6 +56,10 @@ public class NodeFactory {
return b ? CACHE.getUnchecked(s) : CACHE_NEGATED.getUnchecked(s);
}
public static Node.Builder newBuilder(String s) {
return new NodeBuilder(s, false);
}
public static Node.Builder builderFromSerialisedNode(String s, Boolean b) {
if (s.contains("/")) {
List<String> parts = Splitter.on('/').limit(2).splitToList(s);

View File

@ -748,26 +748,6 @@ public abstract class PermissionHolder {
}
}
public void clearParents() {
synchronized (nodes) {
boolean b = nodes.removeIf(Node::isGroupNode);
if (b) {
invalidateCache(true);
}
}
}
public void clearParents(String server) {
String finalServer = Optional.ofNullable(server).orElse("global");
synchronized (nodes) {
boolean b = nodes.removeIf(n -> n.isGroupNode() && n.getServer().orElse("global").equalsIgnoreCase(finalServer));
if (b) {
invalidateCache(true);
}
}
}
public void clearParents(String server, String world) {
String finalServer = Optional.ofNullable(server).orElse("global");
String finalWorld = Optional.ofNullable(world).orElse("null");
@ -824,30 +804,6 @@ public abstract class PermissionHolder {
}
}
public void clearMetaKeys(String key, boolean temp) {
synchronized (nodes) {
boolean b = nodes.removeIf(n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key));
if (b) {
invalidateCache(true);
}
}
}
public void clearMetaKeys(String key, String server, boolean temp) {
String finalServer = Optional.ofNullable(server).orElse("global");
synchronized (nodes) {
boolean b = nodes.removeIf(n ->
n.isMeta() && (n.isTemporary() == temp) &&
n.getMeta().getKey().equalsIgnoreCase(key) &&
n.getServer().orElse("global").equalsIgnoreCase(finalServer)
);
if (b) {
invalidateCache(true);
}
}
}
public void clearMetaKeys(String key, String server, String world, boolean temp) {
String finalServer = Optional.ofNullable(server).orElse("global");
String finalWorld = Optional.ofNullable(world).orElse("null");

View File

@ -61,6 +61,7 @@ does-not-temp-inherit: "{0} does not temporarily inherit '{1}'."
track-already-contains: "Track {0} already contains the group '{1}'."
track-does-not-contain: "Track {0} does not contain the group '{1}'."
track-ambiguous-call: "The user specified is a member of multiple groups on this track. Unable to determine their location."
group-already-exists: "That group already exists!"
group-does-not-exist: "That group does not exist!"
@ -219,16 +220,17 @@ user-removegroup-error-primary: "You cannot remove a user from their primary gro
user-primarygroup-success: "&b{0}&a's primary group was set to &b{1}&a."
user-primarygroup-error-alreadyhas: "The user already has this group set as their primary group."
user-primarygroup-error-notmember: "&b{0}&a was not already a member of &b{1}&a, adding them now."
user-showtracks-info: "&aShowing tracks that contain the group '&b{0}&a' ({1}'s primary group)"
user-promote-success-promote: "&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a."
user-promote-success-remove: "&b{0}&a was removed from &b{1}&a, added to &b{2}&a, and their primary group was set to &b{3}&a."
user-track-error-not-contain-group: "The user specified isn't already in any groups on this track."
user-promote-success: "&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a."
user-promote-success-server: "&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a."
user-promote-success-server-world: "&aPromoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a, world &b{4}&a."
user-promote-error-endoftrack: "The end of track &4{0}&c was reached. Unable to promote user."
user-promote-error-malformed: >
{PREFIX}The next group on the track, {0}, no longer exists. Unable to promote user.
{PREFIX}Either create the group, or remove it from the track and try again.
user-promote-error-not-contain-group: "Promotions are done based on primary groups. The users primary group is not on the track specified."
user-demote-success-promote: "&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a."
user-demote-success-remove: "&b{0}&a was removed from &b{1}&a, added to &b{2}&a, and their primary group was set to &b{3}&a."
user-demote-success: "&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a."
user-demote-success-server: "&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a."
user-demote-success-server-world: "&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a on server &b{3}&a, world &b{4}&a."
user-demote-error-endoftrack: "The end of track &4{0}&c was reached. Unable to demote user."
user-demote-error-malformed: >
{PREFIX}The previous group on the track, {0}, no longer exists. Unable to demote user.\n
@ -243,7 +245,7 @@ group-info: >
{PREFIX}&f- &3Use &b/{3} group {4} permission info &3to see all permissions.
track-info: >
{PREFIX}&b&l> Showing Track: &f{0}\n
{PREFIX}&b&l> &bShowing Track: &f{0}\n
{PREFIX}&f- &7Path: &f{1}
track-clear: "&b{0}&a's groups track was cleared."
track-append-success: "&aGroup &b{0}&a was successfully appended to track &b{1}&a."