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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import org.patchbukkit.permissions.PatchBukkitPermissionManager;
@SuppressWarnings("removal") @SuppressWarnings("removal")
public class PatchBukkitPluginManager implements PluginManager { public class PatchBukkitPluginManager implements PluginManager {
private final Server server; private final Server server;
private final PatchBukkitEventManager eventManager; private final PatchBukkitEventManager eventManager;
private final Map<String, Plugin> plugins = new ConcurrentHashMap<>(); private final Map<String, Plugin> plugins = new ConcurrentHashMap<>();
private final Map<String, Permission> permissions = new HashMap<>(); PermissionManager permissionManager;
public PatchBukkitPluginManager(Server server) { public PatchBukkitPluginManager(Server server) {
this.server = server; this.server = server;
this.eventManager = new PatchBukkitEventManager(server); this.eventManager = new PatchBukkitEventManager(server);
this.permissionManager = new PatchBukkitPermissionManager();
} }
@Override @Override
@ -159,117 +161,82 @@ public class PatchBukkitPluginManager implements PluginManager {
@Override @Override
public @Nullable Permission getPermission(@NotNull String name) { public @Nullable Permission getPermission(@NotNull String name) {
return permissions.get(name); return this.permissionManager.getPermission(name);
} }
@Override @Override
public void addPermission(@NotNull Permission perm) { public void addPermission(@NotNull Permission perm) {
permissions.put(perm.getName(), perm); this.permissionManager.addPermission(perm);
} }
@Override @Override
public void removePermission(@NotNull Permission perm) { public void removePermission(@NotNull Permission perm) {
throw new UnsupportedOperationException( this.permissionManager.removePermission(perm);
"Unimplemented method 'removePermission'"
);
} }
@Override @Override
public void removePermission(@NotNull String name) { public void removePermission(@NotNull String name) {
throw new UnsupportedOperationException( this.permissionManager.removePermission(name);
"Unimplemented method 'removePermission'"
);
} }
@Override @Override
public @NotNull Set<Permission> getDefaultPermissions(boolean op) { public @NotNull Set<Permission> getDefaultPermissions(boolean op) {
throw new UnsupportedOperationException( return this.permissionManager.getDefaultPermissions(op);
"Unimplemented method 'getDefaultPermissions'"
);
} }
@Override @Override
public void recalculatePermissionDefaults(@NotNull Permission perm) { public void recalculatePermissionDefaults(@NotNull Permission perm) {
throw new UnsupportedOperationException( this.permissionManager.recalculatePermissionDefaults(perm);
"Unimplemented method 'recalculatePermissionDefaults'"
);
} }
@Override @Override
public void subscribeToPermission( public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) {
@NotNull String permission, this.permissionManager.subscribeToPermission(permission, permissible);
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'subscribeToPermission'"
);
} }
@Override @Override
public void unsubscribeFromPermission( public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) {
@NotNull String permission, this.permissionManager.unsubscribeFromPermission(permission, permissible);
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'unsubscribeFromPermission'"
);
} }
@Override @Override
public @NotNull Set<Permissible> getPermissionSubscriptions( public @NotNull Set<Permissible> getPermissionSubscriptions(@NotNull String permission) {
@NotNull String permission return this.permissionManager.getPermissionSubscriptions(permission);
) {
throw new UnsupportedOperationException(
"Unimplemented method 'getPermissionSubscriptions'"
);
} }
@Override @Override
public void subscribeToDefaultPerms( public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) {
boolean op, this.permissionManager.subscribeToDefaultPerms(op, permissible);
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'subscribeToDefaultPerms'"
);
} }
@Override @Override
public void unsubscribeFromDefaultPerms( public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) {
boolean op, this.permissionManager.unsubscribeFromDefaultPerms(op, permissible);
@NotNull Permissible permissible
) {
throw new UnsupportedOperationException(
"Unimplemented method 'unsubscribeFromDefaultPerms'"
);
} }
@Override @Override
public @NotNull Set<Permissible> getDefaultPermSubscriptions(boolean op) { public @NotNull Set<Permissible> getDefaultPermSubscriptions(boolean op) {
throw new UnsupportedOperationException( return this.permissionManager.getDefaultPermSubscriptions(op);
"Unimplemented method 'getDefaultPermSubscriptions'"
);
} }
@Override @Override
public @NotNull Set<Permission> getPermissions() { public @NotNull Set<Permission> getPermissions() {
throw new UnsupportedOperationException( return this.permissionManager.getPermissions();
"Unimplemented method 'getPermissions'"
);
} }
@Override @Override
public void addPermissions(List<Permission> perm) { public void addPermissions(@NotNull List<Permission> perm) {
throw new UnsupportedOperationException( this.permissionManager.addPermissions(perm);
"Unimplemented method 'addPermissions'"
);
} }
@Override @Override
public void clearPermissions() { public void clearPermissions() {
throw new UnsupportedOperationException( this.permissionManager.clearPermissions();
"Unimplemented method 'clearPermissions'" }
);
@Override
public void overridePermissionManager(@NotNull Plugin plugin, @Nullable PermissionManager permissionManager) {
this.permissionManager = permissionManager;
} }
@Override @Override
@ -288,14 +255,4 @@ public class PatchBukkitPluginManager implements PluginManager {
"Unimplemented method 'isTransitiveDependency'" "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.Collection;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.EntityEffect; import org.bukkit.EntityEffect;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Server; import org.bukkit.Server;
@ -24,9 +26,11 @@ import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue; import org.bukkit.metadata.MetadataValue;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission; import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment; import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.permissions.ServerOperator;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.util.BoundingBox; import org.bukkit.util.BoundingBox;
@ -46,6 +50,7 @@ public class PatchBukkitEntity implements Entity {
protected final UUID uuid; protected final UUID uuid;
private final String name; private final String name;
private static PermissibleBase perm;
public PatchBukkitEntity( public PatchBukkitEntity(
UUID uuid, UUID uuid,
@ -55,6 +60,24 @@ public class PatchBukkitEntity implements Entity {
this.name = name; 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 @Override
public void setMetadata(@NotNull String metadataKey, @NotNull MetadataValue newMetadataValue) { public void setMetadata(@NotNull String metadataKey, @NotNull MetadataValue newMetadataValue) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
@ -127,15 +150,13 @@ public class PatchBukkitEntity implements Entity {
} }
@Override @Override
public boolean hasPermission(@NotNull String name) { public boolean hasPermission(String name) {
// TODO Auto-generated method stub return PatchBukkitEntity.getPermissibleBase().hasPermission(name);
throw new UnsupportedOperationException("Unimplemented method 'hasPermission'");
} }
@Override @Override
public boolean hasPermission(@NotNull Permission perm) { public boolean hasPermission(Permission perm) {
// TODO Auto-generated method stub return PatchBukkitEntity.getPermissibleBase().hasPermission(perm);
throw new UnsupportedOperationException("Unimplemented method 'hasPermission'");
} }
@Override @Override
@ -183,14 +204,12 @@ public class PatchBukkitEntity implements Entity {
@Override @Override
public boolean isOp() { public boolean isOp() {
// TODO Auto-generated method stub return PatchBukkitEntity.getPermissibleBase().isOp();
throw new UnsupportedOperationException("Unimplemented method 'isOp'");
} }
@Override @Override
public void setOp(boolean value) { public void setOp(boolean value) {
// TODO Auto-generated method stub PatchBukkitEntity.getPermissibleBase().setOp(value);
throw new UnsupportedOperationException("Unimplemented method 'setOp'");
} }
@Override @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);
}
}