Hide methods from disguises that can't use them, fixes #603
This commit is contained in:
parent
cd5df563de
commit
07f4e766c1
@ -242,7 +242,7 @@ public abstract class DisguiseBaseCommand implements CommandExecutor {
|
||||
if (addMethods) {
|
||||
// If this is a method, add. Else if it can be a param of the previous argument, add.
|
||||
for (WatcherMethod method : ParamInfoManager.getDisguiseWatcherMethods(disguisePerm.getWatcherClass())) {
|
||||
if (!perms.isAllowedDisguise(disguisePerm, Collections.singletonList(method.getName()))) {
|
||||
if (!perms.isAllowedDisguise(disguisePerm, Collections.singletonList(method.getName())) || !method.isUsable(disguisePerm.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,10 @@ public class DisguiseHelpCommand extends DisguiseBaseCommand implements TabCompl
|
||||
|
||||
try {
|
||||
for (WatcherMethod method : ParamInfoManager.getDisguiseWatcherMethods(watcher)) {
|
||||
if (!method.isUsable(type.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args.length < 2 || !args[1].equalsIgnoreCase(LibsMsg.DHELP_SHOW.get())) {
|
||||
if (!perms.isAllowedDisguise(type, Collections.singleton(method.getName().toLowerCase(Locale.ENGLISH)))) {
|
||||
ignored++;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package me.libraryaddict.disguise.disguisetypes;
|
||||
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import me.libraryaddict.disguise.utilities.translations.TranslateType;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -19,7 +19,10 @@ import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodGroupType;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodIgnoredBy;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodOnlyUsedBy;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
@ -83,6 +86,7 @@ public class FlagWatcher {
|
||||
return pitchLock != null;
|
||||
}
|
||||
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setPitchLocked(boolean pitchLocked) {
|
||||
if (isPitchLocked() == pitchLocked) {
|
||||
return;
|
||||
@ -137,6 +141,7 @@ public class FlagWatcher {
|
||||
return yawLock != null;
|
||||
}
|
||||
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setYawLocked(boolean yawLocked) {
|
||||
if (!DisguiseConfig.isMovementPacketsEnabled()) {
|
||||
return;
|
||||
@ -149,6 +154,7 @@ public class FlagWatcher {
|
||||
setYawLock(yawLocked ? 0F : null);
|
||||
}
|
||||
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setPitchLock(Float pitch) {
|
||||
if (!DisguiseConfig.isMovementPacketsEnabled()) {
|
||||
return;
|
||||
@ -183,6 +189,7 @@ public class FlagWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setYawLock(Float yaw) {
|
||||
this.yawLock = yaw;
|
||||
|
||||
@ -236,6 +243,7 @@ public class FlagWatcher {
|
||||
return getEquipment().getHelmet();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.EQUIPPABLE)
|
||||
public void setHelmet(ItemStack itemStack) {
|
||||
getEquipment().setHelmet(itemStack);
|
||||
}
|
||||
@ -244,6 +252,7 @@ public class FlagWatcher {
|
||||
return getEquipment().getBoots();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.EQUIPPABLE)
|
||||
public void setBoots(ItemStack itemStack) {
|
||||
getEquipment().setBoots(itemStack);
|
||||
}
|
||||
@ -252,6 +261,7 @@ public class FlagWatcher {
|
||||
return getEquipment().getLeggings();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.EQUIPPABLE)
|
||||
public void setLeggings(ItemStack itemStack) {
|
||||
getEquipment().setLeggings(itemStack);
|
||||
}
|
||||
@ -260,6 +270,7 @@ public class FlagWatcher {
|
||||
return getEquipment().getChestplate();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.EQUIPPABLE)
|
||||
public void setChestplate(ItemStack itemStack) {
|
||||
getEquipment().setChestplate(itemStack);
|
||||
}
|
||||
@ -269,6 +280,7 @@ public class FlagWatcher {
|
||||
this.upsideDown = upsideDown;
|
||||
}
|
||||
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setUpsideDown(boolean upsideDown) {
|
||||
if (isUpsideDown() == upsideDown) {
|
||||
return;
|
||||
@ -467,6 +479,7 @@ public class FlagWatcher {
|
||||
}
|
||||
|
||||
@NmsAddedIn(NmsVersion.v1_14)
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setEntityPose(EntityPose entityPose) {
|
||||
setData(MetaIndex.ENTITY_POSE, entityPose);
|
||||
sendData(MetaIndex.ENTITY_POSE);
|
||||
@ -476,6 +489,7 @@ public class FlagWatcher {
|
||||
return getEquipment().getArmorContents();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.EQUIPPABLE)
|
||||
public void setArmor(ItemStack[] items) {
|
||||
getEquipment().setArmorContents(items);
|
||||
}
|
||||
@ -664,6 +678,7 @@ public class FlagWatcher {
|
||||
return equipment.getItemInMainHand();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setItemInMainHand(ItemStack itemstack) {
|
||||
setItemStack(EquipmentSlot.HAND, itemstack);
|
||||
}
|
||||
@ -672,6 +687,7 @@ public class FlagWatcher {
|
||||
return equipment.getItemInOffHand();
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setItemInOffHand(ItemStack itemstack) {
|
||||
setItemStack(EquipmentSlot.OFF_HAND, itemstack);
|
||||
}
|
||||
@ -753,6 +769,7 @@ public class FlagWatcher {
|
||||
return getEntityFlag(7);
|
||||
}
|
||||
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setFlyingWithElytra(boolean flying) {
|
||||
setEntityFlag(7, flying);
|
||||
sendData(MetaIndex.ENTITY_META);
|
||||
@ -816,16 +833,16 @@ public class FlagWatcher {
|
||||
|
||||
@Deprecated
|
||||
@NmsAddedIn(NmsVersion.v1_12)
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setRightClicking(boolean rightClicking) {
|
||||
setMainHandRaised(rightClicking);
|
||||
}
|
||||
|
||||
//@NmsRemovedIn(val = NmsVersion.v1_13)
|
||||
public boolean isMainHandRaised() {
|
||||
return !NmsVersion.v1_13.isSupported() && getEntityFlag(4);
|
||||
}
|
||||
|
||||
//@NmsRemovedIn(val = NmsVersion.v1_13)
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setMainHandRaised(boolean setRightClicking) {
|
||||
if (NmsVersion.v1_13.isSupported()) {
|
||||
return;
|
||||
@ -839,6 +856,7 @@ public class FlagWatcher {
|
||||
return getEntityFlag(1);
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {DisguiseType.PLAYER})
|
||||
public void setSneaking(boolean setSneaking) {
|
||||
setEntityFlag(1, setSneaking);
|
||||
sendData(MetaIndex.ENTITY_META);
|
||||
@ -1027,6 +1045,7 @@ public class FlagWatcher {
|
||||
}
|
||||
|
||||
@NmsAddedIn(NmsVersion.v1_14)
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setSleeping(boolean sleeping) {
|
||||
if (isSleeping() == sleeping) {
|
||||
return;
|
||||
@ -1043,6 +1062,7 @@ public class FlagWatcher {
|
||||
}
|
||||
|
||||
@NmsAddedIn(NmsVersion.v1_14)
|
||||
@MethodIgnoredBy(value = {}, group = MethodGroupType.NO_LOOK)
|
||||
public void setSwimming(boolean swimming) {
|
||||
if (isSwimming() == swimming) {
|
||||
return;
|
||||
|
@ -92,8 +92,8 @@ import me.libraryaddict.disguise.disguisetypes.watchers.ZoglinWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieVillagerWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import me.libraryaddict.disguise.utilities.translations.LibsMsg;
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@ import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.apache.commons.lang.math.RandomUtils;
|
||||
import org.bukkit.Color;
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
public class ArrowWatcher extends FlagWatcher {
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.TreeSpecies;
|
||||
|
||||
|
@ -5,7 +5,7 @@ import me.libraryaddict.disguise.disguisetypes.AnimalColor;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.entity.Cat;
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
@ -8,7 +8,7 @@ import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import me.libraryaddict.disguise.utilities.translations.TranslateType;
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
@ -4,7 +4,7 @@ import me.libraryaddict.disguise.DisguiseConfig;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.Fox;
|
||||
|
||||
|
@ -2,8 +2,8 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.Spellcaster;
|
||||
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.inventory.MainHand;
|
||||
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.GolemCrack;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
public class IronGolemWatcher extends InsentientWatcher {
|
||||
|
@ -9,11 +9,14 @@ import com.comphenix.protocol.wrappers.WrappedAttribute.Builder;
|
||||
import lombok.Getter;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodGroupType;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodOnlyUsedBy;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -124,6 +127,7 @@ public class LivingWatcher extends FlagWatcher {
|
||||
|
||||
@Override
|
||||
@NmsAddedIn(NmsVersion.v1_13)
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setMainHandRaised(boolean setRightClicking) {
|
||||
setHandInUse(true);
|
||||
|
||||
@ -136,6 +140,7 @@ public class LivingWatcher extends FlagWatcher {
|
||||
}
|
||||
|
||||
@NmsAddedIn(NmsVersion.v1_13)
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setOffhandRaised(boolean setLeftClicking) {
|
||||
setHandInUse(false);
|
||||
|
||||
@ -296,6 +301,7 @@ public class LivingWatcher extends FlagWatcher {
|
||||
return getData(MetaIndex.LIVING_ARROWS);
|
||||
}
|
||||
|
||||
@MethodOnlyUsedBy(value = {DisguiseType.PLAYER})
|
||||
public void setArrowsSticking(int arrowsNo) {
|
||||
setData(MetaIndex.LIVING_ARROWS, Math.max(0, Math.min(127, arrowsNo)));
|
||||
sendData(MetaIndex.LIVING_ARROWS);
|
||||
@ -324,6 +330,7 @@ public class LivingWatcher extends FlagWatcher {
|
||||
|
||||
@Deprecated
|
||||
@NmsAddedIn(NmsVersion.v1_12)
|
||||
@MethodOnlyUsedBy(value = {}, group = MethodGroupType.HOLDABLE)
|
||||
public void setRightClicking(boolean rightClicking) {
|
||||
setMainHandRaised(rightClicking);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ReflectionManager;
|
||||
import org.bukkit.Material;
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.MushroomCow;
|
||||
|
||||
|
@ -2,8 +2,8 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.Ocelot;
|
||||
|
||||
|
@ -4,7 +4,7 @@ import me.libraryaddict.disguise.DisguiseConfig;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.Panda;
|
||||
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,7 @@ import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@ import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.disguisetypes.VillagerData;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.entity.Villager.Profession;
|
||||
|
@ -2,7 +2,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
public class VindicatorWatcher extends IllagerWatcher {
|
||||
|
@ -3,7 +3,7 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
import me.libraryaddict.disguise.disguisetypes.AnimalColor;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.DyeColor;
|
||||
|
||||
|
@ -5,7 +5,7 @@ import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.disguisetypes.VillagerData;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.entity.Villager.Profession;
|
||||
|
@ -2,8 +2,8 @@ package me.libraryaddict.disguise.disguisetypes.watchers;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.MetaIndex;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
public class ZombieWatcher extends InsentientWatcher {
|
||||
|
@ -2,6 +2,7 @@ package me.libraryaddict.disguise.utilities.parser;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
@ -19,6 +20,11 @@ public class WatcherMethod {
|
||||
private final Class param;
|
||||
private final boolean randomDefault;
|
||||
private final boolean hideFromTab;
|
||||
private final boolean[] unusableBy;
|
||||
|
||||
public boolean isUsable(DisguiseType type) {
|
||||
return !unusableBy[type.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -41,6 +41,8 @@ import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
|
||||
import me.libraryaddict.disguise.utilities.DisguiseValues;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.sounds.SoundGroup;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -2,6 +2,7 @@ package me.libraryaddict.disguise.utilities.reflection;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 17/02/2020.
|
||||
@ -18,6 +19,15 @@ public class WatcherInfo {
|
||||
private String method;
|
||||
private String param;
|
||||
private String descriptor;
|
||||
private boolean[] unusableBy;
|
||||
|
||||
public void setUnusableBy(DisguiseType[] types) {
|
||||
unusableBy = new boolean[DisguiseType.values().length];
|
||||
|
||||
for (DisguiseType type : types) {
|
||||
unusableBy[type.ordinal()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSupported() {
|
||||
if (getAdded() >= 0 && added > ReflectionManager.getVersion().ordinal()) {
|
||||
|
@ -0,0 +1,36 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.annotations;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Getter
|
||||
public enum MethodGroupType {
|
||||
NO_LOOK(DisguiseType.AREA_EFFECT_CLOUD, DisguiseType.DRAGON_FIREBALL, DisguiseType.DROPPED_ITEM, DisguiseType.EGG, DisguiseType.ENDER_CRYSTAL,
|
||||
DisguiseType.ENDER_PEARL, DisguiseType.ENDER_SIGNAL, DisguiseType.FALLING_BLOCK, DisguiseType.FIREBALL, DisguiseType.FIREWORK,
|
||||
DisguiseType.FISHING_HOOK, DisguiseType.LEASH_HITCH, DisguiseType.MARKER, DisguiseType.PRIMED_TNT, DisguiseType.SHULKER, DisguiseType.SMALL_FIREBALL,
|
||||
DisguiseType.SNOWBALL, DisguiseType.SPLASH_POTION, DisguiseType.THROWN_EXP_BOTTLE),
|
||||
|
||||
EQUIPPABLE(DisguiseType.ARMOR_STAND, DisguiseType.DROWNED, DisguiseType.GIANT, DisguiseType.HUSK, DisguiseType.MODDED_LIVING, DisguiseType.MODDED_MISC,
|
||||
DisguiseType.PIG_ZOMBIE, DisguiseType.PIGLIN, DisguiseType.PIGLIN_BRUTE, DisguiseType.PLAYER, DisguiseType.SKELETON, DisguiseType.STRAY,
|
||||
DisguiseType.WITHER_SKELETON, DisguiseType.ZOMBIE),
|
||||
|
||||
HOLDABLE(EQUIPPABLE, DisguiseType.ENDERMAN, DisguiseType.EVOKER, DisguiseType.ILLUSIONER, DisguiseType.IRON_GOLEM, DisguiseType.PILLAGER,
|
||||
DisguiseType.RAVAGER, DisguiseType.VEX, DisguiseType.VINDICATOR, DisguiseType.WANDERING_TRADER, DisguiseType.WITCH, DisguiseType.ZOMBIE_VILLAGER),
|
||||
|
||||
NONE();
|
||||
|
||||
private final DisguiseType[] disguiseTypes;
|
||||
|
||||
MethodGroupType(DisguiseType... types) {
|
||||
this.disguiseTypes = types;
|
||||
}
|
||||
|
||||
MethodGroupType(MethodGroupType inheritFrom, DisguiseType... types) {
|
||||
this.disguiseTypes = Arrays.copyOf(types, types.length + inheritFrom.getDisguiseTypes().length);
|
||||
|
||||
System.arraycopy(inheritFrom.getDisguiseTypes(), 0, getDisguiseTypes(), types.length, inheritFrom.getDisguiseTypes().length);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.annotations;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodIgnoredBy {
|
||||
DisguiseType[] value();
|
||||
|
||||
MethodGroupType group() default MethodGroupType.NONE;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection.annotations;
|
||||
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MethodOnlyUsedBy {
|
||||
DisguiseType[] value();
|
||||
|
||||
MethodGroupType group() default MethodGroupType.NONE;
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection;
|
||||
package me.libraryaddict.disguise.utilities.reflection.annotations;
|
||||
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
@ -1,4 +1,6 @@
|
||||
package me.libraryaddict.disguise.utilities.reflection;
|
||||
package me.libraryaddict.disguise.utilities.reflection.annotations;
|
||||
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsVersion;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
@ -1,12 +1,15 @@
|
||||
package me.libraryaddict.disguise.utilities.watchers;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
|
||||
import me.libraryaddict.disguise.utilities.LibsPremium;
|
||||
import me.libraryaddict.disguise.utilities.parser.RandomDefaultValue;
|
||||
import me.libraryaddict.disguise.utilities.reflection.ClassGetter;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodIgnoredBy;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.MethodOnlyUsedBy;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsAddedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.annotations.NmsRemovedIn;
|
||||
import me.libraryaddict.disguise.utilities.reflection.WatcherInfo;
|
||||
import me.libraryaddict.disguise.utilities.sounds.DisguiseSoundEnums;
|
||||
import me.libraryaddict.disguise.utilities.sounds.SoundGroup;
|
||||
@ -19,9 +22,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by libraryaddict on 13/02/2020.
|
||||
@ -120,6 +125,7 @@ public class CompileMethods {
|
||||
|
||||
int added = -1;
|
||||
int removed = -1;
|
||||
DisguiseType[] unusableBy = new DisguiseType[0];
|
||||
|
||||
if (method.isAnnotationPresent(NmsAddedIn.class)) {
|
||||
added = method.getAnnotation(NmsAddedIn.class).value().ordinal();
|
||||
@ -133,12 +139,32 @@ public class CompileMethods {
|
||||
removed = method.getDeclaringClass().getAnnotation(NmsRemovedIn.class).value().ordinal();
|
||||
}
|
||||
|
||||
if (method.isAnnotationPresent(MethodOnlyUsedBy.class)) {
|
||||
DisguiseType[] usableBy = method.getAnnotation(MethodOnlyUsedBy.class).value();
|
||||
|
||||
if (usableBy.length == 0) {
|
||||
usableBy = method.getAnnotation(MethodOnlyUsedBy.class).group().getDisguiseTypes();
|
||||
}
|
||||
|
||||
List<DisguiseType> list = Arrays.asList(usableBy);
|
||||
|
||||
unusableBy =
|
||||
Arrays.stream(DisguiseType.values()).filter(type -> !list.contains(type)).collect(Collectors.toList()).toArray(new DisguiseType[0]);
|
||||
} else if (method.isAnnotationPresent(MethodIgnoredBy.class)) {
|
||||
unusableBy = method.getAnnotation(MethodIgnoredBy.class).value();
|
||||
|
||||
if (unusableBy.length == 0) {
|
||||
unusableBy = method.getAnnotation(MethodIgnoredBy.class).group().getDisguiseTypes();
|
||||
}
|
||||
}
|
||||
|
||||
String param = method.getParameterCount() == 1 ? method.getParameterTypes()[0].getName() : null;
|
||||
|
||||
WatcherInfo info = new WatcherInfo();
|
||||
info.setMethod(method.getName());
|
||||
info.setAdded(added);
|
||||
info.setRemoved(removed);
|
||||
info.setUnusableBy(unusableBy);
|
||||
info.setDeprecated(method.isAnnotationPresent(Deprecated.class));
|
||||
info.setParam(param);
|
||||
info.setDescriptor(getMethodDescriptor(method));
|
||||
|
@ -103,8 +103,9 @@ public class DisguiseMethods {
|
||||
|
||||
MethodHandle method = MethodHandles.publicLookup().findVirtual(watcher, info.getMethod(), type);
|
||||
|
||||
WatcherMethod m = new WatcherMethod(watcher, method, info.getMethod(), returnType, param, info.isRandomDefault(),
|
||||
info.isDeprecated() && info.getAdded() == 0);
|
||||
WatcherMethod m =
|
||||
new WatcherMethod(watcher, method, info.getMethod(), returnType, param, info.isRandomDefault(), info.isDeprecated() && info.getAdded() == 0,
|
||||
info.getUnusableBy());
|
||||
|
||||
methods.add(m);
|
||||
|
||||
@ -156,7 +157,7 @@ public class DisguiseMethods {
|
||||
try {
|
||||
WatcherMethod method = new WatcherMethod(disguiseClass,
|
||||
MethodHandles.publicLookup().findVirtual(disguiseClass, methodName, MethodType.methodType(returnType, cl)), methodName, null,
|
||||
cl, randomDefault, false);
|
||||
cl, randomDefault, false, new boolean[DisguiseType.values().length]);
|
||||
|
||||
methods.add(method);
|
||||
|
||||
@ -167,7 +168,7 @@ public class DisguiseMethods {
|
||||
|
||||
WatcherMethod getMethod =
|
||||
new WatcherMethod(disguiseClass, MethodHandles.publicLookup().findVirtual(disguiseClass, getName, MethodType.methodType(cl)),
|
||||
getName, cl, null, randomDefault, false);
|
||||
getName, cl, null, randomDefault, false, new boolean[DisguiseType.values().length]);
|
||||
|
||||
methods.add(getMethod);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user