There are two entirely different ways a plugin can interact with SignShop. The plugin can either listen and cancel events generated by SignShop or create and register blocks, messages and events.
Because of that, I will explain both "parts" separately here. And I will try to refer to good code examples in stead of trying to explain how it should be implemented through words.
So first of, the events you can listen to.
SignShop offers the following events:
All of those events can be cancelled so that the result will not be executed. And when generated, the "canbecancelled" flag can be set to false (it's true by default).
When you cancel one of the events, you should tell the player why you're cancelling it. And you should check whether the event can be cancelled by calling "canBeCancelled" before you cancel the event.
The "canbecancelled" flag is only used in very special cases though.
A good example of a SignShop event listener is the PermissionChecker which can be found here.
This shows a class which checks the player's permissions when a shop is being built and during the transaction checks.
So what do all of those events stand, when are they generated and how are they of use to me, you ask.
Generated when a shop is created. In other words, when the player hits the sign with redstone and finalizes the shop setup.
When it's cancelled, the shop will not be registered, so it won't end up in the sellers.yml and it won't turn blue.
A protection plugin could cancel that plugin when a shop is built on ground that is protected.
Generated when any part of a shop is destroyed.
So it gets generated when the sign, any attachable (chest, lever, button, etc.) or a miscblock (Bank sign, Share sign, etc.) is destroyed.
When it's cancelled, the block will not be destroyed. And when you listen to it with an EventPriority of Monitor, you'll get notified whenever a shop is destroyed (if it hasn't been cancelled yet).
You can figure out what part of the shop was destroyed by calling "getReason" on the event object.
This can be used for various reasons. But mostly to protect a shop or clean up any blocks attached to the shop.
Generated when an IExpirable is found to be expired by the internal TimeManager.
A good example of how this can be used is SSHotel which has a RentExpired listener, code can be found here.
You can create a class that is derived from IExpirable and pass an instance to the TimeManager (org.wargamer2010.signshop.timing package).
The TimeManager will then keep track of it, store it in the timing.yml so it's restored on reboot and notify you when it's expired by tossing the SSExpiredEvent.
Generated when a player tries to link a block to a shop.
This can either be during shop setup or when the player attempts to link additional blocks to an existing shop.
In other words, this is thrown when, for example, Player X hits a chest and then hits a valid SignShop sign.
This can be used to prevent players from linking blocks they don't own.
Generated when a money transaction is taking place.
This can either happen when the preconditions are checked for a transaction or when the money is actually taken/given.
So when a player hits a Sell sign, this event is first fired with the "isCheckOnly" flag set to true to make sure the owner has enough money and the player is able to carry more money.
If that is the case, the event is fired twice again but with the "isCheckOnly" flag set to false.
I said twice because it's fired once with TransactionType set to "TakeFromOwner" and once with "GiveToPlayer".
It's generated twice for both the check and the actual transaction so for a Sell shop, the event is fired four times in total.
If there is no listener which sets the "Handled" flag to true (by calling "setHandled" on the event object), the DefaultMoneyTransaction listener will handle it.
That code can be found here.
This event can be used to handle money transactions. The SharedMoneyTransaction class uses this to distribute money across the people denoted on the Share sign.
You could use this to give people diamonds for every piece of meat they buy. Or you could, for example, use this if your plugin is not supported by Vault.
Generated when a player hits the shop and after the prerequisites have been checked.
When this is cancelled, the player will not see the confirm message and the transaction is never executed.
In the Sell shop case, this happens when the player is checked for the items by takeVariablePlayerItems, shop is checked for it's free space by giveShopItems, etc.
By listening to this event you can inject additional checks like checking for permissions, permits, etc.
You can also alter the price by calling "setPrice".
Generated after the transaction has taken place and should generally not be cancelled.
When it is cancelled, the player will not see the transaction message ("You have bought ...").
You can, for instance, use it to give more money to the player, tell the entire server about the transaction or log it somewhere.
Generated when a part of a shop is interacted with (or "being touched").
In other words, this is fired when the lever of a Device shop is switched or the door of a Hotel shop is being opened.
Cancelling this will cancel the interaction and will prevent the lever from being switched or the door from being messed with.
SignShopHotel uses this to prevent people from entering a room they haven't rented yet (code here).
Creating a Custom Shop
Coming soon ...