diff --git a/pom.xml b/pom.xml
index 5c4a7a85..9003fa97 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
         <maven.compiler.target>1.8</maven.compiler.target>
 
         <!-- Spigot properties -->
-        <spigot.version>1.18.1</spigot.version>
+        <spigot.version>1.20</spigot.version>
         <spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
 
         <!-- Default settings for sonarcloud.io -->
@@ -80,7 +80,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.8.1</version>
+                <version>3.11.0</version>
                 <configuration>
                     <excludes>
                         <!-- package info files are only important for Javadocs -->
@@ -108,7 +108,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-shade-plugin</artifactId>
-                <version>3.2.4</version>
+                <version>3.3.0</version>
 
                 <configuration>
                     <relocations>
@@ -221,16 +221,16 @@
         </dependency>
 
         <dependency>
-            <groupId>com.github.TheBusyBiscuit</groupId>
+            <groupId>com.github.Slimefun</groupId>
             <artifactId>Slimefun4</artifactId>
-            <version>RC-30</version>
+            <version>RC-33</version>
             <scope>provided</scope>
         </dependency>
 
         <dependency>
-            <groupId>io.github.baked-libs</groupId>
+            <groupId>com.github.baked-libs.dough</groupId>
             <artifactId>dough-api</artifactId>
-            <version>1.1.1</version>
+            <version>39856a32c4</version>
             <scope>compile</scope>
         </dependency>
 
@@ -244,10 +244,11 @@
         <dependency>
             <groupId>org.bstats</groupId>
             <artifactId>bstats-bukkit</artifactId>
-            <version>2.2.1</version>
+            <version>3.0.1</version>
             <scope>compile</scope>
         </dependency>
 
+
         <dependency>
             <groupId>com.sk89q.worldedit</groupId>
             <artifactId>worldedit-bukkit</artifactId>
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/SensibleToolboxPlugin.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/SensibleToolboxPlugin.java
index d20afdd7..ef9a81b0 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/SensibleToolboxPlugin.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/SensibleToolboxPlugin.java
@@ -9,7 +9,7 @@
 import javax.annotation.Nonnull;
 import javax.annotation.ParametersAreNonnullByDefault;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bstats.bukkit.Metrics;
 import org.bukkit.Server;
 import org.bukkit.command.Command;
@@ -250,7 +250,7 @@ public void onEnable() {
             RecipeUtil.setupRecipes();
             RecipeBook.buildRecipes();
 
-            protectionManager = new ProtectionManager(getServer());
+            protectionManager = new ProtectionManager(this);
         });
 
         getServer().getScheduler().runTaskTimer(this, LocationManager.getManager()::tick, 1L, 1L);
@@ -544,9 +544,9 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
     @Override
     public <T> T onConfigurationValidate(ConfigurationManager configurationManager, String key, T oldVal, T newVal) {
         if (key.equals("save_interval")) {
-            Validate.isTrue((Integer) newVal > 0, "save_interval must be > 0");
+            Preconditions.checkArgument((Integer) newVal > 0, "save_interval must be > 0");
         } else if (key.equals("energy.tick_rate")) {
-            Validate.isTrue((Integer) newVal > 0, "energy.tick_rate must be > 0");
+            Preconditions.checkArgument((Integer) newVal > 0, "energy.tick_rate must be > 0");
         } else if (key.startsWith("gui.texture.")) {
             STBUtil.parseMaterialSpec(newVal.toString());
         } else if (key.equals("default_access")) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/MinecraftVersion.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/MinecraftVersion.java
index bfefebf3..3a8f0379 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/MinecraftVersion.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/MinecraftVersion.java
@@ -2,7 +2,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Server;
 
 import io.github.thebusybiscuit.sensibletoolbox.SensibleToolboxPlugin;
@@ -50,6 +50,18 @@ public enum MinecraftVersion {
      *
      */
     MINECRAFT_1_18(18, "1.18.x"),
+    /**
+     * This constant represents Minecraft (Java Edition) Version 1.19
+     * (The "The Wild Update" Update)
+     *
+     */
+    MINECRAFT_1_19(19, "1.19.x"),
+    /**
+     * This constant represents Minecraft (Java Edition) Version 1.20
+     * (The "Trails and Tales" Update)
+     *
+     */
+    MINECRAFT_1_20(20, "1.20.x"),
 
     /**
      * This constant represents an exceptional state in which we were unable
@@ -151,7 +163,7 @@ public boolean isMinecraftVersion(int minecraftVersion) {
      * @return Whether this {@link MinecraftVersion} is newer or equal to the given {@link MinecraftVersion}
      */
     public boolean isAtLeast(@Nonnull MinecraftVersion version) {
-        Validate.notNull(version, "A Minecraft version cannot be null!");
+        Preconditions.checkArgument(version != null, "A Minecraft version cannot be null!");
 
         if (this == UNKNOWN) {
             return false;
@@ -171,7 +183,7 @@ public boolean isAtLeast(@Nonnull MinecraftVersion version) {
      * @return Whether this {@link MinecraftVersion} is older than the given one
      */
     public boolean isBefore(@Nonnull MinecraftVersion version) {
-        Validate.notNull(version, "A Minecraft version cannot be null!");
+        Preconditions.checkArgument(version != null, "A Minecraft version cannot be null!");
 
         if (this == UNKNOWN) {
             return true;
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/filters/Filter.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/filters/Filter.java
index 4140c2e2..1e1a8492 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/filters/Filter.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/filters/Filter.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.filters;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.inventory.ItemStack;
 
 import java.util.ArrayList;
@@ -95,7 +95,7 @@ public void addItem(@Nonnull ItemStack stack) {
      * @return true if the filter should pass the item; false otherwise
      */
     public boolean shouldPass(@Nonnull ItemStack stack) {
-        Validate.notNull(stack, "Cannot filter null ItemStacks");
+        Preconditions.checkArgument(stack != null, "Cannot filter null ItemStacks");
 
         if (filteredItems.isEmpty()) {
             return !whiteList;
@@ -197,7 +197,7 @@ public FilterType getFilterType() {
      *            the filtering type
      */
     public void setFilterType(@Nonnull FilterType filterType) {
-        Validate.notNull(filterType, "FilterType cannot be null!");
+        Preconditions.checkArgument(filterType != null, "FilterType cannot be null!");
         this.filterType = filterType;
     }
 }
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ChargeMeter.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ChargeMeter.java
index ab570cda..417cc522 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ChargeMeter.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ChargeMeter.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Color;
 import org.bukkit.Material;
 import org.bukkit.inventory.ItemStack;
@@ -31,7 +31,7 @@ public class ChargeMeter extends MonitorGadget {
     public ChargeMeter(InventoryGUI gui) {
         super(gui);
 
-        Validate.isTrue(getOwner() instanceof ChargeableBlock, "Attempt to add charge meter to non-chargeable block!");
+        Preconditions.checkArgument(getOwner() instanceof ChargeableBlock, "Attempt to add charge meter to non-chargeable block!");
 
         chargeable = (ChargeableBlock) getOwner();
         this.indicator = new ItemStack(Material.LEATHER_HELMET);
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/DirectionGadget.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/DirectionGadget.java
index 31f74002..d1bd19a2 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/DirectionGadget.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/DirectionGadget.java
@@ -3,7 +3,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 import org.bukkit.block.BlockFace;
@@ -30,8 +30,8 @@ public class DirectionGadget extends ClickableGadget {
     public DirectionGadget(InventoryGUI gui, int slot, ItemStack mainTexture) {
         super(gui, slot);
 
-        Validate.isTrue(gui.getOwningItem() instanceof Directional, "DirectionalGadget can only be used on a directional item!");
-        Validate.isTrue(slot >= 9 && slot < gui.getInventory().getSize() - 9 && slot % 9 > 0 && slot % 9 < 8, "DirectionalGadget can't be placed at edge of inventory window!");
+        Preconditions.checkArgument(gui.getOwningItem() instanceof Directional, "DirectionalGadget can only be used on a directional item!");
+        Preconditions.checkArgument(slot >= 9 && slot < gui.getInventory().getSize() - 9 && slot % 9 > 0 && slot % 9 < 8, "DirectionalGadget can't be placed at edge of inventory window!");
 
         this.mainTexture = mainTexture;
         this.allowSelf = true;
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/EnergyFlowGadget.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/EnergyFlowGadget.java
index 013fc284..668ea44c 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/EnergyFlowGadget.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/EnergyFlowGadget.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 import org.bukkit.block.BlockFace;
@@ -33,7 +33,7 @@ public class EnergyFlowGadget extends CyclerGadget<EnergyFlow> {
     public EnergyFlowGadget(InventoryGUI gui, int slot, BlockFace face) {
         super(gui, slot, face.toString());
 
-        Validate.isTrue(gui.getOwningItem() instanceof BatteryBox, "Energy flow gadget can only be used on a battery box!");
+        Preconditions.checkArgument(gui.getOwningItem() instanceof BatteryBox, "Energy flow gadget can only be used on a battery box!");
 
         this.face = face;
         add(EnergyFlow.IN, ChatColor.DARK_AQUA, Material.BLUE_WOOL, "Device accepts energy", "on this face");
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/FilterTypeGadget.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/FilterTypeGadget.java
index f5864197..32ed3cbc 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/FilterTypeGadget.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/FilterTypeGadget.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 
@@ -27,7 +27,7 @@ public class FilterTypeGadget extends CyclerGadget<FilterType> {
     public FilterTypeGadget(InventoryGUI gui, int slot) {
         super(gui, slot, "Filter Type");
 
-        Validate.isTrue(gui.getOwningItem() instanceof Filtering, "Filter Type gadget can only be added to filtering items!");
+        Preconditions.checkArgument(gui.getOwningItem() instanceof Filtering, "Filter Type gadget can only be added to filtering items!");
 
         add(FilterType.MATERIAL, ChatColor.GRAY, Material.STONE, "Match material only");
         add(FilterType.ITEM_META, ChatColor.LIGHT_PURPLE, Material.ENCHANTED_BOOK, "Match material, block metadata", "and item metadata (NBT)");
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/LightMeter.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/LightMeter.java
index 3d7e8218..bf0c9288 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/LightMeter.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/LightMeter.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 
 import io.github.thebusybiscuit.sensibletoolbox.api.LightMeterHolder;
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.InventoryGUI;
@@ -22,7 +22,7 @@ public class LightMeter extends MonitorGadget {
      */
     public LightMeter(InventoryGUI gui) {
         super(gui);
-        Validate.isTrue(gui.getOwningBlock() instanceof LightMeterHolder, "Attempt to install light meter in non-lightmeter-holder block!");
+        Preconditions.checkArgument(gui.getOwningBlock() instanceof LightMeterHolder, "Attempt to install light meter in non-lightmeter-holder block!");
     }
 
     @Override
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/NumericGadget.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/NumericGadget.java
index d26099b5..98dd7649 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/NumericGadget.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/NumericGadget.java
@@ -1,7 +1,7 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets;
 
-import org.apache.commons.lang.Validate;
-import org.apache.commons.lang.math.IntRange;
+import com.google.common.base.Preconditions;
+
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
@@ -12,6 +12,7 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.GUIUtil;
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.InventoryGUI;
 import io.github.thebusybiscuit.sensibletoolbox.utils.STBUtil;
+import io.github.thebusybiscuit.sensibletoolbox.utils.IntRange;
 
 /**
  * A GUI gadget which allows an integer value to be displayed
@@ -67,7 +68,7 @@ public void onClicked(InventoryClickEvent event) {
         } else if (event.isRightClick()) {
             newValue += event.isShiftClick() ? altIncr : incr;
         }
-        newValue = Math.max(Math.min(newValue, range.getMaximumInteger()), range.getMinimumInteger());
+        newValue = Math.max(Math.min(newValue, range.getMaximumInt()), range.getMinimumInt());
         if (newValue != value && callback.run(newValue)) {
             value = newValue;
             event.setCurrentItem(getTexture());
@@ -86,7 +87,7 @@ public void onClicked(InventoryClickEvent event) {
      *            the new value
      */
     public void setValue(int value) {
-        Validate.isTrue(range.containsInteger(value), "Value " + value + " is out of range");
+        Preconditions.checkArgument(range.containsInteger(value), "Value " + value + " is out of range");
         this.value = value;
         updateGUI();
     }
@@ -95,8 +96,8 @@ public void setValue(int value) {
     public ItemStack getTexture() {
         ItemMeta meta = icon.getItemMeta();
         meta.setDisplayName(ChatColor.YELLOW + title + ": " + ChatColor.AQUA + value);
-        String max = range.getMaximumInteger() == Integer.MAX_VALUE ? "\u221e" : Integer.toString(range.getMaximumInteger());
-        String min = range.getMaximumInteger() == Integer.MIN_VALUE ? "-\u221e" : Integer.toString(range.getMinimumInteger());
+        String max = range.getMaximumInt() == Integer.MAX_VALUE ? "\u221e" : Integer.toString(range.getMaximumInt());
+        String min = range.getMaximumInt() == Integer.MIN_VALUE ? "-\u221e" : Integer.toString(range.getMinimumInt());
         String[] lore = { "Valid value range: " + min + "-" + max, "L-Click: -" + incr, "R-Click: +" + incr, "With Shift held, +/-" + altIncr };
         meta.setLore(GUIUtil.makeLore(lore));
         icon.setItemMeta(meta);
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ProgressMeter.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ProgressMeter.java
index 9fb5a6a0..4a2f99bb 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ProgressMeter.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/gui/gadgets/ProgressMeter.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.meta.ItemMeta;
 
@@ -31,13 +31,13 @@ public class ProgressMeter extends MonitorGadget {
     public ProgressMeter(InventoryGUI gui) {
         super(gui);
 
-        Validate.isTrue(getGUI().getOwningBlock() instanceof AbstractProcessingMachine, "Attempt to install progress meter in non-processing machine " + getGUI().getOwningBlock());
+        Preconditions.checkArgument(getGUI().getOwningBlock() instanceof AbstractProcessingMachine, "Attempt to install progress meter in non-processing machine " + getGUI().getOwningBlock());
 
         machine = (AbstractProcessingMachine) getGUI().getOwningBlock();
-        Validate.isTrue(machine.getProgressCounterSlot() > 0 || machine.getProgressItemSlot() > 0, "At least one of counter slot and item slot must be >= 0!");
+        Preconditions.checkArgument(machine.getProgressCounterSlot() > 0 || machine.getProgressItemSlot() > 0, "At least one of counter slot and item slot must be >= 0!");
 
         this.progressIcon = machine.getProgressIcon().clone();
-        Validate.isTrue(progressIcon.getType().getMaxDurability() > 0, "Material " + progressIcon + " doesn't have a durability!");
+        Preconditions.checkArgument(progressIcon.getType().getMaxDurability() > 0, "Material " + progressIcon + " doesn't have a durability!");
     }
 
     @Override
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBBlock.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBBlock.java
index 5be60054..b7aac2aa 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBBlock.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBBlock.java
@@ -9,7 +9,7 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.GameMode;
@@ -519,9 +519,9 @@ public final PersistableLocation getPersistableLocation() {
      *             if the new location is null or the block's current location is non-null
      */
     public final void setLocation(BlockAccess blockAccess, Location loc) {
-        Validate.notNull(blockAccess, "Do not call this method directly");
-        Validate.notNull(loc, "Location must not be null");
-        Validate.isTrue(persistableLocation == null, "Attempt to change the location of existing STB block @ " + persistableLocation);
+        Preconditions.checkArgument(blockAccess != null, "Do not call this method directly");
+        Preconditions.checkArgument(loc != null, "Location must not be null");
+        Preconditions.checkArgument(persistableLocation == null, "Attempt to change the location of existing STB block @ " + persistableLocation);
         persistableLocation = new PersistableLocation(loc);
     }
 
@@ -565,7 +565,7 @@ public Block getAuxiliaryBlock(Location loc, RelativePosition pos) {
      *            the block's new location
      */
     public final void moveTo(BlockAccess blockAccess, final Location oldLoc, final Location newLoc) {
-        Validate.notNull(blockAccess, "Don't call this method directly");
+        Preconditions.checkArgument(blockAccess != null, "Don't call this method directly");
 
         oldLoc.getBlock().removeMetadata(BaseSTBBlock.STB_BLOCK, SensibleToolbox.getPluginInstance());
         for (RelativePosition pos : getBlockStructure()) {
@@ -637,7 +637,7 @@ public final void moveTo(BlockAccess blockAccess, final Location oldLoc, final L
      *            is being restored from persisted data
      */
     public final void preRegister(BlockAccess blockAccess, Location location, boolean isPlacing) {
-        Validate.notNull(blockAccess, "Don't call this method directly");
+        Preconditions.checkArgument(blockAccess != null, "Don't call this method directly");
         location.getBlock().setMetadata(BaseSTBBlock.STB_BLOCK, new FixedMetadataValue(SensibleToolboxPlugin.getInstance(), this));
 
         for (RelativePosition pos : getBlockStructure()) {
@@ -1045,9 +1045,9 @@ private boolean attachLabelSign(PlayerInteractEvent event) {
     }
 
     private boolean placeLabelSign(@Nonnull Block signBlock, @Nonnull BlockFace face, @Nonnull Material signType) {
-        Validate.notNull(signBlock, "The Sign Block cannot be null");
-        Validate.notNull(face, "The Face cannot be null");
-        Validate.notNull(signType, "The Sign Type cannot be null");
+        Preconditions.checkArgument(signBlock != null, "The Sign Block cannot be null");
+        Preconditions.checkArgument(face != null, "The Face cannot be null");
+        Preconditions.checkArgument(signType != null, "The Sign Type cannot be null");
 
         if (!signBlock.isEmpty() && !Tag.WALL_SIGNS.isTagged(signBlock.getType())) {
             // something in the way!
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBItem.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBItem.java
index 6923c3ab..ebce478e 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBItem.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBItem.java
@@ -10,7 +10,7 @@
 import javax.annotation.Nullable;
 import javax.annotation.ParametersAreNonnullByDefault;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.ChatColor;
 import org.bukkit.Keyed;
 import org.bukkit.Material;
@@ -110,7 +110,7 @@ protected void updateHeldItemStack(Player player, EquipmentSlot hand) {
      */
     public final boolean checkPlayerPermission(@Nonnull Permissible player, @Nonnull ItemAction action) {
         String prefix = SensibleToolboxPlugin.getInstance().getItemRegistry().getPermissionPrefix(this);
-        Validate.notNull(prefix, "Can't determine permission node prefix for " + getItemTypeID());
+        Preconditions.checkArgument(prefix != null, "Can't determine permission node prefix for " + getItemTypeID());
         return player.hasPermission(prefix + "." + action.getNode() + "." + getItemTypeID());
     }
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBMachine.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBMachine.java
index 8dc758d8..6aeae512 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBMachine.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/items/BaseSTBMachine.java
@@ -11,8 +11,8 @@
 
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Strings;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
@@ -357,7 +357,7 @@ private void buildChargeLabel() {
             }
         }
 
-        s.append(StringUtils.repeat(" ", 15 - s.length()));
+        s.append(Strings.repeat(" ", 15 - s.length()));
         chargeLabel = s.toString();
     }
 
@@ -405,7 +405,7 @@ protected ItemStack getInventoryItem(int slot) {
      *             if the given slot has not previously been configured to hold items
      */
     protected void setInventoryItem(int slot, ItemStack item) {
-        Validate.isTrue(getGUI().getSlotType(slot) == SlotType.ITEM, "Attempt to insert item into non-item slot");
+        Preconditions.checkArgument(getGUI().getSlotType(slot) == SlotType.ITEM, "Attempt to insert item into non-item slot");
         getInventory().setItem(slot, item != null && item.getAmount() > 0 ? item : null);
         update(false);
     }
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeCollection.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeCollection.java
index bbc3a520..2b1837f2 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeCollection.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeCollection.java
@@ -7,7 +7,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.inventory.ItemStack;
 
 import com.google.common.base.Joiner;
@@ -34,7 +34,7 @@ public class CustomRecipeCollection {
      *            wildcarded (data value ignored)
      */
     public void addCustomRecipe(@Nonnull CustomRecipe recipe, boolean allowWild) {
-        Validate.notNull(recipe, "A custom recipe cannot be null");
+        Preconditions.checkArgument(recipe != null, "A custom recipe cannot be null");
         String key = recipe.makeKey(false);
         ProcessingResult pr = new ProcessingResult(recipe.getResult(), recipe.getProcessingTime());
         recipes.put(key, pr);
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeManager.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeManager.java
index cb9c501f..a9cdffdb 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeManager.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/CustomRecipeManager.java
@@ -8,7 +8,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.inventory.ItemStack;
 
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBMachine;
@@ -53,7 +53,7 @@ public static synchronized CustomRecipeManager getManager() {
      *            allow wildcarded data values
      */
     public void addCustomRecipe(@Nonnull CustomRecipe recipe, boolean allowWild) {
-        Validate.notNull(recipe, "A custom recipe cannot be null");
+        Preconditions.checkArgument(recipe != null, "A custom recipe cannot be null");
         CustomRecipeCollection collection = map.get(recipe.getProcessorID());
 
         if (collection == null) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/SupplementaryResult.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/SupplementaryResult.java
index 564e2c60..eb85db49 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/SupplementaryResult.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/api/recipes/SupplementaryResult.java
@@ -2,7 +2,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.inventory.ItemStack;
 
 /**
@@ -25,7 +25,7 @@ public class SupplementaryResult {
      *            the chance, out of 1000, that the item will be produced
      */
     public SupplementaryResult(ItemStack result, int chance) {
-        Validate.isTrue(chance > 0 && chance <= 1000, "chance out of range: must be 0 < chance <= 1000");
+        Preconditions.checkArgument(chance > 0 && chance <= 1000, "chance out of range: must be 0 < chance <= 1000");
         this.result = result;
         this.chance = chance;
     }
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/BlockUpdateDetector.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/BlockUpdateDetector.java
index 2f5a6711..cf33afca 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/BlockUpdateDetector.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/BlockUpdateDetector.java
@@ -1,6 +1,5 @@
 package io.github.thebusybiscuit.sensibletoolbox.blocks;
 
-import org.apache.commons.lang.math.IntRange;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
@@ -21,6 +20,8 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets.NumericGadget;
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets.RedstoneBehaviourGadget;
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBBlock;
+import io.github.thebusybiscuit.sensibletoolbox.utils.IntRange;
+
 import me.desht.dhutils.Debugger;
 
 public class BlockUpdateDetector extends BaseSTBBlock {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/Elevator.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/Elevator.java
index be171167..b1f1067b 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/Elevator.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/Elevator.java
@@ -3,7 +3,7 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.DyeColor;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
@@ -73,7 +73,7 @@ public Recipe getMainRecipe() {
 
     @Nullable
     public Elevator findOtherElevator(@Nonnull BlockFace direction) {
-        Validate.isTrue(direction == BlockFace.UP || direction == BlockFace.DOWN, "direction must be UP or DOWN");
+        Preconditions.checkArgument(direction == BlockFace.UP || direction == BlockFace.DOWN, "direction must be UP or DOWN");
 
         Block b = getLocation().getBlock();
         Elevator res = null;
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/PaintCan.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/PaintCan.java
index 99706b9f..b0b81981 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/PaintCan.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/PaintCan.java
@@ -5,7 +5,7 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.StringUtils;
+import com.google.common.base.Strings;
 import org.bukkit.ChatColor;
 import org.bukkit.DyeColor;
 import org.bukkit.Location;
@@ -302,7 +302,7 @@ protected String[] getSignLabel(BlockFace face) {
         ChatColor cc = STBUtil.dyeColorToChatColor(getColor());
         res[1] = cc.toString() + getColor();
         res[2] = getPaintLevel() + "/" + getMaxPaintLevel();
-        res[3] = cc + StringUtils.repeat("◼", (getPaintLevel() * 13) / getMaxPaintLevel());
+        res[3] = cc + Strings.repeat("◼", (getPaintLevel() * 13) / getMaxPaintLevel());
         return res;
     }
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/RedstoneClock.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/RedstoneClock.java
index 63566bc8..2e7f585a 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/RedstoneClock.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/RedstoneClock.java
@@ -2,7 +2,6 @@
 
 import java.awt.Color;
 
-import org.apache.commons.lang.math.IntRange;
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
 import org.bukkit.Material;
@@ -22,6 +21,7 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets.RedstoneBehaviourGadget;
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBBlock;
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBItem;
+import io.github.thebusybiscuit.sensibletoolbox.utils.IntRange;
 
 public class RedstoneClock extends BaseSTBBlock {
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/SoundMuffler.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/SoundMuffler.java
index 9e03deec..e9256f93 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/SoundMuffler.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/SoundMuffler.java
@@ -1,6 +1,6 @@
 package io.github.thebusybiscuit.sensibletoolbox.blocks;
 
-import org.apache.commons.lang.math.IntRange;
+
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
 import org.bukkit.Material;
@@ -18,6 +18,7 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.gui.gadgets.NumericGadget;
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBBlock;
 import io.github.thebusybiscuit.sensibletoolbox.listeners.SoundMufflerListener;
+import io.github.thebusybiscuit.sensibletoolbox.utils.IntRange;
 
 /**
  * The {@link SoundMuffler} muffles or mutes nearby sounds.
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/AutoBuilder.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/AutoBuilder.java
index dc82fda8..f8b7d22b 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/AutoBuilder.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/AutoBuilder.java
@@ -2,7 +2,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.DyeColor;
@@ -195,7 +195,7 @@ public AutoBuilderMode getBuildMode() {
     }
 
     public void setBuildMode(@Nonnull AutoBuilderMode buildMode) {
-        Validate.notNull(buildMode, "The Build mode cannot be null");
+        Preconditions.checkArgument(buildMode != null, "The Build mode cannot be null");
         this.buildMode = buildMode;
         setStatus(workArea == null ? BuilderStatus.NO_WORKAREA : BuilderStatus.READY);
     }
@@ -245,7 +245,7 @@ public BuilderStatus getStatus() {
     }
 
     private void setStatus(@Nonnull BuilderStatus status) {
-        Validate.notNull(status, "The Status cannot be null");
+        Preconditions.checkArgument(status != null, "The Status cannot be null");
 
         if (status != this.status) {
             this.status = status;
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/BigStorageUnit.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/BigStorageUnit.java
index 6e1e953d..45ed1331 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/BigStorageUnit.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/blocks/machines/BigStorageUnit.java
@@ -6,7 +6,6 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.WordUtils;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
@@ -33,6 +32,7 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.items.AbstractProcessingMachine;
 import io.github.thebusybiscuit.sensibletoolbox.utils.BukkitSerialization;
 import io.github.thebusybiscuit.sensibletoolbox.utils.STBUtil;
+import io.github.thebusybiscuit.sensibletoolbox.utils.WordUtils;
 
 import me.desht.dhutils.Debugger;
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/FriendCommand.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/FriendCommand.java
index f891d6f4..443c8422 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/FriendCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/FriendCommand.java
@@ -4,7 +4,7 @@
 import java.util.Set;
 import java.util.UUID;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.command.CommandSender;
@@ -35,7 +35,7 @@ public boolean execute(Plugin plugin, CommandSender sender, String[] args) {
 
         if (args.length >= 1) {
             UUID id = getID(args[0]);
-            Validate.notNull(id, "Unknown player: " + args[0]);
+            Preconditions.checkArgument(id != null, "Unknown player: " + args[0]);
             fm.addFriend(target.getUniqueId(), id);
             MiscUtil.statusMessage(sender, target.getName() + " is now friends with " + args[0]);
         } else if (args.length == 0) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/GiveCommand.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/GiveCommand.java
index 24266513..811a831a 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/GiveCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/GiveCommand.java
@@ -4,7 +4,7 @@
 import java.util.List;
 import java.util.Locale;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
@@ -57,7 +57,7 @@ public boolean execute(Plugin plugin, CommandSender sender, String[] args) {
 
         String id = args[0].replace(" ", "").toLowerCase(Locale.ROOT);
         BaseSTBItem item = SensibleToolbox.getItemRegistry().getItemById(id);
-        Validate.notNull(item, "Unknown SensibleToolbox item: " + args[0]);
+        Preconditions.checkArgument(item != null, "Unknown SensibleToolbox item: " + args[0]);
         target.getInventory().addItem(item.toItemStack(amount));
         MiscUtil.statusMessage(target, "You received " + amount + " x &6" + item.getItemName() + "&-.");
         return true;
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/RedrawCommand.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/RedrawCommand.java
index d2ee876a..3efc2f9c 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/RedrawCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/RedrawCommand.java
@@ -3,7 +3,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.World;
 import org.bukkit.block.Block;
@@ -32,7 +32,7 @@ public boolean execute(Plugin plugin, CommandSender sender, String[] args) {
 
         if (hasOption("w")) {
             World w = Bukkit.getWorld(getStringOption("w"));
-            Validate.notNull(w, "Unknown world: " + getStringOption("w"));
+            Preconditions.checkArgument(w != null, "Unknown world: " + getStringOption("w"));
             redrawn = redraw(w, type);
         } else {
             for (World w : Bukkit.getWorlds()) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/ShowCommand.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/ShowCommand.java
index 25c7e916..1f0023e6 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/ShowCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/ShowCommand.java
@@ -10,7 +10,7 @@
 
 import javax.annotation.ParametersAreNonnullByDefault;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
@@ -69,7 +69,7 @@ public boolean execute(Plugin plugin, CommandSender sender, String[] args) {
 
             if (hasOption("w")) {
                 World w = Bukkit.getWorld(getStringOption("w"));
-                Validate.notNull(w, "Unknown world: " + getStringOption("w"));
+                Preconditions.checkArgument(w != null, "Unknown world: " + getStringOption("w"));
                 show(pager, w, id);
             } else {
                 for (World w : Bukkit.getWorlds()) {
@@ -127,13 +127,13 @@ private void showDetails(CommandSender sender, MessagePager pager, String locStr
             try {
                 Location loc = MiscUtil.parseLocation(locStr);
                 item = LocationManager.getManager().get(loc);
-                Validate.notNull(item, "No STB block at " + locStr);
+                Preconditions.checkArgument(item != null, "No STB block at " + locStr);
             } catch (IllegalArgumentException e) {
                 throw new DHUtilsException(e.getMessage());
             }
         }
 
-        Validate.notNull(item, "No valid STB item/block found");
+        Preconditions.checkArgument(item != null, "No valid STB item/block found");
 
         YamlConfiguration conf = item.freeze();
         pager.add(ChatColor.AQUA.toString() + item + ":");
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/UnfriendCommand.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/UnfriendCommand.java
index b60131f6..2485004c 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/UnfriendCommand.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/commands/UnfriendCommand.java
@@ -2,7 +2,7 @@
 
 import java.util.UUID;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.plugin.Plugin;
@@ -26,7 +26,7 @@ public boolean execute(Plugin plugin, CommandSender sender, String[] args) {
         Player target = getTargetPlayer(sender, getStringOption("p"));
 
         UUID id = getID(args[0]);
-        Validate.notNull(id, "Unknown player: " + args[0]);
+        Preconditions.checkArgument(id != null, "Unknown player: " + args[0]);
         fm.removeFriend(target.getUniqueId(), id);
         MiscUtil.statusMessage(sender, target.getName() + " is no longer friends with " + args[0]);
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBFriendManager.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBFriendManager.java
index a4709722..9ffa6ebb 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBFriendManager.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBFriendManager.java
@@ -13,7 +13,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.configuration.file.YamlConfiguration;
 
 import io.github.thebusybiscuit.sensibletoolbox.SensibleToolboxPlugin;
@@ -62,7 +62,7 @@ public boolean isFriend(@Nonnull UUID id1, @Nonnull UUID id2) {
     @Override
     @Nonnull
     public Set<UUID> getFriends(@Nonnull UUID id) {
-        Validate.notNull(id, "Cannot get friends for null!");
+        Preconditions.checkArgument(id != null, "Cannot get friends for null!");
 
         return friendMap.computeIfAbsent(id, key -> new HashSet<>());
     }
@@ -115,7 +115,7 @@ private String removeExtension(@Nonnull String name) {
         String separator = File.separator;
         String fileName;
 
-        // Remove the path upto the filename.
+        // Remove the path up to the filename.
         int lastSeparatorIndex = name.lastIndexOf(separator);
 
         if (lastSeparatorIndex == -1) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBItemRegistry.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBItemRegistry.java
index 7e490dd4..2727b3bc 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBItemRegistry.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/STBItemRegistry.java
@@ -13,7 +13,7 @@
 import javax.annotation.Nullable;
 import javax.annotation.ParametersAreNonnullByDefault;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Keyed;
@@ -49,8 +49,8 @@ public class STBItemRegistry implements ItemRegistry, Keyed {
 
     @ParametersAreNonnullByDefault
     public STBItemRegistry(Plugin plugin, String registryKey) {
-        Validate.notNull(plugin, "The Plugin cannot be null");
-        Validate.notNull(registryKey, "The registry cannot be null");
+        Preconditions.checkArgument(plugin != null, "The Plugin cannot be null");
+        Preconditions.checkArgument(registryKey != null, "The registry cannot be null");
 
         this.namespacedKey = new NamespacedKey(plugin, registryKey);
     }
@@ -85,7 +85,7 @@ public <T extends BaseSTBItem> void registerItem(T item, Plugin plugin, String c
         }
 
         String id = item.getItemTypeID();
-        Validate.isTrue(id.length() <= MAX_ITEM_ID_LENGTH, "Item ID '" + id + "' is too long! (32 chars max)");
+        Preconditions.checkArgument(id.length() <= MAX_ITEM_ID_LENGTH, "Item ID '" + id + "' is too long! (32 chars max)");
 
         ReflectionDetails<T> details = new ReflectionDetails<>((Class<T>) item.getClass());
         reflectionDetailsMap.put(id, details);
@@ -146,7 +146,7 @@ public BaseSTBItem fromItemStack(@Nullable ItemStack stack) {
 
     @Nonnull
     private Configuration getItemAttributes(@Nonnull ItemStack stack) {
-        Validate.notNull(stack, "ItemStack cannot be null!");
+        Preconditions.checkArgument(stack != null, "ItemStack cannot be null!");
 
         if (!stack.hasItemMeta()) {
             return new MemoryConfiguration();
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/enderstorage/EnderStorageManager.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/enderstorage/EnderStorageManager.java
index cc02636c..4fa8d811 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/enderstorage/EnderStorageManager.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/enderstorage/EnderStorageManager.java
@@ -10,7 +10,7 @@
 import java.util.Set;
 import java.util.UUID;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.OfflinePlayer;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.Listener;
@@ -48,7 +48,7 @@ File getStorageDir() {
     }
 
     public GlobalEnderHolder getGlobalInventoryHolder(int frequency) {
-        Validate.isTrue(frequency > 0 && frequency <= MAX_ENDER_FREQUENCY, "Frequency out of range: " + frequency);
+        Preconditions.checkArgument(frequency > 0 && frequency <= MAX_ENDER_FREQUENCY, "Frequency out of range: " + frequency);
         GlobalEnderHolder h = globalInvs.get(frequency);
 
         if (h == null) {
@@ -67,7 +67,7 @@ public GlobalEnderHolder getGlobalInventoryHolder(int frequency) {
     }
 
     public PlayerEnderHolder getPlayerInventoryHolder(OfflinePlayer player, Integer frequency) {
-        Validate.isTrue(frequency > 0 && frequency <= MAX_ENDER_FREQUENCY, "Frequency out of range: " + frequency);
+        Preconditions.checkArgument(frequency > 0 && frequency <= MAX_ENDER_FREQUENCY, "Frequency out of range: " + frequency);
         Map<Integer, PlayerEnderHolder> map = playerInvs.get(player.getUniqueId());
 
         if (map == null) {
@@ -105,7 +105,7 @@ private void setupStorageStructure(SensibleToolboxPlugin plugin, File storageDir
                 File newDir = new File(storageDir, f.getName());
                 mkdir(newDir);
                 File newFile = new File(newDir, "1");
-                Validate.isTrue(f.renameTo(newFile), "can't move " + f + " to " + newFile);
+                Preconditions.checkArgument(f.renameTo(newFile), "can't move " + f + " to " + newFile);
             }
 
             for (File f : oldDir.listFiles()) {
@@ -125,7 +125,7 @@ private void setupStorageStructure(SensibleToolboxPlugin plugin, File storageDir
     }
 
     void mkdir(File dir) {
-        Validate.isTrue(dir.mkdir(), "can't create directory: " + dir);
+        Preconditions.checkArgument(dir.mkdir(), "can't create directory: " + dir);
     }
 
     void setChanged(EnderStorageHolder holder) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/gui/STBInventoryGUI.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/gui/STBInventoryGUI.java
index 9170e8da..4c251986 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/gui/STBInventoryGUI.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/gui/STBInventoryGUI.java
@@ -4,8 +4,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.lang.Validate;
-import org.apache.commons.lang.math.IntRange;
+import com.google.common.base.Preconditions;
+
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Location;
@@ -34,6 +34,8 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBItem;
 import io.github.thebusybiscuit.sensibletoolbox.utils.BukkitSerialization;
 import io.github.thebusybiscuit.sensibletoolbox.utils.STBUtil;
+import io.github.thebusybiscuit.sensibletoolbox.utils.IntRange;
+
 import me.desht.dhutils.Debugger;
 import me.desht.dhutils.text.LogUtils;
 
@@ -128,7 +130,7 @@ public void addLabel(String label, int slot, ItemStack texture, String... lore)
 
     @Override
     public int addMonitor(MonitorGadget gadget) {
-        Validate.isTrue(gadget.getSlots().length > 0, "Gadget has no slots!");
+        Preconditions.checkArgument(gadget.getSlots().length > 0, "Gadget has no slots!");
         monitors.add(gadget);
         for (int slot : gadget.getSlots()) {
             setSlotType(slot, SlotType.GADGET);
@@ -138,19 +140,19 @@ public int addMonitor(MonitorGadget gadget) {
 
     @Override
     public ItemStack getItem(int slot) {
-        Validate.isTrue(getSlotType(slot) == SlotType.ITEM, "Slot " + slot + " is not an item slot");
+        Preconditions.checkArgument(getSlotType(slot) == SlotType.ITEM, "Slot " + slot + " is not an item slot");
         return inventory.getItem(slot);
     }
 
     @Override
     public void setItem(int slot, ItemStack stack) {
-        Validate.isTrue(getSlotType(slot) == SlotType.ITEM, "Slot " + slot + " is not an item slot");
+        Preconditions.checkArgument(getSlotType(slot) == SlotType.ITEM, "Slot " + slot + " is not an item slot");
         inventory.setItem(slot, stack);
     }
 
     @Override
     public ClickableGadget getGadget(int slot) {
-        Validate.isTrue(getSlotType(slot) == SlotType.GADGET, "Slot " + slot + " is not a gadget slot");
+        Preconditions.checkArgument(getSlotType(slot) == SlotType.GADGET, "Slot " + slot + " is not a gadget slot");
         return gadgets[slot];
     }
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/storage/LocationManager.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/storage/LocationManager.java
index fc27ecec..398115d1 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/storage/LocationManager.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/core/storage/LocationManager.java
@@ -19,7 +19,7 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.Chunk;
 import org.bukkit.Location;
@@ -114,7 +114,7 @@ DatabaseManager getDatabaseConnection() {
     }
 
     public void addTicker(@Nonnull BaseSTBBlock stb) {
-        Validate.notNull(stb, "Cannot add a ticker that is null!");
+        Preconditions.checkArgument(stb != null, "Cannot add a ticker that is null!");
 
         Location loc = stb.getLocation();
         World w = loc.getWorld();
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/items/EnderTuner.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/items/EnderTuner.java
index 6f5009f2..93d9183d 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/items/EnderTuner.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/items/EnderTuner.java
@@ -2,7 +2,6 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.math.IntRange;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
@@ -27,6 +26,7 @@
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBBlock;
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBItem;
 import io.github.thebusybiscuit.sensibletoolbox.utils.STBUtil;
+import io.github.thebusybiscuit.sensibletoolbox.utils.IntRange;
 
 public class EnderTuner extends BaseSTBItem {
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/listeners/GeneralListener.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/listeners/GeneralListener.java
index 1a7785af..2aa9c338 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/listeners/GeneralListener.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/listeners/GeneralListener.java
@@ -3,7 +3,7 @@
 import java.util.Iterator;
 import java.util.concurrent.ThreadLocalRandom;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.Location;
 import org.bukkit.Material;
@@ -149,7 +149,7 @@ public void onBlockWillPlace(BlockPlaceEvent event) {
         if (stb != null) {
             // sanity check: we should only get here if the item is an STB block, since
             // onBlockPrePlaceCheck() will have cancelled the event if it wasn't
-            Validate.isTrue(stb instanceof BaseSTBBlock, "trying to place a non-block STB item? " + stb.getItemTypeID());
+            Preconditions.checkArgument(stb instanceof BaseSTBBlock, "trying to place a non-block STB item? " + stb.getItemTypeID());
             ((BaseSTBBlock) stb).placeBlock(event.getBlock(), event.getPlayer(), STBUtil.getFaceFromYaw(event.getPlayer().getLocation().getYaw()).getOppositeFace());
 
             if (event.isCancelled()) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/BukkitSerialization.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/BukkitSerialization.java
index 6ffe4857..b9ae3095 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/BukkitSerialization.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/BukkitSerialization.java
@@ -6,7 +6,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.inventory.Inventory;
 import org.bukkit.inventory.ItemStack;
@@ -32,7 +32,7 @@ public static String toBase64(@Nonnull Inventory inventory) {
     }
 
     public static String toBase64(@Nonnull Inventory inventory, int maxItems) {
-        Validate.notNull(inventory, "Cannot serialize a 'null' Inventory!");
+        Preconditions.checkArgument(inventory != null, "Cannot serialize a 'null' Inventory!");
         if (maxItems <= 0 || maxItems > inventory.getSize()) {
             maxItems = inventory.getSize();
         }
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/ColoredMaterial.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/ColoredMaterial.java
index 2891c721..cf11b9a8 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/ColoredMaterial.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/ColoredMaterial.java
@@ -6,7 +6,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.DyeColor;
 import org.bukkit.Material;
 
@@ -190,8 +190,9 @@ public enum ColoredMaterial {
      *            The {@link Material Materials} for this {@link ColoredMaterial}.
      */
     ColoredMaterial(@Nonnull Material[] materials) {
-        Validate.noNullElements(materials, "The List cannot contain any null elements");
-        Validate.isTrue(materials.length == 16, "Expected 16, received: " + materials.length + ". Did you miss a color?");
+        //This one I wasn't sure of, so I'm guessing
+        Preconditions.checkArgument(materials != null, "The List cannot contain any null elements");
+        Preconditions.checkArgument(materials.length == 16, "Expected 16, received: " + materials.length + ". Did you miss a color?");
 
         list = Collections.unmodifiableList(Arrays.asList(materials));
     }
@@ -217,7 +218,7 @@ public List<Material> asList() {
      */
     @Nonnull
     public Material get(int index) {
-        Validate.isTrue(index >= 0 && index < 16, "The index must be between 0 and 15 (inclusive).");
+        Preconditions.checkArgument(index >= 0 && index < 16, "The index must be between 0 and 15 (inclusive).");
 
         return list.get(index);
     }
@@ -232,7 +233,7 @@ public Material get(int index) {
      */
     @Nonnull
     public Material get(@Nonnull DyeColor color) {
-        Validate.notNull(color, "Color cannot be null!");
+        Preconditions.checkArgument(color != null, "Color cannot be null!");
 
         return get(color.ordinal());
     }
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/IntRange.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/IntRange.java
new file mode 100644
index 00000000..a56eeeb7
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/IntRange.java
@@ -0,0 +1,33 @@
+package io.github.thebusybiscuit.sensibletoolbox.utils;
+
+public class IntRange {
+
+    private final int min;
+    private final int max;
+
+    public IntRange(int number) {
+        this(number, number);
+    }
+
+    public IntRange(int number1, int number2) {
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    ///////////////////////////
+    // Accessors
+    ///////////////////////////
+
+    public int getMinimumInt() { return min; }
+    public int getMaximumInt() { return max; }
+
+
+    public boolean containsInteger(int value) {
+        return value >= min && value <= max;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/STBUtil.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/STBUtil.java
index 9ef689cd..f4ade782 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/STBUtil.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/STBUtil.java
@@ -13,8 +13,8 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Strings;
+import com.google.common.base.Preconditions;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.DyeColor;
@@ -562,7 +562,7 @@ public static boolean canFabricateWith(@Nullable ItemStack stack) {
      *            the player
      */
     public static void complain(@Nonnull Player player) {
-        Validate.notNull(player, "Cannot complain to nobody");
+        Preconditions.checkArgument(player != null, "Cannot complain to nobody");
         player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1.0F, 1.0F);
     }
 
@@ -660,7 +660,8 @@ public static ItemStack parseMaterialSpec(String spec) {
         boolean glowing = false;
 
         for (int i = 1; i < fields.length; i++) {
-            if (StringUtils.isNumeric(fields[i])) {
+            // I went with STBUtil here, I couldn't figure out an alternative.
+            if (STBUtil.isNumeric(fields[i])) {
                 amount = Integer.parseInt(fields[i]);
             } else if (fields[i].equalsIgnoreCase("glow")) {
                 glowing = true;
@@ -687,8 +688,8 @@ public static ItemStack parseMaterialSpec(String spec) {
      * @return the number of 90-degree rotations between the faces
      */
     public static int getFaceRotation(BlockFace face1, BlockFace face2) {
-        Validate.isTrue(face1.getModY() == 0 && Math.abs(face1.getModX() + face1.getModZ()) == 1, "invalid face " + face1);
-        Validate.isTrue(face2.getModY() == 0 && Math.abs(face2.getModX() + face2.getModZ()) == 1, "invalid face " + face2);
+        Preconditions.checkArgument(face1.getModY() == 0 && Math.abs(face1.getModX() + face1.getModZ()) == 1, "invalid face " + face1);
+        Preconditions.checkArgument(face2.getModY() == 0 && Math.abs(face2.getModX() + face2.getModZ()) == 1, "invalid face " + face2);
 
         if (face1 == face2) {
             return 0;
@@ -710,7 +711,7 @@ public static int getFaceRotation(BlockFace face1, BlockFace face2) {
      * @return the rotated face
      */
     public static BlockFace getRotatedFace(BlockFace face, int rotation) {
-        Validate.isTrue(face.getModY() == 0 && Math.abs(face.getModX() + face.getModZ()) == 1, "invalid face " + face);
+        Preconditions.checkArgument(face.getModY() == 0 && Math.abs(face.getModX() + face.getModZ()) == 1, "invalid face " + face);
 
         switch (rotation) {
             case 0:
@@ -751,8 +752,8 @@ public static boolean isCable(Block block) {
      */
     public static void levelToDurability(ItemStack stack, int val, int max) {
         short maxDur = stack.getType().getMaxDurability();
-        Validate.isTrue(maxDur > 0, "Item stack " + stack + " does not have a durability bar!");
-        Validate.isTrue(val >= 0 && val <= max, "Value " + val + " out of range 0.." + max);
+        Preconditions.checkArgument(maxDur > 0, "Item stack " + stack + " does not have a durability bar!");
+        Preconditions.checkArgument(val >= 0 && val <= max, "Value " + val + " out of range 0.." + max);
         float d = val / (float) max;
         short dur = (short) (maxDur * d);
         stack.setDurability((short) (Math.max(1, maxDur - dur)));
@@ -800,7 +801,7 @@ public static boolean isPotionIngredient(Material type) {
      */
     @Nullable
     public static Material getWallSign(@Nonnull Material signType) {
-        Validate.notNull(signType, "The Sign Type cannot be null");
+        Preconditions.checkArgument(signType != null, "The Sign Type cannot be null");
 
         if (SensibleToolboxPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
             if (signType == Material.CRIMSON_SIGN) {
@@ -886,7 +887,7 @@ public static DyeColor getColorFromDye(@Nonnull Material type) {
      */
     @Nullable
     public static String getPlayerNameFromUUID(@Nonnull UUID uuid) {
-        Validate.notNull(uuid, "UUID cannot be null!");
+        Preconditions.checkArgument(uuid != null, "UUID cannot be null!");
         return Bukkit.getOfflinePlayer(uuid).getName();
     }
 
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/VanillaInventoryUtils.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/VanillaInventoryUtils.java
index f0d37407..edcfdaf9 100644
--- a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/VanillaInventoryUtils.java
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/VanillaInventoryUtils.java
@@ -8,7 +8,6 @@
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.apache.commons.lang.math.IntRange;
 import org.bukkit.Bukkit;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
@@ -209,7 +208,7 @@ public static ItemStack pullFromInventory(Inventory targetInv, int amount, ItemS
             return null;
         }
         IntRange range = getExtractionSlots(targetInv);
-        for (int slot = range.getMinimumInteger(); slot <= range.getMaximumInteger(); slot++) {
+        for (int slot = range.getMinimumInt(); slot <= range.getMaximumInt(); slot++) {
             ItemStack stack = targetInv.getItem(slot);
 
             if (stack != null) {
diff --git a/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/WordUtils.java b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/WordUtils.java
new file mode 100644
index 00000000..35ea9d42
--- /dev/null
+++ b/src/main/java/io/github/thebusybiscuit/sensibletoolbox/utils/WordUtils.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.thebusybiscuit.sensibletoolbox.utils;
+
+
+/**<p>This class is modified from Apache's commons-lang package.
+ * <p>Operations on Strings that contain words.</p>
+ *
+ * <p>This class tries to handle <code>null</code> input gracefully.
+ * An exception will not be thrown for a <code>null</code> input.
+ * Each method documents its behaviour in more detail.</p>
+ *
+ * @author Apache Jakarta Velocity
+ * @author Apache Software Foundation
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: WordUtils.java 905636 2010-02-02 14:03:32Z niallp $
+ */
+public final class WordUtils {
+
+    private WordUtils() {}
+
+    /**
+     * <p>Wraps a single line of text, identifying words by <code>' '</code>.</p>
+     *
+     * <p>New lines will be separated by the system property line separator.
+     * Very long words, such as URLs will <i>not</i> be wrapped.</p>
+     *
+     * <p>Leading spaces on a new line are stripped.
+     * Trailing spaces are not stripped.</p>
+     *
+     * <pre>
+     * WordUtils.wrap(null, *) = null
+     * WordUtils.wrap("", *) = ""
+     * </pre>
+     *
+     * @param str  the String to be word wrapped, may be null
+     * @param wrapLength  the column to wrap the words at, less than 1 is treated as 1
+     * @return a line with newlines inserted, <code>null</code> if null input
+     */
+    public static String wrap(String str, int wrapLength) {
+        return wrap(str, wrapLength, null, false);
+    }
+
+    /**
+     * <p>Wraps a single line of text, identifying words by <code>' '</code>.</p>
+     *
+     * <p>Leading spaces on a new line are stripped.
+     * Trailing spaces are not stripped.</p>
+     *
+     * <pre>
+     * WordUtils.wrap(null, *, *, *) = null
+     * WordUtils.wrap("", *, *, *) = ""
+     * </pre>
+     *
+     * @param str  the String to be word wrapped, may be null
+     * @param wrapLength  the column to wrap the words at, less than 1 is treated as 1
+     * @param newLineStr  the string to insert for a new line,
+     *  <code>null</code> uses the system property line separator
+     * @param wrapLongWords  true if long words (such as URLs) should be wrapped
+     * @return a line with newlines inserted, <code>null</code> if null input
+     */
+    public static String wrap(String str, int wrapLength, String newLineStr, boolean wrapLongWords) {
+        if (str == null) {
+            return null;
+        }
+        if (newLineStr == null) {
+            newLineStr = java.lang.System.lineSeparator();
+        }
+        if (wrapLength < 1) {
+            wrapLength = 1;
+        }
+        int inputLineLength = str.length();
+        int offset = 0;
+        StringBuffer wrappedLine = new StringBuffer(inputLineLength + 32);
+
+        while ((inputLineLength - offset) > wrapLength) {
+            if (str.charAt(offset) == ' ') {
+                offset++;
+                continue;
+            }
+            int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);
+
+            if (spaceToWrapAt >= offset) {
+                // normal case
+                wrappedLine.append(str.substring(offset, spaceToWrapAt));
+                wrappedLine.append(newLineStr);
+                offset = spaceToWrapAt + 1;
+
+            } else {
+                // really long word or URL
+                if (wrapLongWords) {
+                    // wrap really long word one line at a time
+                    wrappedLine.append(str.substring(offset, wrapLength + offset));
+                    wrappedLine.append(newLineStr);
+                    offset += wrapLength;
+                } else {
+                    // do not wrap really long word, just extend beyond limit
+                    spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
+                    if (spaceToWrapAt >= 0) {
+                        wrappedLine.append(str.substring(offset, spaceToWrapAt));
+                        wrappedLine.append(newLineStr);
+                        offset = spaceToWrapAt + 1;
+                    } else {
+                        wrappedLine.append(str.substring(offset));
+                        offset = inputLineLength;
+                    }
+                }
+            }
+        }
+
+        // Whatever is left in line is short enough to just pass through
+        wrappedLine.append(str.substring(offset));
+
+        return wrappedLine.toString();
+    }
+}
diff --git a/src/main/java/me/desht/dhutils/blocks/RelativePosition.java b/src/main/java/me/desht/dhutils/blocks/RelativePosition.java
index ce2224f0..b3bb8c9a 100644
--- a/src/main/java/me/desht/dhutils/blocks/RelativePosition.java
+++ b/src/main/java/me/desht/dhutils/blocks/RelativePosition.java
@@ -1,6 +1,6 @@
 package me.desht.dhutils.blocks;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 
 import io.github.thebusybiscuit.sensibletoolbox.api.items.BaseSTBBlock;
 
@@ -19,7 +19,7 @@ public class RelativePosition {
     private final int left;
 
     public RelativePosition(int front, int up, int left) {
-        Validate.isTrue(front != 0 || up != 0 || left != 0, "At least one of front, up, left must be non-zero");
+        Preconditions.checkArgument(front != 0 || up != 0 || left != 0, "At least one of front, up, left must be non-zero");
         this.front = front;
         this.up = up;
         this.left = left;
diff --git a/src/main/java/me/desht/dhutils/commands/AbstractCommand.java b/src/main/java/me/desht/dhutils/commands/AbstractCommand.java
index beadd651..c2c90f57 100644
--- a/src/main/java/me/desht/dhutils/commands/AbstractCommand.java
+++ b/src/main/java/me/desht/dhutils/commands/AbstractCommand.java
@@ -12,8 +12,8 @@
 import javax.annotation.Nonnull;
 import javax.annotation.ParametersAreNonnullByDefault;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Strings;
+import com.google.common.base.Preconditions;
 import org.bukkit.command.CommandSender;
 import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.entity.Player;
@@ -67,7 +67,7 @@ public AbstractCommand(String label, int minArgs, int maxArgs) {
     public abstract boolean execute(Plugin plugin, CommandSender sender, String[] args);
 
     public void addAlias(@Nonnull String label) {
-        Validate.notNull(label, "The alias cannot be null");
+        Preconditions.checkArgument(label != null, "The alias cannot be null");
         String[] fields = label.split(" ");
         cmdRecs.add(new CommandRecord(fields));
     }
@@ -218,7 +218,7 @@ protected void showUsage(CommandSender sender, String alias, String prefix) {
             indent = "";
         } else {
             int l = prefix.length();
-            indent = sender instanceof Player ? StringUtils.repeat(" ", l + 2) : StringUtils.repeat(" ", l);
+            indent = sender instanceof Player ? Strings.repeat(" ", l + 2) : Strings.repeat(" ", l);
         }
 
         for (int i = 0; i < usage.length; i++) {
diff --git a/src/main/java/me/desht/dhutils/commands/CommandManager.java b/src/main/java/me/desht/dhutils/commands/CommandManager.java
index 0f3ca679..17acfb6d 100644
--- a/src/main/java/me/desht/dhutils/commands/CommandManager.java
+++ b/src/main/java/me/desht/dhutils/commands/CommandManager.java
@@ -8,7 +8,7 @@
 
 import javax.annotation.Nonnull;
 
-import org.apache.commons.lang.Validate;
+import com.google.common.base.Preconditions;
 import org.bukkit.Sound;
 import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
@@ -31,7 +31,7 @@ public CommandManager(@Nonnull Plugin plugin) {
     }
 
     public void registerCommand(@Nonnull AbstractCommand cmd) {
-        Validate.notNull(cmd, "Command cannot be null!");
+        Preconditions.checkArgument(cmd != null, "Command cannot be null!");
 
         Debugger.getInstance().debug(2, "register command: " + cmd.getClass().getName());
         cmdList.add(cmd);