mirror of
https://github.com/sekwah41/Advanced-Portals.git
synced 2025-02-27 09:42:26 +01:00
feat: adding auto complete for tags
This commit is contained in:
parent
106a0ae8b4
commit
c64c342a4d
@ -6,9 +6,11 @@ import com.sekwah.advancedportals.core.commands.CommandWithSubCommands;
|
||||
import com.sekwah.advancedportals.core.commands.subcommands.desti.CreateDestiSubCommand;
|
||||
import com.sekwah.advancedportals.core.commands.subcommands.portal.*;
|
||||
import com.sekwah.advancedportals.core.connector.commands.CommandRegister;
|
||||
import com.sekwah.advancedportals.core.registry.TagRegistry;
|
||||
import com.sekwah.advancedportals.core.serializeddata.DataStorage;
|
||||
import com.sekwah.advancedportals.core.module.AdvancedPortalsModule;
|
||||
import com.sekwah.advancedportals.core.repository.ConfigRepository;
|
||||
import com.sekwah.advancedportals.core.tags.activation.DestiTag;
|
||||
import com.sekwah.advancedportals.core.util.InfoLogger;
|
||||
import com.sekwah.advancedportals.core.util.Lang;
|
||||
|
||||
@ -35,6 +37,9 @@ public class AdvancedPortalsCore {
|
||||
@Inject
|
||||
private ConfigRepository configRepository;
|
||||
|
||||
@Inject
|
||||
private TagRegistry tagRegistry;
|
||||
|
||||
public AdvancedPortalsCore(File dataStorageLoc, InfoLogger infoLogger) {
|
||||
this.dataStorage = new DataStorage(dataStorageLoc);
|
||||
this.infoLogger = infoLogger;
|
||||
@ -61,24 +66,26 @@ public class AdvancedPortalsCore {
|
||||
Lang.loadLanguage(configRepository.getTranslation());
|
||||
|
||||
this.registerCommands();
|
||||
this.registerTags();
|
||||
|
||||
this.infoLogger.log(Lang.translate("logger.pluginenable"));
|
||||
}
|
||||
|
||||
private void registerTags() {
|
||||
this.tagRegistry.registerTag(new DestiTag());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void registerCommands() {
|
||||
this.registerPortalCommand(commandRegister);
|
||||
this.registerDestinationCommand(commandRegister);
|
||||
|
||||
// TODO run annotation grabbing shit
|
||||
}
|
||||
|
||||
private void registerPortalCommand(CommandRegister commandRegister) {
|
||||
this.portalCommand = new CommandWithSubCommands(this);
|
||||
|
||||
// TODO remove once annotations are done
|
||||
this.portalCommand.registerSubCommand("version", new VersionSubCommand());
|
||||
this.portalCommand.registerSubCommand("langupdate", new LangUpdateSubCommand());
|
||||
this.portalCommand.registerSubCommand("reload", new ReloadSubCommand());
|
||||
@ -95,8 +102,6 @@ public class AdvancedPortalsCore {
|
||||
|
||||
private void registerDestinationCommand(CommandRegister commandRegister) {
|
||||
this.destiCommand = new CommandWithSubCommands(this);
|
||||
|
||||
// TODO remove once annotations are done
|
||||
this.destiCommand.registerSubCommand("create", new CreateDestiSubCommand());
|
||||
|
||||
commandRegister.registerCommand("destination", this.destiCommand);
|
||||
@ -126,4 +131,8 @@ public class AdvancedPortalsCore {
|
||||
public AdvancedPortalsModule getModule() {
|
||||
return this.module;
|
||||
}
|
||||
|
||||
public TagRegistry getTagRegistry() {
|
||||
return this.tagRegistry;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.google.inject.Inject;
|
||||
import com.sekwah.advancedportals.core.commands.SubCommand;
|
||||
import com.sekwah.advancedportals.core.connector.containers.CommandSenderContainer;
|
||||
import com.sekwah.advancedportals.core.connector.containers.PlayerContainer;
|
||||
import com.sekwah.advancedportals.core.registry.TagRegistry;
|
||||
import com.sekwah.advancedportals.core.serializeddata.DataTag;
|
||||
import com.sekwah.advancedportals.core.permissions.PortalPermissions;
|
||||
import com.sekwah.advancedportals.core.portal.AdvancedPortal;
|
||||
@ -11,6 +12,7 @@ import com.sekwah.advancedportals.core.services.PortalServices;
|
||||
import com.sekwah.advancedportals.core.util.InfoLogger;
|
||||
import com.sekwah.advancedportals.core.util.Lang;
|
||||
import com.sekwah.advancedportals.core.util.TagReader;
|
||||
import com.sekwah.advancedportals.core.warphandler.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -24,6 +26,9 @@ public class CreatePortalSubCommand implements SubCommand {
|
||||
@Inject
|
||||
InfoLogger infoLogger;
|
||||
|
||||
@Inject
|
||||
TagRegistry tagRegistry;
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSenderContainer sender, String[] args) {
|
||||
if(args.length > 1) {
|
||||
@ -67,8 +72,63 @@ public class CreatePortalSubCommand implements SubCommand {
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSenderContainer sender, String[] args) {
|
||||
// TODO add tab complete for tags
|
||||
return null;
|
||||
|
||||
if(TagReader.isClosedString(args)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<Tag> allTags = tagRegistry.getTags();
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
if(args.length > 0) {
|
||||
var lastArg = args[args.length - 1];
|
||||
// Check if the split results in exactly 2 or if its 1 and ends with :
|
||||
var split = lastArg.split(":");
|
||||
if(split.length == 2 || (split.length == 1 && lastArg.endsWith(":"))) {
|
||||
// Loop over tags in allTags and check if the first half of split is equal to the tag name or alias
|
||||
for(Tag tag : allTags) {
|
||||
if(tag instanceof Tag.AutoComplete autoComplete) {
|
||||
var tagSuggestions = autoComplete.autoComplete(split.length == 2 ? split[1] : "");
|
||||
if(tagSuggestions != null) {
|
||||
// Loop over suggestions and add split[0] + ":" to the start
|
||||
for (String tagSuggestion : tagSuggestions) {
|
||||
suggestions.add(split[0] + ":" + tagSuggestion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is returning right but something is going wrong with "desti:A" whenever anything is typed after :
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<DataTag> portalTags = TagReader.getTagsFromArgs(args);
|
||||
|
||||
allTags.stream().filter(tag -> {
|
||||
for (DataTag portalTag : portalTags) {
|
||||
if(portalTag.NAME.equals(tag.getName())) {
|
||||
return false;
|
||||
}
|
||||
// check the tag aliases
|
||||
for (String alias : tag.getAliases()) {
|
||||
if(portalTag.NAME.equals(alias)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}).forEach(tag -> {
|
||||
suggestions.add(tag.getName());
|
||||
suggestions.addAll(Arrays.stream(tag.getAliases()).toList());
|
||||
});
|
||||
|
||||
// Loop over all suggestions and add : to the end
|
||||
for (int i = 0; i < suggestions.size(); i++) {
|
||||
suggestions.set(i, suggestions.get(i) + ":");
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,7 +27,7 @@ import java.util.Set;
|
||||
public class Destination implements TagTarget {
|
||||
|
||||
@Inject
|
||||
TagRegistry<Destination> tagRegistry;
|
||||
TagRegistry tagRegistry;
|
||||
|
||||
@SerializedName("l")
|
||||
private PlayerLocation loc;
|
||||
|
@ -2,6 +2,7 @@ package com.sekwah.advancedportals.core.module;
|
||||
|
||||
import com.google.inject.*;
|
||||
import com.sekwah.advancedportals.core.AdvancedPortalsCore;
|
||||
import com.sekwah.advancedportals.core.registry.TagRegistry;
|
||||
import com.sekwah.advancedportals.core.serializeddata.config.Config;
|
||||
import com.sekwah.advancedportals.core.serializeddata.config.ConfigProvider;
|
||||
import com.sekwah.advancedportals.core.serializeddata.DataStorage;
|
||||
@ -45,6 +46,7 @@ public class AdvancedPortalsModule extends AbstractModule {
|
||||
|
||||
// Providers
|
||||
bind(Config.class).toProvider(ConfigProvider.class);
|
||||
bind(TagRegistry.class).asEagerSingleton();
|
||||
|
||||
// Delayed Bindings
|
||||
for(DelayedBinding delayedBinding : delayedBindings) {
|
||||
|
@ -20,7 +20,7 @@ import java.util.Map;
|
||||
public class AdvancedPortal implements TagTarget {
|
||||
|
||||
@Inject
|
||||
transient TagRegistry<AdvancedPortal> tagRegistry;
|
||||
transient TagRegistry tagRegistry;
|
||||
|
||||
@SerializedName("max")
|
||||
private WorldLocation maxLoc;
|
||||
|
@ -2,13 +2,9 @@ package com.sekwah.advancedportals.core.registry;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.sekwah.advancedportals.core.AdvancedPortalsCore;
|
||||
import com.sekwah.advancedportals.core.portal.AdvancedPortal;
|
||||
import com.sekwah.advancedportals.core.warphandler.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Allows a portal to register a tag and add a handler. If a plugin wants to add functionality
|
||||
@ -16,23 +12,18 @@ import java.util.Map;
|
||||
*
|
||||
* @author sekwah41
|
||||
*/
|
||||
public class TagRegistry<T> {
|
||||
public class TagRegistry {
|
||||
|
||||
@Inject
|
||||
private AdvancedPortalsCore portalsCore;
|
||||
AdvancedPortalsCore portalsCore;
|
||||
|
||||
/**
|
||||
* List of tag names which should be in order alphabetically
|
||||
*/
|
||||
private ArrayList<String> tags = new ArrayList();
|
||||
/**
|
||||
* Description of tags for help commands (will try to use translation strings before rendering
|
||||
* Possibly add a way to allow addons to supply extra info to the Lang class in the future.
|
||||
*/
|
||||
private Map<String, String> tagDesc = new HashMap();
|
||||
private Map<String, Tag.Activation> activationHandlers = new HashMap();
|
||||
private Map<String, Tag.Creation> creationHandlers = new HashMap();
|
||||
private Map<String, Tag.TagStatus> statusHandlers = new HashMap();
|
||||
private final ArrayList<String> literalTags = new ArrayList<>();
|
||||
|
||||
private final ArrayList<Tag> tags = new ArrayList<>();
|
||||
|
||||
private final Map<String, Tag.Activation> activationTags = new HashMap<>();
|
||||
private final Map<String, Tag.Creation> creationTags = new HashMap<>();
|
||||
private final Map<String, Tag.TagStatus> statusTags = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Portals to trigger when a portal is activated
|
||||
@ -41,7 +32,7 @@ public class TagRegistry<T> {
|
||||
* @return
|
||||
*/
|
||||
public Tag.Activation getActivationHandler(String arg) {
|
||||
return this.activationHandlers.get(arg);
|
||||
return this.activationTags.get(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,7 +41,7 @@ public class TagRegistry<T> {
|
||||
* @return
|
||||
*/
|
||||
public Tag.Creation getCreationHandler(String arg) {
|
||||
return this.creationHandlers.get(arg);
|
||||
return this.creationTags.get(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,81 +50,57 @@ public class TagRegistry<T> {
|
||||
* @return
|
||||
*/
|
||||
public Tag.TagStatus getTagStatusHandler(String arg) {
|
||||
return this.statusHandlers.get(arg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* It is reccomended that you use the taghandlers to add tag functionality. However
|
||||
* if needed such as extra data for a tag then this is here.
|
||||
*
|
||||
* @param tag
|
||||
* @return if the tag was registered
|
||||
*/
|
||||
private boolean registerTag(String tag) {
|
||||
if (tag.contains(" ")) {
|
||||
this.portalsCore.getInfoLogger().logWarning("The tag '"
|
||||
+ tag + "' is invalid as it contains spaces.");
|
||||
return false;
|
||||
}
|
||||
if (this.tags.contains(tag)) {
|
||||
this.portalsCore.getInfoLogger().logWarning("The tag "
|
||||
+ tag + " has already been registered.");
|
||||
return false;
|
||||
}
|
||||
this.tags.add(tag);
|
||||
Collections.sort(this.tags);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean registerTag(String tag, String desc) {
|
||||
if (registerTag(tag)) {
|
||||
this.tagDesc.put(tag, desc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non referenced copy of the array list.
|
||||
* @return
|
||||
*/
|
||||
public ArrayList<String> getTags() {
|
||||
ArrayList<String> newArrayList = new ArrayList<>();
|
||||
newArrayList.addAll(this.tags);
|
||||
return newArrayList;
|
||||
}
|
||||
|
||||
public boolean isTagRegistered(String tag){
|
||||
return this.tagDesc.containsKey(tag);
|
||||
return this.statusTags.get(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* File must extend
|
||||
* @return if the tag has been registered or if it already exists.
|
||||
*/
|
||||
public boolean registerTag(String tag, Tag tagHandler) {
|
||||
public boolean registerTag(Tag tag) {
|
||||
|
||||
if (tag == null) {
|
||||
String tagName = tag.getName();
|
||||
|
||||
this.tags.add(tag);
|
||||
|
||||
// Check literal tags for clashes
|
||||
if(this.literalTags.contains(tagName)) {
|
||||
this.portalsCore.getInfoLogger().logWarning("A tag with the name " + tagName + " already exists.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String alias : tag.getAliases()) {
|
||||
if(this.literalTags.contains(alias)) {
|
||||
this.portalsCore.getInfoLogger().logWarning("A tag with the alias " + alias + " already exists.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add name and aliases to literalTags to check for clashes
|
||||
this.literalTags.add(tagName);
|
||||
Collections.addAll(this.literalTags, tag.getAliases());
|
||||
|
||||
if (tagName == null) {
|
||||
this.portalsCore.getInfoLogger().logWarning("A tag cannot be null.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.registerTag(tag)) {
|
||||
return false;
|
||||
if (tag instanceof Tag.Activation tagActivation) {
|
||||
this.activationTags.put(tagName, tagActivation);
|
||||
}
|
||||
|
||||
if (tagHandler instanceof Tag.Activation tagActivation) {
|
||||
this.activationHandlers.put(tag, tagActivation);
|
||||
if (tag instanceof Tag.TagStatus tagStatus) {
|
||||
this.statusTags.put(tagName, tagStatus);
|
||||
}
|
||||
if (tagHandler instanceof Tag.TagStatus tagStatus) {
|
||||
this.statusHandlers.put(tag, tagStatus);
|
||||
}
|
||||
if (tagHandler instanceof Tag.Creation tagCreation) {
|
||||
this.creationHandlers.put(tag, tagCreation);
|
||||
if (tag instanceof Tag.Creation tagCreation) {
|
||||
this.creationTags.put(tagName, tagCreation);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public List<Tag> getTags() {
|
||||
// Make a copy of the list to prevent issues with modification
|
||||
|
||||
return this.tags;
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,14 @@ package com.sekwah.advancedportals.core.tags.activation;
|
||||
|
||||
import com.sekwah.advancedportals.core.connector.containers.PlayerContainer;
|
||||
import com.sekwah.advancedportals.core.registry.TagTarget;
|
||||
import com.sekwah.advancedportals.core.util.Lang;
|
||||
import com.sekwah.advancedportals.core.warphandler.ActivationData;
|
||||
import com.sekwah.advancedportals.core.warphandler.Tag;
|
||||
|
||||
public class DestiTag implements Tag.Activation {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DestiTag implements Tag.Activation, Tag.AutoComplete {
|
||||
|
||||
private final TagType[] tagTypes = new TagType[]{ TagType.PORTAL };
|
||||
|
||||
@ -14,6 +18,21 @@ public class DestiTag implements Tag.Activation {
|
||||
return tagTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "destination";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[]{"desti"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return Lang.translate("tag.desti.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preActivated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData) {
|
||||
return false;
|
||||
@ -28,4 +47,15 @@ public class DestiTag implements Tag.Activation {
|
||||
public boolean activated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> autoComplete(String argData) {
|
||||
List<String> autoCompletes = new ArrayList<>();
|
||||
// Get all and filter by the argData
|
||||
|
||||
autoCompletes.add("AIR");
|
||||
autoCompletes.add("WATER");
|
||||
|
||||
return autoCompletes;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,30 @@ import java.util.HashMap;
|
||||
|
||||
public class TagReader {
|
||||
|
||||
public static boolean isClosedString(String[] args) {
|
||||
StringBuilder currentValue = new StringBuilder();
|
||||
boolean inQuotes = false;
|
||||
|
||||
for (String arg : args) {
|
||||
if (arg.contains(":") && !inQuotes) {
|
||||
int colonIndex = arg.indexOf(':');
|
||||
currentValue = new StringBuilder(arg.substring(colonIndex + 1));
|
||||
inQuotes = currentValue.toString().startsWith("\"");
|
||||
} else {
|
||||
if (!currentValue.isEmpty()) {
|
||||
currentValue.append(" ");
|
||||
}
|
||||
currentValue.append(arg);
|
||||
}
|
||||
|
||||
if (inQuotes && arg.endsWith("\"")) {
|
||||
inQuotes = false;
|
||||
}
|
||||
}
|
||||
|
||||
return inQuotes;
|
||||
}
|
||||
|
||||
public static ArrayList<DataTag> getTagsFromArgs(String[] args) {
|
||||
HashMap<String, ArrayList<String>> tagMap = new HashMap<>();
|
||||
StringBuilder currentValue = new StringBuilder();
|
||||
|
@ -3,6 +3,8 @@ package com.sekwah.advancedportals.core.warphandler;
|
||||
import com.sekwah.advancedportals.core.connector.containers.PlayerContainer;
|
||||
import com.sekwah.advancedportals.core.registry.TagTarget;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* If a tag can be used for any of them then either make it cast the target or if it doesn't need a target
|
||||
* then the exact same tag can be registered into both and ignore the portal info.
|
||||
@ -28,6 +30,24 @@ public interface Tag {
|
||||
*/
|
||||
TagType[] getTagTypes();
|
||||
|
||||
String getName();
|
||||
|
||||
String[] getAliases();
|
||||
|
||||
String description();
|
||||
|
||||
interface AutoComplete extends Tag {
|
||||
|
||||
/**
|
||||
* This is used to get the auto complete for the tag. This is called when the player is typing the tag.
|
||||
*
|
||||
* @param argData
|
||||
* @return
|
||||
*/
|
||||
List<String> autoComplete(String argData);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The events for portal creation and destroying
|
||||
*/
|
||||
|
@ -120,3 +120,5 @@ items.selector.name=Portal Region Selector
|
||||
items.selector.pos=Select pos %1$s
|
||||
items.interact.left=Left Click
|
||||
items.interact.right=Right Click
|
||||
|
||||
tag.desti.description=Sets the destination of the portal
|
||||
|
Loading…
Reference in New Issue
Block a user