api/Ships 6 R2


Ships 6 uses a compatibility layer to suit the need for both Sponge and Bukkit users alike.

Compatibility layer:

As this is on the Bukkit site, this will be focusing on the BukkitToCore compatibility layer and displaying how to convert from Bukkit to ShipsCore. With that in mind, SpongeToCore is not that different. 


In ShipsCore there is not a Location class, instead there is a Position class which is implemented by BlockPosition and ExactPosition.

BlockPosition is the position of a Block while an Exact Position is more exact on its location within the world. Both BlockPosition and ExactPosition can be converted to one and another by simply using the to() function, however both position types share the same functions so you will find that many functions that require a position will use the Position class. You can convert a Bukkit Block into a BlockPosition with the following code

org.bukkit.block.Block block;
BlockPosition position = new BBlockPosition(block);

 Note that the implementation of BlockPosition has a B infront of it, this is to stand for Bukkit as appose to the Sponge variant in SpongeToCore which starts with S. You will find this a common trend within the implementation of the interfaces for Core. When it comes to ExactPosition, you require a Bukkit Location, it works in the same way as BlockPosition.

org.bukkit.Location location;
ExactPosition position = new BExactPosition(location);

 Sometimes you may want to write as much as you can just using ShipsCore to make your code work on any implementation of ShipsCore, to get a Position without Bukkit you require a Extent such as ExtentWorld which is ShipsCore's version of a World. When you have the world you need the X, Y, Z position that you want.

int x;
int y;
int z;
ExtentWorld world;
BlockPosition position = world.getPosition(x, y, z);

 Note that it returns a BlockPosition with int X, Y, Z. If you were to have double X, Y, Z then it would return a ExactPosition.


Block Details:

BlockDetails are ShipsCores version of BlockData which was added in 1.13. They hold all information about the block including TileEntity data in ShipsCore. 

Blocks can hold a lot of different information such as facing direction, if they are on fire, etc. All of this can be accessed by using the KeyedData class. KeyedData holds a single object that can only be accessed if the BlockType supports it, such as WaterLoggedKeyedData can only be accessed if the BlockType supports being WaterLogged.


You can get and set the KeyedData by the following

BlockDetails details;
boolean waterLogged = details.get(KeyedData.WATER_LOGGED).get(); 
details.set(KeyedData.WATER_LOGGED, !waterLogged);

 Note that .get() is on the end of get. This is because get returns a optional value in cases where the BlockType does not support the key. 

Tile Entity

A TileEntity is data of a block that is not normally supported by BlockDetails, in Bukkit this data is typically stored in BlockState. With ShipsCore a TileEntity comes in two forms, a LiveTileEntity and a TileEntitySnapshot. The LiveTileEntity is for if the TileEntity data has come directly from a block, this means any modifications you do to it will results in changes to the world. A TileEntitySnapshot is a snapshot, meaning that any changes that are done to it will not take effect on the world. If you wish to only get data from a TileEntity and do not care if the TileEntity is Live or a snapshot then you can as both TileEntitySnapshot and LiveTileEntity both extend TileEntity which is used as the base for each TileEntity for the block, after that then that interface is split into the TileEntitySnapshot and LiveTileEntity meaning that every TileEntity has a general interface, live interface and snapshot interface. For example.


BlockPosition position;
LiveTileEntity tileEntity = position.getTileEntity().get();
FurnaceTileEntity furnace = (FurnaceTileEntity)tileEntity; //this has all functions of a Live and Snapshot FurnaceTileEntity
LiveFurnaceTileEntity liveFurnace = (LiveFurnaceTileEntity)furnace;

One thing that is unique to ShipsCore is that you can set TileEntity data from a BlockDetails, so if you set a block with that same BlockDetails, the TileEntity contained in the BlockDetails to be transferred with it. This also allows the ease of creating a block snapshot like interface that contains every bit of data that can be applied to a block. 

For example, lets assume there is a furnace on the BlockPosition we will be using in the code below, this furnace has a item in the fuel slot, we want to get a BlockDetail of that furnace and read the item in the BlockDetail

BlockPosition position;
TiledBlockDetails tiledDetails = (TiledBlockDetails)position.getBlockDetails();
TileEntitySnapshot tileEntity = tiledDetails.getTileEntity();
FurnaceInventorySnapshot fis = (FurnaceInventorySnapshot)tileEntity.getInventory();
ItemStack item = fis.getFuelSlot().getItem().get();

 Note that we can get the LiveTileEntity of the BlockPosition which will be more accurate on the current data of the position, however it was an example. 



Worlds within ShipsCore are called ExtentWorld. To convert a Bukkit World to a ExtentWorld is similar to everything else.

org.bukkit.World bWorld;
ExtentWorld world = new BExtentWorld(bWorld);

 However if you are working within ShipsCore only, you can get the world by its name or UUID. Note that you can get the World by what the platform prefers to use to identify the world, such as Bukkit prefers the world name and Sponge prefers the world UUID.

String worldName; <br />CorePlugin.getServer().getWorld(worldName, true);



In both Bukkit and Sponge you listen to events using a Listen class, ShipsCore is no exception. You can find a list of all ShipsCore events here

public void onBlockBreak(BlockBreakEvent.ByPlayer event){

 Note that the example listener is listening for a nested event, most events in ShipsCore have nested sub events of the main event. This means whenever a sub event fires, the main event also fires. In turn this means that you can listen to Event and every ShipsCore implemented event (including plugins that have ShipsCore events in them) will be fired to that event listener. 


Also note that the compatibility layer still relies on its implemention, im the case of Bukkit there is only one BlockBreakEvent to listen to and it needs to have a player, therefore BlockBreakEvent.ByPlugin will not fire on the Bukkit implementation however will on Sponges implementation.


Command Source:

By default, commands have the source of CommandSource however a command source can be many different objects including a ConsoleSource, LivePlayer or even CommandBlock. For your conviniance this has been broken down considerably. Any Source that has a text based output (such as Players chat, or Console messages) can be casted into a CommandViewer which allows the use of sending messages. Another benefit is if you wanted the location that a command was sent, this is where the CommandSource can be casted into Positionable which exposes the location that the source is at. Due to the fact a command block has a BlockPosition while a player has a ExactPosition the position given is not determined 


Getting a Vessel

When it comes to Ships 6 and Vessels, custom plugins can add there own type of vessel with its own code running in the background, this results in custom versions of vessels needing to be loaded and received in there own way. 

After the ship is loaded it will be registered within the Ships plugin. You can get the list of registered Ships by invoking the function found in the ShipsPlugin however if you wish to find a single Ship that has a set requirement then you can either search for it yourself using the previously mentioned list, or you can use one of the provided ShipFinder tools (Note, you may find a ShipLoader, these load from the file and should only be used to initially load the ship)