Important
Final Notes:
The NBT format has been reworked in Minecraft 1.20.5 and this library will not updated any further because it was not intended for that.
The final version support range is Minecraft 1.9.0 - 1.20.4 and can still be used for that. The binaries stay available in Maven Central.
Thank you for supporting StructureBlockLib all those years
branch | status | version | download |
---|---|---|---|
master | Download latest release | ||
development | Download snapshots |
JavaDocs: https://shynixn.github.io/StructureBlockLib/apidocs/
StructureBlockLib is a bukkit API and implementation for handling structures on spigot server.
- Bukkit API for the StructureBlock.
- API to save or load structures without an actual structure block.
- Asynchronous implementation and API.
- Fluent API.
- Version support 1.9.R1 - 1.20.R3
- Java support 8 - Latest
- Include the dependency to StructureBlockLib
Maven
<dependency>
<groupId>com.github.shynixn.structureblocklib</groupId>
<artifactId>structureblocklib-bukkit-api</artifactId>
<version>2.13.0</version>
<scope>provided</scope>
</dependency>
Gradle
dependencies {
compileOnly("com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.13.0")
}
Jar File
StructureBlockLibBukkitApi.jar
- If you need more information, check out the sample implementation of a plugin using StructureBlockLib in the
structureblocklib-bukkit-sample
folder. - All calls are not blocking and complete in the future.
// Minimal configuration
Plugin plugin;
Path path = plugin.getDataFolder().toPath().resolve("mystructure.nbt");
StructureBlockLibApi.INSTANCE
.saveStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.sizeX(32)
.sizeY(5)
.sizeZ(32)
.saveToPath(path)
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to save structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Saved structure 'mystructure'."));
// Maximal configuration
Plugin plugin;
Path path = plugin.getDataFolder().toPath().resolve("mystructure.nbt");
StructureBlockLibApi.INSTANCE
.saveStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.sizeX(32)
.sizeY(5)
.sizeZ(32)
.includeEntities(false) // See JavaDoc for default values.
.restriction(StructureRestriction.UNLIMITED) // See JavaDoc for default values.
.author("me")
.saveToPath(path)
.onProgress(c -> plugin.getLogger().log(Level.INFO, String.format("Percentage %.2f", c)))
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to save structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Saved structure 'mystructure'."));
Store a structure on your server to the default structure storage, so it can be used by ordinary StructureBlocks
// Minimal configuration
Plugin plugin;
StructureBlockLibApi.INSTANCE
.saveStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.sizeX(32)
.sizeY(5)
.sizeZ(32)
.saveToWorld("world", "me", "mystructure")
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to save structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Saved structure 'mystructure'."));
// Minimal configuration
Plugin plugin;
Path path = plugin.getDataFolder().toPath().resolve("mystructure.nbt");
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.loadFromPath(path)
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to load structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Loaded structure 'mystructure'."));
// Maximal configuration
Plugin plugin;
Path path = plugin.getDataFolder().toPath().resolve("mystructure.nbt");
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.includeEntities(true) // See JavaDoc for default values.
.seed(50L) // See JavaDoc for default values.
.integrity(0.2F) // See JavaDoc for default values.
.mirror(StructureMirror.FRONT_BACK) // See JavaDoc for default values.
.rotation(StructureRotation.ROTATION_90) // See JavaDoc for default values.
.loadFromPath(path)
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to load structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Loaded structure 'mystructure'."));
Load a structure on your server from the default structure storage, so you can use structures from ordinary StructureBlocks
// Minimal configuration
Plugin plugin;
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.loadFromWorld("world", "me", "mystructure")
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to load structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Loaded structure 'mystructure'."));
// Minimal configuration
Plugin plugin;
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.onProcessBlock(part -> {
// onProcessBlock is called for every block before it is placed.
if (part.getSourceBlock().getBlockData().getMaterial() == Material.AIR) {
// When the block in the structure file equals AIR, we do not want to place it -> return false.
return false;
}
// When the block in the structure file is something else, we do want to place it -> return true.
return true;
})
.loadFromWorld("world", "me", "mystructure")
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to load structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Loaded structure 'mystructure'."));
// Minimal configuration
Plugin plugin;
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(new Location(Bukkit.getWorld("world"), 100, 100, 100))
.includeEntities(true)
.onProcessEntity(part -> {
// onProcessEntity is called for every entity before it is placed.
if (part.getEntity().isPresent()) {
if (part.getEntity().get().getType() == EntityType.COW) {
// When the entity in the structure file equals COW, we do not want to place it -> return false.
return false;
}
}
// When the entity in the structure file is something else, we do want to place it -> return true.
return true;
})
.loadFromWorld("world", "me", "mystructure")
.onException(e -> plugin.getLogger().log(Level.SEVERE, "Failed to load structure.", e))
.onResult(e -> plugin.getLogger().log(Level.INFO, ChatColor.GREEN + "Loaded structure 'mystructure'."));
List<StructureEntity<Entity, Location>> entities = new ArrayList<>();
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(player.getLocation()) // We do need an existing world.
.includeEntities(false) // Do not place entities.
.includeBlocks(false) // Do not place blocks.
.onProcessEntity(entity -> {
entities.add(entity);
return false;
})
.loadFromWorld("world", "me", "mystructure")
.onException(c -> c.printStackTrace())
.onResult(e -> {
for (StructureEntity<Entity, Location> structureEntity : entities) {
// Do something with the entities
structureEntity.spawnEntity(player.getLocation().add(-3, 0, 0));
}
});
List<StructurePlacePart<Block, World>> blocks = new ArrayList<>();
StructureBlockLibApi.INSTANCE
.loadStructure(plugin)
.at(player.getLocation()) // We do need an existing world.
.includeEntities(false) // Do not place entities.
.includeBlocks(false) // Do not place blocks.
.onProcessBlock(part -> {
blocks.add(part);
return false;
})
.loadFromWorld("world", "me", "mystructure")
.onException(c -> c.printStackTrace())
.onResult(e -> {
for (StructurePlacePart<Block, World> structureBlock : blocks) {
// Do something with the blocks
System.out.println(structureBlock.getSourceBlock().getType());
}
});
Plugin plugin;
Location location = new Location(Bukkit.getWorld("world"), 100, 100, 100);
location.getBlock().setType(Material.STRUCTURE_BLOCK);
StructureBlockSave structureBlock = StructureBlockLibApi.INSTANCE.getStructureBlockAt(location, plugin);
structureBlock.setStructureMode(StructureMode.SAVE);
structureBlock.setSaveName("sample_save");
structureBlock.setSizeX(31);
structureBlock.setSizeY(15);
structureBlock.setSizeZ(12);
structureBlock.update();
- In order to use the StructureBlockLib Api on your server, you need to put the implementation of the Api on your server.
- Add the dependencies to the libraries tag
plugin.yml
libraries:
- com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.13.0
- com.github.shynixn.structureblocklib:structureblocklib-bukkit-core:2.13.0
- Just go to the releases page and download the plugin.
- Include both dependencies and shade them in your plugin jar file. If you do not know how to do that, you should go with the option above instead. There are several tutorials on spigotmc.org.
Maven
<dependency>
<groupId>com.github.shynixn.structureblocklib</groupId>
<artifactId>structureblocklib-bukkit-api</artifactId>
<version>2.13.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.shynixn.structureblocklib</groupId>
<artifactId>structureblocklib-bukkit-core</artifactId>
<version>2.13.0</version>
<scope>compile</scope>
</dependency>
Gradle
dependencies {
implementation("com.github.shynixn.structureblocklib:structureblocklib-bukkit-api:2.13.0")
implementation("com.github.shynixn.structureblocklib:structureblocklib-bukkit-core:2.13.0")
}
- Install Java 17 or higher
- Fork the StructureBlockLib project on github and clone it to your local environment.
- StructureBlockLib requires spigot server implementations from 1.9.4 to 1.20.2 to be correctly installed in your local Maven cache. As this requires multiple java version to build different versions, a Dockerfile is provided to build these dependencies in a docker container and then copy it to your local Maven cache.
Note: If using Windows, execute the commands using Git Bash.
mkdir -p ~/.m2/repository/org/spigotmc/
docker build --target dependencies-jdk8 -t structureblocklib-dependencies-jdk8 .
docker create --name structureblocklib-dependencies-jdk8 structureblocklib-dependencies-jdk8 bash
docker cp structureblocklib-dependencies-jdk8:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/
docker rm -f structureblocklib-dependencies-jdk8
docker build --target dependencies-jdk17 -t structureblocklib-dependencies-jdk17 .
docker create --name structureblocklib-dependencies-jdk17 structureblocklib-dependencies-jdk17 bash
docker cp structureblocklib-dependencies-jdk17:/root/.m2/repository/org/spigotmc ~/.m2/repository/org/
docker rm -f structureblocklib-dependencies-jdk17
- Open the project with an IDE, gradle sync for dependencies.
- Setup your own minecraft server
- Change
// val destinationDir = File("C:/temp/plugins")
to your plugins folder in thestructureblocklib-bukkit-sample/build.gradle.kts
file. - Run the
pluginJar
task to generate a plugin.jar file. - Run your minecraft server
- Run the provided docker file.
- The source code is copied to a new docker container and built to a plugin.
- This plugin is installed on a new minecraft server which is accessible on the host machine on the default port on
localhost
.
docker build -t structureblocklib .
docker run --name=structureblocklib -p 25565:25565 -p 5005:5005 structureblocklib
The source code is licensed under the MIT license.