Skip to content

Commit

Permalink
Added asynchronous player input (async prompt) function.
Browse files Browse the repository at this point in the history
  • Loading branch information
walterhiggins committed Apr 13, 2014
1 parent 7b7d8cb commit 8c81b37
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
57 changes: 57 additions & 0 deletions docs/API-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Walter Higgins
* [Examples](#examples)
* [Fireworks Module](#fireworks-module)
* [Examples](#examples-1)
* [Asynchronous Input Module](#asynchronous-input-module)
* [Http Module](#http-module)
* [http.request() function](#httprequest-function)
* [sc-mqtt module](#sc-mqtt-module)
Expand Down Expand Up @@ -819,6 +820,62 @@ location. For example...

![firework example](img/firework.png)

## Asynchronous Input Module

The `input` module provides a simple way to prompt players for input at the
in-game prompt. In Javascript browser environments the `prompt()` function provides
a way to block execution and ask the user for input. Execution is blocked until the user
provides input using the modal dialog and clicks OK. Unfortunately Minecraft provides no
equivalent modal dialog which can be used to gather player text input. The only way to gather text
input from the player in Minecraft is to do so asynchronously. That is - a prompt message can be
sent to the player but the player is not obliged to provide input immediately, nor does the program
execution block until the player does so.

So ScriptCraft has no `prompt()` implementation because `prompt()` is a synchronous function and
Minecraft's API provides no equivalent functions or classes which can be used to implement this synchronously.
The Minecraft API does however have a 'Conversation' API which allows for prompting of the player and asynchronously gathering text input from the player.

This new `input()` function is best illustrated by example. The following code is for a number-guessing game:

```javascript
var input = require('input');
exports.numberguess = function(player){
var randomNumber = Math.ceil(Math.random() * 10);
input( player, 'Think of a number between 1 and 10 (q to quit)', function( guess, repeat ) {
if ( guess == 'q'){
return;
}
if ( +guess !== randomNumber ) {
if (+guess < randomNumber ) {
player.sendMessage('Too low - guess again');
}
if (+guess > randomNumber ) {
player.sendMessage('Too high - guess again');
}
repeat();
} else {
player.sendMessage('You guessed correctly');
}
});
};
```

The `input()` function takes 3 parameters, the player, a prompt message and a callback which will be invoked when the player has entered some text at the in-game command prompt.
The callback is bound to an object which has the following properties:

* sender : The player who input the text
* value : The value of the text which has been input.
* message: The message prompt.
* repeat: A function which when invoked will repeat the original prompt. (this is for flow control)

The callback function as well as being bound to an object with the above properties (so you can use this.value inside your callback to get the value which has just been input), can also take the following parameters (in exact order):

* value
* repeat
* sender

The `value` parameter will be the same as `this.value`, the `repeat` parameter will be the same as `this.repeat` and so on.

## Http Module

For handling http requests. Not to be confused with the more robust
Expand Down
4 changes: 4 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 2014 04 13

Added asynchronous `input()` function module.

# 2014 03 15

## Version 2.0.6
Expand Down
86 changes: 86 additions & 0 deletions src/main/js/modules/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*************************************************************************
## Asynchronous Input Module
The `input` module provides a simple way to prompt players for input at the
in-game prompt. In Javascript browser environments the `prompt()` function provides
a way to block execution and ask the user for input. Execution is blocked until the user
provides input using the modal dialog and clicks OK. Unfortunately Minecraft provides no
equivalent modal dialog which can be used to gather player text input. The only way to gather text
input from the player in Minecraft is to do so asynchronously. That is - a prompt message can be
sent to the player but the player is not obliged to provide input immediately, nor does the program
execution block until the player does so.
So ScriptCraft has no `prompt()` implementation because `prompt()` is a synchronous function and
Minecraft's API provides no equivalent functions or classes which can be used to implement this synchronously.
The Minecraft API does however have a 'Conversation' API which allows for prompting of the player and asynchronously gathering text input from the player.
This new `input()` function is best illustrated by example. The following code is for a number-guessing game:
```javascript
var input = require('input');
exports.numberguess = function(player){
var randomNumber = Math.ceil(Math.random() * 10);
input( player, 'Think of a number between 1 and 10 (q to quit)', function( guess, repeat ) {
if ( guess == 'q'){
return;
}
if ( +guess !== randomNumber ) {
if (+guess < randomNumber ) {
player.sendMessage('Too low - guess again');
}
if (+guess > randomNumber ) {
player.sendMessage('Too high - guess again');
}
repeat();
} else {
player.sendMessage('You guessed correctly');
}
});
};
```
The `input()` function takes 3 parameters, the player, a prompt message and a callback which will be invoked when the player has entered some text at the in-game command prompt.
The callback is bound to an object which has the following properties:
* sender : The player who input the text
* value : The value of the text which has been input.
* message: The message prompt.
* repeat: A function which when invoked will repeat the original prompt. (this is for flow control)
The callback function as well as being bound to an object with the above properties (so you can use this.value inside your callback to get the value which has just been input), can also take the following parameters (in exact order):
* value
* repeat
* sender
The `value` parameter will be the same as `this.value`, the `repeat` parameter will be the same as `this.repeat` and so on.
***/

var bkPrompt = org.bukkit.conversations.Prompt,
bkConversationFactory = org.bukkit.conversations.ConversationFactory;

function asyncInput( sender, promptMesg, callback) {
var repeat = function(){
asyncInput( sender, promptMesg, callback);
};
var prompt = new bkPrompt( ) {
getPromptText: function( ctx ) {
return promptMesg;
},
acceptInput: function( ctx, value ) {
callback.apply( { repeat: repeat, sender: sender, message: promptMesg, value: value },
[value, repeat, sender]);
return null;
},
blocksForInput: function( ctx ) {
return true;
}
};
new bkConversationFactory( __plugin )
.withModality( true )
.withFirstPrompt( prompt )
.buildConversation( sender )
.begin( );
}
module.exports = asyncInput;

0 comments on commit 8c81b37

Please sign in to comment.