Hi. I just wanted to plubly my first API. It permits creating block reloading, and has a lot of options. You just have to put it inside of your plugin, just don't remove the credits to me. It's in two classes : one for creating the defaults, and another for the reloader itself. Reloader.java : Code: package dev.bukkit.moddingear; import java.util.ArrayList; import java.util.List; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; public class Reloader { // Block reloader by Moddingear // Add all the metadata adresses you use on blocks for it to be applied when reloading // Takes cares of block data, type and metadata // Set the default settings with ReloaderDefaults // Add it to your main class with ReloaderDefaults reloaderDefaults; and reloaderDefaults = new ReloaderDefaults(this); // Shut it down in ReloaderDefaults with Shutdown(); private Plugin plugin; Block block; List<BlockState> Active = new ArrayList<>(); //Active blockstates used/usable List<BlockState> Inactive = new ArrayList<>(); //Inactive blockstates used/usable List<String> KnownMetadatas = new ArrayList<>(); //Metadatas used, already filled with the default ones when you create it Directions Dir; //The direction where you want it to go ReloadCycleType RCT; //The blocks to be used when reloading, self explainatory : StartType ST; // Random is random between the block you put in the list of active blocks FinishType FT; // First is the first block of the list, and Order is in their order of appearance in the list ReloadAnimationType RAT; //The way the blocks reloads : FROM is from the block to away, TO is the opposite, and bounce makes it go away then go back int Phases; //Amount of movements the block will do before the original block is refilled private int cp = 0; //Starting phase, do not touch if you don't know what it is long Wait; //Time between movements of the block boolean Overwrite; //Deletes the blocks it goes by or not boolean Shutdown = false; //Do not touch private List<Material> Activemats = new ArrayList<>(); private List<Byte> Activedata = new ArrayList<>(); private List<Material> Inactivemats = new ArrayList<>(); private List<Byte> Inactivedata = new ArrayList<>(); private ReloaderDefaults reldef; public enum Directions { X_POSITIVE, X_NEGATIVE, Y_POSITIVE, Y_NEGATIVE, Z_POSITIVE, Z_NEGATIVE } public enum ReloadCycleType { RANDOM, ORDER, FIRST } public enum StartType { RANDOM, FIRST } public enum FinishType { RANDOM, FIRST } public enum ReloadAnimationType { FROM, TO, BOUNCEFROM, BOUNCETO } public Reloader(ReloaderDefaults reldef, Block block, BlockState Active, BlockState Inactive, Directions Dir, int Phases, long Wait) { this.block = block; this.Active.add(Active); this.Inactive.add(Inactive); this.Dir = Dir; this.Phases = Phases; this.Wait = Wait; RCT = reldef.RCT; FT = reldef.FT; RAT = reldef.RAT; Overwrite = reldef.Overwrite; this.Active.addAll(reldef.Active); this.Inactive.addAll(reldef.Inactive); reldef.Reloaders.add(this); this.reldef = reldef; this.plugin = reldef.plugin; } @SuppressWarnings("deprecation") public void StartReloading(){ for (BlockState blockState : Active) { Activemats.add(blockState.getType()); Activedata.add(blockState.getRawData()); } for (BlockState blockState : Inactive) { Inactivemats.add(blockState.getType()); Inactivedata.add(blockState.getRawData()); } BlockState Inactive = null; switch (ST) { case RANDOM: boolean chosen = false; while (!chosen) { for (BlockState blockState : this.Inactive) { int RandomNumber = (int) (Math.random()*10); if (RandomNumber == 0) { chosen = true; Inactive = blockState; } } } break; case FIRST: Inactive = this.Inactive.get(0); } Setas(block, Inactive, plugin); Reloading(plugin); } private void Reloading(final Plugin plugin) { if (cp == Phases + 1) { endReloading(plugin); return; } int distance = 0; switch (RAT) { case FROM: distance = cp; break; case TO: distance = Phases - cp; break; case BOUNCEFROM: if (cp <= Phases /2) { distance = cp; } else { distance = Phases - cp; } break; case BOUNCETO: if (cp <= Phases /2) { distance = Phases /2 - cp; } else { distance = cp - Phases /2; } break; } distance++; Location blockplace = block.getLocation(); switch (Dir) { case X_POSITIVE: blockplace.add(distance, 0, 0); break; case X_NEGATIVE: blockplace.add(-distance, 0, 0); break; case Y_POSITIVE: blockplace.add(0, distance, 0); break; case Y_NEGATIVE: blockplace.add(0, -distance, 0); break; case Z_POSITIVE: blockplace.add(0, 0, distance); break; case Z_NEGATIVE: blockplace.add(0, 0, -distance); break; } Block blockat = blockplace.getBlock(); boolean place = true; if (!Overwrite) { if (blockat.getType() != Material.AIR) { place = false; } } if (place) { switch (RCT) { case FIRST: Setas(blockat, this.Active.get(0), plugin); break; case RANDOM: boolean chosen = false; while (!chosen) { for (BlockState blockState : this.Inactive) { int RandomNumber = (int) (Math.random()*10); if (RandomNumber == 0) { chosen = true; Setas(blockat, blockState, plugin); } } } break; case ORDER: Setas(blockat, Active.get(cp % Active.size()), plugin); break; } } cp++; final boolean placed = place; final Location placedat = blockplace; BukkitRunnable Runned = new BukkitRunnable() { @Override public void run() { if (placed) { BlockState voidblock = placedat.getBlock().getState(); voidblock.setType(Material.AIR); for (String string : KnownMetadatas) { if (voidblock.hasMetadata(string)) { voidblock.removeMetadata(string, plugin); } } } if (!Shutdown) { Reloading(plugin); } } }; Runned.runTaskLater(plugin, Wait); reldef.Runned.add(Runned); } private void endReloading(Plugin plugin) { BlockState Active = null; switch (FT) { case RANDOM: boolean chosen = false; while (!chosen) { for (BlockState blockState : this.Active) { int RandomNumber = (int) (Math.random()*10); if (RandomNumber == 0) { chosen = true; Active = blockState; } } } break; case FIRST: Active = this.Active.get(0); } Setas(block, Active, plugin); } @SuppressWarnings("deprecation") private void Setas(Block block, BlockState state, Plugin plugin) { block.setType(state.getType()); block.setData(state.getRawData()); for (String string : KnownMetadatas) { if (block.hasMetadata(string)) { block.removeMetadata(string, plugin); } if (state.hasMetadata(string)) { block.setMetadata(string, new FixedMetadataValue(plugin, state.getMetadata(string).get(0).asString())); } } } } ReloaderDefaults.java : Code: package dev.bukkit.moddingear; import java.util.ArrayList; import java.util.List; import org.bukkit.block.BlockState; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; import dev.bukkit.moddingear.Reloader.Directions; import dev.bukkit.moddingear.Reloader.FinishType; import dev.bukkit.moddingear.Reloader.ReloadAnimationType; import dev.bukkit.moddingear.Reloader.ReloadCycleType; import dev.bukkit.moddingear.Reloader.StartType; public class ReloaderDefaults { Plugin plugin; List<BlockState> Active = new ArrayList<>(); List<BlockState> Inactive = new ArrayList<>(); List<String> KnownMetadatas = new ArrayList<>(); Directions Dir; ReloadCycleType RCT = ReloadCycleType.FIRST; StartType ST = StartType.FIRST; FinishType FT = FinishType.FIRST; ReloadAnimationType RAT = ReloadAnimationType.TO; int Phases; long Wait; boolean Overwrite; List<Reloader> Reloaders = new ArrayList<>(); List<BukkitRunnable> Runned = new ArrayList<>(); public ReloaderDefaults(Plugin plugin) { this.plugin = plugin; } public void Shutdown() { for (Reloader rel : Reloaders) { rel.Shutdown = false; } for (BukkitRunnable bukkitRunnable : Runned) { bukkitRunnable.run(); } } } I haven't got the opportunity to test it yet, but i'm sure it works fine, as it's an adapted version of the one that is in my plugin. Report any bugs you find please
@mcdorli It's a ressource for making blocks reload in a certain way : The block being reloaded switches to it's inactive state then a block with it's acitve state slowly goes to the original block's position then replaces it. About the section, I think this should be in ressources ?
@Maxx_Qc It's useful for minigames, when blocks needs to deplete for a certain amount of time, and you want the player to see when the block will be back. For status blocks or things like so.