Skip to content

Commit 4a38e3e

Browse files
Merge pull request #102 from ParallelMC/hats
Hats
2 parents 66da060 + 251a53d commit 4a38e3e

7 files changed

Lines changed: 196 additions & 1 deletion

File tree

api/build.gradle

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ bukkit {
303303
description = 'Opens the point redemption shop for a player'
304304
usage = '/openpointsredemption (player)'
305305
}
306+
hat {
307+
description = 'Allows you to wear the item in your main hand as a hat'
308+
usage = '/hat'
309+
permissionMessage = 'You do not have permission.'
310+
permission = 'parallelutils.hat.*'
311+
}
306312
}
307313

308314
permissions {
@@ -502,5 +508,8 @@ bukkit {
502508
'parallelutils.recalculatepoints' {
503509
description = 'Gives access to the /recalculatepoints dev command'
504510
}
511+
'parallelutils.hat.*' {
512+
description = 'Allows you to wear any item as a hat'
513+
}
505514
}
506515
}

api/src/main/java/parallelmc/parallelutils/Constants.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package parallelmc.parallelutils;
22

3-
import java.util.ArrayList;
3+
import net.kyori.adventure.text.Component;
4+
import net.kyori.adventure.text.minimessage.MiniMessage;
45

56
public class Constants {
67

78
public static final Version VERSION = new Version(4, 4, 0);
89
public static final String PLUGIN_NAME = "ParallelUtils";
10+
public static final Component PLUGIN_PREFIX = MiniMessage.miniMessage()
11+
.deserialize("<dark_aqua>[<white><bold>P</bold><dark_aqua>] <reset>");
912
public static final String DEFAULT_WORLD = "world2";
1013

1114
public static final String[] OVERWORLD_TYPE_WORLDS = {"world", "world2", "world_skyteaser"};
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package parallelmc.parallelutils.util;
2+
3+
import net.kyori.adventure.text.Component;
4+
import net.kyori.adventure.text.TextComponent;
5+
import net.kyori.adventure.text.format.NamedTextColor;
6+
import org.bukkit.Bukkit;
7+
import org.bukkit.entity.Player;
8+
import parallelmc.parallelutils.Constants;
9+
10+
/**
11+
* A set of utilities to make sending messages easier
12+
*/
13+
public class MessageTools {
14+
15+
/**
16+
* Sends a message to a player with the Parallel prefix prepended to it
17+
* (This version of the method sends an "INFO" style message)
18+
* @param player The player to send the message to
19+
* @param message The message without the prefix
20+
*/
21+
public static void sendMessage(Player player, String message) {
22+
TextComponent finalMessage = (TextComponent) Constants.PLUGIN_PREFIX
23+
.append(Component.text(message, NamedTextColor.AQUA));
24+
player.sendMessage(finalMessage);
25+
}
26+
27+
/**
28+
* Sends a message to a player with the Parallel prefix prepended to it
29+
* @param player The player to send the message to
30+
* @param message The message without the prefix
31+
* @param messageType The type of message; this determines the message color
32+
*/
33+
public static void sendMessage(Player player, String message, MessageType messageType) {
34+
TextComponent finalMessage = switch (messageType) {
35+
case INFO -> (TextComponent) Constants.PLUGIN_PREFIX.append(Component.text(message, NamedTextColor.AQUA));
36+
case SUCCESS -> (TextComponent) Constants.PLUGIN_PREFIX.append(Component.text(message, NamedTextColor.GREEN));
37+
case ERROR -> (TextComponent) Constants.PLUGIN_PREFIX.append(Component.text(message, NamedTextColor.RED));
38+
};
39+
player.sendMessage(finalMessage);
40+
}
41+
42+
/**
43+
* Sends a message to console with the Parallel prefix prepended to it
44+
* (This version of the method sends an "INFO" style message)
45+
* @param message The message without the prefix
46+
*/
47+
public static void sendConsoleMessage(String message) {
48+
TextComponent finalMessage = (TextComponent) Constants.PLUGIN_PREFIX
49+
.append(Component.text(message, NamedTextColor.AQUA));
50+
Bukkit.getConsoleSender().sendMessage(finalMessage);
51+
}
52+
53+
/**
54+
* Sends a message to console with the Parallel prefix prepended to it
55+
* @param message The message without the prefix
56+
* @param messageType The type of message; this determines the message color
57+
*/
58+
public static void sendConsoleMessage(String message, MessageType messageType) {
59+
TextComponent finalMessage = switch (messageType) {
60+
case INFO -> (TextComponent) Constants.PLUGIN_PREFIX.append(Component.text(message, NamedTextColor.AQUA));
61+
case SUCCESS -> (TextComponent) Constants.PLUGIN_PREFIX.append(Component.text(message, NamedTextColor.GREEN));
62+
case ERROR -> (TextComponent) Constants.PLUGIN_PREFIX.append(Component.text(message, NamedTextColor.RED));
63+
};
64+
Bukkit.getConsoleSender().sendMessage(finalMessage);
65+
}
66+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package parallelmc.parallelutils.util;
2+
3+
/**
4+
* An enum to allow sending a different color of Parallel message depending on the message type
5+
*/
6+
public enum MessageType {
7+
INFO,
8+
SUCCESS,
9+
ERROR
10+
}

modules/src/main/java/parallelmc/parallelutils/modules/bitsandbobs/BitsAndBobs.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import parallelmc.parallelutils.ParallelClassLoader;
1010
import parallelmc.parallelutils.ParallelModule;
1111
import parallelmc.parallelutils.ParallelUtils;
12+
import parallelmc.parallelutils.modules.bitsandbobs.commands.Hat;
1213
import parallelmc.parallelutils.modules.bitsandbobs.minimodules.*;
1314
import parallelmc.parallelutils.modules.bitsandbobs.minimodules.togglepvp.OnPvp;
1415
import parallelmc.parallelutils.modules.bitsandbobs.minimodules.togglepvp.TogglePvpCommand;
@@ -54,13 +55,15 @@ public void onEnable() {
5455
FileConfiguration config = puPlugin.getConfig();
5556

5657
puPlugin.getCommand("togglepvp").setExecutor(new TogglePvpCommand());
58+
puPlugin.getCommand("hat").setExecutor(new Hat());
5759

5860
manager.registerEvents(new DoorKnocker(), plugin);
5961
manager.registerEvents(new SpecialItems(), plugin);
6062
manager.registerEvents(new OnPvp(), plugin);
6163
manager.registerEvents(new ShardLotto(), plugin);
6264
manager.registerEvents(new ChickenFeatherDrops(), plugin);
6365
manager.registerEvents(new EntityTweaks(), plugin);
66+
manager.registerEvents(new HatSlotStuff(), plugin);
6467
manager.registerEvents(new SilenceMobs(), plugin);
6568

6669
if (config.getBoolean("speedy-minecarts", false)) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package parallelmc.parallelutils.modules.bitsandbobs.commands;
2+
3+
import org.bukkit.Material;
4+
import org.bukkit.command.Command;
5+
import org.bukkit.command.CommandExecutor;
6+
import org.bukkit.command.CommandSender;
7+
import org.bukkit.entity.Player;
8+
import org.bukkit.inventory.ItemStack;
9+
import org.bukkit.inventory.PlayerInventory;
10+
import org.jetbrains.annotations.NotNull;
11+
import parallelmc.parallelutils.util.MessageTools;
12+
import parallelmc.parallelutils.util.MessageType;
13+
14+
public class Hat implements CommandExecutor {
15+
@Override
16+
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
17+
if (commandSender instanceof Player player) {
18+
PlayerInventory inventory = player.getInventory();
19+
ItemStack heldItem = inventory.getItemInMainHand();
20+
if (heldItem.getType() == Material.AIR) {
21+
MessageTools.sendMessage(player, "You aren't holding anything in your hand!", MessageType.ERROR);
22+
return true;
23+
}
24+
// If the player has permission to wear all hats, or they're holding paper/leather horse armor with
25+
// custom model data, swap their hand and hat slots
26+
if (player.hasPermission("parallelutils.hat.*") ||
27+
((heldItem.getType() == Material.PAPER || heldItem.getType() == Material.LEATHER_HORSE_ARMOR)
28+
&& heldItem.getItemMeta().hasCustomModelData())) {
29+
30+
ItemStack helmetItem = inventory.getHelmet();
31+
inventory.setItemInMainHand(helmetItem);
32+
inventory.setHelmet(heldItem);
33+
MessageTools.sendMessage(player, "Item set as hat!", MessageType.SUCCESS);
34+
} else {
35+
MessageTools.sendMessage(player, "You don't have permission to set this item as your hat!", MessageType.ERROR);
36+
}
37+
return true;
38+
} else {
39+
MessageTools.sendConsoleMessage("You must be a player to run this command!", MessageType.ERROR);
40+
}
41+
return true;
42+
}
43+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package parallelmc.parallelutils.modules.bitsandbobs.minimodules;
2+
3+
import org.bukkit.Bukkit;
4+
import org.bukkit.Material;
5+
import org.bukkit.entity.Player;
6+
import org.bukkit.event.EventHandler;
7+
import org.bukkit.event.Listener;
8+
import org.bukkit.event.inventory.InventoryClickEvent;
9+
import org.bukkit.event.inventory.InventoryType;
10+
import org.bukkit.inventory.EquipmentSlot;
11+
import org.bukkit.inventory.ItemStack;
12+
import org.bukkit.plugin.Plugin;
13+
import parallelmc.parallelutils.util.BukkitTools;
14+
import parallelmc.parallelutils.util.MessageTools;
15+
import parallelmc.parallelutils.util.MessageType;
16+
17+
public class HatSlotStuff implements Listener {
18+
19+
Plugin plugin;
20+
21+
public HatSlotStuff() {
22+
plugin = BukkitTools.getPlugin();
23+
}
24+
25+
@EventHandler
26+
public void onHelmetSlotClick(InventoryClickEvent event) {
27+
// Make sure the player is clicking on the helmet slot with an actual item that isn't already supposed to go
28+
// in the head slot
29+
if (event.getClickedInventory() != null &&
30+
event.getClickedInventory().getType() == InventoryType.PLAYER &&
31+
event.getRawSlot() == 5 &&
32+
event.getWhoClicked().getItemOnCursor().getType() != Material.AIR &&
33+
event.getWhoClicked().getItemOnCursor().getType().getEquipmentSlot() != EquipmentSlot.HEAD) {
34+
35+
// Get the cursor and helmet items
36+
Player player = (Player) event.getWhoClicked();
37+
ItemStack cursorItem = player.getItemOnCursor();
38+
if (player.hasPermission("parallelutils.hat.*") ||
39+
((cursorItem.getType() == Material.PAPER || cursorItem.getType() == Material.LEATHER_HORSE_ARMOR)
40+
&& cursorItem.getItemMeta().hasCustomModelData())) {
41+
42+
ItemStack helmetItem = player.getInventory().getHelmet();
43+
player.getInventory().setHelmet(null);
44+
player.setItemOnCursor(null);
45+
46+
// Swap the cursor and helmet items
47+
// Delay hat placement by one tick (ty Mojang)
48+
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
49+
@Override
50+
public void run() {
51+
player.getInventory().setHelmet(cursorItem);
52+
player.setItemOnCursor(helmetItem);
53+
MessageTools.sendMessage(player, "Item set as hat!", MessageType.SUCCESS);
54+
}
55+
},1L);
56+
}
57+
}
58+
}
59+
60+
61+
}

0 commit comments

Comments
 (0)