[Plugin] Shoebill 1.1 - SA-MP Java Development Kit

Yay

A nice script coming soon
Reply

Is there some nice way to manage dialogs? I'm about to build a house management system based on dialogs where clicking back will show the previous dialog and such.

Only idea I get is to put that whole set of dialogs in a separate class and create one method per dialog..
Reply

That's nice to hear
It would be nice to see it when you finished it.

@dusk: Yes, there is a very easy way to interact with dialogs. Please take a look at shoebill-common.
Here is a simple example:

Код:
@Command
public boolean house(Player player) {
    ListDialog.create(player, eventManager)
            .caption("Your house")
            .buttonCancel("Back")
            .buttonOk("Next")
            .item("Change house title", item -> {
                InputDialog.create(player, eventManager)
                        .caption(item.getCurrentDialog().getCaption() + " - Change title")
                        .message("Please enter the new house title:")
                        .buttonCancel("Back")
                        .buttonOk("Ok")
                        .parentDialog(item.getCurrentDialog()) //set the parent dialog to the "Your House"-Dialog
                        .onClickCancel(AbstractDialog::showParentDialog) //show parent dialog when he presses cancel
                        .onClickOk((dialog, text) -> {
                            if(text.length() > 0) {
                                //Update house and database etc.
                                dialog.showParentDialog(); //show the parent dialog when the text changed successfully
                            } else {
                                player.sendMessage(Color.RED, "* The name is not valid!");
                                dialog.show();
                            }
                        })
                        .build()
                        .show();
            })
            .item("Change rent price", item -> {
                //Implement
             })
            .item("Sell house", item -> {
                player.sendMessage(Color.RED, "* You can't sell your house because there are still people in it.");
                item.getCurrentDialog().show(); //Reshow Dialog
            })
            .onClickCancel(dialog -> {
                player.sendMessage(Color.GREEN, "* You canceled the house editing.");
            })
            .build()
            .show();
    return true;
}
Reply

Woow. This is going to make dialog menus fun

What about this:
Код:
Collection<ListDialogItem> items = new ArrayList<ListDialogItem>();
// add some stuff to "items" dynamically(i do not know their values at compile time)
ListDialog.create(player, eventManager)
      .caption("stuff")
      .item("Single action", item -> {
           // do things
      })
      .items(items)
      .onClickOk((dialog, item) -> {
            // do something with items from "items" collection
      })
      .build()
      .show();
Will "onClickOk" be called when selecting "Single action"? Or only its handler function.

Will this even work? Or does items orverride item data?
Reply

@dusk:
onClickOk will be called after the "Single action", but also after every other item. It will always be called when you click button0 / enter. If you have a collection of data, I always do it like this:

Код:
Collection<Person> data = new ArrayList<>(); //data from dynamic source
ListDialog listDialog = ListDialog.create(player, eventManager)
        .caption("My dialog with dynamic data")
        .buttonCancel("Cancel")
        .buttonOk("Ok")
        .build();
for(Person person : data) {
    listDialog.addItem(person.getName(), item -> {
        //Do things with the person object
    });
}
// check if the listdialog contains data
if(listDialog.getItems().size() > 0) listDialog.show();
else player.sendMessage(Color.RED, "* There is no data available!");
There are also some other custom types of Dialogs in shoebill-common. For example the PageListDialog, which automatically adds a "<< Next Page <<" and ">> Prev Page >>" (you can change the text) Item to your dialog if there are too many items in one page (also customizable), here is a example:

Код:
PageListDialog pageListDialog = PageListDialog.create(player, eventManager)
        .caption("Pagination")
        .prevPage("<< Previous Page <<")
        .nextPage(">> Next Page >>")
        .itemsPerPage(10)
        .build();
for(int i = 0; i < 50; i++) {
    pageListDialog.addItem("Item " + i);
}
pageListDialog.show();
You can see my project "wl-vehicle-manager", which uses dialog, although it has stopped development:
https://github.com/GTAUN/wl-vehicle-...vehicle/dialog
Reply

I just started the development of a new project called B-RP.
But unfortunately, now I can only give a screenshot to see. At present it is nothing, needs a lot of development work.
Reply

Quote:
Originally Posted by mk124
Посмотреть сообщение
I just started the development of a new project called B-RP.
But unfortunately, now I can only give a screenshot to see. At present it is nothing, needs a lot of development work.
Nice work! Keep it up!
Reply

@Rancho: Thank you for your support.
Reply

[Image: 1T90srp]

- Call Shoebill-Functions from Pawn



If you want to update, please use the shoebill-updater. Just start the update-shoebill.bat/.sh file and shoebill will download the newest version.


I'm happy to tell you, that Shoebill now supports calling Java functions from Pawn. At this moment, Integers, Floats and Strings are supported. You can also pass variables by their reference and change their value in Java.
Here is a little example:

At first, you need to add a new native function into your Pawn-Script:
pawn Код:
native CallShoebillFunction(name[], {Float,_}:...);
(The best way is to use a include, but you can also just declare it at the top of your script)

Now, you need to register a function, this happens in Java. Every AMX-File has it's own function-pool. If you want to register a function in every amx-file, you need to loop through all amx instances or add a eventhandler to the AmxLoadEvent. In this example, I will register my function in the AmxLoadEvent, so it's available for every amx-file.

PHP код:
eventManager.registerHandler(AmxLoadEvent.class, -> {
     
e.getAmxInstance().registerFunction("GetPlayerFactionName"objects -> {
         
Player player Player.get((Integer) objects[0]);
         
//Do something to get player's faction etc.
         
objects[1] = "Los Santos PoPo";
         
//Return value for pawn (not always needed)
         
return 1;
     }, 
Integer.class, String.class);
 }); 
The .registerFunction-Method is available in every AmxInstance-Object.
First, you need to declare a new, then you need to add the function that will be called in java. After that, you need to add the parameter-types, in this case Integer (for the playerid) and then a String (as reference, the faction name will be written into this variable). If you register function, you also need to unregister them via the .unregisterFunction-Method:

PHP код:
eventManager.registerHandler(AmxUnloadEvent.class, -> {
    
e.getAmxInstance().unregisterFunction("GetPlayerFactionName");
}); 
Now you can call the function from pawn, e.g. in OnPlayerSpawn:

pawn Код:
public OnPlayerConnect(playerid)
{
    new factionName[] = "Unknown";
    CallShoebillFunction("GetPlayerFactionName", playerid, factionName);
    printf("Factionname: %s", factionName);
    return 1;
}
Result: "Factionname: Los Santos PoPo"
Reply

Could you present more examples using player's variables, global variables, foreaching online players?
Reply

@BRICS:

You can take a look at my post #209 for player variables (http://forum.sa-mp.com/showpost.php?...&postcount=209). I don't know what you mean by global variables, you can just use Java like in any other project, and you can also declare variables like normal. You can get all players via
Код:
Player.get()
or
Код:
Player.getHumans() // no bots
These functions will return a Collection<Player> and you can iterate through them like normal collections. Just ****** on how to loop through a collection in java.
Reply

Nice waiting for B-RP
Reply

@[ND]xXZeusXx.: Thank you, if you have any suggestions please let us know
Reply

Quote:
Originally Posted by mk124
Посмотреть сообщение
@BRICS:

You can take a look at my post #209 for player variables (http://forum.sa-mp.com/showpost.php?...&postcount=209). I don't know what you mean by global variables, you can just use Java like in any other project, and you can also declare variables like normal. You can get all players via
Код:
Player.get()
or
Код:
Player.getHumans() // no bots
These functions will return a Collection<Player> and you can iterate through them like normal collections. Just ****** on how to loop through a collection in java.
Код:
Iterator<Player> it = Player.getHumans().iterator();
Player p;
while(it.hasNext()) {
	// get "Player" instance
	p = it.next();
}
http://docs.oracle.com/javase/7/docs...ollection.html
http://docs.oracle.com/javase/7/docs.../Iterator.html
Reply

@BigETI:

Or just use normal for(each) loops:

Код:
for(Player player : Player.getHumans()) {
      ...
}
Reply

What about multiple command names? For example that /commands and /cmds would execute the same code. Is there an easy way for that?

I looked into shoebill-commons command annotation values, couldn't find anything of use. Or does the name in @Command is used for an alternative name?

And what is @CustomCommand used for ? Aren't all commands that we create custom?
Reply

Quote:
Originally Posted by mk124
Посмотреть сообщение
@BRICS:

You can take a look at my post #209 for player variables (http://forum.sa-mp.com/showpost.php?...&postcount=209). I don't know what you mean by global variables, you can just use Java like in any other project, and you can also declare variables like normal. You can get all players via
Код:
Player.get()
or
Код:
Player.getHumans() // no bots
These functions will return a Collection<Player> and you can iterate through them like normal collections. Just ****** on how to loop through a collection in java.
Quote:
Originally Posted by BigETI
Посмотреть сообщение
Код:
Iterator<Player> it = Player.getHumans().iterator();
Player p;
while(it.hasNext()) {
	// get "Player" instance
	p = it.next();
}
http://docs.oracle.com/javase/7/docs...ollection.html
http://docs.oracle.com/javase/7/docs.../Iterator.html
Thanks you!
Reply

When I have a class registered to a VehicleLifecycleHolder, if I create a vehicle during runtime, will it be added to that holder?

For example let's say my vehicle class is named GameVehicle and extends VehicleLifecycyleObject. If I use Vehicle.create or instantiate my own GameVehicle, will it be added to vehicle holder or is there a way to do it manually?
Reply

It supports calling SAMP native functions from different threads?
Reply

Quote:
Originally Posted by spell
Посмотреть сообщение
It supports calling SAMP native functions from different threads?
I think it would work but I wouldn't advise it. This plugin doesn't change the fact that the server is single-threaded, and so any code you wish to be processed by the samp thread should be added with Shoebill.get().runOnSampThread(runnable).
Reply


Forum Jump:


Users browsing this thread: 9 Guest(s)