To put it simply, this is just a lucky blocks plugin that allows you to easily create 'random blocks' and 'events' for them with the RandomBlocks api as an 'addon'.
- Native Minecraft Version:
- 1.13
- Tested Minecraft Versions:
- 1.13
- 1.14
- 1.15
- 1.16
If you already heard of lucky blocks then you will know what happens when you break them in game, for those that don't it simply picks a weight/chance based event to occur from the type of random block that was broken.
![]()
Although luck is implemented, crafting with luck upgrades is currently disabled due to how spigot handles crafting and causes duplication issues.
![]()
I've attempted to fix/find a way around this with several different ways with no success, so until I can find a way to fix it, crafting with luck upgrades is going to be disabled.
root command = /randomblocks
alias command = /rbs
permission = randomblocks.admin
Comes with tab completion
/rbs help - gives this list
/rbs give <player> <random block> <amount> - give random blocks to a player
/rbs edit <random block> <event> <field> <value> - edit a random blocks' field for an event
/rbs test <random block> <event> - test a random blocks' event
/rbs enable <random block> - enables a random block
/rbs enable <random block> <event> - enables a random blocks event
/rbs disable <random block> - disables a random block
/rbs disable <random block> <event> - disables a random blocks event
/rbs savedata - saves current data
/rbs buggered <fix/remove> fixes or removes random blocks that have an incorrect block
/rbs delete <random block/@all> <world/@all> deletes all random blocks in a world
Code (YAML):
#How often to check for buggered random blocks
checkBuggeredInterval: 20
#The action to take once a buggered random block is found - true = fix, false = remove
fixOrRemove: false
#Should random blocks trigger if they are broken in creative
triggerInCreative: false
#If random blocks should trigger when it fades - true = trigger, false = drop
#For more info: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/block/BlockFadeEvent.html
triggerOnFade: true
Code (YAML):
#List of all random block locations and data
blockLocs: []
Code (YAML):main: fun.stuf.testaddon.TestAddon
name: RBTestAddon
version: 1.0.0
api-version: '1.14'
author: StealthMuskrat
depend:
- RandomBlocks
Code (Java):package fun.stuf.testaddon;
import fun.stuf.randomblocks.RandomBlocks;
import fun.stuf.randomblocks.events.RandomBlockBreakEvent;
import fun.stuf.randomblocks.events.RandomBlockPlaceEvent;
import fun.stuf.randomblocks.randomblock.Event;
import fun.stuf.randomblocks.randomblock.RandomBlock;
import fun.stuf.utils.C;
import fun.stuf.utils.Items;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
//Adding a random block with events example
public class TestAddon extends JavaPlugin {
public static TestAddon testAddon;
@Override
public void onEnable() {
testAddon = this;
//String = random block name - must be alphanumeric and/or underscores
//ItemStack = the itemstack that players hold - must be a block
//Material = the type of block that represents a placed random block - must be solid
RandomBlock testBlock = new RandomBlock("Test_Block",new ItemStack(Material.CARROT),Material.SAND) {
@Override
public void onPlace(RandomBlockPlaceEvent e) {
e.getRandomBlock(); //The random block type that was placed
e.getWorld(); //The world the random block was placed in
e.getBlock(); //The block that was placed
e.getCenter(); //The center of the block that was placed
e.getEntity(); //The entity that placed the block (might be null)
e.getDisplayStand(); //The display armor stand (might be null)
e.getInnerStand(); //The inner armor stand (might be null)
//Example usage
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_CAT_HURT,1,1);
}
};
//THE BELOW SETTINGS ARE OPTIONAL
//IF YOU ARE USING DISPLAY STAND, SET THE DISPLAY NAME
//IF YOU ARE USING INNER STAND, SET THE INNER TEXTURE
//Sets the recipe to make the random block (no recipe by default) the recipe result is irrelevant as it will be changed to the random blocks' itemstack
testBlock.setRecipe(new FurnaceRecipe(new NamespacedKey(this,"test_block"), new ItemStack(Material.STONE),Material.TNT,10,160));
testBlock.setTriggerOnExplode(false); //If this random block should trigger if it gets exploded (false by default)
testBlock.setTriggerOnBurn(true); //If this random block should trigger if it gets burned (false by default)
testBlock.setDisplayName(C.parse("&aTest &bBlock")); //Sets the display name for the display armor stand (null by default)
testBlock.setUseDisplayStand(true); //If should use display armor stand (false by default)
//Sets the texture of the inner armor stand (value/url/uuid/username/material/itemstack)
testBlock.setInnerTexture("http://textures.minecraft.net/texture/87c63d9079b75f90979783cf07ca726f65e3024415ac622a7c906cd25082af");
testBlock.setSmallInnerStand(true); //If the inner armor stand should be small (false by default)
testBlock.setUseInnerStand(true); //If should use inner armor stand (false by default)
//Event Manager is where events are stored and handled
testBlock.getEventManager(); //Gets the event manager
testBlock.getEventManager().setIsUsingLuck(false); //Sets if picking events uses luck (false by default)
//If you are not using luck, then don't worry about the next 4 options
//Adds a luck upgrade for increasing luck in the crafting table by the set amount, add as many as you want. Amount must be between -100 and 100 inclusive
testBlock.getEventManager().addLuckUpgrade(Material.IRON_INGOT,1);
//Sets the chance of getting a good/neutral/bad event at a luck of 0, must add up to 100 (default 25/50/25)
testBlock.getEventManager().setChanceAt0(25,50,25);
//Sets the chance of getting a good/neutral/bad event at a luck of 100, must add up to 100 (default 75/20/5)
testBlock.getEventManager().setChanceAt0(75,20,5);
//Sets the chance of getting a good/neutral/bad event at a luck of -100, must add up to 100 (default 5/20/75)
testBlock.getEventManager().setChanceAt0(5,20,75);
//Add as many events as you want
//Event - The event to occur
testBlock.addEvent(new Event() {
//Non final public primitive fields + strings are editable in game
public int speed = 2;
public int explosionRadius = 5;
public int fuseTicks = 50;
public double health = 10;
public boolean powered = true;
public boolean glowing = true;
public String customName = "&bSuper Creeper";
//The name of the event - must be alphanumeric and/or underscores
@Override
public String getName() {
return "super_creeper";
}
//The weight/chance of the event to happen, must be >= 0
@Override
public double getWeight() {
return .1;
}
//The type of event, GOOD - NEUTRAL - BAD
//If you are not using luck, then set this to whatever because it doesn't really matter
@Override
public EventType getType() {
return EventType.BAD;
}
//What happens when you break the block
@Override
public void onBreak(RandomBlockBreakEvent e) {
//+ the above methods in the onPlace method
e.isRemoveDisplayStand(); //If the display armor stand is going to be removed
e.isRemoveInnerStand(); //If the inner armor stand is going to be removed
e.setRemoveDisplayStand(true); //Set if the display armor stand should be removed (true by default)
e.setRemoveInnerStand(true); //Set if the inner armor stand should be removed (true by default)
//Example usage
e.getWorld().playSound(e.getCenter(), Sound.ENTITY_CREEPER_DEATH,1,.5F);
e.getWorld().getNearbyEntities(e.getCenter(),5,5,5).forEach(entity -> {
Vector velocity = entity.getLocation().toVector().subtract(e.getCenter().toVector()).normalize();
velocity.multiply(5.5-entity.getLocation().distance(e.getCenter()));
entity.setVelocity(velocity);
});
if(e.getEntity() instanceof Player) {
Player player = (Player) e.getEntity();
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,80,1,false,false,false));
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,160,1,false,false,false));
}
e.getWorld().spawn(e.getCenter(),Creeper.class,creeper -> {
creeper.setExplosionRadius(explosionRadius);
creeper.setPowered(powered);
creeper.setMaxFuseTicks(fuseTicks);
creeper.setHealth(health);
creeper.setCustomName(C.parse(customName));
creeper.setGlowing(glowing);
creeper.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,2000,speed,false,false,false));
if(e.getEntity() instanceof LivingEntity)
creeper.setTarget((LivingEntity) e.getEntity());
});
}
});
//Add as many random blocks as you want
//Add/register the random block
RandomBlocks.getInstance().addRandomBlock(testBlock);
//Can also do as a 1 liner
RandomBlocks.getInstance().addRandomBlock(new RandomBlock("Stinky", Items.buildItem(Material.ACACIA_WOOD).displayName("&r&eUh oh, Stinky").build(),Material.ACACIA_LOG) {
@Override
public void onPlace(RandomBlockPlaceEvent e) {
e.getWorld().playSound(e.getCenter(),Sound.BLOCK_ANVIL_PLACE,1,.5F);
}
}.setTriggerOnExplode(true)
.setUseDisplayStand(true)
.setDisplayName(C.parse("&6&kM&2Uh oh, Stinky!&6&kM"))
.setRecipe(new ShapelessRecipe(new NamespacedKey(this,"stinky"),new ItemStack(Material.STONE))
.addIngredient(1,Material.DIRT).addIngredient(1,Material.ROTTEN_FLESH)
.addIngredient(1,Material.SLIME_BALL).addIngredient(1,Material.WATER_BUCKET))
.addEvent(new Event() {
@Override
public String getName() {
return "ear_rape";
}
@Override
public double getWeight() {
return .5;
}
@Override
public EventType getType() {
return EventType.NEUTRAL;
}
@Override
public void onBreak(RandomBlockBreakEvent e) {
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_ENDER_DRAGON_DEATH,10,1.8F);
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_WITHER_DEATH,10,.6F);
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_ELDER_GUARDIAN_DEATH,10,.55F);
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_TURTLE_DEATH,1,.5F);
int taskId = Bukkit.getScheduler().runTaskTimer(testAddon,()->{
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_GENERIC_EXPLODE,10,2);
e.getWorld().playSound(e.getCenter(),Sound.ENTITY_CAT_DEATH,10,.65F);
e.getWorld().playSound(e.getCenter(),Sound.BLOCK_NOTE_BLOCK_BELL,10,1.75F);
},0,1).getTaskId();
Bukkit.getScheduler().runTaskLater(testAddon,()->Bukkit.getScheduler().cancelTask(taskId),100);
}
}).addEvent(new Event() {
public float height = 10;
@Override
public String getName() {
return "fall";
}
@Override
public double getWeight() {
return .5;
}
@Override
public EventType getType() {
return EventType.BAD;
}
@Override
public void onBreak(RandomBlockBreakEvent e) {
if(e.getEntity() != null)
e.getEntity().setFallDistance(height);
}
}).addEvent(new Event() {
@Override
public String getName() {
return "not_stinky";
}
@Override
public double getWeight() {
return .1;
}
@Override
public EventType getType() {
return EventType.GOOD;
}
@Override
public void onBreak(RandomBlockBreakEvent e) {
int taskId = Bukkit.getScheduler().runTaskTimer(testAddon,()->{
FallingBlock fallingBlock = e.getWorld().spawnFallingBlock(e.getBlock().getLocation(),Material.DIAMOND_BLOCK.createBlockData());
fallingBlock.setVelocity(new Vector(0,3,0));
e.getWorld().spawnParticle(Particle.END_ROD,e.getCenter(),10,.25,.25,.25,.4);
},0,4).getTaskId();
Bukkit.getScheduler().runTaskLater(testAddon,()->Bukkit.getScheduler().cancelTask(taskId),20);
}
}));
}
}
RandomBlockBreakEvent
RandomBlockPlaceEvent

RandomBlocks 1.1.0
Tell it like it is, they are not 'lucky blocks' they are random blocks