diff --git a/plugin.yml b/plugin.yml index 46c97e1b..41ee73de 100644 --- a/plugin.yml +++ b/plugin.yml @@ -42,6 +42,7 @@ permissions: massivecore.buffer.whitespace: {description: add whitespace to buffer, default: false} massivecore.cmdurl: {description: run all lines of url content, default: false} massivecore.click: {description: click, default: false} + massivecore.config: {description: edit config, default: false} # misc massivecore.notpdelay: {description: teleport without delay, default: false} massivecore.variable.book: {description: replace ***book*** with content of book in your hand, default: false} @@ -84,6 +85,7 @@ permissions: massivecore.buffer.whitespace: true massivecore.cmdurl: true massivecore.click: true + massivecore.config: true massivecore.notpdelay: true massivecore.variable.book: true massivecore.variable.buffer: true diff --git a/src/com/massivecraft/massivecore/MassiveCore.java b/src/com/massivecraft/massivecore/MassiveCore.java index a5f748f5..91fbfb01 100644 --- a/src/com/massivecraft/massivecore/MassiveCore.java +++ b/src/com/massivecraft/massivecore/MassiveCore.java @@ -228,8 +228,11 @@ public class MassiveCore extends MassivePlugin PlayerUtil.get(), // Integration - IntegrationVault.get(), - + IntegrationVault.get() + ); + + // Some commands rely on the MConf being present. + this.activate( // Command CmdMassiveCore.get(), CmdMassiveCoreUsys.get(), diff --git a/src/com/massivecraft/massivecore/MassiveCoreMConf.java b/src/com/massivecraft/massivecore/MassiveCoreMConf.java index 43bef543..bc051fe0 100644 --- a/src/com/massivecraft/massivecore/MassiveCoreMConf.java +++ b/src/com/massivecraft/massivecore/MassiveCoreMConf.java @@ -6,6 +6,7 @@ import java.util.Map; import org.bukkit.permissions.Permissible; +import com.massivecraft.massivecore.command.editor.EditorField; import com.massivecraft.massivecore.store.Entity; import com.massivecraft.massivecore.util.MUtil; import com.massivecraft.massivecore.util.PermUtil; @@ -112,6 +113,7 @@ public class MassiveCoreMConf extends Entity public volatile long millisBetweenRemotePollWithoutPusher = TimeUnit.MILLIS_PER_SECOND * 10; public volatile long millisBetweenRemotePollWithPusher = TimeUnit.MILLIS_PER_MINUTE * 1; + @EditorField(singletonName = "iOn") public boolean warnOnLocalAlter = false; } diff --git a/src/com/massivecraft/massivecore/MassiveCorePerm.java b/src/com/massivecraft/massivecore/MassiveCorePerm.java index c0a37871..d6d787cc 100644 --- a/src/com/massivecraft/massivecore/MassiveCorePerm.java +++ b/src/com/massivecraft/massivecore/MassiveCorePerm.java @@ -41,6 +41,7 @@ public enum MassiveCorePerm BUFFER_ADD("buffer.add"), BUFFER_WHITESPACE("buffer.whitespace"), CMDURL("cmdurl"), + CONFIG("config"), NOTPDELAY("notpdelay"), VARIABLE_BOOK("variable.book"), VARIABLE_BUFFER("variable.buffer"), diff --git a/src/com/massivecraft/massivecore/command/MassiveCommand.java b/src/com/massivecraft/massivecore/command/MassiveCommand.java index fb1f221a..e6cb08e7 100644 --- a/src/com/massivecraft/massivecore/command/MassiveCommand.java +++ b/src/com/massivecraft/massivecore/command/MassiveCommand.java @@ -333,8 +333,8 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand public void addChild(MassiveCommand child, int index) { if (this.children.isEmpty() && ! (child instanceof MassiveCommandHelp)) - { - this.children.add(0, MassiveCommandHelp.get()); + { + this.children.add(0, new MassiveCommandHelp()); index++; } child.addToChain(this); @@ -783,8 +783,8 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand public List getArgs() { return this.args; } public void setArgs(List args) { this.args = args; } - public List getChain() { return this.chain; } - public void setChain(List chain) { this.chain = chain; } + public List getChain() { return new MassiveList<>(this.chain); } + public void setChain(List chain) { this.chain = new MassiveList<>(chain); } // Adds command to tree structure public void addToChain(MassiveCommand command) @@ -842,8 +842,9 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand { MassiveCommand child = matches.entrySet().iterator().next().getValue(); args.remove(0); - chain.add(this); - child.execute(sender, args, chain); + List childChain = new MassiveList<>(chain); + childChain.add(this); + child.execute(sender, args, childChain); } // Crap! else @@ -934,7 +935,7 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand public void perform() throws MassiveException { // Per default we just act as the help command! - List chain = new ArrayList(this.getChain()); + List chain = this.getChain(); chain.add(this); MassiveCommandHelp.get().execute(this.sender, this.getArgs(), chain); diff --git a/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java b/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java index 24d1c1e8..489711ab 100644 --- a/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java +++ b/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java @@ -16,10 +16,10 @@ public class MassiveCommandHelp extends MassiveCommand // -------------------------------------------- // // INSTANCE & CONSTRUCT // -------------------------------------------- // - + protected static MassiveCommandHelp i = new MassiveCommandHelp(); public static MassiveCommandHelp get() { return i; } - private MassiveCommandHelp() + public MassiveCommandHelp() { // Aliases this.addAliases("?", "h", "help"); @@ -67,23 +67,16 @@ public class MassiveCommandHelp extends MassiveCommand { boolean visible = super.isVisibleTo(sender); if ( ! (this.hasParent() && visible)) return visible; - + int visibleSiblingCount = 0; for (MassiveCommand sibling : this.getParent().getChildren()) { - if (sibling == this) continue; + if (sibling instanceof MassiveCommandHelp) continue; if (sibling.isVisibleTo(sender)) visibleSiblingCount++; - } + } int pageHeight = (sender instanceof Player) ? Txt.PAGEHEIGHT_PLAYER : Txt.PAGEHEIGHT_CONSOLE; - if (visibleSiblingCount <= pageHeight) - { - return false; - } - else - { - return true; - } + return visibleSiblingCount > pageHeight; } } diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditReflection.java b/src/com/massivecraft/massivecore/command/editor/CommandEditReflection.java new file mode 100644 index 00000000..2bf2df93 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditReflection.java @@ -0,0 +1,40 @@ +package com.massivecraft.massivecore.command.editor; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public class CommandEditReflection extends CommandEditAbstract +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditReflection(EditSettings settings, Property property, Class clazz) + { + super(settings, property, null); + for (Field field : clazz.getDeclaredFields()) + { + if ( ! this.isOkay(field)) continue; + Property propertyReflection = PropertyReflection.get(field); + this.addChild(propertyReflection.createEditCommand(settings)); + } + } + + // -------------------------------------------- // + // OKAY + // -------------------------------------------- // + + public boolean isOkay(Field field) + { + if ( ! this.isModifiersOkay(field.getModifiers())) return false; + return true; + } + + public boolean isModifiersOkay(int modifiers) + { + if (Modifier.isStatic(modifiers)) return false; + if (Modifier.isVolatile(modifiers)) return false; + return true; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditSingleton.java b/src/com/massivecraft/massivecore/command/editor/CommandEditSingleton.java new file mode 100644 index 00000000..ee7c4606 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditSingleton.java @@ -0,0 +1,45 @@ +package com.massivecraft.massivecore.command.editor; + +import com.massivecraft.massivecore.command.type.RegistryType; +import com.massivecraft.massivecore.command.type.Type; +import com.massivecraft.massivecore.command.type.TypeSingleton; + +public class CommandEditSingleton extends CommandEditReflection +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditSingleton(O object, String permission) + { + this(object, getType(object), permission); + } + + @SuppressWarnings("unchecked") + public CommandEditSingleton(O object, Type typeObject, String permission) + { + super(EditSettingsSingleton.get(object, typeObject, permission), new PropertyThis<>(typeObject), (Class) object.getClass()); + String name = typeObject.getName(object); + this.setAliases(name); + this.setDesc("edit " + name); + } + + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + private static Type getType(O object) + { + // Get the return value + Type ret = TypeSingleton.get(object); + + // If no registered type exists. Use this one. + if ( ! RegistryType.isRegistered(object.getClass())) + { + RegistryType.register((Class) object.getClass(), ret); + } + return ret; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditSingletons.java b/src/com/massivecraft/massivecore/command/editor/CommandEditSingletons.java new file mode 100644 index 00000000..eb608e88 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditSingletons.java @@ -0,0 +1,63 @@ +package com.massivecraft.massivecore.command.editor; + +import java.util.Collection; +import java.util.List; + +import com.massivecraft.massivecore.collections.MassiveList; +import com.massivecraft.massivecore.command.MassiveCommand; +import com.massivecraft.massivecore.command.requirement.RequirementHasPerm; +import com.massivecraft.massivecore.command.type.RegistryType; + +public abstract class CommandEditSingletons extends MassiveCommand +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private final String permission; + public String getPermission() { return this.permission; } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditSingletons(Class clazz, String permission) + { + // Aliases + String name = RegistryType.getType(clazz).getName() + "s"; + this.setAliases(name); + this.setDesc("edit " + name); + + // Requirements + this.permission = permission; + this.addRequirements(RequirementHasPerm.get(permission)); + } + + // -------------------------------------------- // + // ABSTRACT + // -------------------------------------------- // + + public abstract Collection getAll(); + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + // This is evaluated every time, because it might change. + // In Factions we use this to edit configuration of flags and perms, and those can be added and removed at any time. + @Override + public List getChildren() + { + List ret = new MassiveList<>(); + for (O singleton : this.getAll()) + { + MassiveCommand cmd = new CommandEditSingleton<>(singleton, this.getPermission()); + List chain = this.getChain(); + chain.add(this); + cmd.setChain(chain); + ret.add(cmd); + } + return ret; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/EditSettings.java b/src/com/massivecraft/massivecore/command/editor/EditSettings.java index e7613e36..466b2fe4 100644 --- a/src/com/massivecraft/massivecore/command/editor/EditSettings.java +++ b/src/com/massivecraft/massivecore/command/editor/EditSettings.java @@ -94,7 +94,6 @@ public class EditSettings // TYPE READ UTILITY // -------------------------------------------- // - // No nice constructors for TreeSet :( public static final Set ALIASES_USED = MUtil.treeset("used", "selected", "chosen"); public O getUsedOrCommandException(String arg, CommandSender sender) throws MassiveException diff --git a/src/com/massivecraft/massivecore/command/editor/EditSettingsSingleton.java b/src/com/massivecraft/massivecore/command/editor/EditSettingsSingleton.java new file mode 100644 index 00000000..5be403c8 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/EditSettingsSingleton.java @@ -0,0 +1,59 @@ + package com.massivecraft.massivecore.command.editor; + +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; + +import com.massivecraft.massivecore.command.type.Type; +import com.massivecraft.massivecore.util.PermUtil; + +public class EditSettingsSingleton extends EditSettings +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private final String permission; + public String getPermission() { return this.permission; } + + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + public static EditSettingsSingleton get(O object, Type typeObject, String permission) + { + return new EditSettingsSingleton(object, typeObject, permission); + } + public EditSettingsSingleton(final O object, Type typeObject, String permission) + { + super(typeObject); + this.permission = permission; + PropertyUsed usedProperty = new PropertyUsed(this) { + + @Override + public O getRaw(CommandSender sender) + { + return object; + } + + @Override + public void setRaw(CommandSender sender, O used) + { + + } + + }; + + this.setUsedProperty(usedProperty); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public Permission getPropertyPermission(Property property) + { + return PermUtil.get(false, permission); + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/EditorField.java b/src/com/massivecraft/massivecore/command/editor/EditorField.java new file mode 100644 index 00000000..9590de19 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/EditorField.java @@ -0,0 +1,16 @@ +package com.massivecraft.massivecore.command.editor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface EditorField +{ + boolean nullable() default true; + + Class type() default void.class; + String singletonName() default "i"; +} diff --git a/src/com/massivecraft/massivecore/command/editor/PropertyReflection.java b/src/com/massivecraft/massivecore/command/editor/PropertyReflection.java new file mode 100644 index 00000000..cbdaccc9 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/PropertyReflection.java @@ -0,0 +1,76 @@ +package com.massivecraft.massivecore.command.editor; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.massivecraft.massivecore.command.type.RegistryType; +import com.massivecraft.massivecore.command.type.Type; +import com.massivecraft.massivecore.util.ReflectionUtil; + +public class PropertyReflection extends Property +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private final Field field; + public Field getField() { return this.field; } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public static PropertyReflection get(Class clazz, String fieldName) + { + return get(ReflectionUtil.getField(clazz, fieldName)); + } + @SuppressWarnings("unchecked") + public static PropertyReflection get(Field field) + { + Type typeObject = (Type) RegistryType.getType(field.getDeclaringClass()); + Type typeValue = (Type) RegistryType.getType(field); + return new PropertyReflection<>(typeObject, typeValue, field); + } + + public PropertyReflection(Type typeObject, Type typeValue, Field field) + { + super(typeObject, typeValue); + ReflectionUtil.makeAccessible(field); + this.setEditable(isEditable(field)); + this.setNullable(isNullable(field)); + this.setName(field.getName()); + this.field = field; + } + + private static boolean isEditable(Field field) + { + return ! Modifier.isFinal(field.getModifiers()); + } + + private static boolean isNullable(Field field) + { + if (field.getType().isPrimitive()) return false; + + EditorField setting = field.getAnnotation(EditorField.class); + if (setting != null && ! setting.nullable()) return false; + + return true; + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public V getRaw(O object) + { + return ReflectionUtil.getField(this.getField(), object); + } + + @Override + public void setRaw(O object, V value) + { + ReflectionUtil.setField(this.getField(), object, value); + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/PropertyThis.java b/src/com/massivecraft/massivecore/command/editor/PropertyThis.java index 63cbf8ff..1aad5725 100644 --- a/src/com/massivecraft/massivecore/command/editor/PropertyThis.java +++ b/src/com/massivecraft/massivecore/command/editor/PropertyThis.java @@ -10,7 +10,7 @@ public class PropertyThis extends Property public PropertyThis(Type objectType) { - super(objectType, objectType, "this"); + super(objectType, objectType, objectType.getName()); } // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/command/massivecore/CmdMassiveCore.java b/src/com/massivecraft/massivecore/command/massivecore/CmdMassiveCore.java index 48d81d3d..a05e0fb9 100644 --- a/src/com/massivecraft/massivecore/command/massivecore/CmdMassiveCore.java +++ b/src/com/massivecraft/massivecore/command/massivecore/CmdMassiveCore.java @@ -7,6 +7,8 @@ import com.massivecraft.massivecore.MassiveCoreMConf; import com.massivecraft.massivecore.MassiveCorePerm; import com.massivecraft.massivecore.command.MassiveCommand; import com.massivecraft.massivecore.command.MassiveCommandVersion; +import com.massivecraft.massivecore.command.editor.CommandEditAbstract; +import com.massivecraft.massivecore.command.editor.CommandEditSingleton; import com.massivecraft.massivecore.command.requirement.RequirementHasPerm; public class CmdMassiveCore extends MassiveCommand @@ -30,6 +32,7 @@ public class CmdMassiveCore extends MassiveCommand public CmdMassiveCoreBuffer cmdMassiveCoreBuffer = new CmdMassiveCoreBuffer(); public CmdMassiveCoreCmdurl cmdMassiveCoreCmdurl = new CmdMassiveCoreCmdurl(); public CmdMassiveCoreClick cmdMassiveCoreClick = new CmdMassiveCoreClick(); + public CommandEditAbstract cmdMassiveCoreConfig = new CommandEditSingleton<>(MassiveCoreMConf.get(), MassiveCorePerm.CONFIG.node); public MassiveCommandVersion cmdMassiveCoreVersion = new MassiveCommandVersion(MassiveCore.get(), MassiveCorePerm.VERSION.node, "v", "version"); // -------------------------------------------- // @@ -47,6 +50,7 @@ public class CmdMassiveCore extends MassiveCommand this.addChild(this.cmdMassiveCoreBuffer); this.addChild(this.cmdMassiveCoreCmdurl); this.addChild(this.cmdMassiveCoreClick); + this.addChild(this.cmdMassiveCoreConfig); this.addChild(this.cmdMassiveCoreVersion); // Requirements diff --git a/src/com/massivecraft/massivecore/command/type/RegistryType.java b/src/com/massivecraft/massivecore/command/type/RegistryType.java new file mode 100644 index 00000000..9853a467 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/RegistryType.java @@ -0,0 +1,219 @@ +package com.massivecraft.massivecore.command.type; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.bukkit.ChatColor; +import org.bukkit.Difficulty; +import org.bukkit.DyeColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.WorldType; +import org.bukkit.block.Biome; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Ocelot; +import org.bukkit.entity.Player; +import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Skeleton.SkeletonType; +import org.bukkit.entity.Villager.Profession; +import org.bukkit.event.EventPriority; +import org.bukkit.inventory.ItemStack; +import org.bukkit.permissions.Permission; +import org.bukkit.potion.PotionEffectType; + +import com.massivecraft.massivecore.Aspect; +import com.massivecraft.massivecore.Multiverse; +import com.massivecraft.massivecore.PotionEffectWrap; +import com.massivecraft.massivecore.SoundEffect; +import com.massivecraft.massivecore.collections.ExceptionSet; +import com.massivecraft.massivecore.collections.MassiveMap; +import com.massivecraft.massivecore.collections.WorldExceptionSet; +import com.massivecraft.massivecore.command.editor.EditorField; +import com.massivecraft.massivecore.command.type.combined.TypeEntry; +import com.massivecraft.massivecore.command.type.combined.TypePotionEffectWrap; +import com.massivecraft.massivecore.command.type.combined.TypeSoundEffect; +import com.massivecraft.massivecore.command.type.container.TypeExceptionSet; +import com.massivecraft.massivecore.command.type.container.TypeList; +import com.massivecraft.massivecore.command.type.container.TypeMap; +import com.massivecraft.massivecore.command.type.container.TypeSet; +import com.massivecraft.massivecore.command.type.enumeration.TypeBiome; +import com.massivecraft.massivecore.command.type.enumeration.TypeChatColor; +import com.massivecraft.massivecore.command.type.enumeration.TypeDifficulty; +import com.massivecraft.massivecore.command.type.enumeration.TypeDyeColor; +import com.massivecraft.massivecore.command.type.enumeration.TypeEntityType; +import com.massivecraft.massivecore.command.type.enumeration.TypeEnvironment; +import com.massivecraft.massivecore.command.type.enumeration.TypeEventPriority; +import com.massivecraft.massivecore.command.type.enumeration.TypeGameMode; +import com.massivecraft.massivecore.command.type.enumeration.TypeHorseColor; +import com.massivecraft.massivecore.command.type.enumeration.TypeHorseStyle; +import com.massivecraft.massivecore.command.type.enumeration.TypeHorseVariant; +import com.massivecraft.massivecore.command.type.enumeration.TypeMaterial; +import com.massivecraft.massivecore.command.type.enumeration.TypeOcelotType; +import com.massivecraft.massivecore.command.type.enumeration.TypeParticleEffect; +import com.massivecraft.massivecore.command.type.enumeration.TypeRabbitType; +import com.massivecraft.massivecore.command.type.enumeration.TypeSkeletonType; +import com.massivecraft.massivecore.command.type.enumeration.TypeSound; +import com.massivecraft.massivecore.command.type.enumeration.TypeVillagerProfession; +import com.massivecraft.massivecore.command.type.enumeration.TypeWorldType; +import com.massivecraft.massivecore.command.type.primitive.TypeBoolean; +import com.massivecraft.massivecore.command.type.primitive.TypeByte; +import com.massivecraft.massivecore.command.type.primitive.TypeDouble; +import com.massivecraft.massivecore.command.type.primitive.TypeFloat; +import com.massivecraft.massivecore.command.type.primitive.TypeInteger; +import com.massivecraft.massivecore.command.type.primitive.TypeLong; +import com.massivecraft.massivecore.command.type.primitive.TypeString; +import com.massivecraft.massivecore.command.type.sender.TypePlayer; +import com.massivecraft.massivecore.command.type.sender.TypeSender; +import com.massivecraft.massivecore.command.type.store.TypeAspect; +import com.massivecraft.massivecore.command.type.store.TypeMultiverse; +import com.massivecraft.massivecore.particleeffect.ParticleEffect; +import com.massivecraft.massivecore.ps.PS; +import com.massivecraft.massivecore.teleport.Destination; +import com.massivecraft.massivecore.util.ReflectionUtil; + +public class RegistryType +{ + // -------------------------------------------- // + // REGISTRY + // -------------------------------------------- // + + private static final Map, Type> registry = new MassiveMap<>(); + public static void register(Class clazz, Type type) { registry.put(clazz, type); } + @SuppressWarnings("unchecked") public static Type unregister(Class clazz) { return (Type) registry.remove(clazz); } + public static boolean isRegistered(Class clazz) { return registry.containsKey(clazz); } + + public static Type getType(Field field) + { + EditorField setting = field.getAnnotation(EditorField.class); + if (setting != null) + { + Class clazz = setting.type(); + if (clazz == void.class) clazz = getType(field.getGenericType()).getClass(); + return ReflectionUtil.getField(clazz, setting.singletonName(), null); + } + + return getType(field.getGenericType()); + } + + public static Type getType(java.lang.reflect.Type reflectType) + { + if (reflectType instanceof Class) + { + Type type = registry.get(reflectType); + if (type == null) throw new IllegalStateException(reflectType + " is not registered."); + return type; + } + if (reflectType instanceof ParameterizedType) + { + ParameterizedType paramType = (ParameterizedType) reflectType; + Class parent = (Class) paramType.getRawType(); + if (Map.class.isAssignableFrom(parent)) + { + TypeEntry typeEntry = TypeEntry.get(getType(paramType.getActualTypeArguments()[0]), getType(paramType.getActualTypeArguments()[1])); + return TypeMap.get(typeEntry); + } + if (List.class.isAssignableFrom(parent)) + { + return TypeList.get(getType(paramType.getActualTypeArguments()[0])); + } + if (Set.class.isAssignableFrom(parent)) + { + return TypeSet.get(getType(paramType.getActualTypeArguments()[0])); + } + if (Entry.class.isAssignableFrom(parent)) + { + return TypeEntry.get(getType(paramType.getActualTypeArguments()[0]), getType(paramType.getActualTypeArguments()[1])); + } + if (ExceptionSet.class.isAssignableFrom(parent)) + { + return TypeExceptionSet.get(getType(paramType.getActualTypeArguments()[0])); + } + } + throw new IllegalArgumentException("Unknown type: " + reflectType); + } + + // -------------------------------------------- // + // DEFAULTS + // -------------------------------------------- // + + static + { + registerAll(); + } + + public static void registerAll() + { + // Primitive + register(Boolean.TYPE, TypeBoolean.getTrue()); + register(Boolean.class, TypeBoolean.getTrue()); + + register(Byte.TYPE, TypeByte.get()); + register(Byte.class, TypeByte.get()); + + register(Double.TYPE, TypeDouble.get()); + register(Double.class, TypeDouble.get()); + + register(Float.TYPE, TypeFloat.get()); + register(Float.class, TypeFloat.get()); + + register(Integer.TYPE, TypeInteger.get()); + register(Integer.class, TypeInteger.get()); + + register(Long.TYPE, TypeLong.get()); + register(Long.class, TypeLong.get()); + + register(String.class, TypeString.get()); + + // Bukkit + register(Destination.class, TypeDestination.get()); + register(ItemStack.class, TypeItemStack.get()); + register(Permission.class, TypePermission.get()); + register(PotionEffectType.class, TypePotionEffectType.get()); + register(PS.class, TypePS.get()); + register(World.class, TypeWorld.get()); + register(PotionEffectWrap.class, TypePotionEffectWrap.get()); + register(SoundEffect.class, TypeSoundEffect.get()); + + // Enum + register(Biome.class, TypeBiome.get()); + register(ChatColor.class, TypeChatColor.get()); + register(Difficulty.class, TypeDifficulty.get()); + register(DyeColor.class, TypeDyeColor.get()); + register(EntityType.class, TypeEntityType.get()); + register(Environment.class, TypeEnvironment.get()); + register(EventPriority.class, TypeEventPriority.get()); + register(GameMode.class, TypeGameMode.get()); + register(Horse.Color.class, TypeHorseColor.get()); + register(Horse.Style.class, TypeHorseStyle.get()); + register(Horse.Variant.class, TypeHorseVariant.get()); + register(Material.class, TypeMaterial.get()); + register(Ocelot.Type.class, TypeOcelotType.get()); + register(ParticleEffect.class, TypeParticleEffect.get()); + register(Rabbit.Type.class, TypeRabbitType.get()); + register(SkeletonType.class, TypeSkeletonType.get()); + register(Sound.class, TypeSound.get()); + register(Profession.class, TypeVillagerProfession.get()); + register(WorldType.class, TypeWorldType.get()); + + // Sender + register(Player.class, TypePlayer.get()); + register(CommandSender.class, TypeSender.get()); + + // Store + register(Aspect.class, TypeAspect.get()); + register(Multiverse.class, TypeMultiverse.get()); + + // Collection + register(WorldExceptionSet.class, TypeExceptionSet.get(TypeWorld.get())); + } + +} diff --git a/src/com/massivecraft/massivecore/command/type/TypeAbstract.java b/src/com/massivecraft/massivecore/command/type/TypeAbstract.java index 2928dac1..78a2a826 100644 --- a/src/com/massivecraft/massivecore/command/type/TypeAbstract.java +++ b/src/com/massivecraft/massivecore/command/type/TypeAbstract.java @@ -63,7 +63,7 @@ public abstract class TypeAbstract implements Type name = name.substring(prefixLength); // We split at uppercase letters, because most class names are camel-case. - final String[] words = name.split("(?=[A-Z])"); + final String[] words = Txt.PATTERN_UPPERCASE.split(name); return Txt.implode(words, " ").toLowerCase(); } diff --git a/src/com/massivecraft/massivecore/command/type/TypeSingleton.java b/src/com/massivecraft/massivecore/command/type/TypeSingleton.java new file mode 100644 index 00000000..f692bb57 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/TypeSingleton.java @@ -0,0 +1,42 @@ +package com.massivecraft.massivecore.command.type; + +import com.massivecraft.massivecore.command.editor.CommandEditAbstract; +import com.massivecraft.massivecore.command.editor.CommandEditReflection; +import com.massivecraft.massivecore.command.editor.EditSettings; +import com.massivecraft.massivecore.command.editor.Property; + +public class TypeSingleton extends TypeAbstractChoice +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + public static TypeSingleton get(T singleton){ return new TypeSingleton<>(singleton); } + public TypeSingleton(T singleton) + { + super.setAll(singleton); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public String getName() + { + return this.getAll().iterator().next().getClass().getSimpleName(); + } + + @Override + public String getIdInner(T value) + { + return value.getClass().getSimpleName(); + } + + @SuppressWarnings("unchecked") + public CommandEditAbstract createEditCommand(EditSettings settings, Property property) + { + return new CommandEditReflection(settings, property, (Class) this.getAll().iterator().next().getClass()); + } + +} diff --git a/src/com/massivecraft/massivecore/command/type/container/TypeExceptionSet.java b/src/com/massivecraft/massivecore/command/type/container/TypeExceptionSet.java new file mode 100644 index 00000000..a47eebad --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/container/TypeExceptionSet.java @@ -0,0 +1,82 @@ +package com.massivecraft.massivecore.command.type.container; + +import java.util.Collection; +import java.util.Set; + +import org.bukkit.command.CommandSender; + +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.collections.ExceptionSet; +import com.massivecraft.massivecore.command.type.Type; +import com.massivecraft.massivecore.command.type.TypeAbstract; +import com.massivecraft.massivecore.command.type.primitive.TypeBoolean; +import com.massivecraft.massivecore.util.Txt; + +public class TypeExceptionSet extends TypeAbstract> +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private final TypeSet typeElements; + public TypeSet getTypeElements() { return this.typeElements; } + + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + public static TypeExceptionSet get(Type innerType) + { + return new TypeExceptionSet(innerType); + } + + public TypeExceptionSet(Type innerType) + { + this.typeElements = TypeSet.get(innerType); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public ExceptionSet read(String arg, CommandSender sender) throws MassiveException + { + String[] args = Txt.PATTERN_WHITESPACE.split(arg, 2); + String first = args[0]; + String second = args.length == 2 ? args[1] : ""; + + boolean standard = TypeBoolean.getTrue().read(first, sender); + Set exceptions = this.getTypeElements().read(second, sender); + + ExceptionSet ret = new ExceptionSet<>(); + ret.standard = standard; + + for (E exception: exceptions) + { + ret.exceptions.add(ret.convert(exception)); + } + + return ret; + } + + @Override + public Collection getTabList(CommandSender sender, String arg) + { + if (arg.contains(" ")) + { + return this.getTypeElements().getTabList(sender, arg.substring(arg.indexOf(' '))); + } + else + { + return TypeBoolean.getTrue().getTabList(sender, arg); + } + } + + @Override + public boolean allowSpaceAfterTab() + { + return this.getTypeElements().allowSpaceAfterTab(); + } + +} diff --git a/src/com/massivecraft/massivecore/command/type/enumeration/TypeEventPriority.java b/src/com/massivecraft/massivecore/command/type/enumeration/TypeEventPriority.java new file mode 100644 index 00000000..ac7f9284 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/enumeration/TypeEventPriority.java @@ -0,0 +1,18 @@ +package com.massivecraft.massivecore.command.type.enumeration; + +import org.bukkit.event.EventPriority; + +public class TypeEventPriority extends TypeEnum +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static TypeEventPriority i = new TypeEventPriority(); + public static TypeEventPriority get() { return i; } + public TypeEventPriority() + { + super(EventPriority.class); + } + +} diff --git a/src/com/massivecraft/massivecore/command/type/store/TypeEntity.java b/src/com/massivecraft/massivecore/command/type/store/TypeEntity.java index 87ce752c..f4217a25 100644 --- a/src/com/massivecraft/massivecore/command/type/store/TypeEntity.java +++ b/src/com/massivecraft/massivecore/command/type/store/TypeEntity.java @@ -12,6 +12,11 @@ public class TypeEntity> extends TypeAbstractChoice // CONSTRUCT // -------------------------------------------- // + public static > TypeEntity get(Coll coll) + { + return new TypeEntity<>(coll); + } + public TypeEntity(Coll coll) { this.coll = coll; @@ -28,6 +33,14 @@ public class TypeEntity> extends TypeAbstractChoice // OVERRIDE // -------------------------------------------- // + @Override + public String getName() + { + String name = this.getColl().getClass().getSimpleName(); + name = name.substring(0, name.length() - "Coll".length()); + return name; + } + @Override public T getExactMatch(String arg) { diff --git a/src/com/massivecraft/massivecore/util/Txt.java b/src/com/massivecraft/massivecore/util/Txt.java index 45ff6ec3..df7ba8ce 100644 --- a/src/com/massivecraft/massivecore/util/Txt.java +++ b/src/com/massivecraft/massivecore/util/Txt.java @@ -41,6 +41,7 @@ public class Txt public static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+"); public static final Pattern PATTERN_NEWLINE = Pattern.compile("\\r?\\n"); + public static final Pattern PATTERN_UPPERCASE = Pattern.compile("(?=[A-Z])"); public static final long millisPerSecond = 1000; public static final long millisPerMinute = 60 * millisPerSecond;