Commit 5653a9f0 authored by Ashijin's avatar Ashijin
Browse files

Added `/cosmetic dye` command and `Colorable: true` option to cosmetics

No related merge requests found
package io.lumine.cosmetics.api.cosmetics;
public interface ColorableCosmetic {
public boolean isColorable();
}
package io.lumine.cosmetics.api.cosmetics;
import io.lumine.utils.serialize.Chroma;
import lombok.Data;
@Data
......@@ -7,14 +8,24 @@ public class EquippedCosmetic {
private final Cosmetic cosmetic;
private final CosmeticVariant variant;
private final Chroma color;
public EquippedCosmetic(Cosmetic cosmetic) {
this.cosmetic = cosmetic;
this.variant = null;
this.color = null;
}
public EquippedCosmetic(CosmeticVariant variant) {
this.cosmetic = variant.getCosmetic();
this.variant = variant;
this.color = null;
}
public EquippedCosmetic(Cosmetic cosmetic, Chroma color) {
this.cosmetic = cosmetic;
this.variant = null;
this.color = color;
}
}
......@@ -4,6 +4,6 @@ import org.bukkit.inventory.ItemStack;
public interface ItemCosmetic {
ItemStack getCosmetic(CosmeticVariant variant);
ItemStack getCosmetic(EquippedCosmetic equipped);
}
......@@ -3,6 +3,7 @@ package io.lumine.cosmetics.api.players;
import io.lumine.cosmetics.api.cosmetics.Cosmetic;
import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.utils.serialize.Chroma;
import org.bukkit.entity.Player;
......@@ -22,6 +23,8 @@ public interface CosmeticProfile {
public void equip(Cosmetic cosmetic);
public void equip(CosmeticVariant cosmetic);
public void equip(Cosmetic cosmetic, Chroma color);
public void unequip(Cosmetic cosmetic);
......
......@@ -13,6 +13,8 @@ public class BaseCommand extends Command<MCCosmeticsPlugin> {
public BaseCommand(MCCosmeticsPlugin plugin) {
super(plugin);
this.addSubCommands(new DyeCommand(this));
}
@Override
......@@ -30,7 +32,7 @@ public class BaseCommand extends Command<MCCosmeticsPlugin> {
@Override
public List<String> onTabComplete(CommandSender sender, String[] args) {
return Collections.emptyList();
return null;
}
@Override
......
package io.lumine.cosmetics.commands;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.ColorableCosmetic;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.constants.Permissions;
import io.lumine.utils.commands.Command;
import io.lumine.utils.serialize.Chroma;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class DyeCommand extends Command<MCCosmeticsPlugin> {
public DyeCommand(Command command) {
super(command);
}
@Override
public boolean onCommand(CommandSender sender, String[] args) {
final var player = (Player) sender;
final var profile = getPlugin().getProfiles().getProfile(player);
var type = args[0];
Chroma color;
try {
color = Chroma.of(args[1]);
} catch(Exception | Error ex) {
ex.printStackTrace();
CommandHelper.sendError(sender, "Invalid dye color");
return true;
}
var maybeManager = getPlugin().getCosmetics().getManager(type);
if(maybeManager.isEmpty()) {
CommandHelper.sendError(sender, "Invalid cosmetic type");
return true;
}
var manager = maybeManager.get();
Optional<EquippedCosmetic> maybeEquipped = profile.getEquipped(manager.getCosmeticClass());
if(maybeEquipped.isEmpty()) {
CommandHelper.sendError(sender, "You don't have that type of cosmetic equipped!");
return true;
}
var equipped = maybeEquipped.get();
if(!(equipped.getCosmetic() instanceof ColorableCosmetic colorable) || !colorable.isColorable()) {
CommandHelper.sendError(sender, "The cosmetic you're wearing isn't dyeable!");
return true;
}
profile.equip(equipped.getCosmetic(), color);
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, String[] args) {
if(args.length == 1) {
return StringUtil.copyPartialMatches(args[0], getPlugin().getCosmetics().getRegisteredTypes((man) -> man.getClass().isAssignableFrom(ColorableCosmetic.class)), new ArrayList<>());
}
return Collections.emptyList();
}
@Override
public String getPermissionNode() {
return Permissions.COMMAND_BASE;
}
@Override
public boolean isConsoleFriendly() {
return false;
}
@Override
public String getName() {
return "dye";
}
}
package io.lumine.cosmetics.managers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.utils.events.extra.ArmorEquipEventListener;
......@@ -9,6 +10,7 @@ import lombok.Getter;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
public class CosmeticsExecutor extends ReloadableModule<MCCosmeticsPlugin> {
......@@ -51,4 +53,15 @@ public class CosmeticsExecutor extends ReloadableModule<MCCosmeticsPlugin> {
return cosmeticManagers.keySet();
}
public Collection<String> getRegisteredTypes(Predicate<MCCosmeticsManager> predicate) {
Collection<String> ret = Lists.newArrayList();
for(var entry : cosmeticManagers.entrySet()) {
if(predicate.test(entry.getValue())) {
ret.add(entry.getKey());
}
}
return ret;
}
}
package io.lumine.cosmetics.managers.back;
import io.lumine.cosmetics.api.cosmetics.ColorableCosmetic;
import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.cosmetics.ItemCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.constants.CosmeticType;
......@@ -12,7 +14,7 @@ import org.bukkit.inventory.ItemStack;
import java.io.File;
public class BackAccessory extends AbstractCosmetic implements ItemCosmetic {
public class BackAccessory extends AbstractCosmetic implements ColorableCosmetic,ItemCosmetic {
public BackAccessory(BackManager manager, File file, String key) {
super(manager, file, CosmeticType.type(BackAccessory.class), key);
......@@ -29,11 +31,14 @@ public class BackAccessory extends AbstractCosmetic implements ItemCosmetic {
}
@Override
public ItemStack getCosmetic(CosmeticVariant variant) {
public ItemStack getCosmetic(EquippedCosmetic equipped) {
var item = getMenuItem();
if(variant != null) {
if(equipped.getVariant() != null) {
var variant = equipped.getVariant();
item = ItemFactory.of(item).color(variant.getColor()).build();
} else if(equipped.getColor() != null) {
item = ItemFactory.of(item).color(equipped.getColor()).build();
}
return item;
......
package io.lumine.cosmetics.managers.hats;
import io.lumine.cosmetics.api.cosmetics.ColorableCosmetic;
import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.cosmetics.ItemCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.constants.CosmeticType;
......@@ -12,7 +14,7 @@ import org.bukkit.inventory.ItemStack;
import java.io.File;
public class Hat extends AbstractCosmetic implements ItemCosmetic {
public class Hat extends AbstractCosmetic implements ColorableCosmetic,ItemCosmetic {
public Hat(HatManager manager, File file, String key) {
super(manager, file, CosmeticType.type(Hat.class), key);
......@@ -30,11 +32,14 @@ public class Hat extends AbstractCosmetic implements ItemCosmetic {
}
@Override
public ItemStack getCosmetic(CosmeticVariant variant) {
public ItemStack getCosmetic(EquippedCosmetic equipped) {
var item = getMenuItem();
if(variant != null) {
if(equipped.getVariant() != null) {
var variant = equipped.getVariant();
item = ItemFactory.of(item).color(variant.getColor()).build();
} else if(equipped.getColor() != null) {
item = ItemFactory.of(item).color(equipped.getColor()).build();
}
return item;
......
package io.lumine.cosmetics.managers.modelengine;
import com.ticxo.modelengine.api.util.ConfigManager;
import io.lumine.cosmetics.api.cosmetics.ColorableCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.config.Scope;
import io.lumine.cosmetics.constants.CosmeticType;
......@@ -16,7 +18,7 @@ import lombok.Getter;
import java.io.File;
public class MEGAccessory extends AbstractCosmetic {
public class MEGAccessory extends AbstractCosmetic implements ColorableCosmetic {
private static final StringProp MODEL = Property.String(Scope.NONE, "ModelId");
private static final StringProp STATE = Property.String(Scope.NONE, "State");
......
package io.lumine.cosmetics.managers.offhand;
import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
import io.lumine.cosmetics.api.cosmetics.ColorableCosmetic;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.cosmetics.ItemCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.constants.CosmeticType;
......@@ -12,7 +13,7 @@ import org.bukkit.inventory.ItemStack;
import java.io.File;
public class Offhand extends AbstractCosmetic implements ItemCosmetic {
public class Offhand extends AbstractCosmetic implements ColorableCosmetic,ItemCosmetic {
public Offhand(OffhandManager manager, File file, String key) {
super(manager, file, CosmeticType.type(Offhand.class), key);
......@@ -29,11 +30,14 @@ public class Offhand extends AbstractCosmetic implements ItemCosmetic {
}
@Override
public ItemStack getCosmetic(CosmeticVariant variant) {
public ItemStack getCosmetic(EquippedCosmetic equipped) {
var item = getMenuItem();
if(variant != null) {
if(equipped.getVariant() != null) {
var variant = equipped.getVariant();
item = ItemFactory.of(item).color(variant.getColor()).build();
} else if(equipped.getColor() != null) {
item = ItemFactory.of(item).color(equipped.getColor()).build();
}
return item;
......
package io.lumine.cosmetics.managers.particle;
import io.lumine.cosmetics.api.cosmetics.ColorableCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.constants.CosmeticType;
import io.lumine.cosmetics.managers.AbstractCosmetic;
......@@ -7,7 +8,7 @@ import io.lumine.utils.menu.Icon;
import java.io.File;
public class ParticleAccessory extends AbstractCosmetic {
public class ParticleAccessory extends AbstractCosmetic implements ColorableCosmetic {
public ParticleAccessory(ParticleManager manager, File file, String key) {
super(manager, file, CosmeticType.type(ParticleAccessory.class), key);
......
......@@ -7,12 +7,14 @@ import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.constants.CosmeticType;
import io.lumine.utils.Schedulers;
import io.lumine.utils.serialize.Chroma;
import lombok.Getter;
import org.bukkit.entity.Player;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.awt.Color;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
......@@ -63,6 +65,16 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
var cosmetic = variant.getCosmetic();
equip(cosmetic);
}
@Override
public void equip(Cosmetic cosmetic, Chroma color) {
if(isEquipped(cosmetic)) {
cosmetic.getManager().unequip(this);
}
equippedCosmetics.put(cosmetic.getType(), new ProfileCosmeticData(cosmetic, color));
equipped.put(cosmetic.getClass(), new EquippedCosmetic(cosmetic, color));
cosmetic.getManager().equip(this);
}
@Override
public void unequip(Cosmetic cosmetic) {
......@@ -116,6 +128,7 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
MCCosmeticsPlugin.inst().getCosmetics().getManager(type).ifPresent(manager -> {
manager.getCosmetic(data.getId()).ifPresent(cosmetic -> {
var c = data.toEquippedCosmetic();
equip((Cosmetic) cosmetic);
});
});
......
......@@ -6,6 +6,7 @@ import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.Cosmetic;
import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.utils.serialize.Chroma;
import lombok.Data;
@Data
......@@ -27,6 +28,12 @@ public class ProfileCosmeticData {
this.variant = variant.getKey();
}
public ProfileCosmeticData(Cosmetic cosmetic, Chroma color) {
this.type = cosmetic.getType();
this.id = cosmetic.getId();
this.variant = color.toHexString();
}
public Optional<EquippedCosmetic> toEquippedCosmetic() {
var maybeManager = MCCosmeticsPlugin.inst().getCosmetics().getManager(type);
if(maybeManager.isEmpty()) {
......@@ -39,14 +46,18 @@ public class ProfileCosmeticData {
}
var cosmetic = (Cosmetic) maybeCosmetic.get();
if(cosmetic.hasVariants() && this.variant != null) {
var maybeVariant = cosmetic.getVariant(this.variant);
if(maybeVariant.isPresent()) {
return Optional.of(new EquippedCosmetic(maybeVariant.get()));
if(variant != null) {
if(variant.startsWith("#")) {
return Optional.of(new EquippedCosmetic(cosmetic, Chroma.of(variant)));
} else if(cosmetic.hasVariants()) {
var maybeVariant = cosmetic.getVariant(this.variant);
if(maybeVariant.isPresent()) {
return Optional.of(new EquippedCosmetic(maybeVariant.get()));
}
}
};
return Optional.empty();
}
return Optional.of(new EquippedCosmetic(cosmetic));
}
}
......@@ -32,7 +32,7 @@ public class ProfileManager extends PlayerRepository<MCCosmeticsPlugin,Profile>
if(event.getNewGameMode().equals(GameMode.SPECTATOR)){
Optional<Profile> profile = this.getProfile(event.getPlayer().getUniqueId());
if(profile.isEmpty()){
if(profile.isEmpty()) {
return;
}
......
......@@ -56,7 +56,7 @@ public class VolatileBackImpl implements VolatileEquipmentHelper {
}
var nmsPlayer = ((CraftPlayer) player).getHandle();
var nmsBack = CraftItemStack.asNMSCopy(back.getCosmetic(equipped.getVariant()));
var nmsBack = CraftItemStack.asNMSCopy(back.getCosmetic(equipped));
ArmorStand stand = activeProfile.get(player);
if(stand == null) {
......
......@@ -51,7 +51,7 @@ public class VolatileHatImpl implements VolatileEquipmentHelper {
if(!(opt instanceof Hat hat))
return;
var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(maybeEquipped.get().getVariant()));
var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(maybeEquipped.get()));
playerTracker.put(player.getEntityId(), player);
......@@ -117,7 +117,7 @@ public class VolatileHatImpl implements VolatileEquipmentHelper {
return;
final var player = profile.getPlayer();
final var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(equip.getVariant()));
final var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(equip));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.HEAD, nmsHat)));
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
......
......@@ -51,7 +51,7 @@ public class VolatileOffhandImpl implements VolatileEquipmentHelper {
if(!(opt instanceof ItemCosmetic offhand))
return;
var nmsOffhand = CraftItemStack.asNMSCopy(offhand.getCosmetic(equip.getVariant()));
var nmsOffhand = CraftItemStack.asNMSCopy(offhand.getCosmetic(equip));
playerTracker.put(player.getEntityId(), player);
......@@ -105,7 +105,7 @@ public class VolatileOffhandImpl implements VolatileEquipmentHelper {
return;
final var player = profile.getPlayer();
final var nmsOffhand = CraftItemStack.asNMSCopy(offhand.getCosmetic(equip.getVariant()));
final var nmsOffhand = CraftItemStack.asNMSCopy(offhand.getCosmetic(equip));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.OFFHAND, nmsOffhand)));
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
......
......@@ -56,7 +56,7 @@ public class VolatileBackImpl implements VolatileEquipmentHelper {
}
var nmsPlayer = ((CraftPlayer) player).getHandle();
var nmsBack = CraftItemStack.asNMSCopy(back.getCosmetic(equipped.getVariant()));
var nmsBack = CraftItemStack.asNMSCopy(back.getCosmetic(equipped));
ArmorStand stand = activeProfile.get(player);
if(stand == null) {
......
......@@ -51,7 +51,7 @@ public class VolatileHatImpl implements VolatileEquipmentHelper {
if(!(opt instanceof Hat hat))
return;
var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(maybeEquipped.get().getVariant()));
var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(maybeEquipped.get()));
playerTracker.put(player.getEntityId(), player);
......@@ -117,7 +117,7 @@ public class VolatileHatImpl implements VolatileEquipmentHelper {
return;
final var player = profile.getPlayer();
final var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(equip.getVariant()));
final var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(equip));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.HEAD, nmsHat)));
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment