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

Is it safe to add an event handler from a different(not samp) thread, assuming the thread will NOT interact with in-game related methods?
Reply

@dusk: I have not explicitly tested it, but the internal ConcurrentHashMap that is used in the EventManager should be thread-safe.
Reply

Not bad but keep it up.
Reply

About the getCommandEntries method, why there is not such method in CommandGroups like in PlayerCommandManager?
So I can get all the commands from a specific group
Reply

@DavidGravelli: Hi, thanks for you support
@Su37Erich: I added a getCommands() method to the CommandGroup class (which is also available for the PlayerCommandManager class) to get all commands in the group and it's child groups. If you call this method on the PlayerCommandManager, you will get ALL commands:

Commit: http://ci.gtaun.net/job/shoebill-common/159/

I will be absent for the next 2 weeks, but I will still try to answer your questions.
Reply

Great
Thank you!
EDIT: The method seems to be protected (for CommandGroup)
getCommands() has protected access in net.gtaun.shoebill.common.command.CommandGroup
Reply

Fixed with http://ci.gtaun.net/job/shoebill-common/160/
Reply

Thanks.
I think that this is a bug:
Код:
System.out.println(commandEntry.getCommand());
It prints something like this:
ban ban
givescore givescore

It prints two times the name of each command

And a question, how does this work?
Код:
timer = Timer.create(2000, 3, interval ->{
Server.get().gameTextToAll(1300, 3, "Something");
}
I thought it was going to show three times the word "something", but the word is only showed once.
(The code is inside a command, variable timer is an instance variable)
Reply

Hello, I'm having an issue.

Код:
----------
Loaded log file: "server_log.txt".
----------

SA-MP Dedicated Server
----------------------
v0.3.7-R2, ©2005-2015 SA-MP Team

[23:01:28] filterscripts = ""  (string)
[23:01:28] 
[23:01:28] Server Plugins
[23:01:28] --------------
[23:01:28]  Loading plugin: Shoebill
[23:01:28]   > Shoebill 1.2 NativePlugin for SA-MP 0.3.7 by MK124, JoJLlmAn & 123marvin123
[23:01:29]   > Java VM has been created.
And then crashes..

I've edited the batch file and put there my path to JRE, but it still doesn't work...




Crash Info
Код:
--------------------------

SA-MP Server: 0.3.7-R2



Exception At Address: 0x100091DE Module: (Shoebill.dll)



Registers:

EAX: 0x00000000	EBX: 0x009E6DC0	ECX: 0x00000000	EDX: 0x00A1A818

ESI: 0x009E62C8	EDI: 0x7C80AE40	EBP: 0x0012F414	ESP: 0x0012F404

EFLAGS: 0x00010206



Stack:

+0000: 0x533C93EC   0x0012FEDC   0x1005EB3C   0xFFFFFFFF

+0010: 0x0012FC28   0x1000E67F   0x00A19940   0x00A19940

+0020: 0x68732F2E   0x6962656F   0x622F6C6C   0x73746F6F

+0030: 0x70617274   0x6F68732F   0x6C696265   0x616C2D6C

+0040: 0x68636E75   0x312D7265   0x532D322E   0x5350414E

+0050: 0x2E544F48   0x0072616A   0x00000000   0x00000000

+0060: 0x00000000   0x00000000   0x00000000   0x00000000

+0070: 0x00000000   0x00000000   0x00000000   0x00000000

+0080: 0x00000000   0x00000000   0x00000000   0x00000000

+0090: 0x00000000   0x00000000   0x00000000   0x00000000

+00A0: 0x00000000   0x00000000   0x00000000   0x00000000

+00B0: 0x00000000   0x00000000   0x00000000   0x00000000

+00C0: 0x00000000   0x00000000   0x00000000   0x00000000

+00D0: 0x00000000   0x00000000   0x00000000   0x00000000

+00E0: 0x00000000   0x00000000   0x00000000   0x00000000

+00F0: 0x00000000   0x00000000   0x00000000   0x00000000

+0100: 0x00000000   0x00000000   0x00000000   0x00000000

+0110: 0x00000000   0x00000000   0x00000000   0x00000000

+0120: 0x00000000   0x00000000   0x00000000   0x00000000

+0130: 0x00000000   0x00000000   0x00000000   0x00000000



--------------------------



Loaded Modules:

samp-server.exe	A: 0x00400000 - 0x00519000	(C:\Documents and Settings\Amministratore\My Documents\Workspace\Eclipse\Shoebill\samp-server.exe)

ntdll.dll	A: 0x7C900000 - 0x7C9B2000	(C:\WINDOWS\system32\ntdll.dll)

kernel32.dll	A: 0x7C800000 - 0x7C8F6000	(C:\WINDOWS\system32\kernel32.dll)

SHELL32.dll	A: 0x7C9C0000 - 0x7D777000	(C:\WINDOWS\system32\SHELL32.dll)

ADVAPI32.dll	A: 0x77DD0000 - 0x77E6B000	(C:\WINDOWS\system32\ADVAPI32.dll)

RPCRT4.dll	A: 0x77E70000 - 0x77F03000	(C:\WINDOWS\system32\RPCRT4.dll)

Secur32.dll	A: 0x77FE0000 - 0x77FF1000	(C:\WINDOWS\system32\Secur32.dll)

GDI32.dll	A: 0x77F10000 - 0x77F59000	(C:\WINDOWS\system32\GDI32.dll)

USER32.dll	A: 0x7E410000 - 0x7E4A1000	(C:\WINDOWS\system32\USER32.dll)

msvcrt.dll	A: 0x77C10000 - 0x77C68000	(C:\WINDOWS\system32\msvcrt.dll)

SHLWAPI.dll	A: 0x77F60000 - 0x77FD6000	(C:\WINDOWS\system32\SHLWAPI.dll)

WSOCK32.dll	A: 0x71AD0000 - 0x71AD9000	(C:\WINDOWS\system32\WSOCK32.dll)

WS2_32.dll	A: 0x71AB0000 - 0x71AC7000	(C:\WINDOWS\system32\WS2_32.dll)

WS2HELP.dll	A: 0x71AA0000 - 0x71AA8000	(C:\WINDOWS\system32\WS2HELP.dll)

WINMM.dll	A: 0x76B40000 - 0x76B6D000	(C:\WINDOWS\system32\WINMM.dll)

IMM32.DLL	A: 0x76390000 - 0x763AD000	(C:\WINDOWS\system32\IMM32.DLL)

LPK.DLL	A: 0x629C0000 - 0x629C9000	(C:\WINDOWS\system32\LPK.DLL)

USP10.dll	A: 0x74D90000 - 0x74DFB000	(C:\WINDOWS\system32\USP10.dll)

comctl32.dll	A: 0x773D0000 - 0x774D3000	(C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\comctl32.dll)

comctl32.dll	A: 0x5D090000 - 0x5D12A000	(C:\WINDOWS\system32\comctl32.dll)

Shoebill.dll	A: 0x10000000 - 0x10090000	(C:\Documents and Settings\Amministratore\My Documents\Workspace\Eclipse\Shoebill\plugins\Shoebill.dll)

jvm.dll	A: 0x70080000 - 0x7069B000	(C:\Program Files\Java\jre1.8.0_77\bin\server\jvm.dll)

VERSION.dll	A: 0x77C00000 - 0x77C08000	(C:\WINDOWS\system32\VERSION.dll)

PSAPI.DLL	A: 0x76BF0000 - 0x76BFB000	(C:\WINDOWS\system32\PSAPI.DLL)

MSVCR100.dll	A: 0x78AA0000 - 0x78B5F000	(C:\Program Files\Java\jre1.8.0_77\bin\server\MSVCR100.dll)

verify.dll	A: 0x00A30000 - 0x00A3C000	(C:\Program Files\Java\jre1.8.0_77\bin\verify.dll)

java.dll	A: 0x6DA30000 - 0x6DA51000	(C:\Program Files\Java\jre1.8.0_77\bin\java.dll)

zip.dll	A: 0x00C00000 - 0x00C13000	(C:\Program Files\Java\jre1.8.0_77\bin\zip.dll)

USERENV.dll	A: 0x769C0000 - 0x76A74000	(C:\WINDOWS\system32\USERENV.dll)
Reply

Hi,

I am currently not home and it is very hard for me to answer you guys. When I am back at home (in about 1 week), I will answer all your questions.

@dusk: I am sorry, I told you that you can add projects in Maven that depend on each other, but that is wrong. You will have to create like an API project and then implement it somewhere else (like Shoebill does).
Reply

Yea, I figured that part out myself. Although my interfaces still defined methods that would require other modules I managed to compile everything.. But man I have a lot of modules! I'm actually building an app that will build everything!
Reply

@dusk, why do you have to separate your app into large amount of modules? Also, if there are modules that are depend on each other, it means they are not separate. I'm not very good at software architecture but that conclusion I made according to my experience.
Reply

@valych I'm not great with architecture either, but I'm quite sure that one project with hundreds of files is not good. First of all, modules increase readability! You're looking for player stuff? Just check the player module and so on. Second, you can easily remove/add parts of your gm(and even do that at runtime with shoebill plugins).

As for them depending on each other, the biggest issue is that my CustomPlayer class has various methods, for example getVehicle which returns an instance of CustomVehicle, but that vehicle class has a method getDriver which returns a CustomPlayer object. A code example:
Код:
// player api module
public interface CustomPlayer {
     CustomVehicle getVehicle(); 
}

// vehicle api module
public interface CustomVehicle {
     CustomPlayer getDriver();
     CustomPlayer[] getPassengers();
}
Reply

@dusk: You will have to make one API that contains everything, not just a specific category. You can make packages for the vehicle classes and Player classes. You can orient yourself by looking at Shoebill-Api and Runtime.
Reply

@dusk: of course, modules help to separate your app logic, but you are making it more painful cause you have to create an intermediate API (as you did).
As work a around, there are packages which you can treat as "modules". E.g. you have to create module for player, vehicle, house and ui (textdraws). So you create a project with com.web-site.mygamemode package. Inside this package you create packages: player, vehicle, house, ui. Then you have your components logically separated. It's obvious, that house component depends on a player, also, player component can depend on house. Same happens for vehicle.
In my opinion, it's much more better structure then create relatively small modules that depend on each other... even though you should bother with their connection.
Anyway, it's your decision I just wanted to express my opinion and (maybe) to help you in some way
Reply

@valych Well as mk124 suggested I got off with only one API. One project with different packages for logic components? I had this layout before and I must say it was a complete mess! You also loose the ability to reload them.

I guess it doesn't really matter as long as it works
Reply

Quote:
Originally Posted by mk124
Посмотреть сообщение
@dusk: Yes, of course, this is possible. You add your dependency to your target projects as usual, and then you need to add a little bit of code. Of course, only one plugin will be loaded at a time, and that means that one of your two plugins will load after your first one, which means that one will lack the required dependency at the onEnable() method. To fix this, you can use the ResourceLoadedEvent. I made a little example for you:

PHP код:
    @Override
    
protected void onEnable() throws Throwable {
        
eventManager getEventManager();
        
//Replace Plugin.class with your target plugin
        
Plugin plugin ResourceManager.get().getPlugin(Plugin.class); //Try to get the instance of the target plugin.
        
if(plugin != nullmyPluginLoaded(plugin); //If the plugin was found, trigger a custom event (not necessarily needed)
        
else { //If the plugin was not found, because this plugin is loaded before, then:
            
EventManagerNode resourceLoadNode eventManager.createChildNode(); //Make a temporary EventManager
            
resourceLoadNode.registerHandler(ResourceLoadEvent.class, -> { //Register the ResourceLoadEvent
                
if(e.getResource().getClass() == Plugin.class) { //If the loaded resource is of type Plugin (<-- change)
                    
myPluginLoaded((Plugine.getResource()); //Trigger callback method (this is not necessarily needed)
                    
resourceLoadNode.destroy(); //Destroy the temporary EventManager because it will not be neaded
                
}
            });
        }
    }
    private 
void myPluginLoaded(Plugin plugin) {
        
//Interact with the loaded event, maybe assign it to a variable.
    

You will need to add this code to both of your plugins (I didn't test this, but it SHOULD work ).
It almost did work. Except that I needed to use ResourceEnableEvent because it seems that ResourceLoadEvent is called before it actually is enabled so my plugin wasn't ready yet.




EDIT: how can getEventManager() return null in onEnable method? This only happens for one of my plugins
Код:
 @Override
    protected void onEnable() throws Throwable {
        Instance.instance = this;
        this.vehicles = new ArrayList<>();
        this.maxSpeeds = new HashMap<>();
        this.random = new Random();
        if(getEventManager() == null)
            logger.error("How can it be null?");
        this.eventManager = getEventManager().createChildNode();
        this.vehicleEngineTimers = new HashMap<>();
        if(Shoebill.get().getResourceManager().getPlugin(DatabasePlugin.class) != null) {
            load();
        } else {
            eventManager.registerHandler(ResourceEnableEvent.class, ee -> {
                if(ee.getResource().getClass().equals(DatabasePlugin.class)) {
                    load();
                }
            });
        }
Код:
2016-04-21 16:40:31,052 ERROR [VehiclePlugin] - How can it be null?
2016-04-21 16:40:31,053 ERROR [err] - java.lang.NullPointerException
2016-04-21 16:40:31,053 ERROR [err] - 	at lt.ltrp.VehiclePlugin.onEnable(VehiclePlugin.java:67)
2016-04-21 16:40:31,053 ERROR [err] - 	at net.gtaun.shoebill.resource.Resource.enable(Resource.java:91)
2016-04-21 16:40:31,054 ERROR [err] - 	at net.gtaun.shoebill.resource.Plugin.enable(Plugin.java:52)
2016-04-21 16:40:31,054 ERROR [err] - 	at net.gtaun.shoebill.resource.ResourceManagerImpl.loadPlugin(ResourceManagerImpl.java:109)
2016-04-21 16:40:31,054 ERROR [err] - 	at net.gtaun.shoebill.resource.ResourceManagerImpl.loadPlugin(ResourceManagerImpl.java:89)
2016-04-21 16:40:31,054 ERROR [err] - 	at net.gtaun.shoebill.resource.ResourceManagerImpl$$Lambda$34/21453518.accept(Unknown Source)
2016-04-21 16:40:31,054 ERROR [err] - 	at java.util.ArrayList.forEach(ArrayList.java:1234)
2016-04-21 16:40:31,055 ERROR [err] - 	at net.gtaun.shoebill.resource.ResourceManagerImpl.loadAllResource(ResourceManagerImpl.java:61)
2016-04-21 16:40:31,055 ERROR [err] - 	at net.gtaun.shoebill.ShoebillImpl.loadPluginsAndGamemode(ShoebillImpl.java:289)
2016-04-21 16:40:31,055 ERROR [err] - 	at net.gtaun.shoebill.ShoebillImpl.access$100(ShoebillImpl.java:47)
2016-04-21 16:40:31,055 ERROR [err] - 	at net.gtaun.shoebill.ShoebillImpl$1.onAmxLoad(ShoebillImpl.java:233)
2016-04-21 16:40:31,055 ERROR [err] - 	at net.gtaun.shoebill.samp.SampCallbackManagerImpl$1.lambda$null$80(SampCallbackManagerImpl.java:60)
2016-04-21 16:40:31,056 ERROR [err] - 	at net.gtaun.shoebill.samp.SampCallbackManagerImpl$1$$Lambda$33/2151717.call(Unknown Source)
2016-04-21 16:40:31,056 ERROR [err] - 	at net.gtaun.shoebill.util.TryUtils.tryTo(TryUtils.java:21)
2016-04-21 16:40:31,056 ERROR [err] - 	at net.gtaun.shoebill.util.TryUtils.tryTo(TryUtils.java:14)
2016-04-21 16:40:31,056 ERROR [err] - 	at net.gtaun.shoebill.samp.SampCallbackManagerImpl$1.lambda$onAmxLoad$81(SampCallbackManagerImpl.java:60)
2016-04-21 16:40:31,057 ERROR [err] - 	at net.gtaun.shoebill.samp.SampCallbackManagerImpl$1$$Lambda$32/32749724.accept(Unknown Source)
2016-04-21 16:40:31,057 ERROR [err] - 	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
2016-04-21 16:40:31,057 ERROR [err] - 	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
2016-04-21 16:40:31,057 ERROR [err] - 	at java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator.forEachRemaining(ConcurrentLinkedQueue.java:851)
2016-04-21 16:40:31,057 ERROR [err] - 	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
2016-04-21 16:40:31,058 ERROR [err] - 	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
2016-04-21 16:40:31,058 ERROR [err] - 	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
2016-04-21 16:40:31,058 ERROR [err] - 	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
2016-04-21 16:40:31,058 ERROR [err] - 	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
2016-04-21 16:40:31,058 ERROR [err] - 	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
2016-04-21 16:40:31,059 ERROR [err] - 	at net.gtaun.shoebill.samp.SampCallbackManagerImpl$1.onAmxLoad(SampCallbackManagerImpl.java:60)
Reply

sorry, please delete
Reply

@dusk: I will take a look at the getEventManager() problem right now.
Reply

Hi, I have a problem with onCancel and onShow in common dialogs.

Consider the following code:
Код:
ListDialog.create()
	.item("asd")
	.onClickOk((thisDialog) -> {
		player.sendMessage("reshowing the dialog");
		thisDialog.show();
	})
	.onShow((thisDialog) -> {
		player.sendMessage("dialog showed");
	})
	.onClose((thisDialog) -> {
		player.sendMessage("dialog hided");
	})
	.build()
	.show(player);
Then you get:
- dialog showed
* player clicks ok *
- dialog showed
- dialog hided

But should be:
- dialog showed
* player clicks anything *
- dialog hided
- dialog showed

My problem, specifically, is that I show some TDs inside onShow (and hide them when closed), so
when I "reshow" the dialog, textdraws are hided but not showed again.

Seeing the code, I think that the problem is on AbstractDialog.java, when you handle the response, onClose(CloseType.RESPONSE) should be called BEFORE onClickOk.
Reply


Forum Jump:


Users browsing this thread: 22 Guest(s)