Add workaround for plugins adding/removing/modifying permission attachments via reflection (#1024)
who knows why they're doing it, it's not even beneficial for performance...
This commit is contained in:
parent
c66622bd09
commit
644c53a074
@ -64,6 +64,19 @@ public class DummyPermissibleBase extends PermissibleBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyFields(PermissibleBase from, PermissibleBase to) {
|
||||
try {
|
||||
ATTACHMENTS_FIELD.set(to, ATTACHMENTS_FIELD.get(from));
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
PERMISSIONS_FIELD.set(to, PERMISSIONS_FIELD.get(from));
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
public static final DummyPermissibleBase INSTANCE = new DummyPermissibleBase();
|
||||
|
||||
private DummyPermissibleBase() {
|
||||
|
@ -25,11 +25,14 @@
|
||||
|
||||
package me.lucko.luckperms.bukkit.model.permissible;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.contexts.ContextsCache;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
@ -39,14 +42,18 @@ import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* PermissibleBase for LuckPerms.
|
||||
*
|
||||
@ -63,6 +70,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
public class LPPermissible extends PermissibleBase {
|
||||
|
||||
private static final Field ATTACHMENTS_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
ATTACHMENTS_FIELD = PermissibleBase.class.getDeclaredField("attachments");
|
||||
ATTACHMENTS_FIELD.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// the LuckPerms user this permissible references.
|
||||
private final User user;
|
||||
|
||||
@ -83,7 +101,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
// the attachments hooked onto the permissible.
|
||||
// this collection is only modified by the attachments themselves
|
||||
final Set<LPPermissionAttachment> attachments = ConcurrentHashMap.newKeySet();
|
||||
final Set<LPPermissionAttachment> lpAttachments = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public LPPermissible(Player player, User user, LPBukkitPlugin plugin) {
|
||||
super(player);
|
||||
@ -91,6 +109,26 @@ public class LPPermissible extends PermissibleBase {
|
||||
this.player = Objects.requireNonNull(player, "player");
|
||||
this.plugin = Objects.requireNonNull(plugin, "plugin");
|
||||
this.contextsCache = plugin.getContextManager().getCacheFor(player);
|
||||
|
||||
injectFakeAttachmentsList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a fake 'attachments' list into the superclass, for dumb plugins
|
||||
* which for some reason decided to add attachments via reflection.
|
||||
*
|
||||
* The fake list proxies (some) calls back to the proper methods on this permissible.
|
||||
*/
|
||||
private void injectFakeAttachmentsList() {
|
||||
FakeAttachmentList fakeList = new FakeAttachmentList();
|
||||
|
||||
try {
|
||||
// the field we need to modify is in the superclass - it has private
|
||||
// and final modifiers so we have to use reflection to modify it.
|
||||
ATTACHMENTS_FIELD.set(this, fakeList);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -154,7 +192,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
*
|
||||
* @param attachments the attachments to add
|
||||
*/
|
||||
public void convertAndAddAttachments(Collection<PermissionAttachment> attachments) {
|
||||
void convertAndAddAttachments(Collection<PermissionAttachment> attachments) {
|
||||
for (PermissionAttachment attachment : attachments) {
|
||||
new LPPermissionAttachment(this, attachment).hook();
|
||||
}
|
||||
@ -167,14 +205,9 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
Set<Map.Entry<String, Boolean>> permissions = this.user.getCachedData().getPermissionData(this.contextsCache.getContexts()).getImmutableBacking().entrySet();
|
||||
Set<PermissionAttachmentInfo> ret = new HashSet<>(permissions.size());
|
||||
|
||||
for (Map.Entry<String, Boolean> entry : permissions) {
|
||||
ret.add(new PermissionAttachmentInfo(this.player, entry.getKey(), null, entry.getValue()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this.user.getCachedData().getPermissionData(this.contextsCache.getContexts()).getImmutableBacking().entrySet().stream()
|
||||
.map(entry -> new PermissionAttachmentInfo(this.player, entry.getKey(), null, entry.getValue()))
|
||||
.collect(ImmutableCollectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -240,11 +273,20 @@ public class LPPermissible extends PermissibleBase {
|
||||
throw new NullPointerException("attachment");
|
||||
}
|
||||
|
||||
LPPermissionAttachment a;
|
||||
|
||||
if (!(attachment instanceof LPPermissionAttachment)) {
|
||||
// try to find a match
|
||||
LPPermissionAttachment match = this.lpAttachments.stream().filter(at -> at.getSource() == attachment).findFirst().orElse(null);
|
||||
if (match != null) {
|
||||
a = match;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given attachment is not a LPPermissionAttachment.");
|
||||
}
|
||||
} else {
|
||||
a = (LPPermissionAttachment) attachment;
|
||||
}
|
||||
|
||||
LPPermissionAttachment a = ((LPPermissionAttachment) attachment);
|
||||
if (a.getPermissible() != this) {
|
||||
throw new IllegalArgumentException("Attachment does not belong to this permissible.");
|
||||
}
|
||||
@ -259,7 +301,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public void clearPermissions() {
|
||||
this.attachments.forEach(LPPermissionAttachment::remove);
|
||||
this.lpAttachments.forEach(LPPermissionAttachment::remove);
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
@ -274,15 +316,102 @@ public class LPPermissible extends PermissibleBase {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
public PermissibleBase getOldPermissible() {
|
||||
PermissibleBase getOldPermissible() {
|
||||
return this.oldPermissible;
|
||||
}
|
||||
|
||||
public AtomicBoolean getActive() {
|
||||
AtomicBoolean getActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
public void setOldPermissible(PermissibleBase oldPermissible) {
|
||||
void setOldPermissible(PermissibleBase oldPermissible) {
|
||||
this.oldPermissible = oldPermissible;
|
||||
}
|
||||
|
||||
/**
|
||||
* A fake list to be injected into the superclass. This implementation simply
|
||||
* proxies calls back to this permissible instance.
|
||||
*
|
||||
* Some (clever/dumb??) plugins attempt to add/remove/query attachments using reflection.
|
||||
*
|
||||
* An instance of this map is injected into the super instance so these plugins continue
|
||||
* to work with LuckPerms.
|
||||
*/
|
||||
private final class FakeAttachmentList implements List<PermissionAttachment> {
|
||||
|
||||
@Override
|
||||
public boolean add(PermissionAttachment attachment) {
|
||||
if (LPPermissible.this.lpAttachments.stream().anyMatch(at -> at.getSource() == attachment)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
new LPPermissionAttachment(LPPermissible.this, attachment).hook();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
removeAttachment((PermissionAttachment) o);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
clearPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@Nonnull Collection<? extends PermissionAttachment> c) {
|
||||
boolean modified = false;
|
||||
for (PermissionAttachment e : c) {
|
||||
if (add(e)) {
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
PermissionAttachment attachment = (PermissionAttachment) o;
|
||||
return LPPermissible.this.lpAttachments.stream().anyMatch(at -> at.getSource() == attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<PermissionAttachment> iterator() {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<PermissionAttachment> listIterator() {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).listIterator();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).toArray();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> T[] toArray(@Nonnull T[] a) {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).toArray(a);
|
||||
}
|
||||
|
||||
@Override public int size() { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean isEmpty() { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean containsAll(@Nonnull Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean addAll(int index, @Nonnull Collection<? extends PermissionAttachment> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean removeAll(@Nonnull Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean retainAll(@Nonnull Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment get(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment set(int index, PermissionAttachment element) { throw new UnsupportedOperationException(); }
|
||||
@Override public void add(int index, PermissionAttachment element) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment remove(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Nonnull @Override public ListIterator<PermissionAttachment> listIterator(int index) { throw new UnsupportedOperationException(); }
|
||||
@Nonnull @Override public List<PermissionAttachment> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,11 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
*/
|
||||
private PermissionRemovedExecutor removalCallback = null;
|
||||
|
||||
/**
|
||||
* Delegate attachment
|
||||
*/
|
||||
private PermissionAttachment source;
|
||||
|
||||
public LPPermissionAttachment(LPPermissible permissible, Plugin owner) {
|
||||
super(DummyPlugin.INSTANCE, null);
|
||||
this.permissible = permissible;
|
||||
@ -102,13 +107,14 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
injectFakeMap();
|
||||
}
|
||||
|
||||
public LPPermissionAttachment(LPPermissible permissible, PermissionAttachment bukkit) {
|
||||
public LPPermissionAttachment(LPPermissible permissible, PermissionAttachment source) {
|
||||
super(DummyPlugin.INSTANCE, null);
|
||||
this.permissible = permissible;
|
||||
this.owner = null;
|
||||
|
||||
// copy
|
||||
this.perms.putAll(bukkit.getPermissions());
|
||||
this.perms.putAll(source.getPermissions());
|
||||
this.source = source;
|
||||
|
||||
injectFakeMap();
|
||||
}
|
||||
@ -148,12 +154,16 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
this.removalCallback = removalCallback;
|
||||
}
|
||||
|
||||
PermissionAttachment getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks this attachment with the parent {@link User} instance.
|
||||
*/
|
||||
public void hook() {
|
||||
this.hooked = true;
|
||||
this.permissible.attachments.add(this);
|
||||
this.permissible.lpAttachments.add(this);
|
||||
for (Map.Entry<String, Boolean> entry : this.perms.entrySet()) {
|
||||
if (entry.getKey() == null || entry.getKey().isEmpty()) {
|
||||
continue;
|
||||
@ -214,7 +224,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
// unhook from the permissible
|
||||
this.hooked = false;
|
||||
this.permissible.attachments.remove(this);
|
||||
this.permissible.lpAttachments.remove(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
|
||||
|
||||
public MonitoredPermissibleBase(LuckPermsPlugin plugin, PermissibleBase delegate, String name) {
|
||||
super(null);
|
||||
DummyPermissibleBase.nullFields(this);
|
||||
DummyPermissibleBase.copyFields(delegate, this);
|
||||
|
||||
this.plugin = plugin;
|
||||
this.delegate = delegate;
|
||||
|
@ -64,6 +64,19 @@ public class DummyPermissibleBase extends PermissibleBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyFields(PermissibleBase from, PermissibleBase to) {
|
||||
try {
|
||||
ATTACHMENTS_FIELD.set(to, ATTACHMENTS_FIELD.get(from));
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
PERMISSIONS_FIELD.set(to, PERMISSIONS_FIELD.get(from));
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
public static final DummyPermissibleBase INSTANCE = new DummyPermissibleBase();
|
||||
|
||||
private DummyPermissibleBase() {
|
||||
|
@ -25,10 +25,13 @@
|
||||
|
||||
package me.lucko.luckperms.nukkit.model.permissible;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.contexts.ContextsCache;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||
import me.lucko.luckperms.nukkit.LPNukkitPlugin;
|
||||
import me.lucko.luckperms.nukkit.model.PermissionDefault;
|
||||
@ -40,14 +43,19 @@ import cn.nukkit.permission.PermissionAttachment;
|
||||
import cn.nukkit.permission.PermissionAttachmentInfo;
|
||||
import cn.nukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* PermissibleBase for LuckPerms.
|
||||
*
|
||||
@ -64,6 +72,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
public class LPPermissible extends PermissibleBase {
|
||||
|
||||
private static final Field ATTACHMENTS_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
ATTACHMENTS_FIELD = PermissibleBase.class.getDeclaredField("attachments");
|
||||
ATTACHMENTS_FIELD.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// the LuckPerms user this permissible references.
|
||||
private final User user;
|
||||
|
||||
@ -84,7 +103,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
// the attachments hooked onto the permissible.
|
||||
// this collection is only modified by the attachments themselves
|
||||
final Set<LPPermissionAttachment> attachments = ConcurrentHashMap.newKeySet();
|
||||
final Set<LPPermissionAttachment> lpAttachments = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public LPPermissible(Player player, User user, LPNukkitPlugin plugin) {
|
||||
super(player);
|
||||
@ -92,6 +111,26 @@ public class LPPermissible extends PermissibleBase {
|
||||
this.player = Objects.requireNonNull(player, "player");
|
||||
this.plugin = Objects.requireNonNull(plugin, "plugin");
|
||||
this.contextsCache = plugin.getContextManager().getCacheFor(player);
|
||||
|
||||
injectFakeAttachmentsList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects a fake 'attachments' list into the superclass, for dumb plugins
|
||||
* which for some reason decided to add attachments via reflection.
|
||||
*
|
||||
* The fake list proxies (some) calls back to the proper methods on this permissible.
|
||||
*/
|
||||
private void injectFakeAttachmentsList() {
|
||||
FakeAttachmentList fakeList = new FakeAttachmentList();
|
||||
|
||||
try {
|
||||
// the field we need to modify is in the superclass - it has private
|
||||
// and final modifiers so we have to use reflection to modify it.
|
||||
ATTACHMENTS_FIELD.set(this, fakeList);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,7 +196,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
*
|
||||
* @param attachments the attachments to add
|
||||
*/
|
||||
public void convertAndAddAttachments(Collection<PermissionAttachment> attachments) {
|
||||
void convertAndAddAttachments(Collection<PermissionAttachment> attachments) {
|
||||
for (PermissionAttachment attachment : attachments) {
|
||||
new LPPermissionAttachment(this, attachment).hook();
|
||||
}
|
||||
@ -170,14 +209,8 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public Map<String, PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
Set<Map.Entry<String, Boolean>> permissions = this.user.getCachedData().getPermissionData(this.contextsCache.getContexts()).getImmutableBacking().entrySet();
|
||||
Map<String, PermissionAttachmentInfo> ret = new HashMap<>(permissions.size());
|
||||
|
||||
for (Map.Entry<String, Boolean> entry : permissions) {
|
||||
ret.put(entry.getKey(), new PermissionAttachmentInfo(this.player, entry.getKey(), null, entry.getValue()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this.user.getCachedData().getPermissionData(this.contextsCache.getContexts()).getImmutableBacking().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toMap(Map.Entry::getKey, entry -> new PermissionAttachmentInfo(this.player, entry.getKey(), null, entry.getValue())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,11 +258,20 @@ public class LPPermissible extends PermissibleBase {
|
||||
throw new NullPointerException("attachment");
|
||||
}
|
||||
|
||||
LPPermissionAttachment a;
|
||||
|
||||
if (!(attachment instanceof LPPermissionAttachment)) {
|
||||
// try to find a match
|
||||
LPPermissionAttachment match = this.lpAttachments.stream().filter(at -> at.getSource() == attachment).findFirst().orElse(null);
|
||||
if (match != null) {
|
||||
a = match;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given attachment is not a LPPermissionAttachment.");
|
||||
}
|
||||
} else {
|
||||
a = (LPPermissionAttachment) attachment;
|
||||
}
|
||||
|
||||
LPPermissionAttachment a = ((LPPermissionAttachment) attachment);
|
||||
if (a.getPermissible() != this) {
|
||||
throw new IllegalArgumentException("Attachment does not belong to this permissible.");
|
||||
}
|
||||
@ -244,7 +286,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Override
|
||||
public void clearPermissions() {
|
||||
this.attachments.forEach(LPPermissionAttachment::remove);
|
||||
this.lpAttachments.forEach(LPPermissionAttachment::remove);
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
@ -259,15 +301,102 @@ public class LPPermissible extends PermissibleBase {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
public PermissibleBase getOldPermissible() {
|
||||
PermissibleBase getOldPermissible() {
|
||||
return this.oldPermissible;
|
||||
}
|
||||
|
||||
public AtomicBoolean getActive() {
|
||||
AtomicBoolean getActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
public void setOldPermissible(PermissibleBase oldPermissible) {
|
||||
void setOldPermissible(PermissibleBase oldPermissible) {
|
||||
this.oldPermissible = oldPermissible;
|
||||
}
|
||||
|
||||
/**
|
||||
* A fake list to be injected into the superclass. This implementation simply
|
||||
* proxies calls back to this permissible instance.
|
||||
*
|
||||
* Some (clever/dumb??) plugins attempt to add/remove/query attachments using reflection.
|
||||
*
|
||||
* An instance of this map is injected into the super instance so these plugins continue
|
||||
* to work with LuckPerms.
|
||||
*/
|
||||
private final class FakeAttachmentList implements List<PermissionAttachment> {
|
||||
|
||||
@Override
|
||||
public boolean add(PermissionAttachment attachment) {
|
||||
if (LPPermissible.this.lpAttachments.stream().anyMatch(at -> at.getSource() == attachment)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
new LPPermissionAttachment(LPPermissible.this, attachment).hook();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
removeAttachment((PermissionAttachment) o);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
clearPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@Nonnull Collection<? extends PermissionAttachment> c) {
|
||||
boolean modified = false;
|
||||
for (PermissionAttachment e : c) {
|
||||
if (add(e)) {
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
PermissionAttachment attachment = (PermissionAttachment) o;
|
||||
return LPPermissible.this.lpAttachments.stream().anyMatch(at -> at.getSource() == attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<PermissionAttachment> iterator() {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<PermissionAttachment> listIterator() {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).listIterator();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).toArray();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> T[] toArray(@Nonnull T[] a) {
|
||||
return ImmutableList.<PermissionAttachment>copyOf(LPPermissible.this.lpAttachments).toArray(a);
|
||||
}
|
||||
|
||||
@Override public int size() { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean isEmpty() { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean containsAll(@Nonnull Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean addAll(int index, @Nonnull Collection<? extends PermissionAttachment> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean removeAll(@Nonnull Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean retainAll(@Nonnull Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment get(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment set(int index, PermissionAttachment element) { throw new UnsupportedOperationException(); }
|
||||
@Override public void add(int index, PermissionAttachment element) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment remove(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Nonnull @Override public ListIterator<PermissionAttachment> listIterator(int index) { throw new UnsupportedOperationException(); }
|
||||
@Nonnull @Override public List<PermissionAttachment> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +96,11 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
*/
|
||||
private PermissionRemovedExecutor removalCallback = null;
|
||||
|
||||
/**
|
||||
* Delegate attachment
|
||||
*/
|
||||
private PermissionAttachment source;
|
||||
|
||||
public LPPermissionAttachment(LPPermissible permissible, Plugin owner) {
|
||||
super(DummyPlugin.INSTANCE, null);
|
||||
this.permissible = permissible;
|
||||
@ -111,6 +116,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
// copy
|
||||
this.perms.putAll(nukkit.getPermissions());
|
||||
this.source = source;
|
||||
|
||||
injectFakeMap();
|
||||
}
|
||||
@ -149,12 +155,16 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
this.removalCallback = removalCallback;
|
||||
}
|
||||
|
||||
PermissionAttachment getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks this attachment with the parent {@link User} instance.
|
||||
*/
|
||||
public void hook() {
|
||||
this.hooked = true;
|
||||
this.permissible.attachments.add(this);
|
||||
this.permissible.lpAttachments.add(this);
|
||||
for (Map.Entry<String, Boolean> entry : this.perms.entrySet()) {
|
||||
if (entry.getKey() == null || entry.getKey().isEmpty()) {
|
||||
continue;
|
||||
@ -215,7 +225,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
// unhook from the permissible
|
||||
this.hooked = false;
|
||||
this.permissible.attachments.remove(this);
|
||||
this.permissible.lpAttachments.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,7 +58,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
|
||||
|
||||
public MonitoredPermissibleBase(LuckPermsPlugin plugin, PermissibleBase delegate, String name) {
|
||||
super(null);
|
||||
DummyPermissibleBase.nullFields(this);
|
||||
DummyPermissibleBase.copyFields(delegate, this);
|
||||
|
||||
this.plugin = plugin;
|
||||
this.delegate = delegate;
|
||||
|
@ -173,6 +173,11 @@ public final class SubjectProxy implements Subject, ProxiedSubject {
|
||||
return CompatibilityUtil.convertContexts(getContextsCache().getContextSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
return getContextsCache().getContextSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o == this || o instanceof SubjectProxy && this.ref.equals(((SubjectProxy) o).ref);
|
||||
|
@ -174,6 +174,11 @@ public final class SubjectProxy implements Subject, ProxiedSubject {
|
||||
return CompatibilityUtil.convertContexts(getContextsCache().getContextSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
return getContextsCache().getContextSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o == this || o instanceof SubjectProxy && this.ref.equals(((SubjectProxy) o).ref);
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.service.model;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -37,4 +39,6 @@ public interface ProxiedSubject {
|
||||
@Nonnull
|
||||
LPSubjectReference asSubjectReference();
|
||||
|
||||
ImmutableContextSet getActiveContextSet();
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user