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. BlockDetails can be converted into many different interfaces to gain access to extra functions that the BlockDetails have, not only that but all BlockDetails can be cast into the top most interface of the block detail, such as a Wall Sign can be cast into a block detail of WallSign, this applies to all blocks including the blocks that Bukkit does not expose.

BlockDetails, much like BlockData have default states they come in, these can be grabbed from the BlockType in the following way.

BlockDetails details = BlockTypes.WALL_SIGN.getDefaultBlockDetails();
WallSign wallSignDetails = (WallSign)details;

You can also convert bukkit BlockData into a BlockDetail if needed, all the applied data from the BlockData will be converted automatically onto the BlockDetails, also note that you do not need to find out what BlockData it is.

org.bukkit.block.data.BlockData data;
BukkitPlatform platform = (BukkitPlatform)CorePlugin.getPlatform();
BlockDetails details = platform.createBlockDetailInstance(data);

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;
CorePlugin.getServer().getWorld(worldName, true);


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. 

No matter what plugin that holds the ships classes, there is a standard way you can use to get them, which is to use a ShipsLoader interface. As mentioned before these only work for particular Ship classes, however theses will work on any ship that comes default with Ships. This is how to use a Ship Loader, in this example we will use the ShipsBlockLoader which will get the ship that is part of the specified block.


BlockPosition position;
    ShipsVessel vessel = new ShipsBlockLoader(position).load();
}catch(IOException e){

 The IOException is if the block specified is not part of a ship