Implement all permission functions

This commit is contained in:
Bjorn Beishline 2026-01-30 13:06:50 -07:00
parent a0f15d5252
commit d51f952a2f
3 changed files with 277 additions and 82 deletions

View File

@ -19,17 +19,19 @@ import org.bukkit.plugin.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull;
import org.patchbukkit.permissions.PatchBukkitPermissionManager;
@SuppressWarnings("removal")
public class PatchBukkitPluginManager implements PluginManager {
private final Server server;
private final PatchBukkitEventManager eventManager;
private final Map<String, Plugin> plugins = new ConcurrentHashMap<>();
private final Map<String, Permission> permissions = new HashMap<>();
PermissionManager permissionManager;
public PatchBukkitPluginManager(Server server) {
this.server = server;
this.eventManager = new PatchBukkitEventManager(server);
this.permissionManager = new PatchBukkitPermissionManager();
}
@Override
@ -159,117 +161,82 @@ public class PatchBukkitPluginManager implements PluginManager {
@Override
public @Nullable Permission getPermission(@NotNull String name) {
return permissions.get(name);
return this.permissionManager.getPermission(name);
}
@Override
public void addPermission(@NotNull Permission perm) {
permissions.put(perm.getName(), perm);
this.permissionManager.addPermission(perm);
}
@Override
public void removePermission(@NotNull Permission perm) {
throw new UnsupportedOperationException(
"Unimplemented method 'removePermission'"
);
this.permissionManager.removePermission(perm);
}
@Override
public void removePermission(@NotNull String name) {
throw new UnsupportedOperationException(
"Unimplemented method 'removePermission'"
);
this.permissionManager.removePermission(name);
}
@Override
public @NotNull Set<Permission> getDefaultPermissions(boolean op) {
throw new UnsupportedOperationException(
"Unimplemented method 'getDefaultPermissions'"
);
return this.permissionManager.getDefaultPermissions(op);
}
@Override
public void recalculatePermissionDefaults(@NotNull Permission perm) {
throw new UnsupportedOperationException(
"Unimplemented method 'recalculatePermissionDefaults'"
);
this.permissionManager.recalculatePermissionDefaults(perm);
}
@Override
public void subscribeToPermission(
@NotNull String permission,
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'subscribeToPermission'"
);
public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) {
this.permissionManager.subscribeToPermission(permission, permissible);
}
@Override
public void unsubscribeFromPermission(
@NotNull String permission,
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'unsubscribeFromPermission'"
);
public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) {
this.permissionManager.unsubscribeFromPermission(permission, permissible);
}
@Override
public @NotNull Set<Permissible> getPermissionSubscriptions(
@NotNull String permission
) {
throw new UnsupportedOperationException(
"Unimplemented method 'getPermissionSubscriptions'"
);
public @NotNull Set<Permissible> getPermissionSubscriptions(@NotNull String permission) {
return this.permissionManager.getPermissionSubscriptions(permission);
}
@Override
public void subscribeToDefaultPerms(
boolean op,
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'subscribeToDefaultPerms'"
);
public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) {
this.permissionManager.subscribeToDefaultPerms(op, permissible);
}
@Override
public void unsubscribeFromDefaultPerms(
boolean op,
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'unsubscribeFromDefaultPerms'"
);
public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) {
this.permissionManager.unsubscribeFromDefaultPerms(op, permissible);
}
@Override
public @NotNull Set<Permissible> getDefaultPermSubscriptions(boolean op) {
throw new UnsupportedOperationException(
"Unimplemented method 'getDefaultPermSubscriptions'"
);
return this.permissionManager.getDefaultPermSubscriptions(op);
}
@Override
public @NotNull Set<Permission> getPermissions() {
throw new UnsupportedOperationException(
"Unimplemented method 'getPermissions'"
);
return this.permissionManager.getPermissions();
}
@Override
public void addPermissions(List<Permission> perm) {
throw new UnsupportedOperationException(
"Unimplemented method 'addPermissions'"
);
public void addPermissions(@NotNull List<Permission> perm) {
this.permissionManager.addPermissions(perm);
}
@Override
public void clearPermissions() {
throw new UnsupportedOperationException(
"Unimplemented method 'clearPermissions'"
);
this.permissionManager.clearPermissions();
}
@Override
public void overridePermissionManager(@NotNull Plugin plugin, @Nullable PermissionManager permissionManager) {
this.permissionManager = permissionManager;
}
@Override
@ -288,14 +255,4 @@ public class PatchBukkitPluginManager implements PluginManager {
"Unimplemented method 'isTransitiveDependency'"
);
}
@Override
public void overridePermissionManager(
@NotNull Plugin plugin,
@Nullable PermissionManager permissionManager
) {
throw new UnsupportedOperationException(
"Unimplemented method 'overridePermissionManager'"
);
}
}

View File

@ -2,10 +2,12 @@ package org.patchbukkit.entity;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.EntityEffect;
import org.bukkit.Location;
import org.bukkit.Server;
@ -24,9 +26,11 @@ import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.permissions.ServerOperator;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.BoundingBox;
@ -46,6 +50,7 @@ public class PatchBukkitEntity implements Entity {
protected final UUID uuid;
private final String name;
private static PermissibleBase perm;
public PatchBukkitEntity(
UUID uuid,
@ -55,6 +60,24 @@ public class PatchBukkitEntity implements Entity {
this.name = name;
}
private static PermissibleBase getPermissibleBase() {
if (PatchBukkitEntity.perm == null) {
PatchBukkitEntity.perm = new PermissibleBase(new ServerOperator() {
@Override
public boolean isOp() {
return false;
}
@Override
public void setOp(boolean value) {
}
});
}
return PatchBukkitEntity.perm;
}
@Override
public void setMetadata(@NotNull String metadataKey, @NotNull MetadataValue newMetadataValue) {
// TODO Auto-generated method stub
@ -127,15 +150,13 @@ public class PatchBukkitEntity implements Entity {
}
@Override
public boolean hasPermission(@NotNull String name) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'hasPermission'");
public boolean hasPermission(String name) {
return PatchBukkitEntity.getPermissibleBase().hasPermission(name);
}
@Override
public boolean hasPermission(@NotNull Permission perm) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'hasPermission'");
public boolean hasPermission(Permission perm) {
return PatchBukkitEntity.getPermissibleBase().hasPermission(perm);
}
@Override
@ -183,14 +204,12 @@ public class PatchBukkitEntity implements Entity {
@Override
public boolean isOp() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'isOp'");
return PatchBukkitEntity.getPermissibleBase().isOp();
}
@Override
public void setOp(boolean value) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'setOp'");
PatchBukkitEntity.getPermissibleBase().setOp(value);
}
@Override

View File

@ -0,0 +1,219 @@
package org.patchbukkit.permissions;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.HashSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableSet;
import io.papermc.paper.plugin.PermissionManager;
public class PatchBukkitPermissionManager implements PermissionManager {
private final Map<String, Permission> permissions = new HashMap<>();
private final Map<Boolean, Set<Permission>> defaultPerms = new LinkedHashMap<>();
private final Map<String, Map<Permissible, Boolean>> permSubs = new HashMap<>();
private final Map<Boolean, Map<Permissible, Boolean>> defSubs = new HashMap<>();
public PatchBukkitPermissionManager() {
this.defaultPerms().put(true, new LinkedHashSet<>());
this.defaultPerms().put(false, new LinkedHashSet<>());
}
public Map<String, Permission> permissions() {
return this.permissions;
}
public Map<Boolean, Set<Permission>> defaultPerms() {
return this.defaultPerms;
}
public Map<String, Map<Permissible, Boolean>> permSubs() {
return this.permSubs;
}
public Map<Boolean, Map<Permissible, Boolean>> defSubs() {
return this.defSubs;
}
@Override
@Nullable
public Permission getPermission(@NotNull String name) {
return this.permissions().get(name.toLowerCase(java.util.Locale.ENGLISH));
}
@Override
public void addPermission(@NotNull Permission perm) {
this.addPermission(perm, true);
}
@Override
public void addPermissions(@NotNull List<Permission> permissions) {
for (Permission permission : permissions) {
this.addPermission(permission, false);
}
this.dirtyPermissibles();
}
// Allow suppressing permission default calculations
private void addPermission(@NotNull Permission perm, boolean dirty) {
String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH);
if (this.permissions().containsKey(name)) {
throw new IllegalArgumentException("The permission " + name + " is already defined!");
}
this.permissions().put(name, perm);
this.calculatePermissionDefault(perm, dirty);
}
@Override
@NotNull
public Set<Permission> getDefaultPermissions(boolean op) {
return ImmutableSet.copyOf(this.defaultPerms().get(op));
}
@Override
public void removePermission(@NotNull Permission perm) {
this.removePermission(perm.getName());
}
@Override
public void removePermission(@NotNull String name) {
this.permissions().remove(name.toLowerCase(java.util.Locale.ENGLISH));
}
@Override
public void recalculatePermissionDefaults(@NotNull Permission perm) {
// we need a null check here because some plugins for some unknown reason pass null into this?
if (perm != null && this.permissions().containsKey(perm.getName().toLowerCase(Locale.ROOT))) {
this.defaultPerms().get(true).remove(perm);
this.defaultPerms().get(false).remove(perm);
this.calculatePermissionDefault(perm, true);
}
}
private void calculatePermissionDefault(@NotNull Permission perm, boolean dirty) {
if ((perm.getDefault() == PermissionDefault.OP) || (perm.getDefault() == PermissionDefault.TRUE)) {
this.defaultPerms().get(true).add(perm);
if (dirty) {
this.dirtyPermissibles(true);
}
}
if ((perm.getDefault() == PermissionDefault.NOT_OP) || (perm.getDefault() == PermissionDefault.TRUE)) {
this.defaultPerms().get(false).add(perm);
if (dirty) {
this.dirtyPermissibles(false);
}
}
}
@Override
public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) {
String name = permission.toLowerCase(java.util.Locale.ENGLISH);
Map<Permissible, Boolean> map = this.permSubs().computeIfAbsent(name, k -> new WeakHashMap<>());
map.put(permissible, true);
}
@Override
public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) {
String name = permission.toLowerCase(java.util.Locale.ENGLISH);
Map<Permissible, Boolean> map = this.permSubs().get(name);
if (map != null) {
map.remove(permissible);
if (map.isEmpty()) {
this.permSubs().remove(name);
}
}
}
@Override
@NotNull
public Set<Permissible> getPermissionSubscriptions(@NotNull String permission) {
String name = permission.toLowerCase(java.util.Locale.ENGLISH);
Map<Permissible, Boolean> map = this.permSubs().get(name);
if (map == null) {
return ImmutableSet.of();
} else {
return ImmutableSet.copyOf(map.keySet());
}
}
@Override
public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) {
Map<Permissible, Boolean> map = this.defSubs().computeIfAbsent(op, k -> new WeakHashMap<>());
map.put(permissible, true);
}
@Override
public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) {
Map<Permissible, Boolean> map = this.defSubs().get(op);
if (map != null) {
map.remove(permissible);
if (map.isEmpty()) {
this.defSubs().remove(op);
}
}
}
@Override
@NotNull
public Set<Permissible> getDefaultPermSubscriptions(boolean op) {
Map<Permissible, Boolean> map = this.defSubs().get(op);
if (map == null) {
return ImmutableSet.of();
} else {
return ImmutableSet.copyOf(map.keySet());
}
}
@Override
@NotNull
public Set<Permission> getPermissions() {
return new HashSet<>(this.permissions().values());
}
@Override
public void clearPermissions() {
this.permissions().clear();
this.defaultPerms().get(true).clear();
this.defaultPerms().get(false).clear();
}
void dirtyPermissibles(boolean op) {
Set<Permissible> permissibles = this.getDefaultPermSubscriptions(op);
for (Permissible p : permissibles) {
p.recalculatePermissions();
}
}
void dirtyPermissibles() {
this.dirtyPermissibles(true);
this.dirtyPermissibles(false);
}
}