From 869ab8ad507195e98fc7646aa25fbbee6dba770f Mon Sep 17 00:00:00 2001
From: mathias <mail@mathias.is>
Date: Tue, 13 Nov 2018 02:32:21 +0200
Subject: [PATCH] Push unfinished code

---
 pom.xml                                      |  25 ++-
 src/main/java/pw/kaboom/extras/Commands.java |  62 ++++++-
 src/main/java/pw/kaboom/extras/Events.java   | 167 +++++++++++++++----
 src/main/java/pw/kaboom/extras/Main.java     |  70 +++++++-
 src/main/resources/plugin.yml                |   3 +
 5 files changed, 281 insertions(+), 46 deletions(-)

diff --git a/pom.xml b/pom.xml
index 60f62a9..32deb28 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,28 +4,41 @@
 	<artifactId>Extras</artifactId>
 	<version>master</version>
 
+	<properties>
+		<maven.compiler.source>11</maven.compiler.source>
+		<maven.compiler.target>11</maven.compiler.target>
+	</properties>
+
 	<dependencies>
 		<dependency>
 			<groupId>com.destroystokyo.paper</groupId>
 			<artifactId>paper-api</artifactId>
 			<version>1.12.2-R0.1-SNAPSHOT</version>
-			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.boydti</groupId>
+			<artifactId>fawe-api</artifactId>
+			<version>latest</version>
 		</dependency>
 		<dependency>
 			<groupId>com.sk89q.worldedit</groupId>
 			<artifactId>worldedit-bukkit</artifactId>
-			<version>6.1.1-SNAPSHOT</version>
+			<version>6.1.4-SNAPSHOT</version>
 		</dependency>
 	</dependencies>
 
 	<repositories>
 		<repository>
-			<id>destroystokyo-repo</id>
-			<url>https://repo.destroystokyo.com/repository/maven-public/</url>
+			<id>papermc</id>
+			<url>https://papermc.io/repo/repository/maven-public/</url>
 		</repository>
 		<repository>
-			<id>sk89q-snapshots</id>
-			<url>http://maven.sk89q.com/artifactory/repo</url>
+			<id>fawe</id>
+			<url>https://ci.athion.net/job/FastAsyncWorldEdit/ws/mvn/</url>
+		</repository>
+		<repository>
+			<id>worldedit</id>
+			<url>https://maven.sk89q.com/repo/</url>
 		</repository>
 	</repositories>
 
diff --git a/src/main/java/pw/kaboom/extras/Commands.java b/src/main/java/pw/kaboom/extras/Commands.java
index f6d8699..ab6d4ff 100644
--- a/src/main/java/pw/kaboom/extras/Commands.java
+++ b/src/main/java/pw/kaboom/extras/Commands.java
@@ -1,6 +1,14 @@
 package pw.kaboom.extras;
 
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.HttpURLConnection;
+
 import com.destroystokyo.paper.profile.PlayerProfile;
+import com.destroystokyo.paper.profile.ProfileProperty;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
@@ -23,6 +31,8 @@ import org.bukkit.entity.Player;
 
 import org.bukkit.inventory.ItemStack;
 
+import org.bukkit.scheduler.BukkitRunnable;
+
 class CommandClearChat implements CommandExecutor {
 	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 		for (int i = 0; i < 100; ++i) {
@@ -169,6 +179,49 @@ class CommandPrefix implements CommandExecutor {
 	}
 }
 
+class CommandSkin implements CommandExecutor {
+	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+		Player player = (Player)sender;
+		if (args.length == 0) {
+			player.sendMessage(ChatColor.RED + "Usage: /" + label + " <username>");
+		} else {
+			try {
+				String name = args[0];
+				URL nameurl = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
+				HttpURLConnection nameconnection = (HttpURLConnection) nameurl.openConnection();
+
+				if (nameconnection.getResponseCode() == 200) {
+					InputStreamReader namestream = new InputStreamReader(nameconnection.getInputStream());
+					String uuid = new JsonParser().parse(namestream).getAsJsonObject().get("id").getAsString();
+					URL uuidurl = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
+					HttpURLConnection uuidconnection = (HttpURLConnection) uuidurl.openConnection();
+
+					if (uuidconnection.getResponseCode() == 200) {
+						InputStreamReader uuidstream = new InputStreamReader(uuidconnection.getInputStream());
+						JsonObject response = new JsonParser().parse(uuidstream).getAsJsonObject().get("properties").getAsJsonArray().get(0).getAsJsonObject();
+						String texture = response.get("value").getAsString();
+						String signature = response.get("signature").getAsString();
+
+						PlayerProfile textureprofile = player.getPlayerProfile();
+						textureprofile.setProperty(new ProfileProperty("textures", texture, signature));
+						player.setPlayerProfile(textureprofile);
+						player.sendMessage("Successfully set your skin to " + name + "'s");
+					} else {
+						player.sendMessage("Failed to change skin. Try again later");
+					}
+					uuidconnection.disconnect();
+				} else {
+					player.sendMessage("A player with that username doesn't exist");
+				}
+				nameconnection.disconnect();
+			} catch (Exception exception) {
+				exception.printStackTrace();
+			}
+		}
+		return true;
+	}
+}
+
 class CommandSpawn implements CommandExecutor {
 	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 		Player player = (Player)sender;
@@ -205,6 +258,11 @@ class CommandUnloadChunks implements CommandExecutor {
 }
 
 class CommandUsername implements CommandExecutor {
+	Main main;
+	CommandUsername(Main main) {
+		this.main = main;
+	}
+
 	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 		Player player = (Player)sender;
 		if (args.length == 0) {
@@ -215,10 +273,10 @@ class CommandUsername implements CommandExecutor {
 
 			PlayerProfile profile = player.getPlayerProfile();
 			profile.setName(name);
-			profile.complete();
-			profile.clearProperties();
 			player.setPlayerProfile(profile);
 			player.sendMessage("Successfully set your username to \"" + name + "\"");
+
+			main.getSkin(name, player);
 		}
 		return true;
 	}
diff --git a/src/main/java/pw/kaboom/extras/Events.java b/src/main/java/pw/kaboom/extras/Events.java
index 73e9966..493d106 100644
--- a/src/main/java/pw/kaboom/extras/Events.java
+++ b/src/main/java/pw/kaboom/extras/Events.java
@@ -1,9 +1,13 @@
 package pw.kaboom.extras;
 
-import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 
+import com.boydti.fawe.FaweAPI;
+
 import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
+import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
@@ -17,6 +21,7 @@ import org.bukkit.attribute.Attribute;
 import org.bukkit.attribute.AttributeInstance;
 
 import org.bukkit.block.Block;
+import org.bukkit.block.CreatureSpawner;
 
 import org.bukkit.entity.Player;
 import org.bukkit.entity.Entity;
@@ -28,9 +33,12 @@ import org.bukkit.entity.Slime;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.Listener;
 
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockDispenseEvent;
 import org.bukkit.event.block.BlockExplodeEvent;
 import org.bukkit.event.block.BlockFromToEvent;
 import org.bukkit.event.block.BlockPhysicsEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
 import org.bukkit.event.block.BlockRedstoneEvent;
 
 import org.bukkit.event.entity.EntityChangeBlockEvent;
@@ -41,6 +49,7 @@ import org.bukkit.event.entity.EntitySpawnEvent;
 import org.bukkit.event.entity.ExplosionPrimeEvent;
 import org.bukkit.event.entity.LingeringPotionSplashEvent;
 import org.bukkit.event.entity.PotionSplashEvent;
+import org.bukkit.event.entity.SpawnerSpawnEvent;
 
 import org.bukkit.event.hanging.HangingPlaceEvent;
 
@@ -49,36 +58,39 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
 import org.bukkit.event.player.PlayerJoinEvent;
 import org.bukkit.event.player.PlayerKickEvent;
 import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerLoginEvent.Result;
 import org.bukkit.event.player.PlayerRespawnEvent;
 
 import org.bukkit.event.server.ServerCommandEvent;
 import org.bukkit.event.server.ServerListPingEvent;
 
+import org.bukkit.inventory.ItemStack;
+
 import org.bukkit.scheduler.BukkitRunnable;
 
 import org.spigotmc.event.player.PlayerSpawnLocationEvent;
 
 import com.sk89q.worldedit.EditSession;
 import com.sk89q.worldedit.Vector;
-import com.sk89q.worldedit.WorldEdit;
-import com.sk89q.worldedit.bukkit.BukkitWorld;
-import com.sk89q.worldedit.schematic.SchematicFormat;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
+import com.sk89q.worldedit.math.transform.Transform;
 
 class PasteSpawn extends BukkitRunnable {
+	Main main;
+	PasteSpawn(Main main) {
+		this.main = main;
+	}
+
 	public void run() {
-		File file = new File("worlds/world/spawn.schematic");
+		boolean allowUndo = false;
 		boolean noAir = false;
-		boolean entities = false;
-		BukkitWorld world = new BukkitWorld(Bukkit.getServer().getWorld("world"));
-		EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
 		Vector position = new Vector(0, 100, 0);
 
 		try {
-			SchematicFormat.getFormat(file).load(file).paste(editSession, position, noAir, entities);
-			editSession.flushQueue();
+			EditSession editSession = ClipboardFormat.findByFile(main.spawnSchematic).load(main.spawnSchematic).paste(FaweAPI.getWorld("world"), position, allowUndo, !noAir, (Transform) null);
 		} catch(Exception exception) {
 			exception.printStackTrace();
-		}
+ 		}
 	}
 }
 
@@ -91,6 +103,17 @@ class Tick extends BukkitRunnable {
 			} else if (worldborder.getCenter().getX() != 0 || worldborder.getCenter().getZ() != 0) {
 				worldborder.setCenter(0, 0);
 			}
+
+			for (Entity entity : world.getEntities()) {
+				if (entity instanceof LivingEntity) {
+					LivingEntity mob = (LivingEntity) entity;
+					AttributeInstance followAttribute = mob.getAttribute(Attribute.GENERIC_FOLLOW_RANGE);
+
+					if (followAttribute != null && followAttribute.getBaseValue() > 32) {
+						followAttribute.setBaseValue(32);
+					}
+				}
+			}
 		}
 	}
 }
@@ -118,6 +141,19 @@ class Events implements Listener {
 		}
 	}
 
+	@EventHandler
+	void onBlockBreak(BlockBreakEvent event) {
+		for (ItemStack item : event.getBlock().getDrops()) {
+			main.editMeta(item);
+		}
+	}
+
+	@EventHandler
+	void onBlockDispense(BlockDispenseEvent event) {
+		ItemStack item = event.getItem();
+		main.editMeta(item);
+	}
+
 	@EventHandler
 	void onBlockExplode(BlockExplodeEvent event) {
 		Block block = event.getBlock();
@@ -164,14 +200,19 @@ class Events implements Listener {
 		}
 
 		if (block.getType() == Material.SOIL ||
-		block.getType() == Material.STATIONARY_LAVA ||
-		block.getType() == Material.STATIONARY_WATER ||
 		block.getType() == Material.LAVA ||
 		block.getType() == Material.WATER) {
 			event.setCancelled(true);
 		}
         }
 
+	@EventHandler
+	void onBlockPlace(BlockPlaceEvent event) {
+		if (event.getItemInHand().toString().length() > 3019) {
+			event.setCancelled(true);
+		}
+        }
+
 	@EventHandler
 	void onBlockRedstone(BlockRedstoneEvent event) {
 		double tps = Bukkit.getServer().getTPS()[0];
@@ -184,28 +225,28 @@ class Events implements Listener {
 	@EventHandler
 	void onEntityAddToWorld(EntityAddToWorldEvent event) {
 		Entity entity = event.getEntity();
-		Location entityLocation = entity.getLocation();
-
+		Entity[] chunkEntities = entity.getLocation().getChunk().getEntities();
 		int onChunk = 0;
-		for (Entity chunkEntity : entityLocation.getWorld().getEntities()) {
-			if (entityLocation.getChunk() == chunkEntity.getLocation().getChunk()) {
+
+		for (Entity chunkEntity : chunkEntities) {
+			if (onChunk < 50 && !(chunkEntity instanceof Player)) {
 				onChunk++;
 			}
 		}
 
-		if (onChunk >= 50) {
+		if (onChunk == 50 && !(entity instanceof LivingEntity)) {
 			entity.remove();
 		}
 
-		if (entity.getType() == EntityType.MAGMA_CUBE) {
-			MagmaCube magmacube = (MagmaCube) event.getEntity();
+		if (entity instanceof MagmaCube) {
+			MagmaCube magmacube = (MagmaCube) entity;
 			if (magmacube.getSize() > 100) {
 				magmacube.setSize(100);
 			}
 		}
 
-		if (entity.getType() == EntityType.SLIME) {
-			Slime slime = (Slime) event.getEntity();
+		if (entity instanceof Slime) {
+			Slime slime = (Slime) entity;
 			if (slime.getSize() > 100) {
 				slime.setSize(100);
 			}
@@ -264,24 +305,26 @@ class Events implements Listener {
 	@EventHandler
 	void onEntitySpawn(EntitySpawnEvent event) {
 		Entity entity = event.getEntity();
-		LivingEntity mob = (LivingEntity) event.getEntity();
-		Location entityLocation = event.getLocation();
-
+		Entity[] chunkEntities = event.getLocation().getChunk().getEntities();
 		int onChunk = 0;
-		for (Entity chunkEntity : entityLocation.getWorld().getEntities()) {
-			if (entityLocation.getChunk() == chunkEntity.getLocation().getChunk()) {
+
+		for (Entity chunkEntity : chunkEntities) {
+			if (onChunk < 50 && !(chunkEntity instanceof Player)) {
 				onChunk++;
 			}
 		}
 
-		if (onChunk >= 50) {
+		if (onChunk == 50 && !(entity instanceof Player)) {
 			event.setCancelled(true);
 		}
 
-		AttributeInstance followAttribute = mob.getAttribute(Attribute.GENERIC_FOLLOW_RANGE);
+		if (entity instanceof LivingEntity) {
+			LivingEntity mob = (LivingEntity) entity;
+			AttributeInstance followAttribute = mob.getAttribute(Attribute.GENERIC_FOLLOW_RANGE);
 
-		if (followAttribute.getBaseValue() > 32) {
-			followAttribute.setBaseValue(32);
+			if (followAttribute != null && followAttribute.getBaseValue() > 32) {
+				followAttribute.setBaseValue(32);
+			}
 		}
 	}
 
@@ -355,8 +398,10 @@ class Events implements Listener {
 			}
 		} else if (arr[0].toLowerCase().equals("/minecraft:gamerule") ||
 		arr[0].toLowerCase().equals("/gamerule")) {
-			if (arr[2] != null && Integer.parseInt(arr[2]) > 6) {
-				event.setMessage(String.join(" ", arr[0], arr[1]) + " 6");
+			if (arr[1] != null && arr[1].toLowerCase().equals("randomtickspeed")) {
+				if (arr[2] != null && Integer.parseInt(arr[2]) > 6) {
+					event.setMessage(String.join(" ", arr[0], arr[1]) + " 6");
+				}
 			}
 		} else if (arr[0].toLowerCase().equals("/minecraft:particle") ||
 		arr[0].toLowerCase().equals("/particle")) {
@@ -369,6 +414,15 @@ class Events implements Listener {
 	@EventHandler
 	void onPlayerJoin(PlayerJoinEvent event) {
 		Player player = event.getPlayer();
+
+		/*if (player.getInventory().getContents() != null) {
+			for (ItemStack item : player.getInventory().getContents()) {
+				main.editMeta(item);
+			}
+		}*/
+		player.getInventory().clear();
+
+		main.getSkin(player.getName(), player);
 		player.setOp(true);
 		player.sendTitle(ChatColor.GRAY + "Kaboom.pw", "Free OP • Anarchy • Creative", 10, 160, 5);
 	}
@@ -380,7 +434,18 @@ class Events implements Listener {
 
 	@EventHandler
 	void onPlayerLogin(PlayerLoginEvent event) {
-		event.allow();
+		if (Bukkit.getOnlinePlayers().size() > 30) {
+			if (main.onlineCount == 5) {
+				event.allow();
+				main.onlineCount = 0;
+			} else {
+				event.disallow(Result.KICK_OTHER, "The server is throttled due to bot attacks. Please try logging in again.");
+				main.onlineCount++;
+			}
+		} else {
+			event.allow();
+		}
+		/*event.allow();*/
 	}
 
 	@EventHandler
@@ -401,6 +466,22 @@ class Events implements Listener {
 		}
 	}
 
+	@EventHandler
+	void onPreCreatureSpawn(PreCreatureSpawnEvent event) {
+		Entity[] chunkEntities = event.getSpawnLocation().getChunk().getEntities();
+		int onChunk = 0;
+
+		for (Entity chunkEntity : chunkEntities) {
+			if (onChunk < 50 && event.getType() != EntityType.PLAYER) {
+				onChunk++;
+			}
+		}
+
+		if (onChunk == 50 && event.getType() != EntityType.PLAYER) {
+			event.setCancelled(true);
+		}
+	}
+
 	@EventHandler
 	void onServerCommand(ServerCommandEvent event) {
 		String arr[] = event.getCommand().split(" ");
@@ -420,8 +501,10 @@ class Events implements Listener {
 			}
 		} else if (arr[0].toLowerCase().equals("/minecraft:gamerule") ||
 		arr[0].toLowerCase().equals("/gamerule")) {
-			if (arr[2] != null && Integer.parseInt(arr[2]) > 6) {
-				event.setCommand(String.join(" ", arr[0], arr[1]) + " 6");
+			if (arr[1] != null && arr[1].toLowerCase().equals("randomtickspeed")) {
+				if (arr[2] != null && Integer.parseInt(arr[2]) > 6) {
+					event.setCommand(String.join(" ", arr[0], arr[1]) + " 6");
+				}
 			}
 		} else if (arr[0].toLowerCase().equals("minecraft:particle") ||
 		arr[0].toLowerCase().equals("particle")) {
@@ -435,4 +518,16 @@ class Events implements Listener {
 	void onServerListPing(ServerListPingEvent event) {
 		event.setMaxPlayers(event.getNumPlayers() + 1);
 	}
+
+	@EventHandler
+	void onSpawnerSpawn(SpawnerSpawnEvent event) {
+		CreatureSpawner spawner = event.getSpawner();
+		Entity entity = event.getEntity();
+		LivingEntity mob = (LivingEntity) entity;
+
+		if (spawner.getSpawnCount() > 200) {
+			spawner.setSpawnCount(200);
+			spawner.update();
+		}
+	}
 }
diff --git a/src/main/java/pw/kaboom/extras/Main.java b/src/main/java/pw/kaboom/extras/Main.java
index 604e688..7aed69e 100644
--- a/src/main/java/pw/kaboom/extras/Main.java
+++ b/src/main/java/pw/kaboom/extras/Main.java
@@ -1,11 +1,32 @@
 package pw.kaboom.extras;
 
+import java.io.File;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.HttpURLConnection;
 import java.util.Arrays;
 import java.util.HashSet;
 
+import com.destroystokyo.paper.profile.PlayerProfile;
+import com.destroystokyo.paper.profile.ProfileProperty;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import org.bukkit.Color;
+import org.bukkit.Material;
+
+import org.bukkit.entity.Player;
+
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.LeatherArmorMeta;
+import org.bukkit.inventory.meta.PotionMeta;
+
 import org.bukkit.plugin.java.JavaPlugin;
 
 public class Main extends JavaPlugin {
+	int onlineCount = 0;
+	File spawnSchematic = new File("worlds/world/spawn.schematic");
 	HashSet<String> consoleCommandBlacklist = new HashSet<String>(Arrays.asList(new String[] {
 		"essentials:action",
 		"essentials:adventure",
@@ -341,13 +362,58 @@ public class Main extends JavaPlugin {
 		this.getCommand("enchantall").setExecutor(new CommandEnchantAll());
 		this.getCommand("jumpscare").setExecutor(new CommandJumpscare());
 		this.getCommand("prefix").setExecutor(new CommandPrefix(this));
+		this.getCommand("skin").setExecutor(new CommandSkin());
 		this.getCommand("spawn").setExecutor(new CommandSpawn());
 		this.getCommand("tellraw").setExecutor(new CommandTellraw());
 		this.getCommand("unloadchunks").setExecutor(new CommandUnloadChunks());
-		this.getCommand("username").setExecutor(new CommandUsername());
+		this.getCommand("username").setExecutor(new CommandUsername(this));
 
-		new PasteSpawn().runTaskTimer(this, 0, 100);
+		new PasteSpawn(this).runTaskTimer(this, 0, 200);
 		new Tick().runTaskTimer(this, 0, 1);
 		this.getServer().getPluginManager().registerEvents(new Events(this), this);
 	}
+
+	public void getSkin(String name, Player player) {
+		try {
+			URL nameurl = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
+			HttpURLConnection nameconnection = (HttpURLConnection) nameurl.openConnection();
+
+			if (nameconnection.getResponseCode() == 200) {
+				InputStreamReader namestream = new InputStreamReader(nameconnection.getInputStream());
+				String uuid = new JsonParser().parse(namestream).getAsJsonObject().get("id").getAsString();
+				URL uuidurl = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
+				HttpURLConnection uuidconnection = (HttpURLConnection) uuidurl.openConnection();
+
+				if (uuidconnection.getResponseCode() == 200) {
+					InputStreamReader uuidstream = new InputStreamReader(uuidconnection.getInputStream());
+					JsonObject response = new JsonParser().parse(uuidstream).getAsJsonObject().get("properties").getAsJsonArray().get(0).getAsJsonObject();
+					String texture = response.get("value").getAsString();
+					String signature = response.get("signature").getAsString();
+
+					PlayerProfile textureprofile = player.getPlayerProfile();
+					textureprofile.setProperty(new ProfileProperty("textures", texture, signature));
+					player.setPlayerProfile(textureprofile);
+				}
+				uuidconnection.disconnect();
+			}
+			nameconnection.disconnect();
+		} catch (Exception exception) {
+			exception.printStackTrace();
+		}
+	}
+
+	public void editMeta(ItemStack item) {
+		if (item.getType() == Material.LINGERING_POTION ||
+		item.getType() == Material.POTION ||
+		item.getType() == Material.SPLASH_POTION) {
+			PotionMeta potion = (PotionMeta) item.getItemMeta();
+			potion.setColor(Color.WHITE);
+		} else if (item.getType() == Material.LEATHER_BOOTS ||
+		item.getType() == Material.LEATHER_CHESTPLATE ||
+		item.getType() == Material.LEATHER_HELMET ||
+		item.getType() == Material.LEATHER_LEGGINGS) {
+			LeatherArmorMeta armor = (LeatherArmorMeta) item.getItemMeta();
+			armor.setColor(Color.fromRGB(160,101,64));
+		}
+	}
 }
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 3f7a48f..f9f7637 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -29,6 +29,9 @@ commands:
       aliases: [rank, tag]
       description: Changes your tag
       permission: extras.prefix
+   skin:
+      description: Changes your skin
+      permission: extras.skin
    spawn:
       description: Teleports you to spawn
       permission: extras.spawn