Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Managers #49

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ Permission node: `htm.command.trust`

Permission node: `htm.command.trust`

### Managers

Managers are users authorized by the owner of a protected block to manage the protection
on their behalf. Managers are able to add and remove trusted members, but cannot transfer,
remove, or change the lock type, nor can they modify flags on the container. Only the owner
can add or remove managers.

`/htm managers add <player>`: Allows a player to trust or untrust players on behalf of the owner.

`/htm managers remove <player>`: Revokes a player's access to trust or untrust players on behalf of the owner.

### Remove

`/htm remove`: Removes all protections from a container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ public class HTMContainerLock {
private Lock type;
private UUID owner;
private HashSet<UUID> trusted;
private HashSet<UUID> managers;
private Map<String, Boolean> flags;

public HTMContainerLock() {
type = null;
owner = null;
trusted = new HashSet<>();
managers = new HashSet<>();
initFlags();
}

Expand All @@ -51,6 +53,12 @@ public void toTag(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup)

tag.put("Trusted", trustedTag);

NbtList managersTag = new NbtList();
for (UUID uuid : managers) {
managersTag.add(NbtHelper.fromUuid(uuid));
}
tag.put("Managers", managersTag);

NbtList flagsTag = new NbtList();
for (Map.Entry<String, Boolean> entry : flags.entrySet()) {
NbtCompound flagTag = new NbtCompound();
Expand Down Expand Up @@ -83,6 +91,12 @@ public void fromTag(NbtCompound tag, RegistryWrapper.WrapperLookup registryLooku
trusted.add(NbtHelper.toUuid(value));
}

NbtList managersTag = tag.getList("Managers", NbtElement.INT_ARRAY_TYPE);

for (NbtElement value : managersTag) {
managers.add(NbtHelper.toUuid(value));
}

NbtList flagTags = tag.getList("Flags", NbtElement.COMPOUND_TYPE);
for (NbtElement flagTag : flagTags) {
NbtCompound compoundTag = (NbtCompound) flagTag;
Expand Down Expand Up @@ -119,6 +133,8 @@ public HashSet<UUID> getTrusted() {
return trusted;
}

public HashSet<UUID> getManagers() { return managers; }

public void setType(Lock type, ServerPlayerEntity owner) {
this.type = type;
this.owner = owner.getUuid();
Expand All @@ -129,6 +145,7 @@ public void remove() {
type = null;
owner = null;
trusted = new HashSet<>();
managers = new HashSet<>();
initFlags();
}

Expand All @@ -144,6 +161,12 @@ public boolean isTrusted(UUID id) {
return trusted.contains(id);
}

public boolean addManager(UUID id) { return managers.add(id);}

public boolean removeManager(UUID id) { return managers.remove(id);}

public boolean isManager(UUID id) { return managers.contains(id); }

public void transfer(UUID id) {
owner = id;
}
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/github/fabricservertools/htm/Utility.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import net.minecraft.text.Text;
import net.minecraft.world.PersistentState;

import java.util.HashSet;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Utility {
public static String getNameFromUUID (UUID uuid, MinecraftServer server) {
Expand All @@ -34,4 +37,35 @@ public static void sendMessage(PlayerEntity player, Text message, boolean action
player.sendMessage(message, actionBar);
}
}

/**
* Accepts a collection of user ids and renders them as a list of usernames.
* @param userIds The unique collection of user ids.
* @param minecraftServer The Minecraft server to query for names.
* @return A comma-delimited string containing a list of names.
*/
public static String joinPlayerNames(
HashSet<UUID> userIds,
MinecraftServer minecraftServer
) {
return Utility.joinPlayerNames(userIds, minecraftServer, ", ");
}

/**
* Accepts a collection of user ids and renders them as a list of usernames.
* @param userIds The unique collection of user ids.
* @param minecraftServer The Minecraft server to query for names.
* @param delimiter The delimiter to use when separating names.
* @return A string containing a list of names separated by {@code delimiter}.
*/
public static String joinPlayerNames(
HashSet<UUID> userIds,
MinecraftServer minecraftServer,
String delimiter
) {
return userIds
.stream()
.map(uuid -> Utility.getNameFromUUID(uuid, minecraftServer))
.collect(Collectors.joining(delimiter));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.github.fabricservertools.htm.command.subcommands;

import com.github.fabricservertools.htm.Utility;
import com.github.fabricservertools.htm.command.SubCommand;
import com.github.fabricservertools.htm.interactions.InfoAction;
import com.github.fabricservertools.htm.interactions.InteractionManager;
import com.github.fabricservertools.htm.interactions.ManagerAction;
import com.github.fabricservertools.htm.interactions.TrustAction;
import com.github.fabricservertools.htm.world.data.GlobalTrustState;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.tree.LiteralCommandNode;
import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.argument.GameProfileArgumentType;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;

import java.util.Collection;
import java.util.stream.Collectors;

import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;

public class ManagerCommands implements SubCommand {
@Override
public LiteralCommandNode<ServerCommandSource> build() {
return literal("managers")
.requires(Permissions.require("htm.command.info", true))
.executes(ManagerCommands::managersList)
.then(
literal("add")
.requires(Permissions.require("htm.command.managers.add", true))
.then(argument("target", GameProfileArgumentType.gameProfile())
.executes(ctx -> ManagerCommands.editManagers(ctx, false)))
)
.then(
literal("remove")
.requires(Permissions.require("htm.command.managers.remove", true))
.then(argument("target", GameProfileArgumentType.gameProfile())
.executes(ctx -> ManagerCommands.editManagers(ctx, true)))
)
.build();
}

private static int managersList(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
ServerPlayerEntity player = context.getSource().getPlayer();


InteractionManager.pendingActions.put(player, new InfoAction());
context.getSource().sendFeedback(() -> Text.translatable("text.htm.select"), false);
return 1;
}

private static int editManagers(CommandContext<ServerCommandSource> context, boolean untrust) throws CommandSyntaxException
{
ServerCommandSource source = context.getSource();
Collection<GameProfile> gameProfiles = GameProfileArgumentType.getProfileArgument(context, "target");

InteractionManager.pendingActions.put(source.getPlayer(), new ManagerAction(gameProfiles, untrust));
return 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
import com.github.fabricservertools.htm.Utility;
import com.github.fabricservertools.htm.api.LockInteraction;
import com.mojang.authlib.GameProfile;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import java.util.HashSet;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

public class InfoAction implements LockInteraction {
Expand All @@ -33,12 +36,12 @@ public void execute(ServerPlayerEntity player, World world, BlockPos pos, HTMCon
player.sendMessage(Text.translatable("text.htm.type", HTMRegistry.getLockId(lock.getType().getType()).toUpperCase()), false);
player.sendMessage(Text.translatable("text.htm.owner", owner.get().getName()), false);
if (lock.isOwner(player)) {
String trustedList = lock.getTrusted()
.stream()
.map(uuid -> Utility.getNameFromUUID(uuid, player.server))
.collect(Collectors.joining(", "));
String managersList = Utility.joinPlayerNames(lock.getManagers(), player.server);
player.sendMessage(Text.translatable("text.htm.managers", managersList), false);

String trustedList = Utility.joinPlayerNames(lock.getTrusted(), player.server);
player.sendMessage(Text.translatable("text.htm.trusted", trustedList), false);

lock.getType().onInfo(player, lock);
}
player.sendMessage(Text.translatable("text.htm.divider"), false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.github.fabricservertools.htm.interactions;

import com.github.fabricservertools.htm.HTMContainerLock;
import com.github.fabricservertools.htm.api.LockInteraction;
import com.mojang.authlib.GameProfile;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import java.util.Collection;
import java.util.Objects;

public class ManagerAction implements LockInteraction {
private final Collection<GameProfile> managers;
private final boolean untrust;

public ManagerAction(Collection<GameProfile> managers, boolean untrust) {
this.managers = managers;
this.untrust = untrust;
}

@Override
public void execute(ServerPlayerEntity player, World world, BlockPos pos, HTMContainerLock lock) {
if (!lock.isLocked()) {
player.sendMessage(Text.translatable("text.htm.error.no_lock"), false);
return;
}

// Only owners can add managers.
if (!lock.isOwner(player)) {
player.sendMessage(Text.translatable("text.htm.error.not_owner"), false);
return;
}

for (GameProfile manager : managers) {
if (lock.getOwner() == manager.getId()) {
player.sendMessage(Text.translatable("text.htm.error.trust_self"), false);
continue;
}

if (untrust) {
//untrust
if (lock.removeManager(manager.getId())) {
player.sendMessage(Text.translatable("text.htm.untrust_manager", manager.getName()), false);
} else {
player.sendMessage(Text.translatable("text.htm.error.manager_not_trusted", manager.getName()), false);
}
} else {
//trust
if (lock.addManager(manager.getId())) {
player.sendMessage(Text.translatable("text.htm.trust_manager", manager.getName()), false);
} else {
player.sendMessage(Text.translatable("text.htm.error.manager_already_trusted", manager.getName()), false);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public void execute(ServerPlayerEntity player, World world, BlockPos pos, HTMCon
return;
}

if (!lock.isOwner(player)) {
// Players and managers can manage trustees.
if (!lock.isOwner(player) && !lock.isManager(player.getUuid())) {
player.sendMessage(Text.translatable("text.htm.error.not_owner"), false);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class KeyLock implements Lock {
@Override
public boolean canOpen(ServerPlayerEntity player, HTMContainerLock lock) {
if (lock.isTrusted(player.getUuid())) return true;
if (lock.isManager(player.getUuid())) return true;
if (Utility.getGlobalTrustState(player.server).isTrusted(lock.getOwner(), player.getUuid()))
return true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class PrivateLock implements Lock {
@Override
public boolean canOpen(ServerPlayerEntity player, HTMContainerLock lock) {
if (lock.isTrusted(player.getUuid())) return true;
if (lock.isManager(player.getUuid())) return true;
return Utility.getGlobalTrustState(player.server).isTrusted(lock.getOwner(), player.getUuid());
}

Expand Down
10 changes: 8 additions & 2 deletions src/main/resources/data/htm/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@
"text.htm.persist": "§bToggled persist ",
"text.htm.no_msg": "§bToggled no messages ",
"text.htm.on": "§a§lOn",
"text.htm.off": "§c§lOff"
}
"text.htm.off": "§c§lOff",

"text.htm.trust_manager": "§bAdded Manager: §a%s",
"text.htm.untrust_manager": "§bRemoved Manager: §a%s",
"text.htm.error.manager_not_trusted": "§r§a%s §cisn't a manager",
"text.htm.error.manager_already_trusted": "§r§a%s §cis already a manager",
"text.htm.managers": "§b§lManagers: §r§a%s"
}
Loading