banner



How To Use Minecraft Plugins

TODOIcon.png

Working on it...

This page is a work in progress, bank check dorsum regularly for more content!

Introduction

This rather large tutorial aims at getting you started with plugin development in Bukkit. It is in no way a consummate tutorial of all possibilities in Bukkit, but rather a general overview of the basics. It starts with making sure yous understand Java, sets upward your workspace in an IDE, and introduces the essentials of most Bukkit plugins.

Videos

Learning Coffee

These tutorials require basic knowledge of the Java programming language. If you are just getting started with Coffee or need a refresher, the following is a non-exhaustive list.

Oracle's Java Tutorials - Official tutorials

Codecademy's Gratis Interactive Courses - Interactive Courses

Other Tutorials

  • Java2s.com - Tutorials
  • Coffee 101 - Tutorials
  • JavaNotes - Free online textbook
  • TheNewBoston - TheNewBoston's video tutorials
  • Derek Banas - Faster paced Video tutorials
  • MOOC.fi - A large course, designed to take about 12 weeks

Setting up an IDE

Before developing a plugin (or learning Java) you will demand to set a development environment. This includes but is non express to installing an IDE (Integrated Evolution Environment). The post-obit tutorial contains instructions for the Eclipse IDE.

For further information, see Setting Upwards Your Workspace

You lot MUST download the Eclipse build for Java developers, Non the one for Java EE developers. The version for Java EE developers does not send Maven support, which is required for this tutorial.

Alternatively, you can employ IntelliJ Thought and follow this tutorial if you prefer JetBrains' IDE instead of Eclipse.

Starting a Plugin Project

Create a Project

Before starting y'all'll need to fix your workspace and files in Eclipse. Kickoff Eclipse, and then create a new Project by selecting File -> New -> Project:

Newproject.png

Now, open up up the Maven folder, and select Maven Project. Click next, and and then tick the Create a uncomplicated projection box on the next page, then click Adjacent: If you lot can't see Maven folder, and so you need to go download the m2eclipse plugin from hither

Newproject2.png

Now, you need to name your group as follows:

  • If you have a domain proper name, the package would be the domain name in contrary.
    • Ex: i-am-a-bukkit-developer.com your package would exist com.i_am_a_bukkit_developer source
    • Avert using a domain yous do not own.
  • No domain? Here are some mutual conventions
    1. Create an business relationship on a source control site such as GitHub or sourceforge
      • For GitHub, follow the instructions here and y'all will have a sub-domain, so your package would be io.github.<username>
    2. Employ your electronic mail. Ex: <username>@gmail.com would be com.gmail.<username>
    3. This is used by many plugin developers. For this, utilise the Java package me.<name>
    4. This is the least preferred method. Just use any unique group naming, again, use this as your concluding resort.

At that place are several things that your group must not begin with and those are:

  • org.bukkit
  • net.bukkit
  • com.bukkit
  • internet.minecraft
  • com.mojang

Once you take the base group name, you will want to stop it off with the plugin name. Lets use the GitHub Pages example for this. If you are creating a plugin called TestPlugin your full group name would be io.github.<username>, and your artifact proper noun would exist TestPlugin. For the version, simply stick with the default for now. It tin can be changed later.

Finish the wizard:

Newproject3.png

If this is your beginning time using Eclipse, close the Welcome tab by clicking the "Ten" next to the Welcome tab on the tab bar. Now, you should have a window that looks like this:

Eclipsemain.png

Click the arrow to the left of your antiquity name, and let's become started!

Reference the Bukkit API

Before you begin developing your plugin you lot will need to add the Bukkit API library to your projection as a dependency, you lot can also add any other API'south you may want to use.

Double-click pom.xml, which is at the lesser of your project's binder. Click the pom.xml tab at the lesser, and you should run across something similar this:

Pomeditor.png

If you wish to use Java half-dozen+ linguistic communication features, you must specify the Java version that the project should be congenital on. Copy and paste this (specifies that the project should be congenital under Coffee 7) earlier </project>:

              <build>       <plugins>           <plugin>               <groupId>org.apache.maven.plugins</groupId>               <artifactId>maven-compiler-plugin</artifactId>               <configuration>                   <source>one.7</source>                   <target>ane.7</target>               </configuration>           </plugin>       </plugins>    </build>            

You may utilise other levels, such as one.viii for Java 8 or 11 for Java 11. Delight note that according to BStats, a sizeable number of servers run Java viii (~64% every bit of April 2021), then compiling for Coffee 11 volition result in many server owners being unable to run your plugin. If you do employ Java 1.8 or 11 features, Eclipse volition advise changing the linguistic communication level when you lot hover over the code "error". Do so.

Before the </project> at the bottom, re-create and paste this block (it tells Eclipse where Bukkit'due south repository is located):

              <repositories>        <repository>          <id>spigot-repo</id>          <url>https://hub.spigotmc.org/nexus/content/repositories/public/</url>        </repository>    </repositories>            

The spigot repository is the only working repository as the old repository "bukkit-repo" (http://repo.bukkit.org/content/groups/public/) is downward.

Next, earlier the </project> at the bottom, copy and paste this block (information technology tells Eclipse that nosotros're building against Bukkit):

              <dependencies>        <dependency>            <groupId>org.spigotmc</groupId>            <artifactId>spigot-api</artifactId>            <version>one.16.v-R0.1-SNAPSHOT</version><!--modify this value depending on the version or use LATEST-->            <type>jar</blazon>            <scope>provided</telescopic>        </dependency>    </dependencies>            

Previously you needed build against bukkit, however bukkit artifacts are no longer distributed at spigot with 1.xvi.

If yous wish to, you may modify the version of Bukkit you're building against. You tin can view the bachelor versions here.

When you terminate, your pom.xml should look similar to this:

Finishedpom.png

Save your pom.xml using File -> Save or pressing Cmd + S. It will take a few minutes to download the dependencies and build the workspace. And then, right click the projects title and click Maven -> Update Project.

Bukkit Javadocs

If you lot accept some feel with Eclipse and Java yous will know that when you hover your mouse over any built in class or method a yellow box will pop upwards, containing the documentation for that grade or method. This is known equally a Javadoc and can likewise be accessed online at the Oracle website. Bukkit likewise has documentation which often contains useful descriptions of each method and class provided by the API, which is available here (Beta Javadocs tin exist found here, and development build Javadocs hither). In order to have this information available within Eclipse, so that information technology will pop up whenever you hover over a Bukkit method or class, kickoff right click on the Bukkit jar where it appears under "Maven Dependencies" in the projection explorer, and select "Backdrop". Choose the Javadoc Location item on the left of the window that pops up, and paste the url https://hub.spigotmc.org/javadocs/spigot/ (or that of the beta/development Javadocs linked above) into the textbox under "Javadoc URL". It should look like this (with the new url):

Bukkitjavadocs.png

Click "Validate", and then click "OK". Done! Now the Bukkit Javadocs are linked to the Bukkit source, and you can access helpful documentation from within Eclipse.

Creating a package

Now you need to create a 'parcel' which will shop all the Java form files nosotros will be using. Correct click on the folder labelled src/primary/java and select New > Package:

Newpackage.png

For your package name, put your group name, and so a period, so your antiquity proper noun in lowercase. For example, if your group name is io.github.name and your antiquity name is TestPlugin, your package name would be io.github.name.testplugin.

Creating the Plugin's Class

Now that we accept our projection prepare up we can outset to add class files and brainstorm making our plugin. The plugin's chief class is the class that extends JavaPlugin. There should simply ever be i class in your plugin that extends JavaPlugin either directly or indirectly. Information technology'due south always good do to create your master class first and requite information technology the same proper name as your plugin. Correct click on the bundle yous created before, and select New > Class. You should have a new form similar to the post-obit

                            package              {$              GroupName              }.{              $ArtifactName              };              import              org.bukkit.plugin.java.JavaPlugin              ;              public              terminal              form              {              $ArtifactName              }              extends              JavaPlugin              {              }            
Warning Warning: Plugins should never invoke their constructors and create new instances

Creating plugin.yml

Now you have setup the projection and the primary class. To allow Bukkit to load your plugin, you must create the plugin.yml file. This file will contain essential data, and without it your plugin will Non work. This time nosotros want to right click on src/main/resources (Warning: Sometimes having your plugin.yml here could crusade errors when you try to run your plugin, if this is the example try placing the plugin.yml directly in the project folder and not inside any src or other folders. This depends on your IDE and surround.). Select New > File. (If you don't see File as an option, select Other > General > File.) Proper noun the file "plugin.yml" and click finish. Eclipse will open your currently blank plugin.yml file in the default text editor. A window may open up letting you lot know editors are available on the Market place. Installing 1 is unnecessary, since .yml files are uncomplicated text files. (Hint: If you want to keep your workspace organized, close the text editor and drag the plugin.yml file onto the master workspace(To the right) and yous volition be able to edit the file inside Eclipse.)

At that place are three essential attributes that must be declared in the plugin.yml.

proper name: the simple name of your plugin.
main: fully qualified name of the plugin'southward main class.
version: the version string of your plugin.

The most simple plugin.yml file would look like this :

                            name              :              {              $PluginName              }              main              :              {              $PackageName              }              .{$MainClass}              version              :              {              $VersionNumber              }            
Lightbulb.png Note: The parcel name for plugins often includes the plugin proper noun so don't be surprised to see <pluginname>.<pluginname> at the end of the 2d line!
Lightbulb.png Annotation: Your main class may or may not be the name of your plugin depending on what you named information technology earlier, proceed in mind this is instance-sensitive.

For more examples, meet #Example_Files_and_Templates

At this bespeak your plugin can be loaded by Bukkit, and will be accompanied with log entries indicating this. Just, it will practice nothing!

onEnable() and onDisable()

These methods are called whenever the plugin is enabled and disabled. By default your plugin will automatically enable itself when loaded so you can register your events and provide some debug output hither. onEnable() is invoked when the plugin is enabled, and should contain logic to prepare your plugin when it is enabled. onDisable() is invoked when a plugin is disabled, and should contain logic to make clean upwardly your plugin and associated land. Additionally plugins tin override the onLoad() method to perform additional logic when the plugin loads.

Introduction to onEnable() and onDisable()

Create the methods onEnable() and onDisable() within the main course created in the previous section. It will expect something similar the following

                            bundle              {$              TopLevelDomain              }.{              $Domain              }.{              $PluginName              };              import              org.bukkit.plugin.java.JavaPlugin              ;              public              final              class              {              $PluginName              }              extends              JavaPlugin              {              @Override              public              void              onEnable              ()              {              // TODO Insert logic to be performed when the plugin is enabled              }              @Override              public              void              onDisable              ()              {              // TODO Insert logic to be performed when the plugin is disabled              }              }            

The methods at present exist, but they don't do anything yet. Note: In that location is no reason to print a message such as "{$PluginName} has been enabled!" as bukkit volition practise this automatically. For more information about events, click here.

Logging a message

A plugin can print a message to the console and the server log. It can achieve this by invoking the correct method from the plugin'south logger. First we must invoke the getLogger() method to retrieve the logger acquaintance with this plugin. Then nosotros can start logging.

We will write to the log when onEnable() method is chosen. We can do that by inserting the following line into the onEnable() method.

                            getLogger              ().              info              (              "onEnable has been invoked!"              );            

You tin can then do the same inside onDisable() , making sure to change the message.

Your main course should now look something similar this:

                            package              {$              TopLevelDomain              }.{              $Domain              }.{              $PluginName              };              import              org.bukkit.plugin.coffee.JavaPlugin              ;              public              last              course              {              $PluginName              }              extends              JavaPlugin              {              @Override              public              void              onEnable              ()              {              getLogger              ().              info              (              "onEnable has been invoked!"              );              }              @Override              public              void              onDisable              ()              {              getLogger              ().              info              (              "onDisable has been invoked!"              );              }              }            

Treatment Reloads

It is of import to remember that this does not just occur on server shutdown and startup, your plugin can as well exist disabled and enabled by other plugins or through employ of the /reload command while the server is running. Assuming that the server has but just been started when the plugin is enabled is therefore a unsafe assumption, as there may well already exist players online, additional worlds loaded, additional chunks loaded, and many other unexpected differences.

For instance:

  • You have a plugin that stores information near a player in a HashMap on the PlayerJoinEvent
  • You rely on having that information available for every player
  • An operator uses the /reload command
  • Your plugin is disabled and all information stored is lost
  • Your plugin is enabled again with several players already online
  • These players practice not have any information stored for them in the HashMap
  • You try to call up information about them but there is none!

For this to work correctly on reload, you would demand to notice all players currently online during onEnable and store the correct information for that player in the HashMap.

                            for              (              Actor              player              :              Bukkit              .              getServer              ().              getOnlinePlayers              ())              {              playerList              .              put              (              player              .              getName              (),              playerData              (              role player              ));              }            

Listeners

Listeners are classes whose methods are invoked in response to an event. All listeners implement org.bukkit.effect.Listener. For further details most creating listeners,

Please Run across: Effect API Reference

Commands

The onCommand() Method

So, you now know how to register events and do something when they happen, merely what if you but want something to happen when a control is typed? You use onCommand . This lawmaking is run whenever a player types a command preceded by the "/" character. East.one thousand. typing "/exercise something" would call the onCommand method. In this case goose egg would happen because no behavior has been programmed.

Avert using command names that are the same equally those that come with Bukkit, and also consider carefully how unique your commands names volition be. E.g. the "give" command is already used past several plugins, and if you implement yet some other "give" command, your plugin will become incompatible with those other plugins. You must register your commands in the plugin'south plugin.yml or they will not trigger this method.

The onCommand method must always render a boolean value - either true or simulated. If the value returned is true and then you won't see any noticeable events. However if it returns simulated then the plugin will revert to your plugin files' 'usage: property' and brandish a message to the user showing them how to use the command as specified in the plugin.yml file.

When using onCommand , you should always register iv parameters.

  • CommandSender sender - who sent the control
  • Command cmd - the control that was executed
  • String commandLabel - the command alias that was used
  • String[] args - an array of additional arguments, east.g. typing /how-do-you-do abc def would put abc in args[0], and def in args[1]

Setting upwardly the control

                            @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Command              cmd              ,              String              characterization              ,              Cord              []              args              )              {              if              (              cmd              .              getName              ().              equalsIgnoreCase              (              "bones"              ))              {              // If the player typed /basic then do the following, annotation: If you only registered this executor for one control, you lot don't need this              // doSomething              return              true              ;              }              //If this has happened the function will render true.                            // If this hasn't happened the value of false will be returned.              return              false              ;              }            

When coding the onCommand role it is always good practise to return false at the very end of the function. Returning false will display the usage dialog set in plugin.yml (see beneath). This mode if anything goes wrong the help message volition be displayed. When returning a value the function will exit so if you render true any lawmaking underneath won't be run, unless a return statement is nested in an if statement or similar.

The .equalsIgnoreCase("basic") just ways that it won't distinguish betwixt upper and lower case characters. For example, the string "Basic" and "BasiC" would both equal basic and the lawmaking would be executed.

Printing Cmd-Shift-O (Organize Imports), importing org.bukkit.command.Command , not org.bukkit.material.Command (this is the control block), or add together these 2 lines at the top of your file:

                            import              org.bukkit.command.Command              ;              import              org.bukkit.command.CommandSender              ;            

Adding your Control to the Plugin.yml

You will besides need to add the command to your plugin.yml file. Add the following to the stop of plugin.yml:

                                name                :                Basic                primary                :                <main packet>.<principal class>                version                :                ane.0                author                :                <your IGN or name>                commands                :                basic                :                description                :                This is a demo command.                usage                :                /<control> [player]                permission                :                <plugin proper name>.basic                permission-message                :                Y'all don't accept <permission>              
  • bones - the name of the command.
  • clarification - the clarification of the command .
  • usage - the aid dialog that users will see when you render simulated in the onCommand method. Write clearly, so that others can discern what the command is and how to employ it.
  • permission - This is used by some assist plugins to work out which commands to bear witness to the user.
  • permission-bulletin - This is output when the player attempts but does non have permission to use the command.

Notation that yml files employ 2 spaces for tabs, as the tab character will crusade issues.

Panel Commands vs. Histrion Commands

You may have noticed the CommandSender sender parameter above. CommandSender is a Bukkit interface which has 2 useful (for plugin writers) subclasses: Player and ConsoleCommandSender . (There are likewise other subclasses that are less common such as BlockCommandSender )

When you're writing your plugin, it'southward a very skilful idea to ensure that commands that can be run from the console actually work, and that commands that should only be run as a logged-in player actually are only run as a logged-in player. Some plugins only return if the sender is not a actor (i.e. someone tried to employ the plugin'due south commands from the console), even when those commands brand perfect sense from the console (e.m. irresolute the weather on the server).

I way to do this is:

                            @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Command              cmd              ,              String              label              ,              String              []              args              )              {              if              (              cmd              .              getName              ().              equalsIgnoreCase              (              "basic"              ))              {              // If the actor typed /basic and so exercise the following...              // do something...              render              true              ;              }              else              if              (              cmd              .              getName              ().              equalsIgnoreCase              (              "basic2"              ))              {              if              (              !              (              sender              instanceof              Thespian              ))              {              sender              .              sendMessage              (              "This command can simply be run by a player."              );              }              else              {              Thespian              player              =              (              Player              )              sender              ;              // exercise something              }              render              truthful              ;              }              return              false              ;              }            

In this case, the command bones can be run by anyone - a logged-in player, or the server operator on the console. Just the command basic2 can just exist run past logged-in players.

In general, you should allow as many commands equally possible to work on both the console and for players. Commands that need a logged-in thespian can utilise the machinery in the instance higher up to bank check that the CommandSender is actually a player before continuing. Such commands would generally depend on some attribute of the player, e.g. a teleportation command needs a player to teleport, an item giving command needs a histrion to give the detail to...

If you want to become more than advanced, yous could do some extra checks on your command arguments then that eastward.g. a teleportation command could be used from the console if and simply if a player'southward name is as well supplied.

Using a split up CommandExecutor class

The examples in a higher place simply put the onCommand() method into the plugin's chief class. For small plugins, this is fine, but if y'all're writing something more extensive, it may make sense to put your onCommand() method into its own grade. Fortunately, this isn't as well hard:

  • Create a new class inside your plugin'due south package. Call information technology something similar MyPluginCommandExecutor (although of class replacing MyPlugin with your plugin's actual name). That form must implement the Bukkit CommandExecutor interface.
  • In your plugin's onEnable() method, you lot need to create an example of your new command executor class, and then make a call like getCommand("basic").setExecutor(myExecutor);, where "basic" is the command we desire to handle, and myExecutor is the instance nosotros created.

All-time explained by case:

MyPlugin.java (the main plugin class):

                            @Override              public              void              onEnable              ()              {              // This will throw a NullPointerException if you lot don't accept the control defined in your plugin.yml file!              this              .              getCommand              (              "basic"              ).              setExecutor              (              new              MyPluginCommandExecutor              (              this              ));              }            

MyPluginCommandExecutor.java:

                            public              course              MyPluginCommandExecutor              implements              CommandExecutor              {              private              final              MyPlugin              plugin              ;              public              MyPluginCommandExecutor              (              MyPlugin              plugin              )              {              this              .              plugin              =              plugin              ;              // Store the plugin in situations where yous need it.              }              @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Command              cmd              ,              Cord              characterization              ,              String              []              args              )              {              // implementation exactly as before...              }              }            

Notice how nosotros ship a reference of the main plugin object to MyPluginCommandExecutor. This allows us piece of cake access to the master plugin objects'south methods if nosotros need to.

By doing this, we can meliorate organise our code - if the main onCommand() method is large and complex, information technology can be split into submethods without cluttering up the plugin'southward primary course.

Notation that if your plugin has multiple commands, you will demand set the command executor for each command individually.

Writing a safe onCommand

When writing an onCommand, it's of import that you don't presume any information, such as the sender being a Player. Things to go along in mind:

Make sure the sender is a Player before casting

Using unproblematic code similar this makes it possible:

                            @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Command              cmd              ,              String              label              ,              String              []              args              )              {              if              (              sender              instanceof              Player              )              {              Player              player              =              (              Player              )              sender              ;              // exercise something              }              else              {              sender              .              sendMessage              (              "You lot must be a player!"              );              render              false              ;              }              // do something              return              simulated              ;              }            

Cheque the arguments length

Don't always presume the sender typed the correct amount of arguments.

                            @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Command              cmd              ,              String              label              ,              String              []              args              )              {              if              (              args              .              length              >              4              )              {              sender              .              sendMessage              (              "Too many arguments!"              );              return              false              ;              }              if              (              args              .              length              <              2              )              {              sender              .              sendMessage              (              "Not plenty arguments!"              );              return              false              ;              }              }            

Check if a Player is online before getting them

Sometimes you lot want to get another player past the name entered by the player. Always make certain the actor is online!

                            @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Control              cmd              ,              Cord              label              ,              String              []              args              )              {              Player              target              =              (              Bukkit              .              getServer              ().              getPlayer              (              args              [              0              ]              ));              if              (              target              ==              null              )              {              sender              .              sendMessage              (              args              [              0              ]              +              " is non online!"              );              render              false              ;              }              return              false              ;              }            

If yous need to change a Player currently non online, the OfflinePlayer grade provides basic manipulation methods.

Plugin Configuration/Settings

The Bukkit API provides a convenient way for plugins to manage user configurable settings. Additionally information technology also serves as an piece of cake manner to store data.

Please see: Configuration API Reference

Permissions

If yous are looking for how to Develop a permissions plugin, refer to http://wiki.bukkit.org/Developing_a_permissions_plugin

With the new Bukkit API for permissions, they couldn't be easier. To find out if a thespian has a particular permission use the post-obit:

                            if              (              player              .              hasPermission              (              "some.pointless.permission"              ))              {              //Do something              }              else              {              //Do something else              }            

You can as well find if a permission has been set or not (equivalent to Java'southward null) with the following office:

                            boolean              isPermissionSet              (              String              proper name              )            

You may exist wondering why there aren't any groups. The answer to that is because they aren't really needed. Previously one of the main uses for groups was to format conversation letters. That nevertheless can be done just as easily with permissions. Within your chat plugin'southward config you would ascertain associations between permissions and prefixes. For example the permission "someChat.prefix.admin" would correspond to the prefix [Admin]. Whenever a player speaks with that permission their name will be prefixed with [Admin].

Another common usage might be to send a message to all users inside a grouping. Again notwithstanding this can be done with permissions with the following:

                            for              (              Player              player              :              Bukkit              .              getServer              ().              getOnlinePlayers              ())              {              if              (              histrion              .              hasPermission              (              "send.receive.message"              ))              {              role player              .              sendMessage              (              "You were sent a message"              );              }              }            

Finally you may be asking, well how practise I set and organise player's permissions if there are no groups? Although the bukkit API doesn't provide groups itself, you must install a permission provider plugin such every bit permissionsBukkit to manage the groups for you. This API provides the interface, not the implementation.

Configuring your permissions

If you desire more than control over your permissions, for example default values or children then you should consider adding them to your plugin.yml. This is completely optional, even so it is advised. Below is an case permissions config that would exist appended to the end of your existing plugin.yml:

                                permissions                :                doorman.*                :                clarification                :                Gives access to all doorman commands                children                :                doorman.kick                :                truthful                doorman.ban                :                true                doorman.knock                :                true                doorman.denied                :                false                doorman.boot                :                description                :                Allows you to boot a user                default                :                op                doorman.ban                :                description                :                Allows you to ban a user                default                :                op                doorman.knock                :                description                :                Knocks on the door!                default                :                true                doorman.denied                :                description                :                Prevents this user from entering the door              

Firstly, each permission your plugin uses is defined as a child node of the permissions node. Each permission can then optionally have a clarification, a default value, and children.

Defaults

By default when a permission isn't divers for a playerhasPermission volition return false. Inside your plugin.yml yous can change this by setting the default node to be ane of iv values:

  • truthful - The permission will be truthful by default.
  • false - The permission volition past simulated by default.
  • op - If the player is an op then this will be true.
  • not op - If the thespian is not an op then this will be true.

Children

Before now you volition probably exist used to the * permission to automatically assign all sub permissions. This has changed with the bukkit API and you tin now define the child permissions. This allows for a lot more than flexibility. Below is an example of how you exercise this:

                            permissions              :              doorman.*              :              description              :              Gives access to all doorman commands              children              :              doorman.kick              :              true              doorman.ban              :              true              doorman.knock              :              true              doorman.denied              :              false            

Here the doorman.* permission has several child permissions assigned to it. The way child permissions work is when doorman.* is set to true, the child permissions are set to their values defined in the plugin.yml. If however doorman.* was fix to false and then all child permissions would exist inverted.

Setting your own permissions

If yous wish to know about developing your own permissions plugins (Ones that actually set permissions) and so check out the tutorial on Developing a permissions plugin.

Scheduling Tasks and Background Tasks

Currently, Minecraft servers operate most all of the game logic in i thread, so each private task that happens in the game needs to be kept very brusque. A complicated piece of code in your plugin has the potential to cause huge delays and lag spikes to the game logic, if not handled properly.

Luckily, Bukkit has support for scheduling code in your plugin. Yous tin can submit a Runnable task to occur one time in the time to come, or on a recurring basis, or you tin spin off a whole new independent thread that can perform lengthy tasks in parallel with the game logic.

In that location is a separate Scheduler Programming tutorial which introduces the Scheduler, and gives more information on using it to schedule synchronous tasks, and on kicking off asynchronous tasks in Bukkit.

Block Manipulation

The easiest fashion to create blocks is to go an existing block and modify it. For example, if you want to alter the cake that is located five blocks above y'all, you lot would starting time take to go your electric current location, add five to your electric current y-coordinate, and then alter it. For instance:

                            @EventHandler              public              void              onPlayerMove              (              PlayerMoveEvent              event              )              {              // Get the player'due south location.              Location              loc              =              event              .              getPlayer              ().              getLocation              ();              // Sets loc to five above where it used to be. Note that this doesn't change the histrion'southward position.              loc              .              setY              (              loc              .              getY              ()              +              v              );              // Gets the cake at the new location.              Cake              b              =              loc              .              getBlock              ();              // Sets the block to type id 1 (rock).              b              .              setType              (              Material              .              STONE              );              }            

The to a higher place code gets the actor's location, gets the block 5 blocks in a higher place the player, and sets it to stone. Note that once you accept a Block, there are other things you lot tin can do besides set up its type. Consult the JavaDocs for more information.

You can use a similar concept to generate buildings and individual blocks programmatically through the employ of algorithms. For example, to generate a solid cube, you could use nested for loops to loop over an unabridged cube and make full it in.

                            public              void              generateCube              (              Location              loc              ,              int              length              )              {              // Set i corner of the cube to the given location.              // Uses getBlockN() instead of getN() to avoid casting to an int later.              int              x1              =              loc              .              getBlockX              ();              int              y1              =              loc              .              getBlockY              ();              int              z1              =              loc              .              getBlockZ              ();              // Figure out the reverse corner of the cube by taking the corner and calculation length to all coordinates.              int              x2              =              x1              +              length              ;              int              y2              =              y1              +              length              ;              int              z2              =              z1              +              length              ;              World              world              =              loc              .              getWorld              ();              // Loop over the cube in the x dimension.              for              (              int              xPoint              =              x1              ;              xPoint              <=              x2              ;              xPoint              ++              )              {              // Loop over the cube in the y dimension.              for              (              int              yPoint              =              y1              ;              yPoint              <=              y2              ;              yPoint              ++              )              {              // Loop over the cube in the z dimension.              for              (              int              zPoint              =              z1              ;              zPoint              <=              z2              ;              zPoint              ++              )              {              // Get the block that nosotros are currently looping over.              Block              currentBlock              =              earth              .              getBlockAt              (              xPoint              ,              yPoint              ,              zPoint              );              // Set the cake to type 57 (Diamond block!)              currentBlock              .              setType              (              Fabric              .              DIAMOND_BLOCK              );              }              }              }              }            

This method will construct a 3D cube or cuboid with the given length and starting point. As for deleting blocks just follow the same method for creating them but set the ID to 0 (air).

(Player) Inventory Manipulation

This section by and large covers thespian inventory manipulation, but the same applies to chest inventory manipulation as well if you discover out how to get a chest's inventory :P. Here is a simple example of inventory manipulation:

                            @EventHandler              public              void              onPlayerJoin              (              PlayerJoinEvent              evt              )              {              Role player              thespian              =              evt              .              getPlayer              ();              // The player who joined              PlayerInventory              inventory              =              thespian              .              getInventory              ();              // The histrion's inventory              ItemStack              itemstack              =              new              ItemStack              (              Material              .              DIAMOND              ,              64              );              // A stack of diamonds              if              (              inventory              .              contains              (              itemstack              ))              {              inventory              .              addItem              (              itemstack              );              // Adds a stack of diamonds to the thespian's inventory              player              .              sendMessage              (              "Welcome! Y'all seem to be reeeally rich, so we gave y'all some more diamonds!"              );              }              }            

So inside onPlayerJoin we first make a few variables to brand our job easier: player, inventory and itemstack. Inventory is the role player's inventory and itemstack is a ItemStack that has 64 diamonds. After that we check if the actor's inventory contains a stack of diamonds. If the actor has a stack of diamonds, we give him/her some other stack with inventory.addItem(itemstack) and send a bulletin. So inventory manipulation isn't really that hard, if we wanted we could remove the stack of diamonds by simply replacing inventory.addItem(itemstack) with inventory.remove(itemstack) and modify the bulletin a piffling flake. Hopefully this helped!

Particular Manipulation

When dealing with items in the code, y'all apply the ItemStack course for looking up and setting all information on that stack.

Enchantments

To enchant an particular you must first know the Bukkit enchantments. If you want to enchant items that tin can't exist enchanted within normal SMP, use addUnsafeEnchantment() instead of addEnchantment()

For example, to give Sharpness one to a stone sword:

                        ItemStack            myItem            =            new            ItemStack            (            Cloth            .            STONE_SWORD            );            //new particular of item code            myItem            .            addEnchantment            (            Enchantment            .            DAMAGE_ALL            ,            i            );            //enchant the item          

ItemMeta

You can set the display name of an particular by doing this.

                        Cord            myDisplayName            =            "Crawly Sword"            ;            //apply the displayname you desire here            ItemStack            myItem            =            new            ItemStack            (            Fabric            .            DIAMOND_SWORD            );            //your detail            ItemMeta            im            =            myItem            .            getItemMeta            ();            //go the itemmeta of the item            im            .            setDisplayName            (            myDisplayName            );            //set up the displayname            myItem            .            setItemMeta            (            im            );            //requite the particular the new itemmeta          

You tin can also set the lores of an item. The lores are the modest annotations on an item, similar "+5 attack impairment" on a stone sword.

                        List            <            String            >            lores            =            new            ArrayList            <            Cord            >            ();            lores            .            add            (            "Example lore"            );            lores            .            add            (            "this one comes on line 2"            );            ItemStack            myItem            =            new            ItemStack            (            Material            .            DIAMOND_SWORD            );            //your item            ItemMeta            im            =            myItem            .            getItemMeta            ();            //get the itemmeta of the item again            im            .            setLore            (            lores            );            //add the lores of course            myItem            .            setItemMeta            (            im            );            //give the particular the new itemmeta          

Metadata

Bukkit is trying to make plugin evolution every bit easy as possible, so HashMaps with key of type Player, Entity, World or even a Block were replaced by Metadata. Metadata is some kind of alternative to HashMap. It allows y'all to add custom "fields" to Players, Entities, Worlds and Blocks. These things are all members of Metadatable course(check [1])It works very simply. Everything that is Metadatable holds its ain HashMap of Metadata which you take admission to. That means, for example, if you're creating an economic system plugin, you would need a HashMap of Player and Bladder or Double. With Metadata, you don't have to! Y'all just attach to player new metadata value, and that's it!

Why to use Metadata

  • Metadata is all handled past Bukkit, which makes it a very good alternative to HashMaps.
  • Metadata can be used to share data between plugins.

Why not utilise Metadata

  • Slightly more difficult to get the value.
  • It is not saved on shutdown (but then over again, neither are any Maps that you create).

Getting & Setting Metadata

                        public            void            setMetadata            (            Metadatable            object            ,            String            key            ,            Object            value            ,            Plugin            plugin            )            {            object            .            setMetadata            (            key            ,            new            FixedMetadataValue            (            plugin            ,            value            ));            }            public            Object            getMetadata            (            Metadatable            object            ,            String            cardinal            ,            Plugin            plugin            )            {            List            <            MetadataValue            >            values            =            object            .            getMetadata            (            cardinal            );            for            (            MetadataValue            value            :            values            )            {            // Plugins are singleton objects, so using == is safe here            if            (            value            .            getOwningPlugin            ()            ==            plugin            )            {            return            value            .            value            ();            }            }            return            goose egg            ;            }          

Note: If yous're manipulating with numbers, booleans or strings, use convenient method to get the upshot. For example, y'all tin use asInt(), asString() or asBoolean() instead of value to find out the value.

Databases

Sometimes flat files aren't enough for what your looking to practise, this is where databases come in. The virtually common database engines available on Linux/Mac/Windows machines typically run on some flavor of SQL (Structured Query Language).

Software offering SQL permit you to create databases with columns and header to identify to contents of each cell. Think of it as a spreadsheet on steroids, where every cavalcade you prepare in your database can enforce rules to ensure integrity. Apart from being more than organised than a simple custom data file, SQL provides faster access and better searching than flat files.

The SQL standard helps applications like Bukkit implement database storage for their data in a consistent way. Unfortunately, there'southward more than i SQL-ready database engine, and each has minor differences in how to configure and use it. Which one yous choose may depend on your particular needs. (Some plugins even offer configurable options to connect to multiple database engines!)

SQLite

Alta189 has written a fantastic SQLite tutorial which I suggest you sentinel if you're interested in using SQL in your plugins, included with the tutorials is a handy library you tin can download and import to make using SQL easier. Once you have watched these video tutorials I would advise you lot go and learn some SQL syntax, information technology's very straightforward and shouldn't take you long to pick up. SQL Tutorials @W3Schools and @1Keydata.

SQLite is cracking for very simple databases, considering there's no server concerns to set up up. Just brand a few calls to create a new database and table. Information technology's easy to back up: but re-create the whole database file in one go. SQLite is a little bit weaker at data integrity, flexibility in data types, and it may not be something you would want to trust for huge databases of millions of rows. But for a new plugin in evolution, it's frequently easiest and fastest to get the SQL basics squared away with SQLite, even if y'all "graduate" to a more server-course database engine subsequently.

MySQL

Another popular SQL database engine is chosen MySQL. Information technology is closer to server-grade than SQLite, where many pop companies or websites depend on it for millions of webpage hits every day. With that security comes a footling bit steeper learning-curve, considering MySQL has more tunable parameters and capabilities.

The coding for plugins accessing MySQL is by and large the same equally tiny SQLite or mega-sized Oracle, with merely small differences in syntax here or there. Merely the administration has room to grow. You may want to set up accounts and privileges within your MySQL setup. You may want to set up upwards SQL scripts that organize your backups and rollback to previous states.

Deploying your Plugin

Once you accept written your plugin, how practice you get it from a collection of source files into a working jar file that tin be installed on a server? First, set up a CraftBukkit server on your local machine. To practice this, visit the wiki page on Setting up a server. Next y'all take to consign your plugin to a .jar so that y'all can run it on your new server. To do this in Eclipse, right-click the projection and click Run every bit > Maven install:

Maveninstall.png

In the time to come, when yous make code changes to your plugin, you want to delete the previous JAR past right-clicking the project and clicking Run as > Maven clean before doing the above. If you're having issues when edifice your plugin, bank check if your Java Evolution Kit (JDK) is properly installed and review Setting Up Your Workspace. You may need to configure your JDK manually if you run into a JDK-related error in the console, as Eclipse may not take detected it correctly. Get to Window -> Preferences, and get to Java -> Installed JREs. Add the latest JDK you've installed as a JRE, tick that 1, and untick the agile ane that was giving y'all issues:

Jrelocation.png

If your project built successfully, the JAR file is at present nether the target binder in your project'due south binder nether your Eclipse workspace. The JAR file you have exported should now exist a working plugin! Assuming of course that in that location are no errors in your code or your plugin.yml file. You can now drop the jar file yous have exported into your Bukkit server's "plugins" folder, reload or relaunch the server, and exam away! In order to connect to a server running locally on your calculator, merely put "localhost" as the IP address of the server in Minecraft multiplayer. If you run across errors that y'all tin't solve for yourself, try visiting the plugin development forum, asking in the bukkitdev IRC channel, or re-reading this wiki. Once yous accept a useful working plugin, consider submitting your project to dev.bukkit for consumption by the Bukkit community. From the magician above, you can come across that the JAR file will be by default a compressed archive (JARs are based on the ZIP archive format). As such, it does not brand sense to put your JAR into a ZIP annal when uploading to BukkitDev and will only increase the file size. Farther, config files can be placed within the JAR and copied into the plugin'south data folder if the configuration file does not exist. At that place is usually no good reason for packaging JAR files into another archive.

Importing other plugins

You lot may wish to edit some other plugin that has the source available. If that plugin has a pom.xml in its folder (nearly of the popular ones, for example WorldEdit and Essentials, do), y'all can import it as a projection by selecting File -> Import, and then opening the Maven folder and selecting Existing Maven Projects:

Importmaven.png

So select the folder that the pom.xml is in, and the projection should be on your sidebar. Edit information technology and compile information technology like you ordinarily would.

Tips and Tricks

Setting a Player on Fire

The Bukkit API is capable of a lot of cool stuff. Hither are some lawmaking snippets for some nice furnishings!

The following code allows a player to prepare some other player on burn down. Running a command similar /ignite Notch would cause Notch to be set on fire!

                        @Override            public            boolean            onCommand            (            CommandSender            sender            ,            Command            cmd            ,            Cord            characterization            ,            String            []            args            )            {            // Uses equalsIgnoreCase() over equals() to take "ignite" and "IgNiTe."            if            (            cmd            .            getName            ().            equalsIgnoreCase            (            "ignite"            ))            {            // Make sure that the player specified exactly one argument (the name of the histrion to ignite).            if            (            args            .            length            !=            i            )            {            // When onCommand() returns simulated, the help bulletin associated with that command is displayed.            return            simulated            ;            }            // Make sure the sender is a player.            if            (            !            (            sender            instanceof            Player            ))            {            sender            .            sendMessage            (            "Only players tin gear up other players on fire."            );            sender            .            sendMessage            (            "This is an arbitrary requirement for demonstration purposes only."            );            return            true            ;            }            // Become the role player who should be set on fire. Remember that indecies starting time with 0, not 1.            Player            target            =            Bukkit            .            getServer            ().            getPlayer            (            args            [            0            ]            );            // Make sure the player is online.            if            (            target            ==            null            )            {            sender            .            sendMessage            (            args            [            0            ]            +            " is non currently online."            );            return            true            ;            }            // Sets the player on fire for i,000 ticks (at that place are ~20 ticks in 2d, so 50 seconds full).            target            .            setFireTicks            (            1000            );            return            true            ;            }            return            false            ;            }          

Killing the role player

To keep with the theme, here's a way to kill the player.

Use this for your onCommand method:

                            @Override              public              boolean              onCommand              (              CommandSender              sender              ,              Command              cmd              ,              String              label              ,              String              []              args              )              {              if              (              cmd              .              getName              ().              equalsIgnoreCase              (              "KillPlayer"              ))              {              Player              target              =              sender              .              getServer              ().              getPlayer              (              args              [              0              ]              );              // Make certain the player is online.              if              (              target              ==              zilch              )              {              sender              .              sendMessage              (              args              [              0              ]              +              " is not currently online."              );              render              true              ;              }              target              .              setHealth              (              0.0D              );              }              render              faux              ;              }            

Here is an extension to that, that will kill the player with an explosion:

                            bladder              explosionPower              =              4F              ;              //This is the explosion power - TNT explosions are 4F past default              Player              target              =              sender              .              getWorld              ().              getPlayer              (              args              [              0              ]              );              target              .              getWorld              ().              createExplosion              (              target              .              getLocation              (),              explosionPower              );              target              .              setHealth              (              0.0D              );            

Creating a Fake Explosion

This code produces the TNT/Creeper Visual and Audio effects. However, no explosion damage is dealt to surrounding entities or blocks. This is useful for nerfing explosions while all the same keeping the aesthetics of them.

                            @EventHandler              public              void              onExplosionPrime              (              ExplosionPrimeEvent              event              )              {              Entity              entity              =              event              .              getEntity              ();              // If the result is near primed TNT (TNT that is about to explode), and so do something              if              (              entity              instanceof              TNTPrimed              )              {              entity              .              getWorld              ().              createExplosion              (              entity              .              getLocation              (),              0              );              }              }            

Hiding a Actor From Another Player

This will hide the player who used this command from a specified player. Everyone else will exist able to see the player.

                        @Override            public            boolean            onCommand            (            CommandSender            sender            ,            Control            cmd            ,            String            label            ,            String            []            args            )            {            if            (            cmd            .            getName            ().            equalsIgnoreCase            (            "HideMe"            )            &&            args            .            length            ==            1            )            {            if            (            !            (            sender            instanceof            Player            ))            {            sender            .            sendMessage            (            "Only players can use this control!"            );            return            true            ;            }            // Afterwards checking to brand sure that the sender is a Player, we can safely cast information technology to 1.            Player            due south            =            (            Player            )            sender            ;            // Gets the thespian who shouldn't encounter the sender.            //Note: getPlayer(string) is now deprecated, employ getPlayer(UUID.fromString(string) instead.            Actor            target            =            Bukkit            .            getServer            ().            getPlayer            (            UUID            .            fromString            (            args            [            0            ]            ));            if            (            target            ==            cypher            )            {            sender            .            sendMessage            (            "Actor "            +            args            [            0            ]            +            " is non online."            );            return            true            ;            }            // Hides a given Player (s) from someone (target).            target            .            hidePlayer            (            southward            );            return            true            ;            }            return            false            ;            }          

Spawn Lightning Bolt Where Thespian is Looking

The code below allows any player with a fishing rod to create a lightning strike past clicking (and aiming somewhere). It'due south a simple and funny pull a fast one on.

                        @EventHandler            public            void            onPlayerInteractBlock            (            PlayerInteractEvent            effect            )            {            Player            thespian            =            event            .            getPlayer            ();            if            (            player            .            getItemInHand            ().            getType            ()            ==            Material            .            FISHING_ROD            )            {            // Creates a bolt of lightning at a given location. In this case, that location is where the histrion is looking.            // Tin can only create lightning upwardly to 200 blocks away.            player            .            getWorld            ().            strikeLightning            (            histrion            .            getTargetBlock            ((            Set            <            Cloth            >            )            null            ,            200            ).            getLocation            ());            }            }          

Automatically formatting your code

Eclipse provides functionality to automatically format your code to Oracle conventions, fixing anarchistic indentations, spacing, and such. But select your projection in the sidebar, and then select Source -> Format.

Request Section

http://forums.bukkit.org/forums/plugin-requests.13/

Instance Files and Templates

  • Bukkit/SamplePlugin on GitHub
  • Example.Java
  • ExamplePlayerListener.Java
  • ExampleBlockListener.Java
  • ExampleEntityListener.Java
  • Core Coffee
    If you lot accept any more than questions on this matter, don't hesitate to visit the BukkitDev IRC channel and ask!
Language   English • беларуская • Deutsch • español • suomi • français • italiano • 한국어 • Nederlands • norsk • polski • português • русский • lietuviųčeština

How To Use Minecraft Plugins,

Source: https://bukkit.fandom.com/wiki/Plugin_Tutorial_(Eclipse)

Posted by: hansonlins1970.blogspot.com

0 Response to "How To Use Minecraft Plugins"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel