How to write a feature¶
Features are small parts of a game that gets added to a phase. Features are the modular core of VGL.
You should try to create as many features as possible so that game designers can easily remix them into new games.
A feature consits of multile parts:
General¶
A feature extends AbstractFeature
.
You can access other features (make sure you read about dependencies first) by calling
YourFeature feature = getPhase().getFeature(YourFeature.class);
You can find a list of existing features here or you can look into
the features package
VGL has.
@FeatureInfo¶
The feature info adds some metadata to features, that is used to generate documentation. its fairly straight
forward. Take a look at this example:
@FeatureInfo(name = "NoBlockBreakFeature", author = "MiniDigger", version = "1.0", description = "Small feature that blocks block breaking if active")
Exposed Variables¶
Its always a good idea to expose as many vars as possible. Exposed vars will end up in the game definitions, so that
game designers can easily adjust them if needed.
You have to be careful to what you expose, not every type can be easily serialized! (if you are missing a type, there is currently no way to add a custom type adapter,
create an issue on github and we will look into that)
Lets look back at our NoBlockBreakFeature:
1 2 3 4 | @Expose private Material[] whitelist = new Material[0]; @Expose private Material[] blacklist = new Material[0]; |
Event Handlers¶
There are two types of event handlers in VGL: normal @EventHandler
s and @GameEvent
s.
The @EventHandler
annotation works like in every other bukkit plugin, but you need to make sure that you only handle events, that are related
to the game the feature runs in. You don't want the NoBlockBreakFeature of the SurvivalGames game affect the Bedwars game that is currently running too!
Thats where @GameEvent
comes in. It tries to figure out if the event was caused by a player and only forward it to your method, if the player plays in the game the
feature is attached too. This doesn't work for every event, you might have to do some checks yourself (like check the world name or something like that).
VGL will print a warning when it couldn't resolve a user.
Generally, @GameEvent
works exactly as @EventHandler
:
1 2 3 4 | @GameEvent public void onBlockBreak(BlockBreakEvent event) { // your event code } |
@GameEvent
provides is the ability to easily get a user object from non-vgl events.You just add a second parameter of type
User
to the method:1 2 3 4 | @GameEvent public void onBlockBreak(BlockBreakEvent event, User user) { log.info(user.getRawDisplayName() + " broke a block!"); } |
Dependencies¶
Some features require that other features are active. For example there is a Scoreboard feature, that provides scoreboards for all players.
The map info feature uses that scoreboard and displays some info about the current active map on it.
That mean, the map info feature depends on both the scoreboard feature and the map feature.
To implement that, you just have to override the getDependencies (or getSoftDependencies) method:
1 2 3 4 | @Override public Class[] getDependencies() { return new Class[]{MapFeature.class, ScoreboardFeature.class}; } |
Once you have that, you can easily access the feature like this:
1 2 3 4 | ScoreboardFeature scoreboardFeature = getPhase().getFeature(ScoreboardFeature.class); Scoreboard scoreboard = scoreboardFeature.getScoreboard(); scoreboard.createAndAddLine(ChatColor.YELLOW + "" + ChatColor.BOLD + "Author: "); ..... |
Start/Stop/Tick methods¶
VGL also provides you with some additonal methods you can override:
- void start(): called when the phase this feature is attached to starts
- void stop(): called when the phase this feature is attached to stops
- void tick(): called when the phase this feature is attached to ticks (20 times each second)
- void init(): called when the feature is added to phase