walterhiggins / ScriptCraft

Write Minecraft Plugins in JavaScript.
MIT License
1.84k stars 379 forks source link

Possible implementation of global TabAutocompletion for commands #329

Open lastuniverse opened 7 years ago

lastuniverse commented 7 years ago

my implementation for global TAB completers of commands and some samples of plugins, such as /warp /spawn /fly /god and sign for lifts and teleports to warps and spawn

https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/completer.js

A living examples of using the module completer.js see links

https://github.com/lastuniverse/scripcraft_plugins/blob/master/plugins/last/last_economy.js after line 135

https://github.com/lastuniverse/scripcraft_plugins/blob/master/plugins/last/last_warp.js after line 564

https://github.com/lastuniverse/scripcraft_plugins/blob/master/plugins/last/last_chat.js after line 541

https://github.com/lastuniverse/scripcraft_plugins/blob/master/plugins/last/last_spawn.js after line 152

https://github.com/lastuniverse/scripcraft_plugins/blob/master/plugins/last/last_party.js Starting with line 152 and up to line 251

TonyGravagno commented 7 years ago

I admit that I don't undersstand this very well yet. We'll try to make sure that this great contribution isn't lost, but I don't think it should be built-in to the plugin itself. The new website will support plugin developers and community contributions like this. I propose that when the site goes live that we focus on this code as being one of those projects.

Suggestions for all of us who will be looking at this:

I'm not asking for these changes to be made now - I'm saying this can be a community project soon. I'll leave this task open. If you do make changes to your code, your repo would be the best place for that, and we'll just refer to the repo later.

Thanks for your patience.

lastuniverse commented 7 years ago

I beg your pardon for my English. I have plans to make a complete translation of all comments and documentation in English for each module, library and plug-in. But unfortunately this will not happen soon. Excuse me.

Updated the contents of the repository. Incorporating the latest developments. In https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/completer.js significant changes have been made, comments and examples have been added (unfortunately the comments are still in Russian). My knowledge of English does not allow for an adequate translation. I will be glad to any help in this matter.

As an example of use (with an attempt to translate comments into English):

// we connect the module of registration and autocompletion of commands var completer = require ('last / completer');

// register the {/youcomand} command and treat it as a command for the client chat var command = completer.addPlayerCommand ('youcomand', function (...) {...});

// register the {/youcomand help} command and treat it as a command for the client's chat command.addComplete ('help', function (...) {...});

// register the {/youcomand data} command without the handler as a command for the client chat var command_data = command.addComplete ('data');

// register the {/youcomand data get } command and treat it as a command for the client chat command_data.addComplete ('get'). addComplete ('@user', function (...) {...});

// register the command {/youcomand data set } and treat it as a command for the client's chat command_data.addComplete ('get'). addComplete ('@user'). addComplete ('@re/\d+/', function (...) {...});

// now the /youcomand command with all its parameters will be available as global, and will be autocomplete by pressing TAB

PS: thank you for taking the time. Sincerely, Lastuniverse.

TonyGravagno commented 7 years ago

Thanks for continuing the effort. We'll get to this eventually... Dosvidanya tovarish.

SEAPUNK commented 7 years ago

I think back when I forked off ScriptCraft into JSC, I was able to implement a global command registration and tab complete system: https://github.com/skewten-incubator/JSC/blob/master/src/java/net/sq10/JSC/JSCPlugin.java#L201-L226

I don't quite remember how well it worked though, but if it was in master, then I guess it worked well enough.

lastuniverse commented 7 years ago

To do this in JAVA is not so difficult. It was not easy to do this in JavaScript (ScriptCraft). I chose a somewhat non-standard approach. But I like the result more than all the alternatives with which I worked.

Translation of the description of this module is my first on the line.

SEAPUNK commented 7 years ago

Note that I pass down the tabComplete event to Javascript, so it's not all done in Java, only the difficult to achieve otherwise parts (i.e. "cleanly" registering global commands). :wink:

https://github.com/skewten-incubator/JSC/blob/master/src/javascript/core/lib/tabcomplete.js

lastuniverse commented 7 years ago

I just had problems with registering global commands from javascript and tabcomplete for them. Global commands registered through the commando very much did not want autocomplete)

The main reason for which I published my version for global commands and autocompletion, and asked to include in the core scriptcraft: https://github.com/walterhiggins/ScriptCraft/blob/4c28000dafb1a547140122ad3339c9993a67d40a/src/main/js/plugins/commando/commando.js#L74

lastuniverse commented 7 years ago

In this example, you will learn how to register commands:

/description help
/description set {username} {you description}
/description set {username} {email}
/description delete {username}
/description list 

where: {username} - the name of the online or offline player (online players are auto-complete by TAB) {you description} - any text

// We connect the module of registration and autocompletion of commands
var  completer = require('last/completer');

// Create/load a data warehouse for description
var store = persist('description', {} );

// Create an array with commands and their descriptions
var help_messages = [
"/description help - this help\n",
"/description set {username} {you description} - remember for the player {username} description {you description}\n",
"/description set {username} {email} - remember for the player {username} the email address {email}\n",
"/description delete {username} - remove player description {username}\n",
"/description list - Show the list of players and their descriptions\n"
];

//  We register the command `/description` without the handler
var point = completer.addPlayerCommand( 'description' );

//  We register the command `/description help` and its handler as a command for the client chat
point.addComplete('help', cmd_help );

//  We register the command `/description help` and its handler as a command for the client chat
point.addComplete('list', cmd_list );

// Register the command `/description set {username}` without the handler.
// Note that the third argument passed to the function, userlist_to_autocomlete.
// It returns an associative array whose keys will be added to the autocomplete list for the `/description set` command
// It's not rational to display all online and offline players as an auto-completion of the `/description set` command.
// But we do this to demonstrate the capabilities of the module `last/completer`.
// The `@any` tag is matched with any input after the `/description set` command, adding the already entered characters to the list of auto-completions.
// In our case, it will be matched against the entered user names, including the users offline.
var point_set = point.addComplete('set', undefined, userlist_to_autocomlete )
                     .addComplete('@any');

    // Register the command `/description set {username} {email}` and set the handler for it.
    point_set.addComplete('@re/(\\w+([-+.\']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)/', cmd_set_email);

    // Register the command `/description set {username} {description}` and set the handler for it.
    point_set.addComplete('@any', cmd_set_description);

// Register the command `/description delete {username}`.
// We could register the processors of the `/description delete {username}` command in the same way as for the `/description set {username} ...` command.
// But to demonstrate the possibilities, I did it this way:
var point_delete = point.addComplete('delete');

    // the tag `@user` will add all users online to the `/description delete` list of auto-completions.
    // when processing the entered text, the `@user` tag will be matched to the names of the users online.
    point_delete.addComplete('@user',cmd_delete); 
    // To be able to specify nicknames of offline players after the `/description delete` command, use the `@any` tag.
    // Pay attention to the fact that nicknames of offline players will not be autocomplete.
    // And also to the fact that the `@any` tag is matched with any input.
    // So we use it last in the chain of autocomplete for the command `/description delete`.
    point_delete.addComplete('@any',cmd_delete);

// handler function for the `/description` and `/description help` commands
// in `params[0]` is a `description`
// in `params[1]` is a `help`
function cmd_help(params, sender){
    echo(sender, help_messages);
}

// handler function for the `/description list` command
// in `params[0]` is a `description`
// in `params[1]` is a `list`
function cmd_list(params, sender){
    var description_msg = ["List of users for whom there is a description:"];
    for(var name in store ){
        str = name + " - ";
        if( store[name].email )
            str += "<"+store[name].email+"> ";
        if( store[name].info )
            str += store[name].info;
        str+="\n";
        description_msg.push(str);
    }

    echo(sender, description_msg);
}

// handler function for the `/description set {username} {email}` commands
// in `params[0]` is a `description`
// in `params[1]` is a `set`
// in `params[2]` is a `{username}`
// in `params[3]` is a `{email}`
function cmd_set_email(params, sender){
    var name = params[2];
    var email = params[3];
    if( !store[name] )
        store[name] = {};
    store[name].email = email;
    echo(sender, "e-mail address <"+email+"> has been successfully added to "+name+"'s description");
}

// handler function for the `/description set {username} {you description}` commands
// in `params[0]` is a `description`
// in `params[1]` is a `set`
// in `params[2]` is a `{username}`
// in `params[3]` is a `{you description}`
function cmd_set_description(params, sender){
    params.shift();
    params.shift();
    var name = params.shift();
    var info = params.join(" ");
    if( !store[name] )
        store[name] = {};
    store[name].info = info;
    echo(sender, "information was successfully added to  "+name+"'s description");
}

// handler function for the `/description delete {username}` commands
// in `params[0]` is a `description`
// in `params[1]` is a `delete`
// in `params[2]` is a `{username}`
function cmd_delete(params, sender){
    var name = params[2];
    if( store[name] ){
        delete store[name];
        echo(sender, "description for user "+name+" successfully deleted");
    }else{
        echo(sender, "no user description for "+name);  
    }

}

// function returns an associative array whose keys are nicknames of all users registered on the server
function userlist_to_autocomlete(sender,patern){
    var result = {};
    var users = org.bukkit.Bukkit.getOfflinePlayers();
    for(var user in users){
        var name = users[user].name;
        result[name] = true;
    }
    return result;
}
TonyGravagno commented 7 years ago

That's really great, thanks. I'd like to get the current release into production (as 3.3.0) and then put this into the very next release (3.4). It would help if someone can help to implement, test, and/or translate the contribution by @lastuniverse and his sample. The less I need to do the faster it will make it into the public eye.

lastuniverse commented 7 years ago

For my part, I can minimize the dependencies for module completer.js, and make the documentation, and a translation for what remains. But I can not guarantee the quality of the translation. It will be necessary to attract an English-speaking person so that he reads and edits the text and comments where necessary. I'll do it soon.

JamesRLamar commented 7 years ago

I'd be glad to review documentation once you draft it.

lastuniverse commented 7 years ago

While doing work on minimizing dependencies, I had questions / suggestions:

1. Localization module

https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/locales.js https://github.com/lastuniverse/scripcraft_plugins/tree/master/data/locales/plugins/last/last_viptools - examples of localization files for Russian and English.

I would like to leave it. Is it possible?

If you agree to include it in the modules then: I will be glad to know your opinion about where the localization files should be stored?

2. Permission module for users and groups

https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/permissions.js https://github.com/lastuniverse/scripcraft_plugins/tree/master/data/config - examples of configurations for users and groups.

// the command "/test user" will be executed if the permissions for the user are set to "test_plugin_name.allow_test" and "test_plugin_name.allow_test_user" point.addComplete('user', handler_function_2, undefined, "test_plugin_name.allow_test_user" );


*I would like to leave it. Is it possible?*

- currently I use the path to store all the settings files
  scriptcraft/data/config/{modules|lib|plugins}/{name_of_modules|lib|plugins}
  https://github.com/lastuniverse/scripcraft_plugins/tree/master/data/config

*If you agree to include it in the modules then: I'm happy to know your opinion on where the configuration files should be stored?*

### 3. Modules:
- https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/users.js - used for centralized storage of information by various plug-ins. The information is tied to the user. The module has a primitive cache for quick access to online user data. It is planned to finalize.
- https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/eventemmiter.js - third-party implementation of EventEmmiter.
- https://github.com/lastuniverse/scripcraft_plugins/blob/master/modules/last/eventex.js - a wrapper that creates a global instance of the EventEmmiter class.

*I would like to leave these modules too. Is it possible?*
lastuniverse commented 7 years ago

made a description of the module locales.js

TonyGravagno commented 7 years ago

I just got back from a trip and honestly do not yet understand the recent proposals, but will get into it in-depth as possible.

@walterhiggins has been careful not to add bulk to the ScriptCraftJS code with non-critical code, and that policy will be respected in upcoming releases. You've already added your code into modules, which is where contributions like this are intended to go. Rather than adding your contribution into this plugin itself, it might be better to offer your code in GitHub as a separate ScriptCraftJS module, with separate doc as you have them, and instructions for copying files into the scriptcraft/modules folder.

One of the features of the new website is that it will provide a catalog of contributions like this which people can add to their servers - like a Bukkit repo but just for this plugin. Eventually people will be able to rate and discuss these addons.

In any case, please keep topics focused- we'll eventually process your tab completion in this ticket and we can discuss localization separately.

Thanks!

lastuniverse commented 7 years ago

I'm looking forward to the new site and the opportunity to spread on it my work

lastuniverse commented 7 years ago

I will be grateful if you answer a few questions.

  1. How long is the estimated time before launching a new site with voiced capabilities?
  2. In which languages / frameworks is this site built?
  3. How can I speed up site commissioning?
  4. What kind of help can I give you for the site?

PS: I have perfectly mastered express.js and webix. If my knowledge will be useful to you, I will be happy to help.

TonyGravagno commented 7 years ago

I just posted a blog on the topic.