diff --git a/Battle-Crates-main/.gitignore b/Battle-Crates-main/.gitignore new file mode 100644 index 0000000..4a410a1 --- /dev/null +++ b/Battle-Crates-main/.gitignore @@ -0,0 +1,70 @@ +# Eclipse +/.classpath +/.project +/.settings + +# Netbeans +/nbproject + +# Fuck mauri! +/build.xml + +# Maven +/target +/dependency-reduced-pom.xml +*/target +*/dependency-reduced-pom.xml + +# Vim +.*.sw[a-p] + +# Various other potential build files +/build +/bin +/dist +/manifest.mf +/MANIFEST.MF +/META-INF/MANIFEST.MF +git.properties +.ssh +key +commiter.sh +key.pub +dependency-reduced-pom.xml + +# Mac Filesystem Dust +.DS_Store + +# IntelliJ IDEA +*.iml +*.ipr +*.iws +.idea/ + +#Libraries jar files +libraries/*.jar +======= +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +out \ No newline at end of file diff --git a/Battle-Crates-main/pom.xml b/Battle-Crates-main/pom.xml new file mode 100644 index 0000000..f9eda53 --- /dev/null +++ b/Battle-Crates-main/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + rip.battle.crates + BattleCrates + 1.0-SNAPSHOT + + + 8 + 8 + + + + + rip.battle.spigot + battlespigot-server + 1.7.10-R0.1-SNAPSHOT + provided + + + rip.battle.core + bukkit + 1.0-SNAPSHOT + provided + + + cc.stormworth.hcf + hcf + 1.0.0-SNAPSHOT + provided + + + + \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/Crates.java b/Battle-Crates-main/src/main/java/rip/battle/crates/Crates.java new file mode 100644 index 0000000..a5ec72a --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/Crates.java @@ -0,0 +1,69 @@ +package rip.battle.crates; + +import cc.stormworth.core.util.command.rCommandHandler; +import com.mongodb.MongoClient; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.configuration.Configuration; +import org.bukkit.plugin.java.JavaPlugin; +import rip.battle.crates.airdrop.AirdropListener; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.listeners.CrateListener; +import rip.battle.crates.reward.RewardsListeners; + +@Getter +public class Crates extends JavaPlugin { + + @Getter private static Crates instance; + + private MongoDatabase mongoDatabase; + + @Override + public void onEnable() { + instance = this; + + saveDefaultConfig(); + loadMongo(); + + Crate.load(); + + Bukkit.getPluginManager().registerEvents(new CrateListener(), this); + Bukkit.getPluginManager().registerEvents(new RewardsListeners(), this); + Bukkit.getPluginManager().registerEvents(new AirdropListener(), this); + + rCommandHandler.registerPackage(this, "rip.battle.crates.crate.commands"); + rCommandHandler.registerPackage(this, "rip.battle.crates.reward.commands"); + } + + @Override + public void onDisable() { + Crate.getCrates().values().forEach(Crate::save); + } + + private void loadMongo() { + Configuration configuration = getConfig(); + if (configuration.getBoolean("mongo.authentication.enabled")) { + ServerAddress serverAddress = + new ServerAddress( + configuration.getString("mongo.host"), configuration.getInt("mongo.port")); + + MongoCredential credential = + MongoCredential.createCredential( + configuration.getString("mongo.authentication.username"), + "admin", + configuration.getString("mongo.authentication.password").toCharArray()); + + mongoDatabase = + new MongoClient(serverAddress, credential, MongoClientOptions.builder().build()) + .getDatabase(getConfig().getString("mongo.database")); + } else { + mongoDatabase = + new MongoClient(configuration.getString("mongo.host"), configuration.getInt("mongo.port")) + .getDatabase(getConfig().getString("mongo.database")); + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/airdrop/Airdrop.java b/Battle-Crates-main/src/main/java/rip/battle/crates/airdrop/Airdrop.java new file mode 100644 index 0000000..411cb37 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/airdrop/Airdrop.java @@ -0,0 +1,82 @@ +package rip.battle.crates.airdrop; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.util.trail.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import rip.battle.crates.Crates; +import rip.battle.crates.crate.Crate; + +import java.util.Arrays; +import java.util.List; + +public class Airdrop extends Crate { + + public Airdrop() { + super("Airdrop"); + getCrates().put("Airdrop", this); + } + + @Override + public List getHologramsLines() { + return Arrays.asList( + getDisplayName() + " Airdrop", + "&7", + "&fLeft click &7for preview rewards", + "&7", + "&7&ostore.battle.rip"); + } + + @Override + public ItemStack generateKey() { + return new ItemBuilder(Material.CHEST) + .name("&6&lAirdrop") + .addToLore( + "&7Purchasable at &fstore.battle.rip&7.", + "", + "&ePlace this down to designate a &6&lLocation &efor the &6&lLoot&e!" + ).build(); + } + + public void startAnimation(Block block, Player player) { + createFlameRings(block.getLocation().add(0, 0, 0.5)); + + block.setMetadata("airdrop", new FixedMetadataValue(Crates.getInstance(), true)); + + /*Dropper dropper = (Dropper) block.getState(); + + List rewardList = new ArrayList<>(getRewards()); + Collections.shuffle(rewardList); + + int i = 0; + + while (i <= 9) { + Reward randomReward = RandomUtils.getRandomReward(rewardList); + + dropper.getInventory().setItem(i, randomReward.getItem()); + + if (!randomReward.getBroadcast().isEmpty()) { + randomReward.getBroadcast().forEach(line -> Bukkit.broadcastMessage(line.replace("{player}", player.getName()))); + } + + i++; + }*/ + } + + private void createFlameRings(Location location) { + double alpha = 0; + for (int count = 0; count < 50; count++) { + alpha += Math.PI / 16; + + Location firstLocation = location.clone().add(Math.cos(alpha), Math.sin(alpha) + 1, Math.sin(alpha)); + Location secondLocation = location.clone().add(Math.cos(alpha + Math.PI), Math.sin(alpha) + 1, Math.sin(alpha + Math.PI)); + + ParticleEffect.FLAME.display(0, 0, 0, 0, 10, firstLocation, 10); + ParticleEffect.FLAME.display(0, 0, 0, 0, 10, secondLocation, 10); + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/airdrop/AirdropListener.java b/Battle-Crates-main/src/main/java/rip/battle/crates/airdrop/AirdropListener.java new file mode 100644 index 0000000..a8a2dd7 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/airdrop/AirdropListener.java @@ -0,0 +1,246 @@ +package rip.battle.crates.airdrop; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.general.LocationUtil; +import cc.stormworth.core.util.general.TaskUtil; +import cc.stormworth.hcf.Main; +import cc.stormworth.hcf.team.Team; +import cc.stormworth.hcf.team.claims.LandBoard; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.Skull; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.scheduler.BukkitRunnable; +import rip.battle.crates.Crates; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.utils.FireworkUtil; +import rip.battle.crates.utils.ItemUtils; +import rip.battle.crates.utils.RandomUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class AirdropListener implements Listener { + + @EventHandler + public void onBlockPlaceEvent(BlockPlaceEvent event) { + Player player = event.getPlayer(); + + ItemStack item = event.getItemInHand(); + + if (!ItemUtils.isAirDrop(item)) { + return; + } + + Airdrop airdrop = (Airdrop) Crate.getByName("Airdrop"); + if (!airdrop.isEnable()) { + player.sendMessage(CC.translate("&cAirdrop is currently disabled.")); + event.setCancelled(true); + player.playSound(player.getLocation(), Sound.ANVIL_BREAK, 1, 1); + return; + } + + if (!player.isOp()) { + + Team team = LandBoard.getInstance().getTeam(player.getLocation()); + + if (team != null && !team.isMember(player.getUniqueId())) { + player.sendMessage(CC.translate("&cYou can only put the &6&lAirdrop&c in your claim or in Wilderness.")); + event.setCancelled(true); + return; + } + + if (Main.getInstance().getServerHandler().isWarzone(player.getLocation())) { + player.sendMessage(CC.translate("&cYou cannot place an &6&lAirdrop&c in a Warzone.")); + event.setCancelled(true); + return; + } + } + + Location location = event.getBlock().getLocation().clone().add(0, 25, 0); + + if (location.getBlock() != null && location.getBlock().getType() != Material.AIR) { + player.sendMessage(CC.translate("&cYou cannot place an &6&lAirdrop&c there.")); + player.sendMessage(CC.translate("&cGo out in the open air to deploy the &6&lAirdrop&c.")); + player.playSound(player.getLocation(), Sound.VILLAGER_NO, 1, 1); + event.setCancelled(true); + return; + } + + FallingBlock block = player.getLocation().getWorld().spawnFallingBlock( + location, + Material.SNOW_BLOCK, + (byte) 3); + + block.setMetadata("airdrop", new FixedMetadataValue(Crates.getInstance(), player.getName())); + + event.setCancelled(true); + + FireworkUtil.launchFirework(event.getBlock().getLocation()); + + ItemUtils.consume(player); + } + + @EventHandler + public void onDeath(EntityChangeBlockEvent event) { + if (!(event.getEntity() instanceof FallingBlock)) { + return; + } + + FallingBlock fallingBlock = (FallingBlock) event.getEntity(); + + if (!fallingBlock.hasMetadata("airdrop")) { + return; + } + + Airdrop airdrop = (Airdrop) Crate.getByName("Airdrop"); + + Player player = Bukkit.getPlayer(fallingBlock.getMetadata("airdrop").get(0).asString()); + + fallingBlock.setDropItem(false); + + Block block = event.getBlock(); + new BukkitRunnable() { + @Override + public void run() { + block.setType(Material.SKULL); + block.setData((byte) 3); + Skull skull = (Skull) block.getState(); + skull.setOwner("conhost"); + skull.update(); + } + }.runTaskLater(Crates.getInstance(), 2L); + for(Player online : Bukkit.getServer().getOnlinePlayers()) { + if(((CraftPlayer) online).getHandle().playerConnection.networkManager.getVersion() < 47){ + new BukkitRunnable() { + @Override + public void run() { + online.sendBlockChange(block.getLocation(), Material.CHEST, (byte) 0); + } + }.runTaskLater(Crates.getInstance(), 2L); + } + } + + block.setMetadata("airdrop", new FixedMetadataValue(Crates.getInstance(), player.getName())); + + TaskUtil.runAsync(Crates.getInstance(), () -> airdrop.startAnimation(block, player)); + } + + /*@EventHandler + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + + if (!(event.getEntity() instanceof FallingBlock)) { + return; + } + + FallingBlock fallingBlock = (FallingBlock) event.getEntity(); + + if (!fallingBlock.hasMetadata("airdrop")) { + return; + } + + Airdrop airdrop = (Airdrop) Crate.getByName("Airdrop"); + + Player player = Bukkit.getPlayer(fallingBlock.getMetadata("airdrop").get(0).asString()); + + Block block = event.getBlock(); + + block.setType(Material.DROPPER); + + airdrop.startAnimation(block, player); + }*/ + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (event.getClickedBlock() == null) { + return; + } + + Block block = event.getClickedBlock(); + + if (!block.hasMetadata("airdrop")) { + return; + } + event.setCancelled(true); + if(block.hasMetadata("airdropOpen")) return; + + if (block.getType() != Material.DROPPER) { + Inventory inventory = Bukkit.createInventory(null, 9, "Airdrop"); + + List rewardList = new ArrayList<>(Airdrop.getByName("Airdrop").getRewards()); + Collections.shuffle(rewardList); + + int i = 0; + + while (i < 9) { + Reward randomReward = RandomUtils.getRandomReward(rewardList); + + inventory.setItem(i, randomReward.getItem()); + + if (!randomReward.getBroadcast().isEmpty()) { + randomReward.getBroadcast().forEach(line -> Bukkit.broadcastMessage(line.replace("{player}", player.getName()))); + } + + i++; + } + + player.openInventory(inventory); + } + block.setMetadata("airdropOpen", new FixedMetadataValue(Crates.getInstance(), true)); + + player.setMetadata("airdropOpen", new FixedMetadataValue(Crates.getInstance(), LocationUtil.parseLocation(block.getLocation()))); + + } + + @EventHandler + public void onInventoryClose(InventoryCloseEvent event) { + Player player = (Player) event.getPlayer(); + + if (!player.hasMetadata("airdropOpen")) { + return; + } + + if (!event.getInventory().getName().equals("Airdrop")) { + return; + } + + Inventory inventory = event.getInventory(); + + for (int i = 0; i < inventory.getSize(); i++) { + ItemStack item = inventory.getItem(i); + + if (item == null) { + continue; + } + + player.getLocation().getWorld().dropItem(player.getLocation(), item); + } + + Location location = LocationUtil.convertLocation(player.getMetadata("airdropOpen").get(0).asString()); + + Block block = location.getBlock(); + + block.setType(Material.AIR); + + player.removeMetadata("airdropOpen", Crates.getInstance()); + block.removeMetadata("airdrop", Crates.getInstance()); + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/Crate.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/Crate.java new file mode 100644 index 0000000..ede9e43 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/Crate.java @@ -0,0 +1,419 @@ +package rip.battle.crates.crate; + +import cc.stormworth.core.CorePlugin; +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.general.LocationUtil; +import cc.stormworth.core.util.holograms.Hologram; +import cc.stormworth.core.util.holograms.Holograms; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.ReplaceOptions; +import lombok.Getter; +import lombok.Setter; +import org.bson.Document; +import org.bukkit.*; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import rip.battle.crates.Crates; +import rip.battle.crates.airdrop.Airdrop; +import rip.battle.crates.misterybox.MysteryBox; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.RewardType; +import rip.battle.crates.supplydrop.SupplyDrop; +import rip.battle.crates.utils.ChatUtils; +import rip.battle.crates.utils.RandomUtils; + +import java.util.*; +import java.util.stream.Collectors; + +@Setter +@Getter +public class Crate { + + private static final MongoCollection collection = Crates.getInstance().getMongoDatabase().getCollection("crates"); + + @Getter + private static final Map crates = Maps.newHashMap(); + + private final String name; + private boolean enable; + + private List rewards = Lists.newArrayList(); + private List placeholders = Lists.newArrayList(); + + private String displayName; + + private ItemStack key; + + private Sound openSound; + + private int minimumReward = 1; + private int maximumReward = 2; + + private Location chestLocation; + + private final Map holograms = Maps.newHashMap(); + + private final Inventory inventory; + + public Crate(String name) { + this.name = name; + this.enable = true; + + this.displayName = ChatColor.GOLD + name; + + this.key = new ItemBuilder(Material.TRIPWIRE_HOOK).name(CC.translate(displayName + " Key")).build(); + this.inventory = Bukkit.createInventory(null, 54, CC.translate("&eEdit Rewards of " + name)); + + if (!name.equalsIgnoreCase("Airdrop")) { + crates.put(name, this); + } + } + + public void destroyHolograms() { + holograms.values().forEach(Hologram::destroy); + holograms.clear(); + } + + public List getHologramsLines() { + return Arrays.asList( + displayName + " Crate", + "&7", + "&fLeft click&7 &7for preview rewards", + "&fRight click&7 to open", + "&7", + "&7&ostore.battle.rip"); + } + + public void sendHolograms() { + if (chestLocation == null) return; + double y = 0.50; + + if (chestLocation.getBlock().getType() == Material.BEACON || chestLocation.getBlock().getType() == Material.ENDER_CHEST + || chestLocation.getBlock().getType() == Material.ENDER_PORTAL || chestLocation.getBlock().getType() == Material.DROPPER) { + y = 0.90; + } + + Location finalLocation = chestLocation.clone().add(0.50, y, 0.50); + Hologram hologram = Holograms.newHologram().at(finalLocation).addLines(getHologramsLines()).build(); + hologram.send(); + this.holograms.put(finalLocation, hologram); + } + + public void createHologram(Location location) { + Location finalLocation = location.clone().add(0.50, 0.50, 0.50); + Hologram hologram = Holograms.newHologram().at(finalLocation).addLines(getHologramsLines()).build(); + hologram.send(); + this.holograms.put(finalLocation, hologram); + } + + public static void load() { + Crate crate; + for (Document document : collection.find()) { + + if (document.containsKey("type")) { + if (document.getString("type").equalsIgnoreCase("supplydrop")) { + crate = new SupplyDrop(); + } else if (document.getString("type").equalsIgnoreCase("mysterybox")) { + crate = new MysteryBox(document.getString("name")); + } else if (document.getString("type").equalsIgnoreCase("airdrop")) { + crate = new Airdrop(); + } else { + crate = new Crate(document.getString("name")); + } + } else { + crate = new Crate(document.getString("name")); + } + + crate.setEnable(document.getBoolean("enable")); + crate.setDisplayName(document.getString("displayName")); + crate.setKey(CorePlugin.GSON.fromJson(document.getString("key"), ItemStack.class)); + if (document.containsKey("openSound")) { + crate.setOpenSound(Sound.valueOf(document.getString("openSound"))); + } + crate.setMinimumReward(document.getInteger("minimumReward")); + crate.setMaximumReward(document.getInteger("maximumReward")); + + for (Document reward : document.getList("rewards", Document.class)) { + crate.getRewards().add(new Reward(reward)); + } + + for (Document placeholder : document.getList("placeholders", Document.class)) { + crate.getPlaceholders().add(new CratePlaceholder(placeholder)); + } + + if (crate instanceof MysteryBox) { + for (Document reward : document.getList("obligatoryrewards", Document.class)) { + ((MysteryBox) crate).getObligatoryRewards().add(new Reward(reward)); + } + } + + if (document.containsKey("chestLocations")) { + for (String location : document.getList("chestLocations", String.class)) { + crate.setChestLocation(LocationUtil.convertLocation(location)); + } + } + + if (document.containsKey("chestLocation")) { + crate.setChestLocation(LocationUtil.convertLocation(document.getString("chestLocation"))); + } + + for (CratePlaceholder placeholder : crate.getPlaceholders()) { + crate.getInventory().setItem(placeholder.getSlot(), placeholder.getItem()); + } + + for (Reward reward : crate.getRewards()) { + crate.getInventory().setItem(reward.getSlot(), reward.getItem()); + } + + if (crate instanceof MysteryBox) { + for (Reward reward : ((MysteryBox) crate).getObligatoryRewards()) { + crate.getInventory().setItem(reward.getSlot(), reward.getItem()); + } + } + + crate.sendHolograms(); + } + + if (!crates.containsKey("Airdrop")) { + crates.put("Airdrop", new Airdrop()); + } + + if (!crates.containsKey("SupplyDrop")) { + crates.put("SupplyDrop", new SupplyDrop()); + } + } + + public void save() { + Document document = new Document(); + + document.append("name", name); + document.append("enable", enable); + document.append("displayName", displayName); + document.append("key", CorePlugin.GSON.toJson(key)); + + if (openSound != null) document.append("openSound", openSound.name()); + + document.append("minimumReward", minimumReward); + document.append("maximumReward", maximumReward); + document.append("rewards", rewards.stream().map(Reward::serialize).collect(Collectors.toList())); + document.append("placeholders", placeholders.stream().map(CratePlaceholder::serialize).collect(Collectors.toList())); + //document.append("chestLocations", chestLocations.stream().map(LocationUtil::parseLocation).collect(Collectors.toList())); + + if (chestLocation != null) { + document.append("chestLocation", LocationUtil.parseLocation(chestLocation)); + } + + if (this instanceof MysteryBox) { + MysteryBox mysteryBox = (MysteryBox) this; + document.append("type", "mysteryBox"); + document.append("obligatoryrewards", mysteryBox.getObligatoryRewards().stream().map(Reward::serialize).collect(Collectors.toList())); + } else if (this instanceof Airdrop) { + document.append("type", "airdrop"); + } else if (this instanceof SupplyDrop) { + document.append("type", "supplydrop"); + } else { + document.append("type", "crate"); + } + + collection.replaceOne(Filters.eq("name", name), document, new ReplaceOptions().upsert(true)); + } + + public static Crate getByLocation(Location location) { + for (Crate crate : crates.values()) { + if (crate.getChestLocation() != null && crate.getChestLocation().equals(location)) { + return crate; + } + } + + return null; + } + + + public static Crate getByName(String name) { + return crates.get(name); + } + + public ItemStack generateKey() { + + if (getName().equalsIgnoreCase("Giftbox")) { + return new ItemBuilder(key.clone()) + .name(CC.translate(displayName + " &7(Package) &a&l* CLICK *")) + .setLore(Lists.newArrayList( + "&7", + "&7You can preview this " + getDisplayName() + " Crate &7 rewards", + "&7By going to the overworld &aSpawn", + "&7", + ChatUtils.getFirstColor(getDisplayName()) + "Right Click &7to open the key", + "&7", + "&7Purchase additional keys at &f&nstore.battle.rip" + )) + .build(); + } + + return new ItemBuilder(key.clone()) + .name(CC.translate(displayName + " Key")) + .setLore(Lists.newArrayList( + "&7", + "&7You can preview this " + getDisplayName() + " Crate &7 rewards", + "&7By going to the overworld &aSpawn", + "&7", + ChatUtils.getFirstColor(getDisplayName()) + "Right Click &7to open the key", + ChatUtils.getFirstColor(getDisplayName()) + "Left Click &7to preview rewards", + "&7", + "&7Purchase additional keys at &f&nstore.battle.rip" + )) + .build(); + } + + public static Crate getCrateByKey(ItemStack key) { + + if (key == null) return null; + + if (key.getItemMeta() == null) return null; + + ItemMeta meta = key.getItemMeta(); + if (meta.hasDisplayName() && meta.hasLore()) { + String name = meta.getDisplayName(); + + if (name.contains(CC.translate("&7(Package)"))) { + return Crate.getByName("Giftbox"); + } + + if (name.contains("Key")) { + name = name.replace(" Key", ""); + + String finalName = name; + + return crates.values() + .stream() + .filter(crate -> crate.getDisplayName().equalsIgnoreCase(finalName)) + .findFirst().orElse(null); + } + } + + return null; + } + + public void openCrate(Player player) { + + if (!enable) { + player.sendMessage(CC.translate("&cThis crate is currently disabled")); + return; + } + + if (getMaximumReward() == 0 || getRewards().isEmpty()) { + player.sendMessage(CC.translate("&cCrate " + getName() + " is empty, please contact an admin.")); + return; + } + + if (player.getInventory().firstEmpty() < 0) { + player.sendMessage(CC.translate("&cInventory Full.")); + return; + } + + int random = new Random().nextInt(getMaximumReward() - getMinimumReward() + 1) + getMinimumReward(); + + List randomRewards = new ArrayList<>(); + + List rewardList = new ArrayList<>(getRewards()); + Collections.shuffle(rewardList); + + for (int i = 0; i < random; i++) { + randomRewards.add(RandomUtils.getRandomReward(rewardList)); + } + + for (Reward reward : randomRewards) { + if (reward.getType() == RewardType.ITEMS) { + if (player.getInventory().firstEmpty() < 0) { + player.sendMessage(CC.translate("&cInventory Full.")); + player.getWorld().dropItem(player.getLocation(), reward.getItem()); + } else { + player.getInventory().addItem(reward.getItem()); + } + } else { + List commands = reward.getCommands(); + + for (String command : commands) { + + if (command.contains("op")) { + continue; + } + + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName())); + } + } + + if (!reward.getBroadcast().isEmpty()) { + reward.getBroadcast().forEach(line -> Bukkit.broadcastMessage(line.replace("{player}", player.getName()))); + } + } + + if (randomRewards.size() == 0) { // if not found any reward + Reward reward = getRewards().get(new Random().nextInt(getRewards().size())); + + if (reward.getType() == RewardType.ITEMS) { + if (player.getInventory().firstEmpty() < 0) { + player.sendMessage(CC.translate("&cInventory Full.")); + player.getWorld().dropItem(player.getLocation(), reward.getItem()); + } else { + player.getInventory().addItem(reward.getItem()); + } + } else { + List commands = reward.getCommands(); + + for (String command : commands) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName())); + } + } + + if (!reward.getBroadcast().isEmpty()) { + reward.getBroadcast().forEach(line -> Bukkit.broadcastMessage(line.replace("{player}", player.getName()))); + } + } + + if (openSound != null) { + player.playSound(player.getLocation(), openSound, 1, 1); + } + + player.sendMessage(CC.translate("&aYou have received " + randomRewards.size() + " reward(s)")); + consumeKey(player); + player.updateInventory(); + } + + public void openEditRewardsInventory(Player player) { + player.openInventory(inventory); + } + + public void consumeKey(Player player) { + if (player.getItemInHand().getAmount() > 1) { + player.getItemInHand().setAmount(player.getItemInHand().getAmount() - 1); + } else { + player.setItemInHand(new ItemStack(Material.AIR)); + } + } + + public Reward getReward(int slot) { + return rewards.stream().filter(reward -> reward.getSlot() == slot).findFirst().orElse(null); + } + + public CratePlaceholder getPlaceholder(int slot) { + return placeholders.stream().filter(reward -> reward.getSlot() == slot).findFirst().orElse(null); + } + + public void delete() { + crates.remove(name); + destroyHolograms(); + + collection.deleteOne(Filters.eq("name", name)); + } + + public void removeHologram() { + holograms.forEach((loc, hologram) -> hologram.destroy()); + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/CratePlaceholder.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/CratePlaceholder.java new file mode 100644 index 0000000..a16030b --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/CratePlaceholder.java @@ -0,0 +1,32 @@ +package rip.battle.crates.crate; + +import cc.stormworth.core.CorePlugin; +import cc.stormworth.core.kt.util.ItemBuilder; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.bson.Document; +import org.bukkit.inventory.ItemStack; + +@Getter +@AllArgsConstructor +public class CratePlaceholder { + + private ItemStack item; + private int slot; + + public CratePlaceholder(Document document) { + this.item = CorePlugin.GSON.fromJson(document.getString("item"), ItemStack.class); + this.slot = document.getInteger("slot"); + } + + public ItemStack getPreview() { + return new ItemBuilder(item.clone()) + .name(" ") + .build(); + } + + public Document serialize(){ + return new Document("item", CorePlugin.GSON.toJson(item)) + .append("slot", slot); + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/commands/CrateCommands.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/commands/CrateCommands.java new file mode 100644 index 0000000..b98743f --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/commands/CrateCommands.java @@ -0,0 +1,286 @@ +package rip.battle.crates.crate.commands; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.chat.Clickable; +import cc.stormworth.core.util.command.annotations.Command; +import cc.stormworth.core.util.command.annotations.Param; +import cc.stormworth.core.util.onedoteight.TitleBuilder; +import cc.stormworth.hcf.profile.HCFProfile; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.crates.airdrop.Airdrop; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.menus.CSGOOpenMenu; +import rip.battle.crates.crate.menus.CrateEditMenu; +import rip.battle.crates.crate.menus.CratePreviewMenu; +import rip.battle.crates.misterybox.MysteryBox; + +public class CrateCommands { + + @Command(names = {"crate", "cr", "crates", "mysterybox", "mb"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void help(Player player) { + player.sendMessage(CC.translate("&a&lCrates Help")); + player.sendMessage(CC.translate("&7- &e/crate create &7- &aCreate a crate")); + player.sendMessage(CC.translate("&7- &e/mystery create &7- &aCreate a mystery box")); + player.sendMessage(""); + player.sendMessage(CC.translate("&7- &e/crate delete &7- &aDelete a crate")); + player.sendMessage(CC.translate("&7- &e/crate list &7- &aList all crates")); + player.sendMessage(CC.translate("&7- &e/crate edit &7- &aEdit a crate")); + player.sendMessage(CC.translate("&7- &e/crate preview &7- &aPreview a crate")); + player.sendMessage(CC.translate("&7- &e/crate give &7- &aGive a crate key to player")); + player.sendMessage(CC.translate("&7- &e/reward &7- &aTo show help for rewards")); + + player.sendMessage(CC.translate("&7- &e/airdrop give &7- &aTo show help for rewards")); + } + + @Command(names = {"airdrop"}, permission = "", hidden = true) + public static void airdrop(Player player) { + Airdrop airdrop = (Airdrop) Crate.getByName("Airdrop"); + + if (airdrop == null) { + player.sendMessage(CC.translate("&cairdrop with that name does not exist!")); + return; + } + + new CratePreviewMenu(airdrop).openMenu(player); + } + + @Command(names = {"crate create", "cr create", "crates create"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void create(Player player, @Param(name = "name") String name) { + if (Crate.getByName(name) != null) { + player.sendMessage(CC.translate("&cCrate with that name already exists!")); + return; + } + + Crate crate = new Crate(name); + + crate.save(); + + player.sendMessage(CC.translate("&aCrate &e" + name + "&a created!")); + } + + @Command(names = {"mysterybox create", "mb create"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void mysterybox(Player player, @Param(name = "name") String name) { + if (Crate.getByName(name) != null) { + player.sendMessage(CC.translate("&cCrate with that name already exists!")); + return; + } + + MysteryBox crate = new MysteryBox(name); + + crate.save(); + + player.sendMessage(CC.translate("&aMystery &e" + name + "&a created!")); + } + + @Command(names = {"crate delete", "cr delete", "crates delete", "crate remove", "cr remove", "crates remove"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void delete(Player player, @Param(name = "name") String name) { + Crate crate = Crate.getByName(name); + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + crate.delete(); + player.sendMessage(CC.translate("&aCrate &e" + name + "&a deleted!")); + } + + @Command(names = {"crate list", "cr list", "crates list", "mysterybox list", "mb list"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void list(Player player) { + player.sendMessage(CC.translate("&aCrates:")); + for (Crate crate : Crate.getCrates().values()) { + if (crate instanceof MysteryBox) { + player.sendMessage(CC.translate("&7- &e" + crate.getName() + " &7- &aMystery Box")); + } else if (crate instanceof Airdrop) { + player.sendMessage(CC.translate("&7- &e" + crate.getName() + " &7- &aAirdrop")); + } else { + player.sendMessage(CC.translate("&7- &e" + crate.getName() + " &7- &aCrate")); + } + } + } + + @Command(names = {"crate edit", "cr edit", "crates edit", "mysterybox edit", "mb edit", "airdrop edit", "ad edit"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void edit(Player player, @Param(name = "name") String name) { + Crate crate = Crate.getByName(name); + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + new CrateEditMenu(crate).openMenu(player); + } + + @Command(names = {"crate test"}, permission = "op", hidden = true) + public static void test(Player player, @Param(name = "name") String name) { + Crate crate = Crate.getByName(name); + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + new CSGOOpenMenu(crate).openMenu(player); + } + + @Command(names = {"airdrop edit", "ad edit"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void airdropEdit(Player player) { + Crate crate = Crate.getByName("Airdrop"); + + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + new CrateEditMenu(crate).openMenu(player); + } + + @Command(names = {"crate preview", "cr preview", "crates preview", "mysterybox preview", "mb preview"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void preview(Player player, @Param(name = "name") String name) { + Crate crate = Crate.getByName(name); + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + new CratePreviewMenu(crate).openMenu(player); + } + + @Command(names = {"crate give", "cr give", "crates give", "mysterybox give", "mb give", "airdrop give", "ad give"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void give(CommandSender player, @Param(name = "name") String name, + @Param(name = "amount") int amount, + @Param(name = "target") Player target) { + + Crate crate = Crate.getByName(name); + + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + ItemStack item = crate.generateKey().clone(); + item.setAmount(amount); + target.getInventory().addItem(item); + + if (crate instanceof MysteryBox) { + player.sendMessage(CC.translate("&eYou have given x" + amount + " &6Mistery&e Keys to &6" + target.getName() + "&e!")); + } else if (crate instanceof Airdrop) { + player.sendMessage(CC.translate("&eYou have given x" + amount + " &6Airdrop&e to &6" + target.getName() + "&e!")); + } else { + player.sendMessage(CC.translate("&eYou have given x" + amount + " &6Crate Keys&e to &6" + target.getName() + "&e!")); + } + } + + @Command(names = {"givekey", "crate givekey"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void give(CommandSender player, + @Param(name = "target") Player target, + @Param(name = "name") String name, + @Param(name = "amount") int amount) { + Crate crate = Crate.getByName(name); + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + ItemStack item = crate.generateKey().clone(); + item.setAmount(amount); + + if (target.getInventory().firstEmpty() == -1) { + target.sendMessage(""); + target.sendMessage(CC.translate("&a&eYour inventory was &cfull&e.")); + + Clickable clickable = new Clickable("&a[Click here] &eto recover the items.", + "&a[Click here]", + "/reclaimitems"); + clickable.sendToPlayer(target); + target.sendMessage(""); + + HCFProfile profile = HCFProfile.get(target); + + profile.getNoReclaimedItems().add(Crate.getByName("Blood").generateKey()); + return; + } + + target.getInventory().addItem(item); + } + + @Command(names = {"crate setchest", "cr setchest", "crates setchest", "mysterybox setchest", "mb setchest"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void setChest(Player player, @Param(name = "name") String name) { + Crate crate = Crate.getByName(name); + + if (crate == null) { + player.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + Block targetBlock = player.getTargetBlock(null, 4); + + if (targetBlock == null) { + player.sendMessage(CC.translate("&cYou must be look a block.")); + return; + } + + Location location = targetBlock.getLocation(); + if (crate.getChestLocation() != null && crate.getChestLocation().equals(location)) { + player.sendMessage(CC.translate("&cThere is another crate.")); + return; + } + + crate.createHologram(location); + + crate.setChestLocation(location); + player.sendMessage(CC.translate("&aSuccessfully set chest location.")); + } + + @Command(names = {"keyall"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void keyall(CommandSender sender, @Param(name = "name") String name, @Param(name = "amount") int amount) { + Crate crate = Crate.getByName(name); + + if (crate == null) { + sender.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + for (Player target : Bukkit.getOnlinePlayers()) { + ItemStack item = crate.generateKey().clone(); + item.setAmount(amount); + if (target.getInventory().firstEmpty() != -1) { + target.getInventory().addItem(item); + } else { + target.getWorld().dropItem(target.getLocation(), item); + } + + TitleBuilder titleBuilder = new TitleBuilder(crate.getDisplayName() + " &areceived.", + "&eAmount: &f" + amount, + 10, 20, 10); + titleBuilder.send(target); + } + + sender.sendMessage(CC.translate("&eYou have given &6x" + amount + " " + crate.getName() + " &eto &6everybody&e.")); + } + + @Command(names = {"keyalldone"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void keyalldone(CommandSender sender) { + + for (Player other : Bukkit.getOnlinePlayers()) { + TitleBuilder titleBuilder = new TitleBuilder("&4&lKeyall", "&7has finished.", 10, 20, 10); + titleBuilder.send(other); + } + } + + @Command(names = {"create removechest", "cr removechest"}, permission = "PLATFORMADMINISTRATOR", hidden = true) + public static void removeLocation(CommandSender sender, @Param(name = "name") String name) { + Crate crate = Crate.getByName(name); + + if (crate == null) { + sender.sendMessage(CC.translate("&cCrate with that name does not exist!")); + return; + } + + crate.setChestLocation(null); + crate.removeHologram(); + sender.sendMessage(CC.translate("&aSuccessfully removed chest location.")); + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/listeners/CrateListener.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/listeners/CrateListener.java new file mode 100644 index 0000000..1d4ce72 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/listeners/CrateListener.java @@ -0,0 +1,189 @@ +package rip.battle.crates.crate.listeners; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.general.TaskUtil; +import com.google.common.collect.Lists; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import rip.battle.crates.Crates; +import rip.battle.crates.airdrop.Airdrop; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.CratePlaceholder; +import rip.battle.crates.crate.menus.CSGOOpenMenu; +import rip.battle.crates.crate.menus.CrateEditMenu; +import rip.battle.crates.crate.menus.CratePreviewMenu; +import rip.battle.crates.misterybox.MysteryBox; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.supplydrop.SupplyDrop; +import rip.battle.crates.utils.RandomUtils; + +import java.util.List; + +public class CrateListener implements Listener { + + @EventHandler + public void onInventoryClose(InventoryCloseEvent event) { + Player player = (Player) event.getPlayer(); + + Inventory inventory = event.getInventory(); + + if (player.hasMetadata("closeByRightClick")) { + player.removeMetadata("closeByRightClick", Crates.getInstance()); + return; + } + + if (inventory.getName().contains(CC.translate("&eEdit Rewards of "))) { + + String name = inventory.getName().replace(CC.translate("&eEdit Rewards of "), ""); + + Crate crate = Crate.getByName(name); + + if (crate == null) { + return; + } + + List placeholders = Lists.newArrayList(); + + for (int i = 0; i < 54; i++) { + ItemStack item = inventory.getItem(i); + + if (item == null || item.getType() == null) { + continue; + } + + if (crate.getReward(i) != null) { + continue; + } + + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + if (box.getObligatoryReward(i) != null) { + continue; + } + } + + placeholders.add(new CratePlaceholder(item, i)); + } + + crate.setPlaceholders(placeholders); + + player.sendMessage(CC.translate("&aSuccessfully updated the rewards of &e" + name + "&a!")); + player.playSound(player.getLocation(), Sound.LEVEL_UP, 0.5F, 0.5F); + + TaskUtil.runAsync(Crates.getInstance(), crate::save); + + TaskUtil.runLater(Crates.getInstance(), () -> new CrateEditMenu(crate).openMenu(player), + 2L); + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (Crate.getCrateByKey(player.getItemInHand()) instanceof Airdrop) { + player.sendMessage(CC.translate("&cTo use AirDrop you have to put the block on the ground.")); + return; + } + + if (Crate.getCrateByKey(player.getItemInHand()) instanceof SupplyDrop) { + return; + } + + if (Crate.getCrateByKey(player.getItemInHand()) instanceof MysteryBox) { + MysteryBox box = (MysteryBox) Crate.getCrateByKey(player.getItemInHand()); + box.openCrate(player); + return; + } + + if (Crate.getCrateByKey(player.getItemInHand()) != null) { + + Crate crate = Crate.getCrateByKey(player.getItemInHand()); + + if (crate.getName().equalsIgnoreCase("Giftbox")) { + crate.consumeKey(player); + if (player.isSneaking()) { + + if (player.getInventory().firstEmpty() == -1) { + player.sendMessage(CC.translate("&cYour inventory is full!")); + return; + } + + Reward reward = RandomUtils.getRandomReward(crate.getRewards()); + + player.getInventory().addItem(reward.getItem()); + } else { + new CSGOOpenMenu(crate).openMenu(player); + } + return; + } + + event.setCancelled(true); + + if (event.getAction().name().contains("RIGHT_CLICK")) { + if (Crate.getCrateByKey(player.getItemInHand()) == crate) { + crate.openCrate(player); + return; + } + + if (player.isSneaking() && player.getGameMode() == GameMode.CREATIVE && player.isOp()) { + new CrateEditMenu(crate).openMenu(player); + return; + } + + new CratePreviewMenu(crate).openMenu(player); + } + if (event.getAction().name().contains("LEFT_CLICK")) { + if (player.isSneaking() && player.getGameMode() == GameMode.CREATIVE && player.isOp()) { + new CrateEditMenu(crate).openMenu(player); + return; + } + + new CratePreviewMenu(crate).openMenu(player); + } + } + + if (event.getClickedBlock() == null) return; + + Location location = event.getClickedBlock().getLocation(); + + Crate crate = Crate.getByLocation(location); + + if (crate == null) { + return; + } + + event.setCancelled(true); + + if (event.getAction().name().contains("RIGHT_CLICK")) { + if (Crate.getCrateByKey(player.getItemInHand()) == crate) { + crate.openCrate(player); + return; + } + + if (player.isSneaking() && player.getGameMode() == GameMode.CREATIVE && player.isOp()) { + new CrateEditMenu(crate).openMenu(player); + return; + } + + new CratePreviewMenu(crate).openMenu(player); + } + if (event.getAction().name().contains("LEFT_CLICK")) { + if (player.isSneaking() && player.getGameMode() == GameMode.CREATIVE && player.isOp()) { + new CrateEditMenu(crate).openMenu(player); + return; + } + + new CratePreviewMenu(crate).openMenu(player); + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CSGOOpenMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CSGOOpenMenu.java new file mode 100644 index 0000000..0c1f6ff --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CSGOOpenMenu.java @@ -0,0 +1,92 @@ +package rip.battle.crates.crate.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import com.google.common.collect.Maps; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.utils.RandomUtils; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class CSGOOpenMenu extends Menu { + + private final Crate crate; + private final Reward randomReward; + private final List rewards; + int time = 0; + private boolean claimed = false; + + @Override + public String getTitle(Player player) { + return crate.getDisplayName() + " Crate"; + } + + public CSGOOpenMenu(Crate crate) { + this.crate = crate; + this.rewards = crate.getRewards(); + + randomReward = RandomUtils.getRandomReward(rewards); + + Collections.shuffle(rewards); + setAutoUpdate(true); + setUpdateAfterClick(false); + } + + @Override + public void onClose(Player player) { + if (!claimed) { + player.getInventory().addItem(randomReward.getItem()); + player.updateInventory(); + player.playSound(player.getLocation(), Sound.LEVEL_UP, 1.0F, 1.0F); + claimed = true; + } + } + + @Override + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + + Collections.rotate(rewards, 1); + + for (int i = 0; i < 9; i++) { + buttons.put(buttons.size(), Button.fromItem(new ItemBuilder(Material.STAINED_GLASS_PANE).data((short) 0).build())); + } + + for (int i = 0; i < 9; i++) { + buttons.put(buttons.size(), Button.fromItem(rewards.get(i).getItem())); + } + + for (int i = 18; i < 27; i++) { + buttons.put(buttons.size(), Button.fromItem(new ItemBuilder(Material.STAINED_GLASS_PANE).data((short) 0).build())); + } + + buttons.put(4, Button.fromItem(new ItemBuilder(Material.STAINED_GLASS_PANE).data((short) 5).build())); + buttons.put(22, Button.fromItem(new ItemBuilder(Material.STAINED_GLASS_PANE).data((short) 5).build())); + + player.playSound(player.getLocation(), Sound.NOTE_STICKS, 1.0F, 1.0F); + + Button button = buttons.get(13); + + if (time == 25) { + if (button.getButtonItem(player).isSimilar(randomReward.getItem())) { + setAutoUpdate(false); + + player.getInventory().addItem(randomReward.getItem()); + player.updateInventory(); + player.playSound(player.getLocation(), Sound.LEVEL_UP, 1.0F, 1.0F); + claimed = true; + } + } else { + time++; + } + + return buttons; + } +} diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateBroadcastMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateBroadcastMenu.java new file mode 100644 index 0000000..b6939ac --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateBroadcastMenu.java @@ -0,0 +1,109 @@ +package rip.battle.crates.crate.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.prompt.CrateBroadCastPrompt; +import rip.battle.crates.crate.prompt.CrateEditLinePrompt; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.menus.RewardEditMenu; +import rip.battle.crates.utils.ChatUtils; + +public class CrateBroadcastMenu extends Menu { + + private final Crate crate; + private final Reward reward; + + public CrateBroadcastMenu(Crate crate, Reward reward) { + this.crate = crate; + this.reward = reward; + + setUpdateAfterClick(true); + } + + @Override + public String getTitle(Player player) { + return "&eBroadcast Lines"; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + buttons.put(0, Button.fromItem(new ItemBuilder(Material.BED) + .name("&cGo Back").build(), + (other) -> new RewardEditMenu(reward, crate).openMenu(other))); + + buttons.put(4, Button.fromItem(new ItemBuilder(Material.BOOK) + .name("&aAdd new lines").build(), + (other) -> ChatUtils.beginPrompt(other, new CrateBroadCastPrompt(crate, reward)))); + + buttons.put(8, Button.fromItem(new ItemBuilder(Material.JUKEBOX) + .name("&eClick to preview broadcast").build(), + (other) -> { + + player.closeInventory(); + + LinkedList lines = reward.getBroadcast(); + + if (lines.isEmpty()) { + other.sendMessage("&cNo broadcast lines set!"); + }else{ + lines.forEach(line -> other.sendMessage(line.replace("{player}", other.getName()))); + } + })); + + int i = 9; + int index = 0; + for (String line : reward.getBroadcast()) { + buttons.put(i++, new BroadcastLineButton(line, index++)); + } + + return buttons; + } + + @RequiredArgsConstructor + public class BroadcastLineButton extends Button{ + + private final String line; + private final int index; + + @Override + public String getName(Player player) { + return line; + } + + @Override + public List getDescription(Player player) { + return Lists.newArrayList( + "&fRight &7click to Delete this line", + "&fLeft &7click to Edit this line" + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.PAPER; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + if (clickType == ClickType.RIGHT) { + reward.getBroadcast().remove(line); + } else if (clickType == ClickType.LEFT) { + ChatUtils.beginPrompt(player, new CrateEditLinePrompt(crate, reward, index)); + } + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateDeleteMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateDeleteMenu.java new file mode 100644 index 0000000..5691862 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateDeleteMenu.java @@ -0,0 +1,52 @@ +package rip.battle.crates.crate.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import cc.stormworth.core.util.chat.CC; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; + +import java.util.Map; + +@RequiredArgsConstructor +public class CrateDeleteMenu extends Menu { + + private final Crate crate; + + @Override + public String getTitle(Player player) { + return "&cDelete Crate or chest"; + } + + @Override + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + + buttons.put(0, Button.fromItem(new ItemBuilder(Material.BED) + .name("&cGo Back").build(), + (other) -> new CrateEditMenu(crate).openMenu(other))); + + buttons.put(getSlot(3, 1), Button.fromItem(new ItemBuilder(Material.FLINT_AND_STEEL).name("&cDelete Crate").build(), + (other) -> { + other.closeInventory(); + crate.delete(); + })); + + buttons.put(getSlot(5, 1), + Button.fromItem(new ItemBuilder(Material.CHEST) + .name("&cDelete Chest").build(), (other) -> { + + + crate.removeHologram(); + crate.setChestLocation(null); + player.sendMessage(CC.translate("&aSuccessfully removed chest location.")); + other.closeInventory(); + })); + + return buttons; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateEditMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateEditMenu.java new file mode 100644 index 0000000..9bf09fd --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CrateEditMenu.java @@ -0,0 +1,190 @@ +package rip.battle.crates.crate.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import cc.stormworth.core.util.chat.CC; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.util.List; +import java.util.Map; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.prompt.CrateKeyItemPrompt; +import rip.battle.crates.crate.prompt.CrateRenamePrompt; +import rip.battle.crates.utils.ChatUtils; + +public class CrateEditMenu extends Menu { + + private final Crate crate; + + public CrateEditMenu(Crate crate) { + this.crate = crate; + + setUpdateAfterClick(true); + } + + @Override + public String getTitle(Player player) { + String name = "&eEditing &a" + crate.getDisplayName() + "&e..."; + + if(name.length() > 32) { + name = name.substring(0, 32); + } + + return name; + } + + @Override + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + + + buttons.put(getSlot(2, 1), Button.fromItem( + new ItemBuilder(Material.NAME_TAG).name("&6Change display name") + .addToLore( + "", + "&7Click to change displayname." + ).build(), + (other) -> ChatUtils.beginPrompt(other, new CrateRenamePrompt(crate)))); + + buttons.put(getSlot(4, 1), Button.fromItem( + new ItemBuilder(Material.CHEST) + .name("&6Edit rewards") + .addToLore( + "", + "&7Click to edit the rewards for this crate." + ).build(), + crate::openEditRewardsInventory)); + + buttons.put(getSlot(6, 1), Button.fromItem( + new ItemBuilder(crate.getKey().getType()) + .data(crate.getKey().getDurability()) + .name("&6Change key item") + .addToLore( + "", + "&7Click to change the key item for this crate." + ).build(), + (other) -> ChatUtils.beginPrompt(other, new CrateKeyItemPrompt(crate)))); + + + buttons.put(getSlot(4, 2), Button.fromItem( + new ItemBuilder(Material.JUKEBOX).name("&6Select open sound") + .addToLore( + "", + "&7Click to select the sound that plays when this crate is opened." + ) + .build(), + (other) -> new SelectSoundMenu(crate).openMenu(player))); + + buttons.put(getSlot(2, 3), new MinAmountButton()); + + buttons.put(getSlot(4, 3), Button.fromItem( + new ItemBuilder(crate.isEnable() ? Material.REDSTONE_TORCH_ON : Material.LEVER) + .name(crate.isEnable() ? "&cDisable crate" : "&aEnable crate") + .addToLore( + "", + "&7Click to " + (crate.isEnable() ? "disable" : "enable") + " this crate." + ).build(), + (other) -> crate.setEnable(!crate.isEnable()) + )); + + buttons.put(getSlot(6, 3), new MaxRewardsButton()); + + + buttons.put(getSlot(5, 5), Button.fromItem( + new ItemBuilder(Material.FLINT_AND_STEEL).name("&4&lDelete crate") + .addToLore( + "", + "&4&lClick to delete this crate." + ).build(), (other) -> new CrateDeleteMenu(crate).openMenu(other))); + + buttons.put(getSlot(3, 5), Button.fromItem( + new ItemBuilder(Material.ENDER_CHEST).name("&6Preview rewards") + .addToLore( + "", + "&7Click to open preview menu of rewards for this crate." + ) + .build(), (other) -> new CratePreviewMenu(crate).openMenu(other))); + + return buttons; + } + + public class MinAmountButton extends Button{ + + @Override + public String getName(Player player) { + return "&6Select Min rewards amount"; + } + + @Override + public List getDescription(Player player) { + return Lists.newArrayList( + "&7Minimum amount of rewards to be given: &f" + crate.getMinimumReward(), + "", + "&fRight click &7to decrease", + "&fLeft click &7to increase", + "" + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.WOOD_BUTTON; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + if(clickType == ClickType.RIGHT) { + if(crate.getMinimumReward() == 1) { + player.sendMessage(CC.translate("&cCrates with a minimum reward of 1 are not allowed.")); + Button.playFail(player); + return; + } + crate.setMinimumReward(crate.getMinimumReward() - 1); + } else if(clickType == ClickType.LEFT) { + crate.setMinimumReward(crate.getMinimumReward() + 1); + } + } + } + + public class MaxRewardsButton extends Button{ + + @Override + public String getName(Player player) { + return "&6Select Max rewards amount"; + } + + @Override + public List getDescription(Player player) { + return Lists.newArrayList( + "&7Maximum amount of rewards to be given: &f" + crate.getMaximumReward(), + "", + "&fRight click &7to decrease", + "&fLeft click &7to increase", + "" + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.STONE_BUTTON; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + if(clickType == ClickType.RIGHT) { + if(crate.getMaximumReward() <= crate.getMinimumReward()) { + player.sendMessage(CC.translate("&cMaximum reward must be greater than or equal to minimum reward.")); + Button.playFail(player); + return; + } + crate.setMaximumReward(crate.getMaximumReward() - 1); + } else if(clickType == ClickType.LEFT) { + crate.setMaximumReward(crate.getMaximumReward() + 1); + } + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CratePreviewMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CratePreviewMenu.java new file mode 100644 index 0000000..498f99f --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/CratePreviewMenu.java @@ -0,0 +1,48 @@ +package rip.battle.crates.crate.menus; + +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import com.google.common.collect.Maps; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.CratePlaceholder; +import rip.battle.crates.misterybox.MysteryBox; + +@RequiredArgsConstructor +public class CratePreviewMenu extends Menu { + + private final Crate crate; + + @Override + public String getTitle(Player player) { + String name = crate.getName(); + + if(name.length() > 32) { + name = name.substring(0, 32); + } + + return ChatColor.GOLD + "Preview " + name; + } + + @Override + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + + for (CratePlaceholder placeholder : crate.getPlaceholders()) { + if (placeholder.getItem() != null) { + buttons.put(placeholder.getSlot(), Button.fromItem(placeholder.getPreview())); + } + } + + crate.getRewards().forEach(reward -> buttons.put(reward.getSlot(), Button.fromItem(reward.getItem()))); + + if(crate instanceof MysteryBox) { + ((MysteryBox) crate).getObligatoryRewards().forEach(reward -> buttons.put(reward.getSlot(), Button.fromItem(reward.getItem()))); + } + + return buttons; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/SelectSoundMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/SelectSoundMenu.java new file mode 100644 index 0000000..ca16207 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/menus/SelectSoundMenu.java @@ -0,0 +1,96 @@ +package rip.battle.crates.crate.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import cc.stormworth.core.menu.pagination.PaginatedMenu; +import cc.stormworth.core.util.chat.CC; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.battle.crates.crate.Crate; + +@RequiredArgsConstructor +public class SelectSoundMenu extends PaginatedMenu { + + private final Crate crate; + + @Override + public String getTitle(Player player) { + return "&6Select sound when open"; + } + + @Override + public String getPrePaginatedTitle(Player player) { + return "&6Select sound when open &f" + crate.getName(); + } + + @Override + public int getMaxItemsPerPage(Player player) { + return 27; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = Maps.newHashMap(); + + buttons.put(4, Button.fromItem(new ItemBuilder(Material.BED).name("&cGo Back").build(), + (other) -> new CrateEditMenu(crate).openMenu(other))); + + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = Maps.newHashMap(); + + for (Sound sound : Sound.values()) { + buttons.put(buttons.size(), new SoundButton(sound)); + } + + return buttons; + } + + @RequiredArgsConstructor + public class SoundButton extends Button{ + private final Sound sound; + + @Override + public String getName(Player player) { + return "&6" + sound.name(); + } + + @Override + public List getDescription(Player player) { + return Lists.newArrayList( + "&fLeft click &6to Set sound", + "&fRight click &7to Play sound" + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.JUKEBOX; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + if(clickType == ClickType.LEFT){ + player.playSound(player.getLocation(), sound, 1, 1); + crate.setOpenSound(sound); + + player.sendMessage(CC.translate("&6Set sound to &f" + sound.name())); + + new CrateEditMenu(crate).openMenu(player); + }else{ + player.playSound(player.getLocation(), sound, 1, 1); + } + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateBroadCastPrompt.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateBroadCastPrompt.java new file mode 100644 index 0000000..01d2fec --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateBroadCastPrompt.java @@ -0,0 +1,49 @@ +package rip.battle.crates.crate.prompt; + +import cc.stormworth.core.util.chat.CC; +import java.util.LinkedList; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.menus.CrateBroadcastMenu; +import rip.battle.crates.reward.Reward; + +public class CrateBroadCastPrompt extends StringPrompt { + + private final Crate crate; + private final Reward reward; + private final LinkedList lines; + + public CrateBroadCastPrompt(Crate crate, Reward reward) { + this.reward = reward; + this.crate = crate; + this.lines = reward.getBroadcast(); + } + + @Override + public String getPromptText(ConversationContext context) { + return CC.translate("&7Enter a lines to broadcast when the crate is opened. " + + "&7&oOr type &ccancel&7&o to cancel or type &aconfirm&7 to end: "); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel") || input.equalsIgnoreCase("confirm")) { + + reward.setBroadcast(lines); + + new CrateBroadcastMenu(crate, reward).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + lines.add(CC.translate(input.replace("{name}", crate.getDisplayName()))); + + player.sendMessage(CC.translate("&aAdded new broadcast line")); + return this; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateEditLinePrompt.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateEditLinePrompt.java new file mode 100644 index 0000000..dba9d09 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateEditLinePrompt.java @@ -0,0 +1,40 @@ +package rip.battle.crates.crate.prompt; + +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.menus.CrateBroadcastMenu; +import rip.battle.crates.reward.Reward; + +@RequiredArgsConstructor +public class CrateEditLinePrompt extends StringPrompt { + + private final Crate crate; + private final Reward reward; + private final int index; + + @Override + public String getPromptText(ConversationContext conversationContext) { + return CC.translate("&7Enter a text to modify the line number &6" + index + "&7. Or type &ccancel&7 to cancel."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + new CrateBroadcastMenu(crate, reward).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + reward.getBroadcast().set(index, CC.translate(input.replace("{name}", crate.getDisplayName()))); + + new CrateBroadcastMenu(crate, reward).openMenu(player); + + return Prompt.END_OF_CONVERSATION; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateKeyItemPrompt.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateKeyItemPrompt.java new file mode 100644 index 0000000..3b9c578 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateKeyItemPrompt.java @@ -0,0 +1,48 @@ +package rip.battle.crates.crate.prompt; + +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.menus.CrateEditMenu; + +@RequiredArgsConstructor +public class CrateKeyItemPrompt extends StringPrompt { + + private final Crate crate; + + @Override + public String getPromptText(ConversationContext conversationContext) { + return CC.translate("&7Put item in your hand and type &6accept&7 to confirm. Or type &6cancel&7 to cancel."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + player.sendMessage(CC.translate("&cCrate rename cancelled.")); + new CrateEditMenu(crate).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + if(player.getItemInHand() == null) { + player.sendMessage(CC.translate("&cYou must have an item in your hand to select it.")); + return this; + } + + if (input.equalsIgnoreCase("accept")) { + crate.setKey(player.getItemInHand()); + player.sendMessage(CC.translate("&aCrate key item set to &6" + player.getItemInHand().getType().name() + "&a.")); + + new CrateEditMenu(crate).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + return this; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateRenamePrompt.java b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateRenamePrompt.java new file mode 100644 index 0000000..e455a97 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/crate/prompt/CrateRenamePrompt.java @@ -0,0 +1,43 @@ +package rip.battle.crates.crate.prompt; + +import cc.stormworth.core.util.chat.CC; +import lombok.AllArgsConstructor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.menus.CrateEditMenu; + +@AllArgsConstructor +public class CrateRenamePrompt extends StringPrompt { + + private final Crate crate; + + @Override + public String getPromptText(ConversationContext conversationContext) { + return CC.translate("&7Enter a new display name for the crate: &6" + crate.getName() + "&7. Or type &6cancel&7 to cancel."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + player.sendMessage(CC.translate("&cCrate rename cancelled.")); + new CrateEditMenu(crate).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } + + crate.setDisplayName(CC.translate(input)); + + player.sendMessage(CC.translate("&aCrate displayname change to &6" + crate.getDisplayName() + "&a.")); + + crate.destroyHolograms(); + crate.sendHolograms(); + + new CrateEditMenu(crate).openMenu(player); + return Prompt.END_OF_CONVERSATION; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/misterybox/MysteryBox.java b/Battle-Crates-main/src/main/java/rip/battle/crates/misterybox/MysteryBox.java new file mode 100644 index 0000000..7b58ccb --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/misterybox/MysteryBox.java @@ -0,0 +1,146 @@ +package rip.battle.crates.misterybox; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.util.chat.CC; +import com.google.common.collect.Lists; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.RewardType; +import rip.battle.crates.utils.ChatUtils; +import rip.battle.crates.utils.RandomUtils; + +import java.util.*; + +@Getter +@Setter +public class MysteryBox extends Crate { + + private List obligatoryRewards = Lists.newArrayList(); + + public MysteryBox(String name) { + super(name); + } + + @Override + public List getHologramsLines() { + return Arrays.asList( + getDisplayName() + " MisteryBox", + "&7", + "&fLeft click &7for preview rewards", + "&fRight click &7to open", + "&7", + "&7&ostore.battle.rip"); + } + + @Override + public ItemStack generateKey() { + return new ItemBuilder(getKey().clone()) + .name(CC.translate(getDisplayName() + " Key")) + .setLore(Lists.newArrayList( + "&7", + "&7You can preview this " + getDisplayName() + " Crate &7 rewards", + "&7By going to the overworld &aSpawn", + "&7", + ChatUtils.getFirstColor(getDisplayName()) + "Right Click &7to open the key", + ChatUtils.getFirstColor(getDisplayName()) + "Left Click &7to preview rewards", + "&7", + "&7Purchase additional keys at &f&nstore.battle.rip" + )) + .build(); + } + + @Override + public void openCrate(Player player) { + + if (!isEnable()) { + player.sendMessage(CC.translate("&cThis misterybox is currently disabled")); + return; + } + + if (getMaximumReward() == 0 || getRewards().isEmpty()) { + player.sendMessage(CC.translate("&cCrate " + getName() + " is empty, please contact an admin.")); + return; + } + + if (player.getInventory().firstEmpty() < 0) { + player.sendMessage(CC.translate("&cInventory Full.")); + return; + } + + int random = new Random().nextInt(getMaximumReward() - getMinimumReward() + 1) + getMinimumReward(); + + List randomRewards = new ArrayList<>(); + + List rewardList = new ArrayList<>(getRewards()); + + Collections.shuffle(rewardList); + + for (int i = 0; i < random; i++) { + randomRewards.add(RandomUtils.getRandomReward(rewardList)); + } + + for (Reward reward : obligatoryRewards) { + if (reward.getType() == RewardType.ITEMS) { + if (player.getInventory().firstEmpty() < 0) { + player.sendMessage(CC.translate("&cInventory Full.")); + player.getWorld().dropItem(player.getLocation(), reward.getItem()); + } else { + player.getInventory().addItem(reward.getItem()); + } + } else { + List commands = reward.getCommands(); + + for (String command : commands) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName())); + } + } + + if (!reward.getBroadcast().isEmpty()) { + reward.getBroadcast().forEach(line -> Bukkit.broadcastMessage(line.replace("{player}", player.getName()))); + } + } + + for (Reward reward : randomRewards) { + if (reward.getType() == RewardType.ITEMS) { + if (player.getInventory().firstEmpty() < 0) { + player.sendMessage(CC.translate("&cInventory Full.")); + player.getWorld().dropItem(player.getLocation(), reward.getItem()); + } else { + player.getInventory().addItem(reward.getItem()); + } + } else { + List commands = reward.getCommands(); + + for (String command : commands) { + if (command.contains("op")) { + continue; + } + + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName())); + } + } + + if (!reward.getBroadcast().isEmpty()) { + reward.getBroadcast().forEach(line -> Bukkit.broadcastMessage(line.replace("{player}", player.getName()))); + } + } + + + if (getOpenSound() != null) { + player.playSound(player.getLocation(), getOpenSound(), 1, 1); + } + + player.sendMessage(CC.translate("&aYou have received " + (randomRewards.size() + obligatoryRewards.size()) + " reward(s)")); + consumeKey(player); + player.updateInventory(); + } + + public Reward getObligatoryReward(int slot) { + return obligatoryRewards.stream().filter(reward -> reward.getSlot() == slot).findFirst().orElse(null); + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/Reward.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/Reward.java new file mode 100644 index 0000000..82b6ae9 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/Reward.java @@ -0,0 +1,152 @@ +package rip.battle.crates.reward; + +import cc.stormworth.core.CorePlugin; +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.util.chat.CC; +import com.google.common.collect.Lists; +import lombok.Getter; +import lombok.Setter; +import org.bson.Document; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import rip.battle.crates.utils.ItemUtils; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +@Getter +@Setter +public class Reward { + + private ItemStack item; + private double chance; + private int slot; + private RewardType type; + private List commands; + private boolean obligatory; + private LinkedList broadcast = Lists.newLinkedList(); + + public Reward(ItemStack item, double chance, int slot, RewardType type, List commands, boolean obligatory) { + this.item = item; + + if (this.item == null) { + this.item = new ItemStack(Material.AIR); + } + + this.chance = chance; + this.slot = slot; + this.type = type; + this.commands = commands; + this.obligatory = obligatory; + + if (this.chance > 1.0) { + this.chance = 1.0; + } + + ItemUtils.removeRewardsLore(this.item); + } + + public Reward(Document document) { + this.item = CorePlugin.GSON.fromJson(document.getString("item"), ItemStack.class); + this.slot = document.getInteger("slot"); + + if (document.get("chance") instanceof Double) { + this.chance = document.getDouble("chance"); + } else if (document.get("chance") instanceof Integer) { + this.chance = Double.parseDouble(document.getInteger("chance").toString()); + } + + if (this.chance > 1.0) { + this.chance = 1.0; + } + + if (document.containsKey("type")) { + this.type = RewardType.getByName(document.getString("type")); + } else { + this.type = RewardType.ITEMS; + } + + if (document.containsKey("commands")) { + this.commands = document.getList("commands", String.class); + } + + if (document.containsKey("broadcast")) { + setBroadcast(new LinkedList<>(document.getList("broadcast", String.class))); + } + } + + public ItemStack getItem() { + + if (this.item == null) { + return new ItemStack(Material.AIR); + } + + ItemStack item = this.item.clone(); + + ItemUtils.removeRewardsLore(item); + return item; + } + + public ItemStack getPreviewItem() { + List lore = Lists.newArrayList(); + + lore.add("&0"); + lore.add("&7Type: &e" + this.type.name()); + lore.add("&0"); + lore.add("&7Chance: &e" + this.chance + "%"); + if (this.commands != null && !this.commands.isEmpty()) { + lore.add("&7Commands: &e"); + for (String command : this.commands) { + lore.add(" &7- &f" + command); + } + } + lore.add("&0"); + lore.add("&fRight Click &7to edit"); + + return new ItemBuilder(this.item.clone()) + .addLoreList(CC.translate(lore)).build(); + } + + public ItemStack getPreviewObligatoryItem() { + List lore = Lists.newArrayList(); + + lore.add("&0"); + lore.add("&7Type: &e" + this.type.name()); + lore.add("&0"); + lore.add("&7Chance: &e" + this.chance + "%"); + lore.add("&cObligatory"); + if (this.commands != null && !this.commands.isEmpty()) { + lore.add("&7Commands: &e"); + for (String command : this.commands) { + lore.add(" &7- &f" + command); + } + } + lore.add("&0"); + lore.add("&fRight Click &7to edit"); + + return new ItemBuilder(this.item.clone()) + .addLoreList(CC.translate(lore)).build(); + } + + public ItemStack getRealItem() { + return item; + } + + public Document serialize() { + Document document = new Document(); + document.append("item", CorePlugin.GSON.toJson(item)); + document.append("slot", slot); + document.append("chance", chance); + document.append("type", type.name()); + + if (commands != null) { + document.append("commands", commands); + } + + document.append("broadcast", new ArrayList<>(broadcast)); + + return document; + } + +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/RewardType.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/RewardType.java new file mode 100644 index 0000000..4814c7b --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/RewardType.java @@ -0,0 +1,17 @@ +package rip.battle.crates.reward; + +public enum RewardType { + + COMMAND, + ITEMS; + + public static RewardType getByName(String name) { + for (RewardType type : RewardType.values()) { + if (type.name().equalsIgnoreCase(name)) { + return type; + } + } + return null; + } + +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/RewardsListeners.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/RewardsListeners.java new file mode 100644 index 0000000..c8a8381 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/RewardsListeners.java @@ -0,0 +1,221 @@ +package rip.battle.crates.reward; + +import cc.stormworth.core.util.chat.CC; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.metadata.FixedMetadataValue; +import rip.battle.crates.Crates; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.CratePlaceholder; +import rip.battle.crates.misterybox.MysteryBox; +import rip.battle.crates.reward.menus.RewardEditMenu; +import rip.battle.crates.utils.ItemUtils; + +public class RewardsListeners implements Listener { + + @EventHandler + public void onInventoryOpen(InventoryOpenEvent event) { + Inventory inventory = event.getInventory(); + + if (inventory.getName().contains(CC.translate("&eEdit Rewards of "))) { + + String name = inventory.getName().replace(CC.translate("&eEdit Rewards of "), ""); + + Crate crate = Crate.getByName(name); + + if (crate == null) { + return; + } + + for (CratePlaceholder placeholder : crate.getPlaceholders()) { + if (placeholder.getItem() == null) { + crate.getPlaceholders().remove(placeholder); + continue; + } + + inventory.setItem(placeholder.getSlot(), placeholder.getItem()); + } + + crate.getRewards().forEach(reward -> inventory.setItem(reward.getSlot(), reward.getPreviewItem())); + + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + box.getObligatoryRewards().forEach(reward -> inventory.setItem(reward.getSlot(), reward.getPreviewObligatoryItem())); + } + + } + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + + Inventory inventory = event.getInventory(); + + if (event.getClickedInventory() == null) { + return; + } + + if (inventory.getName().contains(CC.translate("&eEdit Rewards of "))) { + + String name = inventory.getName().replace(CC.translate("&eEdit Rewards of "), ""); + + Crate crate = Crate.getByName(name); + + if (crate == null) { + return; + } + + if (event.getClick() == ClickType.RIGHT) { + + if (event.getClickedInventory() == player.getInventory()) { + return; + } + + event.setCancelled(true); + + + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + if (box.getObligatoryReward(event.getSlot()) != null) { + player.setMetadata("closeByRightClick", new FixedMetadataValue(Crates.getInstance(), true)); + + new RewardEditMenu(box.getObligatoryReward(event.getSlot()), crate).openMenu(player); + return; + } + } + + if (crate.getReward(event.getSlot()) != null) { + player.setMetadata("closeByRightClick", new FixedMetadataValue(Crates.getInstance(), true)); + new RewardEditMenu(crate.getReward(event.getSlot()), crate).openMenu(player); + } else if (crate.getPlaceholder(event.getSlot()) != null) { + CratePlaceholder placeholder = crate.getPlaceholder(event.getSlot()); + Reward newReward = new Reward(placeholder.getItem().clone(), 100, placeholder.getSlot(), RewardType.ITEMS, null, false); + + crate.getPlaceholders().remove(placeholder); + crate.getRewards().add(newReward); + + player.setMetadata("closeByRightClick", new FixedMetadataValue(Crates.getInstance(), true)); + + new RewardEditMenu(newReward, crate).openMenu(player); + } else { + Reward newReward = new Reward(event.getCurrentItem(), 100, event.getSlot(), RewardType.ITEMS, null, false); + + crate.getRewards().add(newReward); + + player.setMetadata("closeByRightClick", new FixedMetadataValue(Crates.getInstance(), true)); + + new RewardEditMenu(newReward, crate).openMenu(player); + } + } else { + if (event.getClick() == ClickType.DROP || event.getClick() == ClickType.CONTROL_DROP) { + if (crate.getPlaceholder(event.getSlot()) != null) { + crate.getPlaceholders().remove(crate.getPlaceholder(event.getSlot())); + } + + if (crate.getReward(event.getSlot()) != null) { + crate.getRewards().remove(crate.getReward(event.getSlot())); + } + + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + if (box.getObligatoryReward(event.getSlot()) != null) { + box.getObligatoryRewards().remove(box.getObligatoryReward(event.getSlot())); + } + } + } else if (event.getClick() == ClickType.SHIFT_LEFT) { + if (event.getClickedInventory() == player.getInventory()) { + + if (ItemUtils.isReward(event.getCursor())) { + Reward reward = ItemUtils.getRewardByItem(event.getCurrentItem().clone(), inventory.firstEmpty()); + + if (reward != null) { + if (reward.isObligatory()) { + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + box.getObligatoryRewards().add(reward); + return; + } + } + + crate.getRewards().add(reward); + + return; + } + } + + crate.getPlaceholders().add(new CratePlaceholder(event.getCurrentItem().clone(), inventory.firstEmpty())); + } else { + if (crate.getPlaceholder(event.getSlot()) != null) { + crate.getPlaceholders().remove(crate.getPlaceholder(event.getSlot())); + } + + if (crate.getReward(event.getSlot()) != null) { + crate.getRewards().remove(crate.getReward(event.getSlot())); + } + + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + if (box.getObligatoryReward(event.getSlot()) != null) { + box.getObligatoryRewards().remove(box.getObligatoryReward(event.getSlot())); + } + } + } + } else if (event.getClick() == ClickType.LEFT) { + if (event.getClickedInventory() == player.getInventory()) { + return; + } + + if (event.getInventory().getItem(event.getSlot()) == null) { + if (ItemUtils.isReward(event.getCursor())) { + Reward reward = ItemUtils.getRewardByItem(event.getCursor().clone(), event.getSlot()); + + if (reward != null) { + if (reward.isObligatory()) { + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + box.getObligatoryRewards().add(reward); + return; + } + } + + crate.getRewards().add(reward); + + return; + } + } + + crate.getPlaceholders().add(new CratePlaceholder(event.getCursor().clone(), event.getSlot())); + } else { + if (crate.getPlaceholder(event.getSlot()) != null) { + crate.getPlaceholders().remove(crate.getPlaceholder(event.getSlot())); + } + + if (crate.getReward(event.getSlot()) != null) { + crate.getRewards().remove(crate.getReward(event.getSlot())); + } + + if (crate instanceof MysteryBox) { + MysteryBox box = (MysteryBox) crate; + + if (box.getObligatoryReward(event.getSlot()) != null) { + box.getObligatoryRewards().remove(box.getObligatoryReward(event.getSlot())); + } + } + } + } + } + } + } + +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/commands/RewardCommand.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/commands/RewardCommand.java new file mode 100644 index 0000000..1d9838b --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/commands/RewardCommand.java @@ -0,0 +1,115 @@ +package rip.battle.crates.reward.commands; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.command.annotations.Command; +import cc.stormworth.core.util.command.annotations.Param; +import com.google.common.collect.Lists; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class RewardCommand { + + @Command(names = {"reward"}, permission = "PLATFORMADMINISTRATOR") + public static void help(Player player) { + player.sendMessage(CC.translate("&a&lReward Help")); + player.sendMessage(CC.translate("&7- &e/reward setchance &7- &aSets the chance for the item in your hand")); + player.sendMessage(CC.translate("&7- &e/reward setobligatory &7- &aSets the item in your hand to be obligatory")); + player.sendMessage(CC.translate("&7- &e/reward addcommand &7- &aAdds a command to the item in your hand")); + } + + @Command(names = {"reward setchance"}, permission = "PLATFORMADMINISTRATOR") + public static void setChance(Player player, @Param(name = "chance") int chance) { + if (chance < 0 || chance > 100) { + player.sendMessage(CC.translate("&cChance must be between 0 and 100!")); + return; + } + + ItemStack itemStack = player.getItemInHand(); + + if (itemStack == null) { + player.sendMessage(CC.translate("&cYou must be holding an item to set the chance!")); + return; + } + + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) { + player.sendMessage(CC.translate("&cYou must be holding an item to set the chance!")); + return; + } + + List lore = meta.getLore(); + + if (lore == null) { + lore = Lists.newArrayList(); + } + + lore.add(0, CC.translate("&7Chance:&a " + chance)); + + meta.setLore(lore); + itemStack.setItemMeta(meta); + + player.sendMessage(CC.translate("&aSuccessfully set chance for &e" + itemStack.getType().name() + " &ato &e" + chance + "%")); + } + + @Command(names = {"reward setobligatory"}, permission = "PLATFORMADMINISTRATOR") + public static void setObligatory(Player player) { + ItemStack itemStack = player.getItemInHand(); + + if (itemStack == null) { + player.sendMessage(CC.translate("&cYou must be holding an item to set the chance!")); + return; + } + + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) { + player.sendMessage(CC.translate("&cYou must be holding an item to set the chance!")); + return; + } + + List lore = meta.getLore(); + + if (lore == null) { + lore = Lists.newArrayList(); + } + + lore.add(0, CC.translate("&7Obligatory")); + + meta.setLore(lore); + itemStack.setItemMeta(meta); + + player.sendMessage(CC.translate("&aSuccessfully set obligatory for &e" + itemStack.getType().name())); + } + + @Command(names = {"reward addcommand"}, permission = "PLATFORMADMINISTRATOR") + public static void setcommand(Player player, @Param(name = "command", wildcard = true) String command) { + ItemStack itemStack = player.getItemInHand(); + + if (itemStack == null) { + player.sendMessage(CC.translate("&cYou must be holding an item to set the chance!")); + return; + } + + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) { + player.sendMessage(CC.translate("&cYou must be holding an item to set the chance!")); + return; + } + + List lore = meta.getLore(); + + if (lore == null) { + lore = Lists.newArrayList(); + } + + lore.add(0, CC.translate("&7Command:&a " + command)); + + meta.setLore(lore); + itemStack.setItemMeta(meta); + + player.sendMessage(CC.translate("&aSuccessfully added command for &e" + itemStack.getType().name())); + } + +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/menus/RewardCommandsMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/menus/RewardCommandsMenu.java new file mode 100644 index 0000000..9a254c0 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/menus/RewardCommandsMenu.java @@ -0,0 +1,113 @@ +package rip.battle.crates.reward.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.RewardType; +import rip.battle.crates.reward.promt.RewardAddCommandPrompt; +import rip.battle.crates.utils.ChatUtils; + +public class RewardCommandsMenu extends Menu { + + private final Reward reward; + private final Crate crate; + + public RewardCommandsMenu(Reward reward, Crate crate) { + this.reward = reward; + this.crate = crate; + + setUpdateAfterClick(true); + } + + @Override + public String getTitle(Player player) { + return ChatColor.GREEN + "Manage commands"; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + + buttons.put(getSlot(0, 0), Button.fromItem( + new ItemBuilder(Material.BED) + .name("&cGo Back") + .addToLore( + "", + "&7Click to go back to the reward edit menu." + ).build(), + (other) -> { + if(reward.getCommands().isEmpty()) { + reward.setType(RewardType.ITEMS); + } + + new RewardEditMenu(reward, crate).openMenu(other); + })); + + if(reward.getCommands().isEmpty()) { + buttons.put(getSlot(4, 0), Button.fromItem( + new ItemBuilder(Material.PAPER) + .name("&bAdd Command") + .addToLore( + "", + "&7Click add command to reward." + ).build(), + (other) -> ChatUtils.beginPrompt(player, new RewardAddCommandPrompt(reward, crate, new RewardCommandsMenu(reward, crate))))); + } + + int slot = 9; + + for (String command : reward.getCommands()) { + buttons.put(slot, new CommandButton(command)); + } + + return buttons; + } + + @RequiredArgsConstructor + public class CommandButton extends Button{ + + private final String command; + + @Override + public String getName(Player player) { + return ChatColor.GOLD + command; + } + + @Override + public List getDescription(Player player) { + return Lists.newArrayList( + "", + "&fLeft Click to edit command", + "&fRight Click to remove command" + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.PAPER; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + reward.getCommands().remove(command); + if (clickType == ClickType.LEFT) { + ChatUtils.beginPrompt(player, new RewardAddCommandPrompt(reward, crate, new RewardCommandsMenu(reward, crate))); + } else if (clickType == ClickType.RIGHT) { + Button.playNeutral(player); + } + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/menus/RewardEditMenu.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/menus/RewardEditMenu.java new file mode 100644 index 0000000..2fcda4a --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/menus/RewardEditMenu.java @@ -0,0 +1,143 @@ +package rip.battle.crates.reward.menus; + +import cc.stormworth.core.kt.util.ItemBuilder; +import cc.stormworth.core.menu.Button; +import cc.stormworth.core.menu.Menu; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import rip.battle.crates.Crates; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.crate.menus.CrateBroadcastMenu; +import rip.battle.crates.misterybox.MysteryBox; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.promt.RewardAddCommandPrompt; +import rip.battle.crates.reward.promt.RewardSetChancePrompt; +import rip.battle.crates.utils.ChatUtils; + +@RequiredArgsConstructor +public class RewardEditMenu extends Menu { + + private final Reward reward; + private final Crate crate; + + @Override + public String getTitle(Player player) { + return "&eEditing reward..."; + } + + @Override + public int size(Map buttons) { + return 3 * 9; + } + + @Override + public void onClose(Player player) { + if (player.hasMetadata("closeByRightClick")) { + player.removeMetadata("closeByRightClick", Crates.getInstance()); + } + } + + @Override + public Map getButtons(Player player) { + Map buttons = Maps.newHashMap(); + + buttons.put(getSlot(0, 0), Button.fromItem( + new ItemBuilder(Material.BED) + .name("&cGo Back") + .addToLore( + "", + "&7Click to go back to the reward edit menu." + ).build(), + (other) -> { + other.closeInventory(); + crate.openEditRewardsInventory(other); + })); + + buttons.put(getSlot(2, 1), Button.fromItem( + new ItemBuilder(Material.EXP_BOTTLE) + .name("&bSet Chance") + .addToLore( + "", + "&7Click to set the chance of this reward", + "", + "&7Current chance: &a" + reward.getChance() + "%" + ).build(), + (other) -> ChatUtils.beginPrompt(other, new RewardSetChancePrompt(reward, crate)) + )); + + if(crate instanceof MysteryBox){ + MysteryBox box = (MysteryBox) crate; + buttons.put(getSlot(4, 1), Button.fromItem( + new ItemBuilder(Material.ANVIL) + .name(box.getObligatoryRewards().contains(reward) ? "&aObligatory" : "&cObligatory") + .addToLore( + "", + (box.getObligatoryRewards().contains(reward) ? "&cClick to unset" : "&aClick to set") + " &7as an obligatory reward" + ).build(), + (other) -> { + if(box.getObligatoryRewards().contains(reward)){ + box.getObligatoryRewards().remove(reward); + box.getRewards().add(reward); + }else{ + box.getObligatoryRewards().add(reward); + box.getRewards().remove(reward); + } + + Button.playNeutral(other); + } + )); + } + + buttons.put(getSlot(6, 1), new CommandButtons()); + + buttons.put(getSlot(4, 2), + Button.fromItem(new ItemBuilder(Material.PAPER) + .name("&6Broadcast Lines") + .addToLore("", + "&7Click to view broadcast lines").build(), + (other) -> new CrateBroadcastMenu(crate, reward).openMenu(other))); + + return buttons; + } + + public class CommandButtons extends Button{ + + @Override + public String getName(Player player) { + return "&bCommands"; + } + + @Override + public List getDescription(Player player) { + return Lists.newArrayList( + "", + "&fLeft Click to add a command to this reward", + "&fRight Click to manage commands", + "", + "&7Current Commands: &a" + (reward.getCommands() == null + || reward.getCommands().isEmpty() ? "None" : Arrays.toString(reward.getCommands().toArray())) + ); + } + + @Override + public Material getMaterial(Player player) { + return Material.BOOK; + } + + @Override + public void clicked(Player player, int slot, ClickType clickType) { + if(clickType == ClickType.LEFT){ + ChatUtils.beginPrompt(player, new RewardAddCommandPrompt(reward, crate, new RewardEditMenu(reward, crate))); + }else{ + new RewardCommandsMenu(reward, crate).openMenu(player); + } + } + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/promt/RewardAddCommandPrompt.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/promt/RewardAddCommandPrompt.java new file mode 100644 index 0000000..d761a93 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/promt/RewardAddCommandPrompt.java @@ -0,0 +1,50 @@ +package rip.battle.crates.reward.promt; + +import cc.stormworth.core.menu.Menu; +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.com.google.common.collect.Lists; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.menus.RewardEditMenu; +import rip.battle.crates.reward.RewardType; + +@RequiredArgsConstructor +public class RewardAddCommandPrompt extends StringPrompt { + + private final Reward reward; + private final Crate crate; + private final Menu menu; + + @Override + public String getPromptText(ConversationContext context) { + return CC.translate("&7Enter the command you want to add. Or type &6cancel&7 to go back."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + new RewardEditMenu(reward, crate).openMenu(player); + return END_OF_CONVERSATION; + } + + reward.setType(RewardType.COMMAND); + + if(reward.getCommands() == null) { + reward.setCommands(Lists.newArrayList()); + } + + reward.getCommands().add(input); + + menu.openMenu(player); + player.sendMessage(CC.translate("&aCommand &e" + input + "&e has been added to the reward.")); + return END_OF_CONVERSATION; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/reward/promt/RewardSetChancePrompt.java b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/promt/RewardSetChancePrompt.java new file mode 100644 index 0000000..597562c --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/reward/promt/RewardSetChancePrompt.java @@ -0,0 +1,55 @@ +package rip.battle.crates.reward.promt; + +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.crate.Crate; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.menus.RewardEditMenu; + +@RequiredArgsConstructor +public class RewardSetChancePrompt extends StringPrompt { + + private final Reward reward; + private final Crate crate; + + @Override + public String getPromptText(ConversationContext context) { + return CC.translate("&7Set the chance of this reward to be given. Or type &6cancel &7to go back."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + new RewardEditMenu(reward, crate).openMenu(player); + return END_OF_CONVERSATION; + } + + try { + double chance = Double.parseDouble(input); + + if (chance < 0 || chance > 1.0) { + player.sendMessage(CC.translate("&cThe chance must be between 0 and 1.0.")); + return this; + } + + reward.setChance(chance); + + player.sendMessage(CC.translate("&aThe chance of this reward is now &6" + chance + "&a%.")); + + new RewardEditMenu(reward, crate).openMenu(player); + } catch (NumberFormatException e) { + player.sendMessage(CC.translate("&cThe chance must be a number between 0 and 100.")); + return this; + } + + + return END_OF_CONVERSATION; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/supplydrop/SupplyDrop.java b/Battle-Crates-main/src/main/java/rip/battle/crates/supplydrop/SupplyDrop.java new file mode 100644 index 0000000..8384920 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/supplydrop/SupplyDrop.java @@ -0,0 +1,39 @@ +package rip.battle.crates.supplydrop; + +import cc.stormworth.core.kt.util.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import rip.battle.crates.crate.Crate; + +import java.util.Arrays; +import java.util.List; + +public class SupplyDrop extends Crate { + + public SupplyDrop() { + super("SupplyDrop"); + getCrates().put("SupplyDrop", this); + } + + @Override + public List getHologramsLines() { + return Arrays.asList( + getDisplayName() + " SupplyDrop", + "&7", + "&fLeft click &7for preview rewards", + "&7", + "&7&ostore.battle.rip"); + } + + @Override + public ItemStack generateKey() { + return new ItemBuilder(Material.DROPPER) + .name("&4&lSupplyDrop") + .addToLore( + "&7Purchasable at &fstore.battle.rip&7.", + "" + ).build(); + } + + +} diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/utils/ChatUtils.java b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/ChatUtils.java new file mode 100644 index 0000000..1e68e16 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/ChatUtils.java @@ -0,0 +1,28 @@ +package rip.battle.crates.utils; + +import lombok.experimental.UtilityClass; +import org.bukkit.ChatColor; +import org.bukkit.conversations.ConversationFactory; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.crates.Crates; + +@UtilityClass +public class ChatUtils { + + public void beginPrompt(Player player, StringPrompt prompt) { + player.closeInventory(); + player.beginConversation( + new ConversationFactory(Crates.getInstance()) + .withFirstPrompt(prompt) + .withTimeout(60) + .withModality(false) + .withLocalEcho(false) + .buildConversation(player)); + } + + public String getFirstColor(String message) { + return ChatColor.translateAlternateColorCodes('&', message.substring(0, 2)); + } + +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/utils/FireworkUtil.java b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/FireworkUtil.java new file mode 100644 index 0000000..28c69ef --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/FireworkUtil.java @@ -0,0 +1,114 @@ +package rip.battle.crates.utils; + +import org.bukkit.Color; +import org.bukkit.FireworkEffect; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftFirework; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Firework; +import org.bukkit.inventory.meta.FireworkMeta; + +import java.util.Random; + +public class FireworkUtil { + + public static void launchFirework(Location loc) { + Firework fw = (Firework) loc.getWorld().spawnEntity(loc, EntityType.FIREWORK); + FireworkMeta fwm = fw.getFireworkMeta(); + + Random random = RandomUtils.getRandom(); + + int randomInt = random.nextInt(4) + 1; + FireworkEffect.Type type; + + if (randomInt == 1) { + type = FireworkEffect.Type.BALL; + } else if (randomInt == 2) { + type = FireworkEffect.Type.BALL_LARGE; + } else if (randomInt == 3) { + type = FireworkEffect.Type.BURST; + } else { + type = FireworkEffect.Type.STAR; + } + + + int r1i = random.nextInt(17) + 1; + int r2i = random.nextInt(17) + 1; + + Color c1 = getColor(r1i); + Color c2 = getColor(r2i); + + FireworkEffect effect = FireworkEffect.builder() + .flicker(random.nextBoolean()) + .withColor(c1) + .withFade(c2).with(type).trail(random.nextBoolean()).build(); + + fwm.addEffect(effect); + + fwm.setPower(3); + + ((CraftFirework) fw).getHandle().expectedLifespan = 5; + + fw.setFireworkMeta(fwm); + } + + public static Color getColor(int i) { + Color color = null; + switch (i) { + case 1: + color = Color.AQUA; + break; + case 2: + color = Color.BLACK; + break; + case 3: + color = Color.BLUE; + break; + case 4: + color = Color.FUCHSIA; + break; + case 5: + color = Color.GRAY; + break; + case 6: + color = Color.GREEN; + break; + case 7: + color = Color.LIME; + break; + case 8: + color = Color.MAROON; + break; + case 9: + color = Color.NAVY; + break; + case 10: + color = Color.OLIVE; + break; + case 11: + color = Color.ORANGE; + break; + case 12: + color = Color.PURPLE; + break; + case 13: + color = Color.RED; + break; + case 14: + color = Color.SILVER; + break; + case 15: + color = Color.TEAL; + break; + case 16: + color = Color.WHITE; + break; + case 17: + color = Color.YELLOW; + break; + default: + break; + } + return color; + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/utils/ItemUtils.java b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/ItemUtils.java new file mode 100644 index 0000000..f19c89e --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/ItemUtils.java @@ -0,0 +1,148 @@ +package rip.battle.crates.utils; + +import cc.stormworth.core.util.chat.CC; +import com.google.common.collect.Lists; +import lombok.experimental.UtilityClass; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import rip.battle.crates.reward.Reward; +import rip.battle.crates.reward.RewardType; + +import java.util.List; + +@UtilityClass +public class ItemUtils { + + public boolean isReward(ItemStack item) { + + if (item == null) return false; + + if (!item.hasItemMeta()) return false; + + if (!item.getItemMeta().hasLore()) return false; + + return item.getItemMeta().getLore().stream().anyMatch(lore -> lore.contains(CC.translate("&7Type: &e"))); + } + + public void consume(Player player) { + + ItemStack item = player.getInventory().getItemInHand(); + + if (item.getAmount() == 1) { + player.getInventory().remove(item); + } else { + item.setAmount(item.getAmount() - 1); + } + + player.updateInventory(); + } + + public RewardType getRewardType(ItemStack item) { + if (!isReward(item)) return null; + + for (String lore : item.getItemMeta().getLore()) { + if (lore.contains(CC.translate("&7Type: &e"))) { + return RewardType.getByName(ChatColor.stripColor(lore).replace(CC.translate("Type: "), "").toUpperCase()); + } + } + + return null; + } + + + public Reward getRewardByItem(ItemStack item, int slot) { + if (!isReward(item)) return null; + + RewardType type = getRewardType(item); + + if (type == null) return null; + + double chance = getChance(item); + + List commands = Lists.newArrayList(); + + if (type == RewardType.COMMAND) { + commands.addAll(getCommands(item)); + } + + return new Reward(item, chance, slot, type, commands, isObligatory(item)); + } + + public void removeRewardsLore(ItemStack item) { + ItemMeta meta = item.getItemMeta(); + + if (meta == null) return; + + List lore = meta.getLore(); + + if (lore == null) return; + + lore.removeIf(line -> line.contains(CC.translate("&7Type: &e"))); + lore.removeIf(line -> line.contains(CC.translate("&7Chance: &e"))); + lore.removeIf(line -> line.contains(CC.translate("&cObligatory"))); + lore.removeIf(line -> line.contains(CC.translate("&7Commands: &e"))); + lore.removeIf(line -> line.contains(CC.translate("&fRight Click &7to edit"))); + lore.removeIf(line -> line.equalsIgnoreCase(CC.translate("&0"))); + + meta.setLore(lore); + + item.setItemMeta(meta); + } + + public double getChance(ItemStack item) { + if (!isReward(item)) return 0; + for (String lore : item.getItemMeta().getLore()) { + if (lore.contains(CC.translate("&7Chance: &e"))) { + return Double.parseDouble(ChatColor.stripColor(lore).replace(CC.translate("Chance: "), "").replace("%", "")); + } + } + + return 0; + } + + public boolean isObligatory(ItemStack item) { + + if (item == null) return false; + + if (!item.hasItemMeta()) return false; + + if (!item.getItemMeta().hasLore()) return false; + + return item.getItemMeta().getLore().stream().anyMatch(lore -> lore.contains(CC.translate("&cObligatory"))); + } + + public boolean isCommandType(ItemStack item) { + + if (item == null) return false; + + if (!item.hasItemMeta()) return false; + + if (!item.getItemMeta().hasLore()) return false; + + return item.getItemMeta().getLore().stream().anyMatch(lore -> lore.contains(CC.translate("&7Commands: &e"))); + } + + public List getCommands(ItemStack item) { + if (!isCommandType(item)) return null; + + List commands = Lists.newArrayList(); + + for (String lore : item.getItemMeta().getLore()) { + if (lore.contains(CC.translate(" &7- &f"))) { + commands.add(ChatColor.stripColor(lore).replace(CC.translate(" - "), "")); + } + } + + return commands; + } + + public boolean isAirDrop(ItemStack item) { + if (item == null) return false; + if (!item.hasItemMeta()) return false; + if (!item.getItemMeta().hasLore()) return false; + if (item.getItemMeta().getDisplayName() == null) return false; + return item.getItemMeta().getDisplayName().equalsIgnoreCase(CC.translate("&6&lAirdrop")); + } +} \ No newline at end of file diff --git a/Battle-Crates-main/src/main/java/rip/battle/crates/utils/RandomUtils.java b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/RandomUtils.java new file mode 100644 index 0000000..9455c38 --- /dev/null +++ b/Battle-Crates-main/src/main/java/rip/battle/crates/utils/RandomUtils.java @@ -0,0 +1,45 @@ +package rip.battle.crates.utils; + +import lombok.Getter; +import lombok.experimental.UtilityClass; +import rip.battle.crates.reward.Reward; + +import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +@UtilityClass +public class RandomUtils { + + @Getter + private static final Random random = ThreadLocalRandom.current(); + + public double getDouble(double min, double max) { + return min + (max - min) * random.nextDouble(); + } + + public Reward getRandomReward(List list) { + + list.removeIf(reward -> reward.getChance() <= 0D); + + if (list.isEmpty()) return null; + + Reward reward = null; + + double total = list.stream().mapToDouble(Reward::getChance).sum(); + + double index = getDouble(0D, total); + double countWeight = 0D; + + for (Reward reward1 : list) { + countWeight += reward1.getChance(); + if (countWeight >= index) { + reward = reward1; + break; + } + } + + return reward; + } + +} diff --git a/Battle-Crates-main/src/main/resources/config.yml b/Battle-Crates-main/src/main/resources/config.yml new file mode 100644 index 0000000..32dce3a --- /dev/null +++ b/Battle-Crates-main/src/main/resources/config.yml @@ -0,0 +1,8 @@ +mongo: + host: localhost + port: 27017 + database: "battlerip" + authentication: + enabled: false + username: "admin" + password: "admin" \ No newline at end of file diff --git a/Battle-Crates-main/src/main/resources/plugin.yml b/Battle-Crates-main/src/main/resources/plugin.yml new file mode 100644 index 0000000..e763fef --- /dev/null +++ b/Battle-Crates-main/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +main: rip.battle.crates.Crates +name: Crates +version: 1.0.0 +author: EnzoL_ +depend: + - Core \ No newline at end of file diff --git a/BattleEntity-main/.gitignore b/BattleEntity-main/.gitignore new file mode 100644 index 0000000..4a410a1 --- /dev/null +++ b/BattleEntity-main/.gitignore @@ -0,0 +1,70 @@ +# Eclipse +/.classpath +/.project +/.settings + +# Netbeans +/nbproject + +# Fuck mauri! +/build.xml + +# Maven +/target +/dependency-reduced-pom.xml +*/target +*/dependency-reduced-pom.xml + +# Vim +.*.sw[a-p] + +# Various other potential build files +/build +/bin +/dist +/manifest.mf +/MANIFEST.MF +/META-INF/MANIFEST.MF +git.properties +.ssh +key +commiter.sh +key.pub +dependency-reduced-pom.xml + +# Mac Filesystem Dust +.DS_Store + +# IntelliJ IDEA +*.iml +*.ipr +*.iws +.idea/ + +#Libraries jar files +libraries/*.jar +======= +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +out \ No newline at end of file diff --git a/BattleEntity-main/pom.xml b/BattleEntity-main/pom.xml new file mode 100644 index 0000000..95a96e9 --- /dev/null +++ b/BattleEntity-main/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + rip.battle.entity + BattleEntity + 1.0-SNAPSHOT + + + 8 + 8 + UTF-8 + + + + BattleEntity + + + + + viaversion-repo + https://repo.viaversion.com + + + + + + rip.battle.spigot + battle-server + 1.8.8-R0.1-SNAPSHOT + provided + + + + BattleAPI + cc.stormworth + 1.0-SNAPSHOT + provided + + + + BattleBukkit + cc.stormworth + 1.0-SNAPSHOT + provided + + + + + org.projectlombok + lombok + 1.18.24 + provided + + + + com.viaversion + viaversion-api + LATEST + provided + + + + \ No newline at end of file diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/Entity.java b/BattleEntity-main/src/main/java/rip/battle/entity/Entity.java new file mode 100644 index 0000000..062b75c --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/Entity.java @@ -0,0 +1,272 @@ +package rip.battle.entity; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.PacketPlayOutAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityStatus; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityTeleport; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.utils.AngleUtils; +import rip.battle.entity.utils.PacketUtils; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +@Getter @Setter +public abstract class Entity { + + private static int ENTITY_ID = -1337; + private final int id; + private final UUID uuid; + private Location location; + + private boolean initialized = false; + private boolean hidden = false; + + private boolean persistent = true; + + private boolean root = true; + + private Set currentWatchers = Sets.newHashSet(); + private Set hiddeFor = Sets.newHashSet(); + + private Set commands = Sets.newHashSet(); + + private Consumer onLeftClick; + private Consumer onRightClick; + + public Entity(Location location) { + this.id = nextId(); + this.location = location; + this.uuid = UUID.randomUUID(); + + EntityManager.addEntity(this); + } + + public abstract String getTypeName(); + + public void initializeData() { + this.initialized = true; + } + + public void onDelete(){ + destroyForCurrentWatchers(); + + EntityManager.removeEntity(this); + } + + public void updateLocation(Location location) { + this.location = location; + + getCurrentWatchersPlayers().forEach(this::sendRePositionPackets); + } + + public Hologram getAttachedHologram(){ //Add HologramEntity + return null; + } + + public boolean isVisible() { + return !hidden; + } + + public boolean isVisibleTo(Player player) { + return !hidden && location.getWorld() == player.getWorld() && location.distance(player.getLocation()) <= 32.0 && !hiddeFor.contains(player.getUniqueId()); + } + + public void updateVisibility(boolean hidden){ + boolean hasChanged = this.hidden != hidden; + + this.hidden = hidden; + + if(hasChanged){ + if(hidden){ + destroyForCurrentWatchers(); + }else{ + + Bukkit.getOnlinePlayers().forEach(player -> { + if (!currentWatchers.contains(player.getUniqueId()) && isVisibleTo(player)) { + currentWatchers.add(player.getUniqueId()); + } + }); + + spawnForCurrentWatchers(); + } + } + + if (getAttachedHologram() != null) { + getAttachedHologram().updateVisibility(hidden); + } + } + + public void updateVisibilityFor(Player player, boolean hidden) { + boolean hasChanged = currentWatchers.contains(player.getUniqueId()) != hidden; + + if(hasChanged){ + + if(hidden){ + hiddeFor.add(player.getUniqueId()); + currentWatchers.remove(player.getUniqueId()); + }else{ + currentWatchers.add(player.getUniqueId()); + } + + if(hidden) { + sendDestroyPackets(player); + }else { + sendSpawnPackets(player); + } + + if (getAttachedHologram() != null) { + getAttachedHologram().updateVisibilityFor(player, hidden); + } + } + } + + public void spawnForCurrentWatchers() { + getCurrentWatchersPlayers().stream().filter(this::isVisibleTo).forEach(this::sendSpawnPackets); + } + + public void onLeftClick(Player player) { + if (!commands.isEmpty()) { + for (String command : commands) { + player.performCommand(command.replace("{player}", player.getName())); + } + }else if (onLeftClick != null) { + onLeftClick.accept(player); + } + } + + public void onRightClick(Player player) { + if (onRightClick != null) { + onRightClick.accept(player); + } + } + + public void spawn(){ + Bukkit.getOnlinePlayers().forEach(player -> { + if(isVisibleTo(player)){ + spawn(player); + } + }); + } + + public boolean isDamageable() { + return false; + } + + public void spawn(Player player){ + + /*if (currentWatchers.contains(player.getUniqueId())) { + return; + }*/ + + currentWatchers.add(player.getUniqueId()); + + sendSpawnPackets(player); + sendUpdatePackets(player); + } + + public void update(Player player){ + + if (!currentWatchers.contains(player.getUniqueId())) { + return; + } + + sendUpdatePackets(player); + } + + public void destroy(Player player) { + currentWatchers.remove(player.getUniqueId()); + + sendDestroyPackets(player); + } + + public boolean hasAnyWatchers() { + return currentWatchers.size() > 0; + } + + public List getCurrentWatchersPlayers() { + return currentWatchers.stream().map(Bukkit::getPlayer).filter(Objects::nonNull).collect(Collectors.toList()); + } + + public boolean isWatcher(Player player){ + return currentWatchers.contains(player.getUniqueId()); + } + + public void updateForCurrentWatchers() { + for (Player player : getCurrentWatchersPlayers()) { + update(player); + } + } + + public void destroyForCurrentWatchers() { + for (Player player : getCurrentWatchersPlayers()) { + sendDestroyPackets(player); + } + } + + public void resendForCurrentWatchers() { + for (Player player : getCurrentWatchersPlayers()) { + destroy(player); + spawn(player); + } + } + + public boolean isMultiPartEntity(){ + return false; + } + + public boolean isRootOfMultiPartEntity(){ + return root; + } + + public void sendSpawnPackets(Player player) {} + + public void sendDestroyPackets(Player player) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityDestroy(id)); + } + + public void sendUpdatePackets(Player player) {} + + public void sendRePositionPackets(Player player) { + + PacketPlayOutEntityTeleport playOutEntityTeleport = new PacketPlayOutEntityTeleport( + this.id, + (int) (this.location.getX() * 32.0D), + (int) (this.location.getY() * 32.0D), + (int) (this.location.getZ() * 32.0D), + AngleUtils.yawToBytes(location.getYaw()), + AngleUtils.yawToBytes(location.getPitch()), + false + ); + + PacketUtils.sendPacket(player, playOutEntityTeleport); + } + + public void sendStatusPacket(byte status){ + PacketPlayOutEntityStatus packet = new PacketPlayOutEntityStatus(id, status); + + PacketUtils.sendPacket(getCurrentWatchersPlayers(), packet); + } + + public void sendAnimationPacket(int animation){ + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(id, animation); + + PacketUtils.sendPacket(getCurrentWatchersPlayers(), packet); + } + + public static int nextId() { + return ENTITY_ID--; + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/EntityManager.java b/BattleEntity-main/src/main/java/rip/battle/entity/EntityManager.java new file mode 100644 index 0000000..05cc219 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/EntityManager.java @@ -0,0 +1,24 @@ +package rip.battle.entity; + +import com.google.common.collect.Maps; +import lombok.Getter; + +import java.util.Map; + +public class EntityManager { + + @Getter private static final Map entities = Maps.newHashMap(); + + public static void addEntity(Entity entity) { + entities.put(entity.getId(), entity); + } + + public static void removeEntity(Entity entity) { + entities.remove(entity.getId()); + } + + public static Entity getEntity(int id) { + return entities.get(id); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/EntityPlugin.java b/BattleEntity-main/src/main/java/rip/battle/entity/EntityPlugin.java new file mode 100644 index 0000000..d378d51 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/EntityPlugin.java @@ -0,0 +1,114 @@ +package rip.battle.entity; + +import cc.stormworth.core.api.BattleAPI; +import com.jonahseguin.drink.CommandService; +import com.jonahseguin.drink.Drink; +import com.jonahseguin.drink.command.DrinkCommandContainer; +import lombok.Getter; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.commands.HologramCommand; +import rip.battle.entity.hologram.commands.sub.*; +import rip.battle.entity.hologram.runnable.HologramUpdateRunnable; +import rip.battle.entity.listeners.PlayerListener; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.commands.NPCCommand; +import rip.battle.entity.npc.commands.sub.*; +import rip.battle.entity.packet.PacketEntityUseAdapter; +import rip.battle.entity.taks.RainbowTask; +import rip.battle.entity.task.EntityVisibilityRunnable; +import rip.battle.entity.tick.TickableEntity; + +@Getter +public class EntityPlugin extends JavaPlugin { + + private HologramManager hologramManager; + private NPCManager npcManager; + private BattleAPI battleAPI; + + @Override + public void onEnable() { + registerManagers(); + registerListeners(); + registerCommands(); + registerRunnables(); + } + + @Override + public void onDisable() { + hologramManager.saveHolograms(); + npcManager.saveNPCs(); + } + + private void registerManagers(){ + hologramManager = new HologramManager(this); + npcManager = new NPCManager(this); + battleAPI = BattleAPI.getBattleAPI(this); + } + + private void registerRunnables(){ + getServer().getScheduler().runTaskTimerAsynchronously(this, new HologramUpdateRunnable(hologramManager), 0L, 1L); + getServer().getScheduler().runTaskTimerAsynchronously(this, new RainbowTask(), 0L, 1L); + getServer().getScheduler().runTaskTimer(this, new EntityVisibilityRunnable(), 0L, 20L); + getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { + for (Entity entity : EntityManager.getEntities().values()) { + + if (entity instanceof TickableEntity){ + TickableEntity livingEntity = (TickableEntity) entity; + livingEntity.tick(); + } + + } + }, 0L, 1L); + } + + private void registerCommands(){ + CommandService drink = Drink.get(this); + + DrinkCommandContainer hologramContainer = drink.register(new HologramCommand(), "hologram"); + + hologramContainer.registerSub(new HologramCreateSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramDeleteSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramAddLineSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramAddItemLineSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramTeleportSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramMoveHereSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramSetLineSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramSetItemLineSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramListSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramRemoveLineSubCommand(hologramManager)); + hologramContainer.registerSub(new HologramEditSubCommand(this, hologramManager)); + + + DrinkCommandContainer npcContainer = drink.register(new NPCCommand(), "npc"); + npcContainer.registerSub(new NPCCreateSubCommand(npcManager)); + npcContainer.registerSub(new NPCDeleteSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetDisplaynameSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetSkinSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetArmorSubCommand(npcManager)); + npcContainer.registerSub(new NPCAddItemLineSubCommand(npcManager)); + npcContainer.registerSub(new NPCAddLineSubCommand(npcManager)); + npcContainer.registerSub(new NPCMoveHereSubCommand(npcManager)); + npcContainer.registerSub(new NPCTeleportSubCommand(npcManager)); + npcContainer.registerSub(new NPCRemoveLineSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetLineSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetItemInHandSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetHelmetSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetChestPlateSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetLeggingsSubCommand(npcManager)); + npcContainer.registerSub(new NPCSetBootsSubCommand(npcManager)); + npcContainer.registerSub(new NPCListCommand(npcManager)); + npcContainer.registerSub(new NPCEditSubCommand(this, npcManager)); + + drink.registerCommands(); + } + + private void registerListeners(){ + battleAPI.registerAdapter(PacketPlayInUseEntity.class, new PacketEntityUseAdapter(this)); + + PluginManager pluginManager = getServer().getPluginManager(); + pluginManager.registerEvents(new PlayerListener(), this); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/CraftHologram.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/CraftHologram.java new file mode 100644 index 0000000..6543896 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/CraftHologram.java @@ -0,0 +1,308 @@ +package rip.battle.entity.hologram; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.Entity; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.hologram.lines.impl.ItemLine; +import rip.battle.entity.hologram.lines.impl.MultipleTextLine; +import rip.battle.entity.hologram.lines.impl.SupplierMultipleTextLine; +import rip.battle.entity.hologram.lines.impl.TextLine; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +@Getter +public class CraftHologram implements Hologram { + + private final List> lines = Lists.newArrayList(); + private Location location; + + private final Set currentWatchers = Sets.newHashSet(); + private final Set hiddenPlayers = Sets.newHashSet(); + + private boolean hidden; + + private Entity parent; + + private String name; + + public CraftHologram(String name, String line, Location location) { + this.name = name; + this.location = location; + addLine(line); + } + + public CraftHologram(String name, ItemStack line, Location location) { + this.name = name; + this.location = location; + addLine(line); + } + + public CraftHologram(String name, Location location) { + this.location = location; + this.name = name; + } + + public boolean isVisible() { + return !hidden; + } + + public boolean isVisibleTo(Player player) { + return !hidden && location.getWorld() == player.getWorld() && location.distance(player.getLocation()) <= 32.0 && !hiddenPlayers.contains(player.getUniqueId()); + } + + @Override + public void destroy() { + onDelete(); + } + + @Override + public void spawn() { + Bukkit.getOnlinePlayers().forEach(player -> { + if (isVisibleTo(player)) { + lines.forEach(line -> line.spawn(player)); + currentWatchers.add(player.getUniqueId()); + } + }); + } + + public void spawnFor(Player player) { + lines.forEach(line -> line.spawn(player)); + + currentWatchers.add(player.getUniqueId()); + } + + public void updateVisibility(boolean hidden){ + boolean hasChanged = this.hidden != hidden; + + this.hidden = hidden; + + if(hasChanged){ + lines.forEach(line -> line.updateVisibility(hidden)); + } + } + + @Override + public void updateVisibilityFor(Player player, boolean hidden) { + boolean hasChanged = currentWatchers.contains(player.getUniqueId()) != hidden; + + if(hasChanged){ + + if(hidden){ + hiddenPlayers.add(player.getUniqueId()); + currentWatchers.remove(player.getUniqueId()); + }else{ + currentWatchers.add(player.getUniqueId()); + } + + lines.forEach(line -> { + if (line.isVisibleTo(player)) { + line.sendSpawnPackets(player); + }else{ + line.sendDestroyPackets(player); + } + }); + } + } + + public List getCurrentWatchersPlayers() { + return currentWatchers.stream().map(Bukkit::getPlayer).filter(Objects::nonNull).collect(Collectors.toList()); + } + + public boolean isWatcher(Player player){ + return currentWatchers.contains(player.getUniqueId()); + } + + protected void updateForCurrentWatchers() { + lines.forEach(Entity::updateForCurrentWatchers); + } + + + public void onDelete() { + lines.forEach(HologramLine::onDelete); + lines.clear(); + + currentWatchers.clear(); + } + + public void updateLocation(Location location){ + this.location = location; + + synchronizeLocations(); + } + + public void addLine(HologramLine line) { + getCurrentWatchersPlayers().forEach(line::spawn); + lines.add(line); + + synchronizeLocations(); + } + + @Override + public void addLine(String text){ + addLine(player -> text); + } + + @Override + public void addLine(Function line) { + addLine(line, null); + } + + @Override + public void addLines(List> lines) { + lines.forEach(this::addLine); + } + + + @Override + public void addLines(Function> lines) { + addLine(new MultipleTextLine(this, this.location.clone(), lines)); + } + + @Override + public void addSupplierLines(Function>> lines) { + addLine(new SupplierMultipleTextLine(this, this.location.clone(), lines)); + } + + @Override + public void addLine(Function line, Consumer onClick) { + addLine(line, onClick, player -> true); + } + + @Override + public void addLine(Function line, Consumer onClick, Predicate shouldSend) { + addLine(new TextLine(this, this.location.clone().subtract(0, 0.25, 0), line, onClick, shouldSend)); + } + + @Override + public void addLine(ItemStack itemStack){ + addLine(itemStack, null); + } + + @Override + public void addLine(ItemStack line, Consumer onClick) { + addLine(line, onClick, player -> true); + } + + @Override + public void addLine(ItemStack line, Consumer onClick, Predicate shouldSend) { + addLine(new ItemLine(this, this.location.clone().subtract(0, 0.25, 0), line, onClick, shouldSend)); + } + + @Override + public void setLine(int line, String text) { + setLine(line, player -> text); + } + + @Override + public void setLine(int line, Function text) { + setLine(line, text, null); + } + + @Override + public void setLine(int line, Function text, Consumer onClick) { + setLine(line, text, onClick, player -> true); + } + + @Override + public void setLine(int line, Function text, Consumer onClick, Predicate shouldSend) { + HologramLine hologramLine = lines.get(line); + + if(hologramLine instanceof TextLine){ + TextLine textLine = (TextLine) hologramLine; + textLine.setText(text); + textLine.setOnLeftClick(onClick); + textLine.setShouldSend(shouldSend); + + textLine.updateForCurrentWatchers(); + } + } + + @Override + public void setLine(int line, ItemStack itemStack) { + setLine(line, itemStack, null); + } + + @Override + public void setLine(int line, ItemStack itemStack, Consumer onClick) { + setLine(line, itemStack, onClick, player -> true); + } + + @Override + public void setLine(int line, ItemStack itemStack, Consumer onClick, Predicate shouldSend) { + HologramLine hologramLine = lines.get(line); + + if(hologramLine instanceof ItemLine){ + ItemLine itemLine = (ItemLine) hologramLine; + itemLine.setItemStack(itemStack); + itemLine.setOnLeftClick(onClick); + itemLine.setShouldSend(shouldSend); + + itemLine.updateForCurrentWatchers(); + } + } + + @Override + public void removeLine(HologramLine line) { + lines.remove(line); + + getCurrentWatchersPlayers().forEach(line::destroy); + } + + @Override + public void removeLine(int index) { + removeLine(lines.remove(index)); + } + + @Override + public void teleport(Location location) { + updateLocation(location); + } + + public void clearLines() { + getCurrentWatchersPlayers().forEach(player -> { + for (HologramLine line : lines) { + line.sendDestroyPackets(player); + } + }); + lines.clear(); + } + + protected void synchronizeLocations(){ + Location startLocation = location.clone().add(0, lines.size() * 0.25, 0); + + for (HologramLine line : lines) { + if (line instanceof ItemLine){ + startLocation.subtract(0, 0.25, 0); + line.updateLocation(startLocation.clone().add(0.0, 0.5, 0.0)); + startLocation.subtract(0, 0.5, 0); + }if (line instanceof TextLine) { + line.updateLocation(startLocation.clone()); + startLocation.subtract(0, 0.25, 0); + }else if (line instanceof MultipleTextLine){ + MultipleTextLine multipleTextLine = (MultipleTextLine) line; + multipleTextLine.updateLocation(startLocation.clone().add(0, 0.25, 0)); + startLocation.subtract(0, 0.25 * multipleTextLine.getLines().apply(Bukkit.getConsoleSender()).size(), 0); + } + } + } + + public void setParent(Entity parent) { + this.parent = parent; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/HologramBuilder.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/HologramBuilder.java new file mode 100644 index 0000000..a7952dc --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/HologramBuilder.java @@ -0,0 +1,133 @@ +package rip.battle.entity.hologram; + +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.impl.UpdatableHologram; +import rip.battle.entity.hologram.lines.HologramLine; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +public class HologramBuilder { + + private final Hologram hologram; + + public HologramBuilder(String name, Location location, boolean updatable) { + if (updatable) { + hologram = new UpdatableHologram(name, location) { + @Override + public int getUpdateInterval() { + return 1; + } + }; + } else { + hologram = new CraftHologram(name, location); + } + } + + public HologramBuilder addLine(String line) { + hologram.addLine(line); + return this; + } + + public HologramBuilder addLine(ItemStack line) { + hologram.addLine(line); + return this; + } + + public HologramBuilder addLine(ItemStack line, Consumer onClick) { + hologram.addLine(line, onClick); + return this; + } + + public HologramBuilder addLine(ItemStack line, Consumer onClick, Predicate shouldSend) { + hologram.addLine(line, onClick, shouldSend); + return this; + } + + public HologramBuilder addLine(String line, Consumer onClick) { + hologram.addLine(player -> line, onClick); + return this; + } + + public HologramBuilder addLine(String line, Consumer onClick, Predicate shouldSend) { + hologram.addLine(player -> line, onClick, shouldSend); + return this; + } + + + public HologramBuilder addLine(Function line, Consumer onClick, Predicate shouldSend) { + hologram.addLine(line, onClick, shouldSend); + return this; + } + + public HologramBuilder addLine(Function line, Consumer onClick) { + hologram.addLine(line, onClick); + return this; + } + + public HologramBuilder addLine(Function line) { + hologram.addLine(line); + return this; + } + + public HologramBuilder removeLine(int index) { + hologram.removeLine(index); + return this; + } + + public HologramBuilder removeLine(HologramLine line) { + hologram.removeLine(line); + return this; + } + + public HologramBuilder addLines(String... lines) { + for (String line : lines) { + hologram.addLine(line); + } + return this; + } + + public HologramBuilder addLines(ItemStack... lines) { + for (ItemStack line : lines) { + hologram.addLine(line); + } + return this; + } + + @SafeVarargs + public final HologramBuilder addLines(Function... lines) { + for (Function line : lines) { + hologram.addLine(line); + } + return this; + } + + public HologramBuilder hide() { + hologram.updateVisibility(true); + return this; + } + + public HologramBuilder show() { + hologram.updateVisibility(false); + return this; + } + + public HologramBuilder hideFor(Player player) { + hologram.updateVisibilityFor(player, true); + return this; + } + + public HologramBuilder showFor(Player player) { + hologram.updateVisibilityFor(player, false); + return this; + } + + public Hologram build() { + return hologram; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/HologramManager.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/HologramManager.java new file mode 100644 index 0000000..560059c --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/HologramManager.java @@ -0,0 +1,122 @@ +package rip.battle.entity.hologram; + +import cc.stormworth.core.util.serialize.ItemStackAdapter; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import lombok.Getter; +import org.bukkit.Location; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.impl.UpdatableHologram; +import rip.battle.entity.hologram.serialization.HologramTypeAdapter; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; + +public class HologramManager { + + @Getter private final Map holograms = Maps.newHashMap(); + + private final EntityPlugin plugin; + + public HologramManager(EntityPlugin plugin){ + this.plugin = plugin; + + loadHolograms(); + } + + public void loadHolograms(){ + File file = new File(plugin.getDataFolder(), "holograms"); + + if (!file.exists()){ + return; + } + + Arrays.stream(file.listFiles()).forEach(file1 -> { + + FileReader fileReader; + + try { + fileReader = new FileReader(file1); + + JsonElement jsonElement = new Gson().fromJson(fileReader, JsonElement.class); + + System.out.println(jsonElement.toString()); + Hologram hologram = HologramTypeAdapter.fromJson(jsonElement); + + holograms.put(file1.getName().replace(".json", ""), hologram); + + System.out.println("Loaded hologram " + file1.getName()); + System.out.println("hologram " + ((CraftHologram)hologram).getLocation()); + + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + public void saveHolograms(){ + + Gson gson = new GsonBuilder() + .registerTypeAdapter(ItemStack.class, new ItemStackAdapter()) + .registerTypeAdapter(Hologram.class, new HologramTypeAdapter()) + .enableComplexMapKeySerialization() + .setPrettyPrinting() + .create(); + + File file = new File(plugin.getDataFolder(), "holograms"); + + if (!file.exists()) + file.mkdirs(); + + holograms.forEach((name, hologram) -> { + try { + FileWriter writer = new FileWriter(new File(plugin.getDataFolder(), + File.separator + "holograms" + File.separator + name + ".json")); + + writer.write(gson.toJson(HologramTypeAdapter.toJson(hologram))); + System.out.println("Saved hologram " + name); + + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + public void addHologram(String name, Hologram hologram) { + this.holograms.put(name, hologram); + } + + public void removeHologram(String name) { + Hologram hologram = this.holograms.remove(name); + + if (hologram != null) { + hologram.destroy(); + } + + File file = new File(plugin.getDataFolder(), "holograms" + File.separator + name + ".json"); + + if (file.exists()) + file.delete(); + } + + public Hologram getHologram(String name) { + return this.holograms.get(name); + } + + public void createHologram(String name, Location location) { + Hologram hologram = new UpdatableHologram(name, location); + + hologram.spawn(); + addHologram(name, hologram); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/api/Hologram.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/api/Hologram.java new file mode 100644 index 0000000..d871c31 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/api/Hologram.java @@ -0,0 +1,74 @@ +package rip.battle.entity.hologram.api; + +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.lines.HologramLine; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public interface Hologram { + + String getName(); + + List> getLines(); + + void addLine(String line); + + void addLine(Function line); + + void addLines(List> lines); + + void addLines(Function> lines); + void addSupplierLines(Function>> lines); + + void addLine(Function line, Consumer onClick); + + void addLine(Function line, Consumer onClick, Predicate shouldSend); + + void addLine(ItemStack line); + + void addLine(ItemStack line, Consumer onClick); + + void addLine(ItemStack line, Consumer onClick, Predicate shouldSend); + + void setLine(int line, String text); + + void setLine(int line, Function text); + + void setLine(int line, Function text, Consumer onClick); + + void setLine(int line, Function text, Consumer onClick, Predicate shouldSend); + + void setLine(int line, ItemStack itemStack); + + void setLine(int line, ItemStack itemStack, Consumer onClick); + + void setLine(int line, ItemStack itemStack, Consumer onClick, Predicate shouldSend); + + void removeLine(HologramLine line); + + void removeLine(int index); + + void teleport(Location location); + + Location getLocation(); + + boolean isVisible(); + + void updateVisibility(boolean hidden); + + void updateVisibilityFor(Player player, boolean hidden); + + boolean isVisibleTo(Player player); + + void destroy(); + + void spawn(); + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/HologramCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/HologramCommand.java new file mode 100644 index 0000000..689b221 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/HologramCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.hologram.commands; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Require; +import com.jonahseguin.drink.annotation.Sender; +import org.bukkit.entity.Player; + +public class HologramCommand { + + @Command(name = "", desc = "Allows you to manage your holograms", usage = "") + @Require("battle.entity.hologram") + public void hologram(@Sender Player player) { + player.sendMessage(CC.translate("&e&lHologram Commands")); + + player.sendMessage(CC.translate("&e/hologram create &7- &fAllows you to create a hologram.")); + player.sendMessage(CC.translate("&e/hologram delete &7- &fAllows you to delete a hologram.")); + player.sendMessage(CC.translate("&e/hologram addline &7- &fAllows you to add a line to a hologram.")); + player.sendMessage(CC.translate("&e/hologram setline &7- &fAllows you to set a line on a hologram.")); + player.sendMessage(CC.translate("&e/hologram additemline &7- &fAllows you to add an item line to a hologram.")); + player.sendMessage(CC.translate("&e/hologram setitemline &7- &fAllows you to set an item line on a hologram.")); + player.sendMessage(CC.translate("&e/hologram removeline &7- &fAllows you to remove a line from a hologram.")); + player.sendMessage(CC.translate("&e/hologram teleport &7- &fAllows you to teleport to a hologram.")); + player.sendMessage(CC.translate("&e/hologram movehere &7- &fAllows you to move a hologram to your location.")); + player.sendMessage(CC.translate("&e/hologram list &7- &fAllows you to list all holograms.")); + player.sendMessage(CC.translate("&e/hologram edit &7- &fAllows you to edit a hologram.")); + + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramAddItemLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramAddItemLineSubCommand.java new file mode 100644 index 0000000..9a06178 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramAddItemLineSubCommand.java @@ -0,0 +1,35 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramAddItemLineSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "additemline", desc = "Allows you to add an item line to a hologram", usage = " ") + public void addline(@Sender Player player, String name) { + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + if (player.getItemInHand() == null) { + player.sendMessage(CC.translate("&cYou must be holding an item in your hand.")); + return; + } + + hologram.addLine(player.getItemInHand()); + player.sendMessage(CC.translate("&aYou have added an item line to the hologram &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramAddLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramAddLineSubCommand.java new file mode 100644 index 0000000..83af3bc --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramAddLineSubCommand.java @@ -0,0 +1,31 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import com.jonahseguin.drink.annotation.Text; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramAddLineSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "addline", desc = "Allows you to add a line to a hologram", usage = " ") + public void addline(@Sender Player player, String name, @Text String line) { + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + hologram.addLine(line); + player.sendMessage(CC.translate("&aYou have added a line to the hologram &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramCreateSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramCreateSubCommand.java new file mode 100644 index 0000000..1db4871 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramCreateSubCommand.java @@ -0,0 +1,27 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; + +@RequiredArgsConstructor +public class HologramCreateSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "create", desc = "Allows you to create a hologram", usage = "") + public void create(@Sender Player player, String name) { + + if (hologramManager.getHologram(name) != null) { + player.sendMessage(CC.translate("&cA hologram with that name already exists.")); + return; + } + + hologramManager.createHologram(name, player.getLocation()); + player.sendMessage(CC.translate("&aYou have created a hologram with the name &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramDeleteSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramDeleteSubCommand.java new file mode 100644 index 0000000..eb898be --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramDeleteSubCommand.java @@ -0,0 +1,29 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramDeleteSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "delete", desc = "Allows you to delete a hologram", usage = "") + public void delete(@Sender Player player, String name) { + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + hologramManager.removeHologram(name); + player.sendMessage(CC.translate("&aYou have deleted the hologram &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramEditSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramEditSubCommand.java new file mode 100644 index 0000000..b858069 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramEditSubCommand.java @@ -0,0 +1,32 @@ +package rip.battle.entity.hologram.commands.sub; + +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.menu.HologramEditMenu; + +@RequiredArgsConstructor +public class HologramEditSubCommand { + + private final EntityPlugin plugin; + private final HologramManager hologramManager; + + @Command(name = "edit", desc = "Edit a hologram") + public void edit(@Sender Player player, String name){ + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null){ + player.sendMessage(ChatColor.RED + "Hologram not found."); + return; + } + + new HologramEditMenu(plugin, hologram, null).open(player); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramListSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramListSubCommand.java new file mode 100644 index 0000000..1b86ae9 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramListSubCommand.java @@ -0,0 +1,43 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +import java.util.Map; + +@RequiredArgsConstructor +public class HologramListSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "list", desc = "Allows you to list all holograms", aliases = {"l", "ls"}) + public void list(@Sender Player player) { + + Map holograms = hologramManager.getHolograms(); + + if (holograms.isEmpty()) { + player.sendMessage(CC.translate("&cThere are no holograms.")); + return; + } + + player.sendMessage(CC.translate("&aThere are &e" + holograms.size() + " &aholograms.")); + + holograms.forEach((name, hologram) -> { + + ComponentBuilder builder = new ComponentBuilder(CC.translate("&e" + name + " &b[Click to teleport]")); + builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(CC.translate("&7Click to teleport")).create())); + builder.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/hologram tp " + name)); + + player.spigot().sendMessage(builder.create()); + }); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramMoveHereSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramMoveHereSubCommand.java new file mode 100644 index 0000000..27db0b0 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramMoveHereSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramMoveHereSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "movehere", desc = "Allows you to move a hologram to your location", usage = "", aliases = {"move", "moveto", "teleporto", "s"}) + public void movehere(@Sender Player player, String name) { + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + hologram.teleport(player.getLocation()); + player.sendMessage(CC.translate("&aYou have moved the hologram &e" + name + "&a to your location.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramRemoveLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramRemoveLineSubCommand.java new file mode 100644 index 0000000..4a993eb --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramRemoveLineSubCommand.java @@ -0,0 +1,32 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramRemoveLineSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "removeline", desc = "Allows you to remove a line of a hologram", usage = " ") + public void removeLine(@Sender Player player, String name, int line) { + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + hologram.removeLine(line); + + player.sendMessage(CC.translate("&aYou have removed a line of the hologram &e" + name + "&a.")); + } + + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramSetItemLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramSetItemLineSubCommand.java new file mode 100644 index 0000000..4f22305 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramSetItemLineSubCommand.java @@ -0,0 +1,38 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramSetItemLineSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "setitemline", desc = "Allows you to set a item line of a hologram", usage = " ") + public void setItemLine(@Sender Player player, String name, int line) { + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + ItemStack item = player.getItemInHand(); + + if (item == null) { + player.sendMessage(CC.translate("&cYou must be holding an item in your hand.")); + return; + } + + hologram.setLine(line, item); + + player.sendMessage(CC.translate("&aYou have set a item line of the hologram &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramSetLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramSetLineSubCommand.java new file mode 100644 index 0000000..320c90f --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramSetLineSubCommand.java @@ -0,0 +1,31 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramSetLineSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "setline", desc = "Allows you to set a line of a hologram", usage = " ") + public void setline(@Sender Player player, String name, int line, String text) { + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + hologram.setLine(line, text); + + player.sendMessage(CC.translate("&aYou have set a line of the hologram &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramTeleportSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramTeleportSubCommand.java new file mode 100644 index 0000000..6b157d3 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/commands/sub/HologramTeleportSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.hologram.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; + +@RequiredArgsConstructor +public class HologramTeleportSubCommand { + + private final HologramManager hologramManager; + + @Command(name = "teleport", desc = "Allows you to teleport to a hologram", usage = "", aliases = {"tp"}) + public void teleport(@Sender Player player, String name) { + + Hologram hologram = hologramManager.getHologram(name); + + if (hologram == null) { + player.sendMessage(CC.translate("&cA hologram with that name does not exist.")); + return; + } + + player.teleport(hologram.getLocation()); + player.sendMessage(CC.translate("&aYou have teleported to the hologram &e" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/impl/UpdatableHologram.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/impl/UpdatableHologram.java new file mode 100644 index 0000000..78f95b9 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/impl/UpdatableHologram.java @@ -0,0 +1,40 @@ +package rip.battle.entity.hologram.impl; + +import lombok.Setter; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.lines.HologramLine; + +@Setter +public class UpdatableHologram extends CraftHologram { + + private long lastUpdate = System.currentTimeMillis(); + + public UpdatableHologram(String name, String line, Location location) { + super(name, line, location); + } + + public UpdatableHologram(String name, ItemStack line, Location location) { + super(name, line, location); + } + + public UpdatableHologram(String name, Location location) { + super(name, location); + } + + public void update(Player player){ + for (HologramLine line : getLines()){ + line.update(player); + } + } + + public int getUpdateInterval(){ + return 1; + } + + public boolean canUpdate() { + return System.currentTimeMillis() - lastUpdate > getUpdateInterval(); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/HologramLine.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/HologramLine.java new file mode 100644 index 0000000..a12eb9b --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/HologramLine.java @@ -0,0 +1,100 @@ +package rip.battle.entity.hologram.lines; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import rip.battle.entity.Entity; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.utils.PacketUtils; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +@Getter +@Setter +public abstract class HologramLine extends Entity { + + private final CraftHologram parent; + private Predicate shouldSend; + + private final int supportEntityID = nextId(); + + public HologramLine(CraftHologram parent, Location location) { + this(parent, location, player -> true, null); + } + + public HologramLine(CraftHologram parent, Location location, Predicate shouldSend) { + this(parent, location, shouldSend, null); + } + + public HologramLine(CraftHologram parent, Location location, Consumer onClick) { + this(parent, location, player -> true, onClick); + } + + public HologramLine(CraftHologram parent, Location location, Predicate shouldSend, Consumer onClick) { + super(location); + this.parent = parent; + this.shouldSend = shouldSend; + this.setOnLeftClick(onClick); + } + + public boolean shouldSend(Player player) { + return shouldSend.test(player); + } + + /*@Override + public void onLeftClick(Player player) { + player.sendMessage("You clicked a hologram line!"); + }*/ + + @Override + public void spawn() { + super.spawn(); + + parent.getCurrentWatchers().addAll(getCurrentWatchers()); + } + + @Override + public void spawn(Player player) { + super.spawn(player); + + parent.getCurrentWatchers().add(player.getUniqueId()); + } + + @Override + public void destroy(Player player) { + super.destroy(player); + + parent.getCurrentWatchers().remove(player.getUniqueId()); + } + + public abstract T getLine(Player player); + + public abstract void setLine(T line); + + public void sendAttachPacket(Player player){ + CraftHologram hologram = getParent(); + + if (hologram == null || hologram.getParent() == null) + return; + + PacketUtils.sendPacket(player, new PacketPlayOutAttachEntity(0, supportEntityID, hologram.getParent().getId())); + } + + @Override + public String getTypeName() { + return "Hologram_Line"; + } + + @Override + public boolean isRoot() { + return false; + } + + @Override + public boolean isMultiPartEntity() { + return true; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/ItemLine.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/ItemLine.java new file mode 100644 index 0000000..c0bceda --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/ItemLine.java @@ -0,0 +1,184 @@ +package rip.battle.entity.hologram.lines.impl; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.utils.DataWatcherUtil; +import rip.battle.entity.utils.PacketUtils; +import rip.battle.entity.utils.PlayerUtil; + +import java.util.Collections; +import java.util.function.Consumer; +import java.util.function.Predicate; + +@Getter @Setter +public class ItemLine extends HologramLine { + + private ItemStack itemStack; + + public ItemLine(CraftHologram parent, Location location, ItemStack itemStack) { + this(parent, location, itemStack, null); + } + + public ItemLine(CraftHologram parent, Location location, ItemStack itemStack, Consumer onClick) { + this(parent, location, itemStack, onClick, player -> true); + } + + public ItemLine(CraftHologram parent, Location location, ItemStack itemStack, Consumer onClick, Predicate shouldSend) { + super(parent, location, shouldSend, onClick); + this.itemStack = itemStack; + setPersistent(false); + } + + @Override + public void sendSpawnPackets(Player player) { + boolean legacy = PlayerUtil.isLegacy(player); + + PacketPlayOutSpawnEntity spawnPacket = new PacketPlayOutSpawnEntity( + getId(), + 2, + (int) getLocation().getX(), + (int) getLocation().getY(), + (int) getLocation().getZ(), + 0, + 0 + ); + + DataWatcher itemDataWatcher = DataWatcherUtil.createDataWatcher(); + + itemDataWatcher.a(0, (byte) 0); + itemDataWatcher.a(1, (short) 0); + itemDataWatcher.a(2, ""); + itemDataWatcher.a(3, (byte) 0); + itemDataWatcher.a(4, (byte) 0); + + itemDataWatcher.add(10, 5); + itemDataWatcher.watch(10, CraftItemStack.asNMSCopy(itemStack)); + + DataWatcherUtil.setFlag(itemDataWatcher, 5, false); + + PacketPlayOutEntityMetadata metadataPacket = new PacketPlayOutEntityMetadata(getId(), itemDataWatcher, true); + + DataWatcher armorStandDataWatcher = DataWatcherUtil.createDataWatcher(); + + if (!legacy) { + armorStandDataWatcher.a(0, (byte) 0); + armorStandDataWatcher.a(1, (short) 0); + armorStandDataWatcher.a(2, ""); + armorStandDataWatcher.a(3, (byte) 0); + armorStandDataWatcher.a(4, (byte) 0); + + DataWatcherUtil.setFlag(armorStandDataWatcher, 5, true); + + armorStandDataWatcher.a(6, (float) 1); + + armorStandDataWatcher.a(7, 0); + + armorStandDataWatcher.a(8, (byte) 0); + armorStandDataWatcher.a(9, (byte) 0); + armorStandDataWatcher.a(10, (byte) 0); + + DataWatcherUtil.setTypeFlag(armorStandDataWatcher, 10, 1, true); + DataWatcherUtil.setTypeFlag(armorStandDataWatcher, 10, 4, false); + DataWatcherUtil.setTypeFlag(armorStandDataWatcher, 10, 8, false); + DataWatcherUtil.setTypeFlag(armorStandDataWatcher, 10, 10, true); + + armorStandDataWatcher.a(11, PacketUtils.ARMOR_STAND_HEAD_POSE); + armorStandDataWatcher.a(12, PacketUtils.ARMOR_STAND_BODY_POSE); + armorStandDataWatcher.a(13, PacketUtils.ARMOR_STAND_LEFT_ARM_POSE); + armorStandDataWatcher.a(14, PacketUtils.ARMOR_STAND_RIGHT_ARM_POSE); + armorStandDataWatcher.a(15, PacketUtils.ARMOR_STAND_LEFT_LEG_POSE); + armorStandDataWatcher.a(16, PacketUtils.ARMOR_STAND_RIGHT_LEG_POSE); + } + + Packet armorStandPacket; + + if (legacy){ + EntityWitherSkull skull = new EntityWitherSkull(((CraftWorld) getLocation().getWorld()).getHandle()); + skull.d(getSupportEntityID()); + skull.setLocation(getLocation().getX(), (getLocation().getY() + 1.5), getLocation().getZ(), 0.0f, 0.0f); + armorStandPacket = new PacketPlayOutSpawnEntity(skull, 66); + } else { + armorStandPacket = new PacketPlayOutSpawnEntityLiving( + getSupportEntityID(), + 30, + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor((getLocation().getY() + 0.15) * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + armorStandDataWatcher + ); + } + + PacketPlayOutAttachEntity attachPacket = new PacketPlayOutAttachEntity(0, getId(), getSupportEntityID()); + + PacketUtils.sendPacket(player, spawnPacket); + PacketUtils.sendPacket(player, metadataPacket); + PacketUtils.sendPacket(player, armorStandPacket); + PacketUtils.sendPacket(player, attachPacket); + } + + @Override + public void sendRePositionPackets(Player player){ + + PacketPlayOutEntityTeleport teleportPacket; + + if (PlayerUtil.isLegacy(player)){ + teleportPacket = new PacketPlayOutEntityTeleport( + getSupportEntityID(), + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor((getLocation().getY() + 1.5) * 32.0D) , + MathHelper.floor(getLocation().getZ() * 32.0D), + (byte) 0, + (byte) 0, + false + ); + }else{ + teleportPacket = new PacketPlayOutEntityTeleport( + getSupportEntityID(), + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor((getLocation().getY() + 0.15) * 32.0D) , + MathHelper.floor(getLocation().getZ() * 32.0D), + (byte) 0, + (byte) 0, + false + ); + } + + PacketUtils.sendPacket(player, teleportPacket); + } + + @Override + public void sendUpdatePackets(Player player) { + PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(); + + packet.setEntityId(getId()); + packet.setData(Collections.singletonList(new DataWatcher.WatchableObject(5, 10, CraftItemStack.asNMSCopy(itemStack)))); + + PacketUtils.sendPacket(player, packet); + } + + @Override + public void sendDestroyPackets(Player player) { + PacketPlayOutEntityDestroy destroyPacket = new PacketPlayOutEntityDestroy(getId(), getSupportEntityID()); + PacketUtils.sendPacket(player, destroyPacket); + + super.sendDestroyPackets(player); + } + + @Override + public ItemStack getLine(Player player) { + return itemStack; + } + + @Override + public void setLine(ItemStack line) { + this.itemStack = line; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/MultipleTextLine.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/MultipleTextLine.java new file mode 100644 index 0000000..9880977 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/MultipleTextLine.java @@ -0,0 +1,105 @@ +package rip.battle.entity.hologram.lines.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.Getter; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.lines.HologramLine; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; + +@Getter +public class MultipleTextLine extends HologramLine> { + + private Function> lines; + + private final Map> textLines = Maps.newHashMap(); + + public MultipleTextLine(CraftHologram parent, Location location, Function> lines) { + super(parent, location); + this.lines = lines; + } + + @Override + public List getLine(Player player) { + return lines.apply(player); + } + + @Override + public void setLine(List line) { + this.lines = player -> line; + } + + @Override + public void sendSpawnPackets(Player player) { + List lines = getLine(player); + + List textLines = this.textLines.get(player.getUniqueId()); + + Location location = getLocation().clone(); + + if (textLines == null) { + textLines = Lists.newArrayList(); + } + + for (String line : lines) { + TextLine textLine = new TextLine(getParent(), location.subtract(0, 0.25, 0), player1 -> line); + + textLine.setMultiLine(true); + textLine.spawn(player); + + textLines.add(textLine); + } + + this.textLines.put(player.getUniqueId(), textLines); + } + + @Override + public void updateLocation(Location location) { + setLocation(location); + + for (List textLines : this.textLines.values()) { + + Location locationCloned = getLocation().clone(); + + for (TextLine textLine : textLines) { + textLine.updateLocation(locationCloned.subtract(0, 0.25, 0)); + } + } + } + + @Override + public void sendDestroyPackets(Player player) { + + List textLines = this.textLines.get(player.getUniqueId()); + + if (textLines == null) { + return; + } + + for (TextLine textLine : textLines) { + textLine.sendDestroyPackets(player); + } + + this.textLines.remove(player.getUniqueId()); + } + + @Override + public void sendUpdatePackets(Player player) { + List textLines = this.textLines.get(player.getUniqueId()); + + if (textLines == null) { + return; + } + + for (TextLine textLine : textLines) { + textLine.sendUpdatePackets(player); + } + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/SupplierMultipleTextLine.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/SupplierMultipleTextLine.java new file mode 100644 index 0000000..1c50e5e --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/SupplierMultipleTextLine.java @@ -0,0 +1,104 @@ +package rip.battle.entity.hologram.lines.impl; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.lines.HologramLine; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.function.Supplier; + +public class SupplierMultipleTextLine extends HologramLine>> { + + private Function>> lines; + + private final Map> textLines = Maps.newHashMap(); + + public SupplierMultipleTextLine(CraftHologram parent, Location location, Function>> lines) { + super(parent, location); + this.lines = lines; + } + + @Override + public Supplier> getLine(Player player) { + return lines.apply(player); + } + + @Override + public void setLine(Supplier> line) { + lines = player -> line; + } + + @Override + public void sendSpawnPackets(Player player) { + List lines = getLine(player).get(); + + List textLines = this.textLines.get(player.getUniqueId()); + + Location location = getLocation().clone(); + + if (textLines == null) { + textLines = Lists.newArrayList(); + } + + for (String line : lines) { + TextLine textLine = new TextLine(getParent(), location.subtract(0, 0.25, 0), player1 -> line); + + textLine.setMultiLine(true); + textLine.spawn(player); + + textLines.add(textLine); + } + + this.textLines.put(player.getUniqueId(), textLines); + } + + @Override + public void updateLocation(Location location) { + setLocation(location); + + for (List textLines : this.textLines.values()) { + + Location locationCloned = getLocation().clone(); + + for (TextLine textLine : textLines) { + textLine.updateLocation(locationCloned.subtract(0, 0.25, 0)); + } + } + } + + @Override + public void sendDestroyPackets(Player player) { + + List textLines = this.textLines.get(player.getUniqueId()); + + if (textLines == null) { + return; + } + + for (TextLine textLine : textLines) { + textLine.sendDestroyPackets(player); + } + + this.textLines.remove(player.getUniqueId()); + } + + @Override + public void sendUpdatePackets(Player player) { + List textLines = this.textLines.get(player.getUniqueId()); + + if (textLines == null) { + return; + } + + for (TextLine textLine : textLines) { + textLine.sendUpdatePackets(player); + } + } +} \ No newline at end of file diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/TextLine.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/TextLine.java new file mode 100644 index 0000000..30d3b4d --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/lines/impl/TextLine.java @@ -0,0 +1,164 @@ +package rip.battle.entity.hologram.lines.impl; + +import cc.stormworth.core.util.chat.CC; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.taks.RainbowTask; +import rip.battle.entity.utils.DataWatcherUtil; +import rip.battle.entity.utils.PacketUtils; +import rip.battle.entity.utils.PlayerUtil; + +import java.util.Collections; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +@Getter +@Setter +public class TextLine extends HologramLine { + + private Function text; + + private boolean multiLine = false; + + public TextLine(CraftHologram parent, Location location, Function text) { + this(parent, location, text, null); + } + + public TextLine(CraftHologram parent, Location location, Function text, Consumer onClick) { + this(parent, location, text, onClick, player -> true); + } + public TextLine(CraftHologram parent, Location location, Function text, Consumer onClick, Predicate shouldSend) { + super(parent, location, shouldSend, onClick); + this.text = text; + setPersistent(false); + } + + @Override + public String getLine(Player player) { + return text.apply(player); + } + + @Override + public void setLine(String line) { + this.text = player -> line; + } + + @Override + public void sendSpawnPackets(Player player) { + + boolean legacy = PlayerUtil.isLegacy(player); + + String text = processPlaceholders(getLine(player), player); + + DataWatcher dataWatcher = DataWatcherUtil.createDataWatcher(); + + dataWatcher.a(0, (byte) 0); + dataWatcher.a(1, (short) 0); + dataWatcher.a(2, text); + dataWatcher.a(3, text.isEmpty() || text.equalsIgnoreCase("&7") || text.equalsIgnoreCase(" ") ? (byte) 0 : (byte) 1); + dataWatcher.a(4, (byte) 0); + if (legacy){ + dataWatcher.a(16, (byte) -2); + }else{ + DataWatcherUtil.setFlag(dataWatcher, 5, true); + + dataWatcher.a(6, (float) 1); + dataWatcher.a(7, 0); + dataWatcher.a(8, (byte) 0); + dataWatcher.a(9, (byte) 0); + + dataWatcher.a(10, (byte) 0); + + DataWatcherUtil.setTypeFlag(dataWatcher, 10, 1, true); + DataWatcherUtil.setTypeFlag(dataWatcher, 10, 4, false); + DataWatcherUtil.setTypeFlag(dataWatcher, 10, 8, false); + DataWatcherUtil.setTypeFlag(dataWatcher, 10, 10, true); + + dataWatcher.a(11, PacketUtils.ARMOR_STAND_HEAD_POSE); + dataWatcher.a(12, PacketUtils.ARMOR_STAND_BODY_POSE); + dataWatcher.a(13, PacketUtils.ARMOR_STAND_LEFT_ARM_POSE); + dataWatcher.a(14, PacketUtils.ARMOR_STAND_RIGHT_ARM_POSE); + dataWatcher.a(15, PacketUtils.ARMOR_STAND_LEFT_LEG_POSE); + dataWatcher.a(16, PacketUtils.ARMOR_STAND_RIGHT_LEG_POSE); + } + + PacketPlayOutSpawnEntityLiving packet = new PacketPlayOutSpawnEntityLiving( + getId(), + legacy ? 55 : 30, + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor(getLocation().getY() * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + dataWatcher + ); + + PacketUtils.sendPacket(player, packet); + + if (legacy){ + EntityWitherSkull skull = new EntityWitherSkull(((CraftWorld) getLocation().getWorld()).getHandle()); + skull.d(getSupportEntityID()); + skull.setLocation(getLocation().getX(), (getLocation().getY() + 3), getLocation().getZ(), 0.0f, 0.0f); + PacketUtils.sendPacket(player, new PacketPlayOutSpawnEntity(skull, 66)); + PacketUtils.sendPacket(player, new PacketPlayOutAttachEntity(0, getId(), getSupportEntityID())); + } + } + + @Override + public void sendUpdatePackets(Player player) { + String text = processPlaceholders(getLine(player), player); + + PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(); + + packet.setEntityId(getId()); + packet.setData(Collections.singletonList(new DataWatcher.WatchableObject(4, 2, text))); + + PacketUtils.sendPacket(player, packet); + } + + @Override + public void sendRePositionPackets(Player player) { + if (PlayerUtil.isLegacy(player)){ + PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport( + getSupportEntityID(), + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor((getLocation().getY() + 3) * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + (byte) 0, + (byte) 0, + false + ); + + PacketUtils.sendPacket(player, packet); + }else{ + super.sendRePositionPackets(player); + } + } + + @Override + public void sendDestroyPackets(Player player) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityDestroy(getSupportEntityID())); + PacketUtils.sendPacket(player, new PacketPlayOutEntityDestroy(getId())); + } + + public String processPlaceholders(String text, Player player) { + + String textFormatted = text; + + if (textFormatted == null) { + return null; + } + + textFormatted = textFormatted.replace("{player}", player.getName()); + textFormatted = textFormatted.replace("{player_displayname}", player.getDisplayName()); + textFormatted = textFormatted.replace("{rainbow}", RainbowTask.getCurrentColor().toString()); + + return CC.translate(textFormatted); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/menu/HologramEditMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/menu/HologramEditMenu.java new file mode 100644 index 0000000..bcca593 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/menu/HologramEditMenu.java @@ -0,0 +1,159 @@ +package rip.battle.entity.hologram.menu; + +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.Menu; +import cc.stormworth.core.util.menu.button.Button; +import cc.stormworth.core.util.menu.button.impl.PlaceholderButton; +import cc.stormworth.core.util.menu.impl.ConfirmationMenu; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.npc.menu.NPCEditMenu; + +import java.util.Map; +public class HologramEditMenu extends Menu { + private final Hologram hologram; + private final HologramManager hologramManager; + private final EntityPlugin plugin; + + private final Menu back; + + public HologramEditMenu(EntityPlugin plugin, Hologram hologram, Menu back) { + this.plugin = plugin; + this.hologramManager = plugin.getHologramManager(); + this.hologram = hologram; + this.back = back; + } + + @Override + public String getTitle(Player player) { + return "&bEditing Hologram &8" + hologram.getName(); + } + + @Override + public int getRows(Player player) { + return 3; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + + if (back != null){ + buttons.put(0, new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + return new ItemBuilder(Material.BED).setName("&cBack").toItemStack(); + } + + @Override + public void onClick(Player player) { + back.open(player); + } + }); + } + + buttons.put(getSlot(1, 1), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(Material.ENDER_PEARL); + + builder.setName("&6Teleport"); + + builder.addLore( + "", + "&7Click to teleport to this hologram." + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + player.closeInventory(); + player.teleport(hologram.getLocation()); + } + }); + + buttons.put(getSlot(1, 4), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(Material.BOOK); + + builder.setName("&6Lines: " + hologram.getLines().size()); + + builder.addLore( + "", + "&7Click to manage lines on this hologram." + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new HologramManageLinesMenu(plugin, hologram).open(player); + } + }); + + + buttons.put(getSlot(1, 7), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(Material.WOOL); + + builder.setWoolColour(DyeColor.RED); + + builder.setName("&4&lDELETE"); + + builder.addLore( + "", + "&7Click to delete this hologram." + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new ConfirmationMenu("&4&lAre you sure?", (value) -> { + + if (value){ + CraftHologram craftHologram = (CraftHologram) hologram; + + if (craftHologram.getParent() != null){ + NPC npc = (NPC) craftHologram.getParent(); + npc.setHologram(null); + hologram.destroy(); + new NPCEditMenu(npc, plugin).open(player); + }else{ + hologramManager.removeHologram(hologram.getName()); + player.closeInventory(); + } + + }else { + new HologramEditMenu(plugin, hologram, null).open(player); + } + + }, new PlaceholderButton(new ItemBuilder(Material.WOOL) + .setWoolColour(DyeColor.RED) + .setName("&4&lDeleting &c" + hologram.getName()) + .toItemStack())) + .open(player); + } + }); + + return buttons; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/menu/HologramManageLinesMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/menu/HologramManageLinesMenu.java new file mode 100644 index 0000000..43826c7 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/menu/HologramManageLinesMenu.java @@ -0,0 +1,149 @@ +package rip.battle.entity.hologram.menu; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.chat.ChatUtils; +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.Menu; +import cc.stormworth.core.util.menu.button.Button; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.hologram.prompt.HologramAddItemLinePrompt; +import rip.battle.entity.hologram.prompt.HologramAddLinePrompt; +import rip.battle.entity.hologram.prompt.HologramEditLinePrompt; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.npc.menu.NPCEditMenu; + +import java.util.Map; + +@RequiredArgsConstructor +public class HologramManageLinesMenu extends Menu { + + private final EntityPlugin plugin; + private final Hologram hologram; + @Override + public String getTitle(Player player) { + return "&bEditing lines of &8" + hologram.getName(); + } + + @Override + public int getRows(Player player) { + return 3; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + buttons.put(0, new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + return new ItemBuilder(Material.BED).setName("&cBack").toItemStack(); + } + + @Override + public void onClick(Player player) { + new HologramEditMenu(plugin, hologram, null).open(player); + } + }); + + buttons.put(getSlot(0, 3), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.BOOK); + + builder.setName("&6Add line"); + + builder.addLore( + "", + "&7Click to add new line to this hologram." + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + ChatUtils.beginPrompt(player, new HologramAddLinePrompt(plugin, hologram), plugin); + } + }); + + buttons.put(getSlot(0, 5), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.DIAMOND_PICKAXE); + + builder.setName("&6Add Item line"); + + builder.addLore( + "", + "&7Click to add new item line to this hologram." + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + ChatUtils.beginPrompt(player, new HologramAddItemLinePrompt(plugin, hologram), plugin); + } + }); + + int startSlot = 9; + + for (HologramLine line : hologram.getLines()) { + buttons.put(startSlot++, new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(Material.PAPER); + + builder.setName("&6" + line.getLine(player)); + + builder.addLore( + "", + "&7Click to edit this line.", + "&cShift click to remove this line." + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player, ClickType clickType) { + if (clickType.isShiftClick()) { + hologram.removeLine(line); + player.sendMessage(CC.translate("&aRemoved line &8" + line.getLine(player) + " &afrom hologram &8" + hologram.getName() + "&a.")); + + if (hologram.getLines().isEmpty()){ + + CraftHologram craftHologram = (CraftHologram) hologram; + + if (craftHologram.getParent() != null){ + NPC npc = (NPC) craftHologram.getParent(); + npc.setHologram(null); + hologram.destroy(); + new NPCEditMenu(npc, plugin).open(player); + } + } + + } else { + ChatUtils.beginPrompt(player, new HologramEditLinePrompt(plugin, hologram, line), plugin); + } + } + }); + } + + return buttons; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramAddItemLinePrompt.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramAddItemLinePrompt.java new file mode 100644 index 0000000..00311bc --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramAddItemLinePrompt.java @@ -0,0 +1,52 @@ +package rip.battle.entity.hologram.prompt; + +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.menu.HologramManageLinesMenu; + +@RequiredArgsConstructor +public class HologramAddItemLinePrompt extends StringPrompt { + + private final EntityPlugin plugin; + private final Hologram hologram; + + @Override + public String getPromptText(ConversationContext conversationContext) { + return CC.translate("&7Enter &aconfirm&7 to set your item in hand as the line or type &ccancel &7to cancel."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } + + ItemStack itemStack = player.getItemInHand(); + + if (itemStack == null || itemStack.getType() == Material.AIR) { + player.sendMessage(CC.translate("&cYou must be holding an item to set it as a hologram line.")); + player.playSound(player.getLocation(), Sound.NOTE_BASS, 1, 1); + return this; + } + + hologram.addLine(itemStack); + + player.sendMessage(CC.translate("&aAdded line to hologram.")); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1, 1); + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramAddLinePrompt.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramAddLinePrompt.java new file mode 100644 index 0000000..7c27e44 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramAddLinePrompt.java @@ -0,0 +1,42 @@ +package rip.battle.entity.hologram.prompt; + +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.Sound; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.menu.HologramManageLinesMenu; + +@RequiredArgsConstructor +public class HologramAddLinePrompt extends StringPrompt { + + private final EntityPlugin plugin; + private final Hologram hologram; + + @Override + public String getPromptText(ConversationContext conversationContext) { + return CC.translate("&7Enter the text for the new line or type &ccancel &7to cancel."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } + + hologram.addLine(input); + + player.sendMessage(CC.translate("&aAdded line to hologram.")); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1, 1); + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramEditLinePrompt.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramEditLinePrompt.java new file mode 100644 index 0000000..eea52a9 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/prompt/HologramEditLinePrompt.java @@ -0,0 +1,66 @@ +package rip.battle.entity.hologram.prompt; + +import cc.stormworth.core.util.chat.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.bukkit.entity.Player; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.hologram.lines.impl.ItemLine; +import rip.battle.entity.hologram.lines.impl.TextLine; +import rip.battle.entity.hologram.menu.HologramManageLinesMenu; + +@RequiredArgsConstructor +public class HologramEditLinePrompt extends StringPrompt { + + private final EntityPlugin plugin; + private final Hologram hologram; + private final HologramLine line; + + @Override + public String getPromptText(ConversationContext context) { + + if (line instanceof ItemLine){ + return CC.translate("&7Enter &aconfirm&7 to set item in hand as the item for this line or type &ccancel &7to cancel."); + } + + return CC.translate("&7Enter the text for the line or type &ccancel &7to cancel."); + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + + Player player = (Player) context.getForWhom(); + + if (input.equalsIgnoreCase("cancel")) { + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } + + if (line instanceof ItemLine){ + if (input.equalsIgnoreCase("confirm")){ + ((ItemLine) line).setLine(player.getItemInHand()); + + line.updateForCurrentWatchers(); + player.sendMessage(CC.translate("&aSet item in hand as the item for this line.")); + + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } + }else{ + TextLine textLine = (TextLine) line; + + textLine.setLine(input); + textLine.updateForCurrentWatchers(); + + player.sendMessage(CC.translate("&aSet text for this line.")); + new HologramManageLinesMenu(plugin, hologram).open(player); + return Prompt.END_OF_CONVERSATION; + } + + return this; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/runnable/HologramUpdateRunnable.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/runnable/HologramUpdateRunnable.java new file mode 100644 index 0000000..7d6378d --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/runnable/HologramUpdateRunnable.java @@ -0,0 +1,28 @@ +package rip.battle.entity.hologram.runnable; + +import lombok.RequiredArgsConstructor; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.hologram.impl.UpdatableHologram; + +@RequiredArgsConstructor +public class HologramUpdateRunnable implements Runnable { + + private final HologramManager hologramManager; + + @Override + public void run() { + for (Hologram hologram : hologramManager.getHolograms().values()) { + if (hologram instanceof UpdatableHologram){ + UpdatableHologram updatableHologram = (UpdatableHologram) hologram; + + if (updatableHologram.canUpdate() && !updatableHologram.getLines().isEmpty()){ + + updatableHologram.getCurrentWatchersPlayers().forEach(updatableHologram::update); + + updatableHologram.setLastUpdate(System.currentTimeMillis()); + } + } + } + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/hologram/serialization/HologramTypeAdapter.java b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/serialization/HologramTypeAdapter.java new file mode 100644 index 0000000..a19f386 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/hologram/serialization/HologramTypeAdapter.java @@ -0,0 +1,92 @@ +package rip.battle.entity.hologram.serialization; + +import cc.stormworth.core.util.location.LocationUtils; +import cc.stormworth.core.util.serialize.ItemStackAdapter; +import com.google.gson.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.impl.UpdatableHologram; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.hologram.lines.impl.ItemLine; +import rip.battle.entity.hologram.lines.impl.TextLine; + +import java.lang.reflect.Type; + +public class HologramTypeAdapter implements JsonDeserializer, JsonSerializer { + + @Override + public Hologram deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + return fromJson(jsonElement); + } + + @Override + public JsonElement serialize(Hologram hologram, Type type, JsonSerializationContext jsonSerializationContext) { + return toJson(hologram); + } + + public static JsonObject toJson(Hologram hologram) { + if (hologram == null) { + return null; + } + + JsonObject object = new JsonObject(); + + CraftHologram craftHologram = (CraftHologram) hologram; + + object.addProperty("location", LocationUtils.serializeLocation(craftHologram.getLocation())); + + object.addProperty("name", craftHologram.getName()); + + JsonArray lines = new JsonArray(); + + for (HologramLine line : craftHologram.getLines()) { + JsonObject lineObject = new JsonObject(); + + if (line instanceof TextLine) { + lineObject.addProperty("text", ((TextLine) line).getText().apply(Bukkit.getConsoleSender())); + }else { + ItemLine itemLine = (ItemLine) line; + lineObject.add("item", ItemStackAdapter.serialize(itemLine.getItemStack())); + } + + lines.add(lineObject); + } + + object.add("lines", lines); + + object.add("hidden", new JsonPrimitive(craftHologram.isHidden())); + + return object; + } + + public static Hologram fromJson(JsonElement jsonElement) { + if (jsonElement == null || !jsonElement.isJsonObject()) { + return null; + } + + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + Location location = LocationUtils.deserializeLocation(jsonObject.get("location").getAsString()); + + JsonArray lines = jsonObject.getAsJsonArray("lines"); + + String name = jsonObject.get("name").getAsString(); + CraftHologram hologram = new UpdatableHologram(name, location); + + for (JsonElement line : lines) { + JsonObject lineObject = line.getAsJsonObject(); + + if (lineObject.has("text")) { + hologram.addLine(lineObject.get("text").getAsString()); + }else { + hologram.addLine(ItemStackAdapter.deserialize(lineObject.get("item"))); + } + } + + hologram.updateVisibility(jsonObject.get("hidden").getAsBoolean()); + + return hologram; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/listeners/PlayerListener.java b/BattleEntity-main/src/main/java/rip/battle/entity/listeners/PlayerListener.java new file mode 100644 index 0000000..823f8d9 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/listeners/PlayerListener.java @@ -0,0 +1,26 @@ +package rip.battle.entity.listeners; + +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import rip.battle.entity.Entity; +import rip.battle.entity.EntityManager; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.HologramManager; +import rip.battle.entity.npc.NPCManager; + +@RequiredArgsConstructor +public class PlayerListener implements Listener { + @EventHandler + public void onQuit(PlayerQuitEvent event){ + Player player = event.getPlayer(); + + for (Entity entity : EntityManager.getEntities().values()){ + entity.destroy(player); + } + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/living/LivingEntity.java b/BattleEntity-main/src/main/java/rip/battle/entity/living/LivingEntity.java new file mode 100644 index 0000000..f1625e8 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/living/LivingEntity.java @@ -0,0 +1,191 @@ +package rip.battle.entity.living; + +import cc.stormworth.core.util.TaskUtil; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityTeleport; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityVelocity; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.Vector; +import rip.battle.entity.Entity; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.living.events.LivingEntityDeathEvent; +import rip.battle.entity.tick.TickableEntity; +import rip.battle.entity.utils.AngleUtils; +import rip.battle.entity.utils.PacketUtils; +import rip.battle.spigot.Battle; +import rip.battle.spigot.knockback.KnockbackProfile; + +@Getter @Setter +public abstract class LivingEntity extends Entity implements TickableEntity { + + private double health = 20; + private double maxHealth = 20; + + private boolean dead; + + private boolean invulnerable; + private long lastDamage; + + private boolean gravity = true; + + private String customName; + + private Vector velocity; + + private boolean onGround; + + public LivingEntity(Location location) { + super(location); + velocity = new Vector(); + } + + @Override + public void tick() { + if (gravity){ + if (!getLocation().getBlock().getType().isSolid()) { + + System.out.println("Falling"); + setVelocity(getVelocity().clone().add(new Vector(0, -0.1, 0))); + + onGround = false; + }else{ + System.out.println("On ground"); + onGround = true; + } + } + } + + public void setVelocity(Vector vector) { + this.velocity = vector; + move(vector); + + getCurrentWatchersPlayers().forEach(currentWatchersPlayer -> sendVelocityPacket(currentWatchersPlayer, vector)); + } + + public void sendVelocityPacket(Player player, Vector vector) { + PacketPlayOutEntityVelocity packet = new PacketPlayOutEntityVelocity(getId(), vector.getX(), vector.getY(), vector.getZ()); + PacketUtils.sendPacket(player, packet); + } + + public void move(Vector vector) { + Location to = getLocation().clone().add(vector); + + if (to.getBlock().getRelative(0, 1, 0).getType().isSolid()) { + to.setY(to.getBlockY() + 1); + } + + setLocation(to); + + getCurrentWatchersPlayers().forEach(this::sendMovePacket); + } + + public void sendMovePacket(Player player) { + PacketPlayOutEntityTeleport teleportPacket = new PacketPlayOutEntityTeleport( + getId(), + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor(getLocation().getY() * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + AngleUtils.yawToBytes(getLocation().getYaw()), + AngleUtils.yawToBytes(getLocation().getPitch()), + true); + + PacketUtils.sendPacket(player, teleportPacket); + + velocity = new Vector(); + } + + @Override + public void onLeftClick(Player player) { + + ItemStack hand = player.getItemInHand(); + + double damage = 1; + + switch (hand.getType()){ + case WOOD_SWORD: + case STONE_SWORD: + damage = 3.0; + break; + case IRON_SWORD: + damage = 4.0; + break; + case GOLD_SWORD: + damage = 5.0; + break; + case DIAMOND_SWORD: + damage = 6.0; + break; + } + + //Change this xd + double finalDamage = damage; + TaskUtil.run(JavaPlugin.getPlugin(EntityPlugin.class), () -> { + damage(player, finalDamage); + }); + } + + public boolean damage(org.bukkit.entity.Entity entity, double damage){ + + if (invulnerable){ + return false; + } + + if (lastDamage + 500L > System.currentTimeMillis()){ + return false; + } + + if (dead){ + return false; + } + + health -= damage; + + if (health <= 0){ + onDeath(entity); + sendStatusPacket((byte) 3); + + TaskUtil.runLater(JavaPlugin.getPlugin(EntityPlugin.class), () -> { + if (dead){ + destroyForCurrentWatchers(); + } + }, 40); + + + Bukkit.getPluginManager().callEvent(new LivingEntityDeathEvent(this, entity)); + return true; + } + + lastDamage = System.currentTimeMillis(); + + sendAnimationPacket(1); + + KnockbackProfile profile = Battle.INSTANCE.getConfig().getCurrentKb(); + + setVelocity(new Vector( + (-MathHelper.sin(entity.getLocation().getYaw() * 3.1415927F / 180.0F) * profile.getHorizontal()), + profile.getVertical(), + (MathHelper.cos(entity.getLocation().getYaw() * 3.1415927F / 180.0F) * profile.getHorizontal()) + )); + return true; + } + + public void onDeath(org.bukkit.entity.Entity entity){ + dead = true; + } + + public void setCustomName(String customName) { + this.customName = customName; + + updateForCurrentWatchers(); + } + + public boolean isCollideWithBlock(Location to){ + return to.getBlock().getType().isSolid(); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/living/events/LivingEntityDeathEvent.java b/BattleEntity-main/src/main/java/rip/battle/entity/living/events/LivingEntityDeathEvent.java new file mode 100644 index 0000000..cbe6fc0 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/living/events/LivingEntityDeathEvent.java @@ -0,0 +1,26 @@ +package rip.battle.entity.living.events; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import rip.battle.entity.living.LivingEntity; + +@RequiredArgsConstructor +@Getter +public class LivingEntityDeathEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + private final LivingEntity entity; + private final org.bukkit.entity.Entity killer; + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/living/impl/VillagerEntity.java b/BattleEntity-main/src/main/java/rip/battle/entity/living/impl/VillagerEntity.java new file mode 100644 index 0000000..1e55fd5 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/living/impl/VillagerEntity.java @@ -0,0 +1,83 @@ +package rip.battle.entity.living.impl; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import rip.battle.entity.living.LivingEntity; +import rip.battle.entity.utils.AngleUtils; +import rip.battle.entity.utils.DataWatcherUtil; +import rip.battle.entity.utils.PacketUtils; + +import java.util.Collections; + +@Setter @Getter +public class VillagerEntity extends LivingEntity { + + public VillagerEntity(Location location) { + super(location); + } + + @Override + public String getTypeName() { + return "Villager"; + } + + @Override + public void sendSpawnPackets(Player player) { + DataWatcher dataWatcher = DataWatcherUtil.createDataWatcher(); + + dataWatcher.a(0, (byte) 0); + dataWatcher.a(1, (short) 300); + dataWatcher.a(2, getCustomName() == null ? "" : getCustomName()); + dataWatcher.a(3, (byte) 1); + dataWatcher.a(4, (byte) 1); + dataWatcher.a(6, (float) 1); + dataWatcher.a(10, (byte) 2); + dataWatcher.a(12, (byte) 0); + dataWatcher.a(16, 0); + + PacketPlayOutSpawnEntityLiving spawnPacket = new PacketPlayOutSpawnEntityLiving( + getId(), + 120, + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor(getLocation().getY() * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + dataWatcher); + + PacketPlayOutEntity.PacketPlayOutEntityLook lookPacket = new PacketPlayOutEntity.PacketPlayOutEntityLook( + getId(), + AngleUtils.yawToBytes(getLocation().getYaw()), + AngleUtils.yawToBytes(getLocation().getPitch()), + true); + + PacketPlayOutEntityHeadRotation headRotationPacket = new PacketPlayOutEntityHeadRotation( + getId(), + AngleUtils.yawToBytes(getLocation().getYaw())); + + PacketPlayOutEntityTeleport teleportPacket = new PacketPlayOutEntityTeleport( + getId(), + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor(getLocation().getY() * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + AngleUtils.yawToBytes(getLocation().getYaw()), + AngleUtils.yawToBytes(getLocation().getPitch()), + true); + + PacketUtils.sendPacket(player, spawnPacket); + PacketUtils.sendPacket(player, lookPacket); + PacketUtils.sendPacket(player, headRotationPacket); + PacketUtils.sendPacket(player, teleportPacket); + } + + @Override + public void sendUpdatePackets(Player player) { + PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(); + + packet.setEntityId(getId()); + packet.setData(Collections.singletonList(new DataWatcher.WatchableObject(4, 2, getCustomName()))); + + PacketUtils.sendPacket(player, packet); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCBuilder.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCBuilder.java new file mode 100644 index 0000000..ccbb4c4 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCBuilder.java @@ -0,0 +1,196 @@ +package rip.battle.entity.npc; + +import cc.stormworth.core.util.UUIDUtils; +import cc.stormworth.core.util.skin.SkinTexture; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.NPC; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.api.Hologram; + +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +public class NPCBuilder { + + public NPCEntity npc; + + public NPCBuilder(String name, Location location) { + npc = new NPCEntity(name, location); + } + + public NPCBuilder setSkin(SkinTexture skin) { + npc.setSkin(skin); + return this; + } + + public NPCBuilder setSkin(Player player) { + npc.setSkin(SkinTexture.getPlayerTexture(player)); + return this; + } + + public NPCBuilder setSkin(String value, String signature) { + npc.setSkin(new SkinTexture(value, signature)); + return this; + } + + public NPCBuilder setSkin(String name) { + UUID uuid = Bukkit.getOfflinePlayer(name).getUniqueId(); + + if (uuid == null){ + CompletableFuture future = UUIDUtils.getUUIDFromMojang(name); + + future.thenAccept(uuidFetch -> { + if (uuidFetch == null){ + return; + } + + CompletableFuture skinFuture = UUIDUtils.getSkinFromMojang(uuidFetch); + + skinFuture.thenAccept(skinFetch -> { + if (skinFetch == null){ + return; + } + + npc.setSkin(skinFetch); + }); + }); + }else { + CompletableFuture skinFuture = UUIDUtils.getSkinFromMojang(uuid); + + skinFuture.thenAccept(skinFetch -> { + if (skinFetch == null){ + return; + } + + npc.setSkin(skinFetch); + }); + } + return this; + } + + public NPCBuilder setDisplayName(String displayName) { + npc.setDisplayName(displayName); + return this; + } + + public NPCBuilder setArmor(Player player) { + + if (player.getInventory().getHelmet() != null) { + npc.setHelmet(player.getInventory().getHelmet()); + } + + if (player.getInventory().getChestplate() != null) { + npc.setChestplate(player.getInventory().getChestplate()); + } + + if (player.getInventory().getLeggings() != null) { + npc.setLeggings(player.getInventory().getLeggings()); + } + + if (player.getInventory().getBoots() != null) { + npc.setBoots(player.getInventory().getBoots()); + } + + return this; + } + + public NPCBuilder setArmor(ItemStack[] armor){ + npc.setArmor(armor); + return this; + } + + public NPCBuilder setHelmet(ItemStack helmet) { + npc.setHelmet(helmet); + return this; + } + + public NPCBuilder setChestplate(ItemStack chestplate) { + npc.setChestplate(chestplate); + return this; + } + + public NPCBuilder setLeggings(ItemStack leggings) { + npc.setLeggings(leggings); + return this; + } + + public NPCBuilder setBoots(ItemStack boots) { + npc.setBoots(boots); + return this; + } + + public NPCBuilder setItemInHand(ItemStack itemInHand) { + npc.setItemInHand(itemInHand); + return this; + } + + public NPCBuilder onInteract(Consumer consumer) { + npc.setOnLeftClick(consumer); + return this; + } + + public NPCBuilder onAttack(Consumer consumer) { + npc.setOnRightClick(consumer); + return this; + } + + public NPCBuilder setHologram(Hologram hologram) { + npc.setHologram(hologram); + return this; + } + + public NPCBuilder setCommands(Set commands) { + npc.setCommands(commands); + return this; + } + + public NPCBuilder addCommand(String command) { + npc.getCommands().add(command); + return this; + } + + public NPCBuilder removeCommand(String command) { + npc.getCommands().remove(command); + return this; + } + + public NPCBuilder setMessages(List messages) { + npc.setMessages(messages); + return this; + } + + public NPCBuilder addMessage(String message) { + npc.getMessages().add(message); + return this; + } + + public NPCBuilder removeMessage(String message) { + npc.getMessages().remove(message); + return this; + } + + public NPCBuilder setMessage(int index, String message) { + npc.getMessages().set(index, message); + return this; + } + + public NPCBuilder setOnRightClick(Consumer onRightClick) { + npc.setOnRightClick(onRightClick); + return this; + } + + public NPCBuilder setOnLeftClick(Consumer onLeftClick) { + npc.setOnLeftClick(onLeftClick); + return this; + } + + public NPCEntity build() { + return npc; + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCEntity.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCEntity.java new file mode 100644 index 0000000..a1a7987 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCEntity.java @@ -0,0 +1,467 @@ +package rip.battle.entity.npc; + +import cc.stormworth.core.util.TaskUtil; +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.skin.SkinTexture; +import com.google.common.collect.Lists; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_8_R3.scoreboard.CraftScoreboard; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.plugin.java.JavaPlugin; +import rip.battle.entity.Entity; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.CraftHologram; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.utils.AngleUtils; +import rip.battle.entity.utils.DataWatcherUtil; +import rip.battle.entity.utils.PacketUtils; +import rip.battle.entity.utils.PlayerUtil; + +import java.util.*; + +@Getter @Setter +public class NPCEntity extends Entity implements NPC { + + private final UUID uuid; + private String name; + private String displayName; + + private GameProfile gameProfile; + + private SkinTexture skin; + + private CraftHologram hologram; + + private boolean hidden; + + private ItemStack itemInHand; + + private ItemStack helmet; + private ItemStack chestplate; + private ItemStack leggings; + private ItemStack boots; + + private List messages = Lists.newArrayList(); + + private int supportEntityID; + + public NPCEntity(String name, String displayName, Location location) { + super(location); + this.name = name; + this.displayName = CC.translate(displayName); + this.uuid = UUID.randomUUID(); + + this.gameProfile = new GameProfile(uuid, displayName); + } + + public NPCEntity(String name, Location location) { + this(name, name, location); + } + + @Override + public String getTypeName() { + return "NPC"; + } + + @Override + public Hologram getAttachedHologram() { + return hologram; + } + + @Override + public void onRightClick(Player player) { + + super.onRightClick(player); + + if (!getCommands().isEmpty()){ + getCommands().forEach(command -> player.performCommand(command.replace("%player%", player.getName()))); + } + + if (!messages.isEmpty()) { + messages.forEach(player::sendMessage); + } + } + + @Override + public void sendSpawnPackets(Player player) { + + DataWatcher dataWatcher = DataWatcherUtil.createNPCDataWatcher(this); + + PacketPlayOutPlayerInfo addPlayerPacket = new PacketPlayOutPlayerInfo( + PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, + gameProfile, + 0, + WorldSettings.EnumGamemode.SURVIVAL, + null); + + PacketPlayOutPlayerInfo removePlayerPacket = new PacketPlayOutPlayerInfo( + PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, + gameProfile, + 0, + WorldSettings.EnumGamemode.SURVIVAL, + null); + + PacketPlayOutNamedEntitySpawn spawnPacket = new PacketPlayOutNamedEntitySpawn( + getId(), + uuid, + MathHelper.floor(getLocation().getX() * 32.0), + MathHelper.floor(getLocation().getY() * 32.0), + MathHelper.floor(getLocation().getZ() * 32.0), + AngleUtils.yawToBytes(getLocation().getYaw()), + AngleUtils.yawToBytes(getLocation().getPitch()), + 0, + dataWatcher + ); + + PacketPlayOutEntity.PacketPlayOutEntityLook lookPacket = new PacketPlayOutEntity.PacketPlayOutEntityLook( + getId(), + AngleUtils.yawToBytes(getLocation().getYaw()), + AngleUtils.yawToBytes(getLocation().getPitch()), + true + ); + + PacketPlayOutEntityHeadRotation headRotationPacket = new PacketPlayOutEntityHeadRotation( + getId(), + AngleUtils.yawToBytes(getLocation().getYaw()) + ); + + PacketPlayOutEntityTeleport teleportPacket = new PacketPlayOutEntityTeleport( + getId(), + MathHelper.floor(getLocation().getX() * 32.0), + MathHelper.floor(getLocation().getY() * 32.0), + MathHelper.floor(getLocation().getZ() * 32.0), + AngleUtils.yawToBytes(getLocation().getYaw()), + AngleUtils.yawToBytes(getLocation().getPitch()), + true + ); + + PacketUtils.sendPacket(player, addPlayerPacket); + + TaskUtil.runLater(JavaPlugin.getPlugin(EntityPlugin.class), () -> { + + PacketUtils.sendPacket(player, spawnPacket); + + if (itemInHand != null) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 0, CraftItemStack.asNMSCopy(itemInHand))); + } + + if (helmet != null) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 4, CraftItemStack.asNMSCopy(helmet))); + } + + if (chestplate != null) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 3, CraftItemStack.asNMSCopy(chestplate))); + } + + if (leggings != null) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 2, CraftItemStack.asNMSCopy(leggings))); + } + + if (boots != null) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 1, CraftItemStack.asNMSCopy(boots))); + } + + TaskUtil.runLater(JavaPlugin.getPlugin(EntityPlugin.class), () -> { + PacketUtils.sendPacket(player, lookPacket); + PacketUtils.sendPacket(player, headRotationPacket); + PacketUtils.sendPacket(player, teleportPacket); + PacketUtils.sendPacket(player, new PacketPlayOutAnimation(getId(), 0)); + PacketUtils.sendPacket(player, removePlayerPacket); + + if (hologram != null) { + hideNamePlate(player); + } + + }, 4L); + + if (hologram != null){ + hologram.spawnFor(player); + } + + }, 1L); + } + + @Override + public void sendUpdatePackets(Player player) { + + PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(); + + packet.setEntityId(getId()); + packet.setData(Collections.singletonList(new DataWatcher.WatchableObject(4, 2, displayName))); + + PacketUtils.sendPacket(player, packet); + } + + @Override + public void updateLocation(Location location) { + super.updateLocation(location); + + if (hologram != null){ + hologram.updateLocation(calculateHologramLocation()); + } + + getCurrentWatchersPlayers().forEach(player -> { + + PacketUtils.sendPacket(player, new PacketPlayOutEntityHeadRotation( + getId(), + AngleUtils.yawToBytes(getLocation().getYaw()) + )); + + PacketUtils.sendPacket(player, new PacketPlayOutAnimation( + getId(), + 0 + )); + }); + } + + public Location calculateHologramLocation(){ + return getLocation().clone().subtract(0, 0.2, 0); + } + + public void setSkin(SkinTexture skin){ + this.skin = skin; + + if (skin != null) { + gameProfile = new GameProfile(uuid, displayName); + + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + }else { + gameProfile = new GameProfile(uuid, displayName); + + gameProfile.getProperties().clear(); + } + + resendForCurrentWatchers(); + } + + @Override + public void destroy() { + onDelete(); + } + + @Override + public void onDelete() { + super.onDelete(); + + if (hologram != null){ + hologram.destroy(); + } + } + + @Override + public void teleport(double x, double y, double z) { + teleport(new Location(getLocation().getWorld(), x, y, z, getLocation().getYaw(), getLocation().getPitch())); + } + + @Override + public void teleport(double x, double y, double z, float yaw, float pitch) { + teleport(new Location(getLocation().getWorld(), x, y, z, yaw, pitch)); + } + + public void teleport(Location location) { + updateLocation(location); + } + + @Override + public void teleport(Location location, float yaw, float pitch) { + + Location newLocation = location.clone(); + + newLocation.setYaw(yaw); + newLocation.setPitch(pitch); + + updateLocation(newLocation); + } + + protected void updateTexture(SkinTexture skin){ + this.skin = skin; + + if (skin != null) { + gameProfile = new GameProfile(uuid, displayName); + + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + + for (Player player : getCurrentWatchersPlayers()) { + destroy(player); + spawn(player); + } + } + } + + public void updateItemInHand(ItemStack itemInHand) { + this.itemInHand = itemInHand; + + for (Player player : getCurrentWatchersPlayers()){ + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 0, CraftItemStack.asNMSCopy(itemInHand == null ? new ItemStack(Material.AIR) : itemInHand))); + } + } + + public void setHelmet(ItemStack helmet) { + this.helmet = helmet; + + for (Player player : getCurrentWatchersPlayers()){ + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 4, CraftItemStack.asNMSCopy(helmet == null ? new ItemStack(Material.AIR) : helmet))); + } + } + + public void setChestplate(ItemStack chestplate) { + this.chestplate = chestplate; + + for (Player player : getCurrentWatchersPlayers()){ + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 3, CraftItemStack.asNMSCopy(chestplate == null ? new ItemStack(Material.AIR) : chestplate))); + } + } + + public void setLeggings(ItemStack leggings) { + this.leggings = leggings; + + for (Player player : getCurrentWatchersPlayers()){ + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 2, CraftItemStack.asNMSCopy(leggings == null ? new ItemStack(Material.AIR) : leggings))); + } + } + + public void setBoots(ItemStack boots) { + this.boots = boots; + + for (Player player : getCurrentWatchersPlayers()){ + PacketUtils.sendPacket(player, new PacketPlayOutEntityEquipment(getId(), 1, CraftItemStack.asNMSCopy(boots == null ? new ItemStack(Material.AIR) : boots))); + } + } + + public void setHologram(Hologram hologram) { + this.hologram = (CraftHologram) hologram; + + if (hologram != null){ + this.hologram.updateLocation(calculateHologramLocation()); + ((CraftHologram) hologram).setParent(this); + + for (Player player : getCurrentWatchersPlayers()){ + hideNamePlate(player); + this.hologram.spawnFor(player); + } + }else{ + for (Player player : getCurrentWatchersPlayers()){ + showNamePlate(player); + } + } + + updateForCurrentWatchers(); + } + + protected void hideNamePlate(Player player){ + if (PlayerUtil.isLegacy(player)){ + if (supportEntityID == 0){ + supportEntityID = nextId(); + DataWatcher slimeDatawatcher = DataWatcherUtil.createDataWatcher(); + + slimeDatawatcher.a(0, (byte) 0); + slimeDatawatcher.a(1, (short) 0); + slimeDatawatcher.a(2, ""); + slimeDatawatcher.a(3, (byte) 0); + slimeDatawatcher.a(4, (byte) 0); + slimeDatawatcher.a(16, (byte) -2); + + PacketPlayOutSpawnEntityLiving packet = new PacketPlayOutSpawnEntityLiving( + supportEntityID, + 55, + MathHelper.floor(getLocation().getX() * 32.0D), + MathHelper.floor(getLocation().getY() * 32.0D), + MathHelper.floor(getLocation().getZ() * 32.0D), + slimeDatawatcher + ); + + PacketUtils.sendPacket(player, packet); + } + PacketUtils.sendPacket(player, new PacketPlayOutAttachEntity(0, supportEntityID, getId())); + }else { + ScoreboardTeam team = new ScoreboardTeam(((CraftScoreboard) Bukkit.getScoreboardManager().getMainScoreboard()).getHandle(), + getDisplayName()); + + team.setNameTagVisibility(ScoreboardTeamBase.EnumNameTagVisibility.NEVER); + + PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(team, 1)); + PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(team, 0)); + PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(team, new ArrayList(){{add(getDisplayName());}}, 3)); + } + } + + protected void showNamePlate(Player player){ + if (PlayerUtil.isLegacy(player)){ + PacketUtils.sendPacket(player, new PacketPlayOutAttachEntity(0, supportEntityID, 0)); + PacketUtils.sendPacket(player, new PacketPlayOutEntityDestroy(supportEntityID)); + supportEntityID = 0; + }else { + ScoreboardTeam team = new ScoreboardTeam(((CraftScoreboard) Bukkit.getScoreboardManager().getMainScoreboard()).getHandle(), + getDisplayName()); + + team.setNameTagVisibility(ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS); + + PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(team, 1)); + PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(team, 0)); + PacketUtils.sendPacket(player, new PacketPlayOutScoreboardTeam(team, new ArrayList(){{add(getDisplayName());}}, 3)); + } + } + + @Override + public void sendDestroyPackets(Player player) { + PacketUtils.sendPacket(player, new PacketPlayOutEntityDestroy(supportEntityID)); + super.sendDestroyPackets(player); + } + + @Override + public void setArmor(Player player) { + PlayerInventory inventory = player.getInventory(); + + setHelmet(inventory.getHelmet()); + setChestplate(inventory.getChestplate()); + setLeggings(inventory.getLeggings()); + setBoots(inventory.getBoots()); + } + + @Override + public void setArmor(ItemStack[] armor) { + setHelmet(armor[3]); + setChestplate(armor[2]); + setLeggings(armor[1]); + setBoots(armor[0]); + } + + @Override + public void setArmor(ItemStack helmet, ItemStack chestplate, ItemStack leggings, ItemStack boots) { + setHelmet(helmet); + setChestplate(chestplate); + setLeggings(leggings); + setBoots(boots); + } + + @Override + public void setItemInHand(ItemStack itemInHand) { + this.itemInHand = itemInHand; + + updateItemInHand(itemInHand); + } + + @Override + public void setDisplayName(String displayName) { + this.displayName = CC.translate(displayName); + + this.gameProfile = new GameProfile(uuid, CC.translate(displayName)); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + resendForCurrentWatchers(); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCManager.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCManager.java new file mode 100644 index 0000000..d58700e --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/NPCManager.java @@ -0,0 +1,116 @@ +package rip.battle.entity.npc; + +import cc.stormworth.core.util.serialize.ItemStackAdapter; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import lombok.Getter; +import org.bukkit.Location; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.hologram.serialization.HologramTypeAdapter; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.npc.serialization.NPCTypeAdapter; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; + +@Getter +public class NPCManager { + + private final Map npcs = Maps.newHashMap(); + + private final EntityPlugin plugin; + + public NPCManager(EntityPlugin plugin) { + this.plugin = plugin; + loadNPCs(); + } + + public void loadNPCs() { + File file = new File(plugin.getDataFolder(), "npcs"); + + if (!file.exists()){ + return; + } + + Arrays.stream(file.listFiles()).forEach(file1 -> { + + FileReader fileReader; + + try { + fileReader = new FileReader(file1); + + JsonElement jsonElement = new Gson().fromJson(fileReader, JsonElement.class); + NPC npc = NPCTypeAdapter.fromJson(jsonElement); + + npcs.put(file1.getName().replace(".json", ""), npc); + + System.out.println("Loaded NPC: " + npc.getName()); + + fileReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + public void saveNPCs(){ + Gson gson = new GsonBuilder() + .registerTypeAdapter(ItemStack.class, new ItemStackAdapter()) + .registerTypeAdapter(Hologram.class, new HologramTypeAdapter()) + .enableComplexMapKeySerialization() + .setPrettyPrinting() + .create(); + + File file = new File(plugin.getDataFolder(), "npcs"); + + if (!file.exists()) + file.mkdirs(); + + npcs.forEach((name, hologram) -> { + try { + FileWriter writer = new FileWriter(new File(plugin.getDataFolder(), + File.separator + "npcs" + File.separator + name + ".json")); + + writer.write(gson.toJson(NPCTypeAdapter.toJson(hologram))); + System.out.println("Saved NPC: " + name); + + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + public void addNPC(NPC npc) { + npcs.put(npc.getName(), npc); + } + + public void removeNPC(NPC npc) { + npc.destroy(); + npcs.remove(npc.getName()); + + File file = new File(plugin.getDataFolder(), "npcs" + File.separator + npc.getName() + ".json"); + + if (file.exists()) + file.delete(); + } + + public NPC getNPC(String name) { + return npcs.get(name); + } + + public void createNPC(String name, Location location) { + NPC npc = new NPCEntity(name, location); + + npc.spawn(); + addNPC(npc); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/api/NPC.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/api/NPC.java new file mode 100644 index 0000000..ca45f9f --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/api/NPC.java @@ -0,0 +1,90 @@ +package rip.battle.entity.npc.api; + +import cc.stormworth.core.util.skin.SkinTexture; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.api.Hologram; + +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +public interface NPC { + + String getName(); + + void setSkin(SkinTexture skin); + + SkinTexture getSkin(); + + void destroy(); + + void destroy(Player player); + + void spawn(); + + void spawn(Player player); + + void updateVisibility(boolean hidden); + + void updateVisibilityFor(Player player, boolean hidden); + + boolean isVisible(); + + boolean isVisibleTo(Player player); + + void teleport(double x, double y, double z); + + void teleport(double x, double y, double z, float yaw, float pitch); + + void teleport(Location location); + + void teleport(Location location, float yaw, float pitch); + + Location getLocation(); + + ItemStack getHelmet(); + + ItemStack getChestplate(); + + ItemStack getLeggings(); + + ItemStack getBoots(); + + ItemStack getItemInHand(); + + void setHelmet(ItemStack itemStack); + + void setChestplate(ItemStack itemStack); + + void setLeggings(ItemStack itemStack); + + void setBoots(ItemStack itemStack); + + void setItemInHand(ItemStack itemStack); + + void setArmor(Player player); + + void setArmor(ItemStack[] armor); + + void setArmor(ItemStack helmet, ItemStack chestplate, ItemStack leggings, ItemStack boots); + + void setDisplayName(String displayName); + + String getDisplayName(); + + Hologram getHologram(); + + void setHologram(Hologram hologram); + + void setMessages(List messages); + + List getMessages(); + + Set getCommands(); + + void setOnRightClick(Consumer onRightClick); + + void setOnLeftClick(Consumer onLeftClick); +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/NPCCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/NPCCommand.java new file mode 100644 index 0000000..e9a92a7 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/NPCCommand.java @@ -0,0 +1,33 @@ +package rip.battle.entity.npc.commands; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import org.bukkit.entity.Player; + +public class NPCCommand { + + @Command(name = "", desc = "Allows you to manage your npc", usage = "") + public void npc(@Sender Player player) { + player.sendMessage(CC.translate("&e&lNPC Commands")); + + player.sendMessage(CC.translate("&e/npc create &7- &fCreates a npc with the given name.")); + player.sendMessage(CC.translate("&e/npc remove &7- &fRemoves a npc with the given name.")); + player.sendMessage(CC.translate("&e/npc setline [text] &7- &fSets a line on a npc.")); + player.sendMessage(CC.translate("&e/npc removeline &7- &fRemoves a line from a npc.")); + player.sendMessage(CC.translate("&e/npc addline &7- &fAdds a line to a npc.")); + player.sendMessage(CC.translate("&e/npc additemline &7- &fAdds a line with an item to a npc.")); + player.sendMessage(CC.translate("&e/npc teleport &7- &fTeleports you to a npc.")); + player.sendMessage(CC.translate("&e/npc movehere &7- &fSets the location of a npc.")); + player.sendMessage(CC.translate("&e/npc setdisplayname &7- &fSets the display name of a npc.")); + player.sendMessage(CC.translate("&e/npc setskin &7- &fSets the skin of a npc.")); + player.sendMessage(CC.translate("&e/npc setarmor &7- &fSets your armor as the armor of a npc.")); + player.sendMessage(CC.translate("&e/npc setitem &7- &fSets your item in hand as the item in hand of a npc.")); + player.sendMessage(CC.translate("&e/npc sethelmet &7- &fSets your helmet as the helmet of a npc.")); + player.sendMessage(CC.translate("&e/npc setchestplate &7- &fSets your chestplate as the chestplate of a npc.")); + player.sendMessage(CC.translate("&e/npc setleggings &7- &fSets your leggings as the leggings of a npc.")); + player.sendMessage(CC.translate("&e/npc setboots &7- &fSets your boots as the boots of a npc.")); + player.sendMessage(CC.translate("&e/npc list &7- &fLists all npcs.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCAddItemLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCAddItemLineSubCommand.java new file mode 100644 index 0000000..d12ac7f --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCAddItemLineSubCommand.java @@ -0,0 +1,46 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import com.jonahseguin.drink.annotation.Text; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.impl.UpdatableHologram; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCAddItemLineSubCommand { + + private final NPCManager npcManager; + + @Command(name = "additemline", desc = "Allows you to add a item line to a npc", usage = "") + public void addLine(@Sender Player player, String name) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + if (npc.getHologram() == null){ + npc.setHologram(new UpdatableHologram(npc.getName() + "_hologram", npc.getLocation())); + } + + ItemStack item = player.getItemInHand(); + + if (item == null) { + player.sendMessage(CC.translate("&cYou must be holding an item in your hand.")); + return; + } + + npc.getHologram().addLine(item); + + player.sendMessage(CC.translate("&aYou have added a line to the npc &f" + name + "&a.")); + } + + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCAddLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCAddLineSubCommand.java new file mode 100644 index 0000000..3d70c6f --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCAddLineSubCommand.java @@ -0,0 +1,37 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import com.jonahseguin.drink.annotation.Text; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.impl.UpdatableHologram; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCAddLineSubCommand { + + private final NPCManager npcManager; + + @Command(name = "addline", desc = "Allows you to add a line to a npc", usage = " ") + public void addLine(@Sender Player player, String name, @Text String line) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + if (npc.getHologram() == null){ + npc.setHologram(new UpdatableHologram(npc.getName() + "_hologram", npc.getLocation())); + } + + npc.getHologram().addLine(line); + + player.sendMessage(CC.translate("&aYou have added a line to the npc &f" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCCreateSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCCreateSubCommand.java new file mode 100644 index 0000000..6e92fb1 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCCreateSubCommand.java @@ -0,0 +1,27 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; + +@RequiredArgsConstructor +public class NPCCreateSubCommand { + + private final NPCManager npcManager; + + @Command(name = "create", desc = "Allows you to create a npc", usage = "") + public void create(@Sender Player player, String name) { + + if (npcManager.getNPC(name) != null) { + player.sendMessage(CC.translate("&cA npc with that name already exists.")); + return; + } + + npcManager.createNPC(name, player.getLocation()); + player.sendMessage(CC.translate("&aYou have created a npc with the name &f" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCDeleteSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCDeleteSubCommand.java new file mode 100644 index 0000000..42cd017 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCDeleteSubCommand.java @@ -0,0 +1,32 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCDeleteSubCommand { + + private final NPCManager npcManager; + + @Command(name = "delete", desc = "Allows you to delete a npc", usage = "") + public void delete(@Sender Player player, String name) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.destroy(); + npcManager.removeNPC(npc); + + player.sendMessage(CC.translate("&aYou have deleted the npc &f" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCEditSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCEditSubCommand.java new file mode 100644 index 0000000..5815b47 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCEditSubCommand.java @@ -0,0 +1,31 @@ +package rip.battle.entity.npc.commands.sub; + +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.npc.menu.NPCEditMenu; + +@RequiredArgsConstructor +public class NPCEditSubCommand { + + private final EntityPlugin plugin; + private final NPCManager npcManager; + + @Command(name = "edit", desc = "Edit an NPC") + public void edit(@Sender Player player, String name){ + NPC npc = npcManager.getNPC(name); + + if (npc == null){ + player.sendMessage(ChatColor.RED + "NPC not found."); + return; + } + + new NPCEditMenu(npc, plugin).open(player); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCListCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCListCommand.java new file mode 100644 index 0000000..282d38e --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCListCommand.java @@ -0,0 +1,43 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +import java.util.Map; + +@RequiredArgsConstructor +public class NPCListCommand { + + private final NPCManager npcManager; + + @Command(name = "list", desc = "List all NPCs", usage = "/npc list", aliases = {"l", "ls"}) + public void list(@Sender Player player){ + Map npcs = npcManager.getNpcs(); + + if (npcs.isEmpty()) { + player.sendMessage(CC.translate("&cThere are no npcs.")); + return; + } + + player.sendMessage(CC.translate("&aThere are &e" + npcs.size() + " &anpcs.")); + + npcs.forEach((name, npc) -> { + + ComponentBuilder builder = new ComponentBuilder(CC.translate("&e" + name + " &b[Click to teleport]")); + builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(CC.translate("&7Click to teleport")).create())); + builder.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/npc tp " + name)); + + player.spigot().sendMessage(builder.create()); + }); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCMoveHereSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCMoveHereSubCommand.java new file mode 100644 index 0000000..e82528c --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCMoveHereSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCMoveHereSubCommand { + + private final NPCManager npcManager; + + @Command(name = "movehere", desc = "Allows you to move a npc to your location", usage = "", aliases = {"mh", "s", "teleporto", "teleporthere"}) + public void moveHere(@Sender Player player, String name) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.teleport(player.getLocation()); + + player.sendMessage(CC.translate("&aYou have moved the npc &f" + name + "&a to your location.")); + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCRemoveLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCRemoveLineSubCommand.java new file mode 100644 index 0000000..2e583bc --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCRemoveLineSubCommand.java @@ -0,0 +1,49 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.hologram.api.Hologram; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCRemoveLineSubCommand { + + private final NPCManager npcManager; + + @Command(name = "removeline", desc = "Allows you to remove a line from a npc", usage = " ") + public void removeLine(@Sender Player player, String name, int line) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + Hologram hologram = npc.getHologram(); + + if (hologram == null) { + player.sendMessage(CC.translate("&cThis npc does not have a hologram.")); + return; + } + + if (line > hologram.getLines().size()) { + player.sendMessage(CC.translate("&cThis npc does not have a line with that index.")); + return; + } + + if (hologram.getLines().size() == 1) { + hologram.destroy(); + npc.setHologram(null); + }else{ + hologram.removeLine(line); + } + + player.sendMessage(CC.translate("&aYou have removed the line &f" + line + " &afrom the npc &f" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetArmorSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetArmorSubCommand.java new file mode 100644 index 0000000..8619b61 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetArmorSubCommand.java @@ -0,0 +1,31 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetArmorSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setarmor", desc = "Allows you to set the armor of a npc", usage = "") + public void setArmor(@Sender Player player, String name) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setArmor(player); + + player.sendMessage(CC.translate("&aYou have set your armor to the npc &f" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetBootsSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetBootsSubCommand.java new file mode 100644 index 0000000..6d24f9b --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetBootsSubCommand.java @@ -0,0 +1,29 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetBootsSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setboots", desc = "Sets the boots of a npc") + public void setBoots(@Sender Player player){ + NPC npc = npcManager.getNPC(player.getName()); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setBoots(player.getInventory().getBoots()); + player.sendMessage(CC.translate("&aYou have set the boots of the npc &f" + npc.getName() + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetChestPlateSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetChestPlateSubCommand.java new file mode 100644 index 0000000..065d53d --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetChestPlateSubCommand.java @@ -0,0 +1,29 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetChestPlateSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setchestplate", desc = "Sets the chestplate of a npc") + public void setBoots(@Sender Player player){ + NPC npc = npcManager.getNPC(player.getName()); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setChestplate(player.getInventory().getChestplate()); + player.sendMessage(CC.translate("&aYou have set the chestplate of the npc &f" + npc.getName() + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetDisplaynameSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetDisplaynameSubCommand.java new file mode 100644 index 0000000..ac2bddf --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetDisplaynameSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetDisplaynameSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setdisplayname", desc = "Allows you to set the display name of a npc", usage = " ") + public void setDisplayname(@Sender Player player, String name, String displayName) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setDisplayName(displayName); + player.sendMessage(CC.translate("&aYou have set the display name of the npc &f" + name + " &ato &f" + displayName + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetHelmetSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetHelmetSubCommand.java new file mode 100644 index 0000000..d98809e --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetHelmetSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetHelmetSubCommand { + + private final NPCManager npcManager; + + @Command(name = "sethelmet", desc = "Sets the helmet of a npc") + public void setBoots(@Sender Player player){ + NPC npc = npcManager.getNPC(player.getName()); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setHelmet(player.getInventory().getHelmet()); + player.sendMessage(CC.translate("&aYou have set the helmet of the npc &f" + npc.getName() + "&a.")); + } + + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetItemInHandSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetItemInHandSubCommand.java new file mode 100644 index 0000000..5cc66e7 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetItemInHandSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetItemInHandSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setitemhand", desc = "Sets the item in hand of a npc", aliases = "setitem") + public void setBoots(@Sender Player player){ + NPC npc = npcManager.getNPC(player.getName()); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setItemInHand(player.getInventory().getItemInHand()); + player.sendMessage(CC.translate("&aYou have set the item in hand of the npc &f" + npc.getName() + "&a.")); + } + + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetLeggingsSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetLeggingsSubCommand.java new file mode 100644 index 0000000..975d6d8 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetLeggingsSubCommand.java @@ -0,0 +1,30 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetLeggingsSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setleggings", desc = "Sets the leggings of a npc") + public void setBoots(@Sender Player player){ + NPC npc = npcManager.getNPC(player.getName()); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + npc.setLeggings(player.getInventory().getLeggings()); + player.sendMessage(CC.translate("&aYou have set the leggings of the npc &f" + npc.getName() + "&a.")); + } + + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetLineSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetLineSubCommand.java new file mode 100644 index 0000000..7d51260 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetLineSubCommand.java @@ -0,0 +1,78 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.OptArg; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.hologram.lines.HologramLine; +import rip.battle.entity.hologram.lines.impl.ItemLine; +import rip.battle.entity.hologram.lines.impl.TextLine; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCSetLineSubCommand { + + private final NPCManager npcManager; + + public void setLine(@Sender Player player, String name, int line, @OptArg String text) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + if (npc.getHologram() == null) { + player.sendMessage(CC.translate("&cThis npc does not have a hologram.")); + return; + } + + if (line > npc.getHologram().getLines().size()) { + player.sendMessage(CC.translate("&cThis npc does not have a line with that index.")); + return; + } + + HologramLine hologramLine = npc.getHologram().getLines().get(line); + + if (hologramLine instanceof ItemLine){ + + if (text != null){ + player.sendMessage(CC.translate("&cYou cannot set the text of an item line.")); + return; + } + + ItemStack item = player.getItemInHand(); + + if (item == null){ + player.sendMessage(CC.translate("&cYou must be holding an item to set the item line.")); + return; + } + + ((ItemLine) hologramLine).setItemStack(item); + hologramLine.updateForCurrentWatchers(); + + player.sendMessage(CC.translate("&aYou have set the item line &f" + line + " &afor the npc &f" + name + "&a.")); + }else { + + if (text == null) { + player.sendMessage(CC.translate("&cYou must provide text to set the text line.")); + return; + } + + ((TextLine) hologramLine).setText(other -> text); + + TextLine textLine = (TextLine) hologramLine; + + textLine.setLine(text); + hologramLine.updateForCurrentWatchers(); + + player.sendMessage(CC.translate("&aYou have set the line &f" + line + " &afor the npc &f" + name + "&a.")); + } + + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetSkinSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetSkinSubCommand.java new file mode 100644 index 0000000..1d5b385 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCSetSkinSubCommand.java @@ -0,0 +1,55 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.skin.SkinTexture; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.OptArg; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +@RequiredArgsConstructor +public class NPCSetSkinSubCommand { + + private final NPCManager npcManager; + + @Command(name = "setskin", desc = "Allows you to set the skin of a npc", usage = " ") + public void setSkin(@Sender Player player, String name, @OptArg String username) { + + if (username == null) { + username = player.getName(); + } + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + if (Objects.equals(username, player.getName())){ + npc.setSkin(SkinTexture.getPlayerTexture(player)); + player.sendMessage(CC.translate("&aYou have set your skin to the npc &f" + name + "&a.")); + } else { + CompletableFuture skinFuture = SkinTexture.getSkinFromUsername(username); + + String finalUsername = username; + skinFuture.thenAccept(skin -> { + if (skin == null) { + player.sendMessage(CC.translate("&cA skin with that name does not exist.")); + return; + } + + npc.setSkin(skin); + player.sendMessage(CC.translate("&aYou have set the skin of the npc &f" + name + "&a to &f" + finalUsername + "&a.")); + }); + + } + + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCTeleportSubCommand.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCTeleportSubCommand.java new file mode 100644 index 0000000..e303478 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/commands/sub/NPCTeleportSubCommand.java @@ -0,0 +1,31 @@ +package rip.battle.entity.npc.commands.sub; + +import cc.stormworth.core.util.chat.CC; +import com.jonahseguin.drink.annotation.Command; +import com.jonahseguin.drink.annotation.Sender; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import rip.battle.entity.npc.NPCManager; +import rip.battle.entity.npc.api.NPC; + +@RequiredArgsConstructor +public class NPCTeleportSubCommand { + + private final NPCManager npcManager; + + @Command(name = "teleport", desc = "Allows you to teleport to a hologram", usage = "", aliases = "tp") + public void teleport(@Sender Player player, String name) { + + NPC npc = npcManager.getNPC(name); + + if (npc == null) { + player.sendMessage(CC.translate("&cA npc with that name does not exist.")); + return; + } + + player.teleport(npc.getLocation()); + + player.sendMessage(CC.translate("&aYou have teleported to the npc &f" + name + "&a.")); + } + +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCEditArmorMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCEditArmorMenu.java new file mode 100644 index 0000000..9f5c04e --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCEditArmorMenu.java @@ -0,0 +1,88 @@ +package rip.battle.entity.npc.menu; + +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.Menu; +import cc.stormworth.core.util.menu.button.Button; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.utils.ArmorPiece; + +import java.util.Map; + +@RequiredArgsConstructor +public class NPCEditArmorMenu extends Menu { + + private final EntityPlugin plugin; + private final NPC npc; + + @Override + public String getTitle(Player player) { + return "&eEditing armor for NPC &6" + npc.getName(); + } + + @Override + public int getRows(Player player) { + return 3; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + buttons.put(0, new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + return new ItemBuilder(Material.BED).setName("&cBack").toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCEditMenu(npc, plugin).open(player); + } + }); + + buttons.put(getSlot(1, 2), new EditArmorPieceButton(npc.getHelmet(), ArmorPiece.HELMET)); + buttons.put(getSlot(1, 3), new EditArmorPieceButton(npc.getChestplate(), ArmorPiece.CHESTPLATE)); + buttons.put(getSlot(1, 4), new EditArmorPieceButton(npc.getLeggings(), ArmorPiece.LEGGINGS)); + buttons.put(getSlot(1, 5), new EditArmorPieceButton(npc.getBoots(), ArmorPiece.BOOTS)); + + return buttons; + } + + @RequiredArgsConstructor + public class EditArmorPieceButton extends Button{ + + private final ItemStack itemStack; + private final ArmorPiece armorPiece; + + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(itemStack == null ? Material.INK_SACK : itemStack.getType()); + + if (itemStack == null) { + builder.setDurability((short) 8); + } + + builder.setName("&6" + armorPiece.name().toLowerCase()); + + builder.addLore( + "", + "&7Click to change the " + armorPiece.name().toLowerCase() + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCSelectArmorPieceMenu(plugin, npc, armorPiece).open(player); + } + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCEditMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCEditMenu.java new file mode 100644 index 0000000..352d851 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCEditMenu.java @@ -0,0 +1,292 @@ +package rip.battle.entity.npc.menu; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.chat.ChatUtils; +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.Menu; +import cc.stormworth.core.util.menu.button.Button; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.hologram.menu.HologramEditMenu; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.npc.prompt.NPCChangeDisplayNamePrompt; + +import java.util.Map; + +@RequiredArgsConstructor +public class NPCEditMenu extends Menu { + + private final NPC npc; + private final EntityPlugin plugin; + + @Override + public String getTitle(Player player) { + return "&eEditing NPC &6" + npc.getName(); + } + + @Override + public int getRows(Player player) { + return 5; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + buttons.put(getSlot(1, 2), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.NAME_TAG); + + builder.setName("&6Change Display Name"); + + builder.addLore( + "", + "&7Current: &e" + npc.getDisplayName(), + "", + "&7Click to change the display name" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + ChatUtils.beginPrompt(player, new NPCChangeDisplayNamePrompt(plugin, npc), plugin); + } + }); + + buttons.put(getSlot(1, 4), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM); + + builder.setDurability((short) 3); + + builder.setName("&6Change Skin"); + + builder.addLore( + "", + "&7Click to change the skin" + ); + + if (npc.getSkin() != null){ + builder.setTexture(npc.getSkin().getValue()); + } + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCSkinMenu(npc, plugin).open(player); + } + }); + + buttons.put(getSlot(1, 6), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.ENDER_PEARL); + + builder.setName("&6Teleport"); + + builder.addLore( + "", + "&7Click to teleport to the NPC" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + player.closeInventory(); + player.teleport(npc.getLocation()); + } + }); + + buttons.put(getSlot(2, 2), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.BARRIER); + + builder.setName("&6Delete"); + + builder.addLore( + "", + "&7Click to delete the NPC" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + player.closeInventory(); + plugin.getNpcManager().removeNPC(npc); + + player.sendMessage(CC.translate("&aSuccessfully deleted NPC &6" + npc.getName())); + } + }); + + buttons.put(getSlot(2, 4), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.POTION); + + builder.setDurability((short) 8238); + + builder.setName("&6Change Visibility"); + + builder.addLore( + "", + "&7Current: " + (npc.isVisible() ? "&aVisible" : "&cHidden"), + "", + "&7Click to change the visibility" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + npc.updateVisibility(npc.isVisible()); + player.sendMessage(CC.translate("&aSuccessfully " + (npc.isVisible() ? "showed" : "hidden") + " NPC &6" + npc.getName())); + } + }); + + buttons.put(getSlot(2, 6), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.DIAMOND_CHESTPLATE); + + builder.setName("&6Edit Armor"); + + builder.addLore( + "", + "&7Click to edit the armor" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCEditArmorMenu(plugin, npc).open(player); + } + }); + + + if (npc.getHologram() != null){ + + buttons.put(getSlot(3, 3), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(npc.getItemInHand() == null ? Material.INK_SACK : npc.getItemInHand().getType()); + + if (npc.getItemInHand() != null) { + builder.setDurability(npc.getItemInHand().getDurability()); + }else { + builder.setDurability((short) 8); + } + + builder.setName("&6Edit Item In Hand"); + + builder.addLore( + "", + "&7Click with item to set the item in hand of npc" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(InventoryClickEvent event) { + if (event.getCursor() != null && event.getCursor().getType() != Material.AIR) { + npc.setItemInHand(event.getCursor()); + player.sendMessage(CC.translate("&aSuccessfully set item in hand of NPC &6" + npc.getName())); + event.setCursor(null); + + player.playSound(player.getLocation(), Sound.CLICK, 1F, 1F); + }else { + player.sendMessage(CC.translate("&cYou must have an item in your cursor to set the item in hand of the NPC")); + } + } + }); + + buttons.put(getSlot(3, 5), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.PAPER); + + builder.setName("&6Edit Hologram"); + + builder.addLore( + "", + "&7Click to edit the hologram" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new HologramEditMenu(plugin, npc.getHologram(), NPCEditMenu.this).open(player); + } + }); + }else{ + buttons.put(getSlot(3, 4), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(npc.getItemInHand() == null ? Material.INK_SACK : npc.getItemInHand().getType()); + + if (npc.getItemInHand() != null) { + builder.setDurability(npc.getItemInHand().getDurability()); + }else { + builder.setDurability((short) 8); + } + + builder.setName("&6Edit Item In Hand"); + + builder.addLore( + "", + "&7Click with item to set the item in hand of npc" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(InventoryClickEvent event) { + if (event.getCursor() != null && event.getCursor().getType() != Material.AIR) { + npc.setItemInHand(event.getCursor()); + player.sendMessage(CC.translate("&aSuccessfully set item in hand of NPC &6" + npc.getName())); + event.setCursor(null); + + player.playSound(player.getLocation(), Sound.CLICK, 1F, 1F); + }else { + player.sendMessage(CC.translate("&cYou must have an item in your cursor to set the item in hand of the NPC")); + } + } + }); + } + + return buttons; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSelectArmorPieceMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSelectArmorPieceMenu.java new file mode 100644 index 0000000..01fbab8 --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSelectArmorPieceMenu.java @@ -0,0 +1,171 @@ +package rip.battle.entity.npc.menu; + +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.Menu; +import cc.stormworth.core.util.menu.button.Button; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.utils.ArmorPiece; + +import java.util.Map; + +@RequiredArgsConstructor +public class NPCSelectArmorPieceMenu extends Menu { + + private final EntityPlugin plugin; + private final NPC npc; + private final ArmorPiece armorPiece; + + @Override + public String getTitle(Player player) { + return "&eSelect a " + armorPiece.name() + " for NPC &6" + npc.getName(); + } + + @Override + public int getRows(Player player) { + return 3; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + buttons.put(0, new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + return new ItemBuilder(Material.BED).setName("&cBack").toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCEditArmorMenu(plugin, npc).open(player); + } + }); + + + if (armorPiece == ArmorPiece.HELMET) { + buttons.put(getSlot(1, 2), new ArmorPieceButton(getPiece("leather"))); + buttons.put(getSlot(1, 3), new ArmorPieceButton(getPiece("chainmail"))); + buttons.put(getSlot(1, 4), new ArmorPieceButton(getPiece("iron"))); + buttons.put(getSlot(1, 5), new ArmorPieceButton(getPiece("gold"))); + buttons.put(getSlot(1, 6), new ArmorPieceButton(getPiece("diamond"))); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + buttons.put(getSlot(1, 2), new ArmorPieceButton(getPiece("leather"))); + buttons.put(getSlot(1, 3), new ArmorPieceButton(getPiece("chainmail"))); + buttons.put(getSlot(1, 4), new ArmorPieceButton(getPiece("iron"))); + buttons.put(getSlot(1, 5), new ArmorPieceButton(getPiece("gold"))); + buttons.put(getSlot(1, 6), new ArmorPieceButton(getPiece("diamond"))); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + buttons.put(getSlot(1, 2), new ArmorPieceButton(getPiece("leather"))); + buttons.put(getSlot(1, 3), new ArmorPieceButton(getPiece("chainmail"))); + buttons.put(getSlot(1, 4), new ArmorPieceButton(getPiece("iron"))); + buttons.put(getSlot(1, 5), new ArmorPieceButton(getPiece("gold"))); + buttons.put(getSlot(1, 6), new ArmorPieceButton(getPiece("diamond"))); + } else if (armorPiece == ArmorPiece.BOOTS) { + buttons.put(getSlot(1, 2), new ArmorPieceButton(getPiece("leather"))); + buttons.put(getSlot(1, 3), new ArmorPieceButton(getPiece("chainmail"))); + buttons.put(getSlot(1, 4), new ArmorPieceButton(getPiece("iron"))); + buttons.put(getSlot(1, 5), new ArmorPieceButton(getPiece("gold"))); + buttons.put(getSlot(1, 6), new ArmorPieceButton(getPiece("diamond"))); + } + + return buttons; + } + + @RequiredArgsConstructor + public class ArmorPieceButton extends Button { + + private final ItemStack item; + + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder itemBuilder = new ItemBuilder(item.getType()); + + itemBuilder.addLore( + "", + "&7Click to select this " + armorPiece.name().toLowerCase() + ); + + return itemBuilder.toItemStack(); + } + + @Override + public void onClick(Player player) { + if (armorPiece == ArmorPiece.HELMET) { + npc.setHelmet(item); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + npc.setChestplate(item); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + npc.setLeggings(item); + } else if (armorPiece == ArmorPiece.BOOTS) { + npc.setBoots(item); + } + + new NPCEditArmorMenu(plugin, npc).open(player); + } + } + + public ItemStack getPiece(String type) { + + if (type.equalsIgnoreCase("leather")) { + if (armorPiece == ArmorPiece.HELMET){ + return new ItemStack(Material.LEATHER_HELMET); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + return new ItemStack(Material.LEATHER_CHESTPLATE); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + return new ItemStack(Material.LEATHER_LEGGINGS); + } else if (armorPiece == ArmorPiece.BOOTS) { + return new ItemStack(Material.LEATHER_BOOTS); + } + }else if (type.equalsIgnoreCase("chainmail")) { + if (armorPiece == ArmorPiece.HELMET) { + return new ItemStack(Material.CHAINMAIL_HELMET); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + return new ItemStack(Material.CHAINMAIL_CHESTPLATE); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + return new ItemStack(Material.CHAINMAIL_LEGGINGS); + } else if (armorPiece == ArmorPiece.BOOTS) { + return new ItemStack(Material.CHAINMAIL_BOOTS); + } + } else if (type.equalsIgnoreCase("iron")) { + if (armorPiece == ArmorPiece.HELMET) { + return new ItemStack(Material.IRON_HELMET); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + return new ItemStack(Material.IRON_CHESTPLATE); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + return new ItemStack(Material.IRON_LEGGINGS); + } else if (armorPiece == ArmorPiece.BOOTS) { + return new ItemStack(Material.IRON_BOOTS); + } + } else if (type.equalsIgnoreCase("gold")) { + if (armorPiece == ArmorPiece.HELMET) { + return new ItemStack(Material.GOLD_HELMET); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + return new ItemStack(Material.GOLD_CHESTPLATE); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + return new ItemStack(Material.GOLD_LEGGINGS); + } else if (armorPiece == ArmorPiece.BOOTS) { + return new ItemStack(Material.GOLD_BOOTS); + } + } else if (type.equalsIgnoreCase("diamond")) { + if (armorPiece == ArmorPiece.HELMET) { + return new ItemStack(Material.DIAMOND_HELMET); + } else if (armorPiece == ArmorPiece.CHESTPLATE) { + return new ItemStack(Material.DIAMOND_CHESTPLATE); + } else if (armorPiece == ArmorPiece.LEGGINGS) { + return new ItemStack(Material.DIAMOND_LEGGINGS); + } else if (armorPiece == ArmorPiece.BOOTS) { + return new ItemStack(Material.DIAMOND_BOOTS); + } + } + + return null; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSkinMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSkinMenu.java new file mode 100644 index 0000000..40ed86b --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSkinMenu.java @@ -0,0 +1,129 @@ +package rip.battle.entity.npc.menu; + +import cc.stormworth.core.util.chat.ChatUtils; +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.Menu; +import cc.stormworth.core.util.menu.button.Button; +import cc.stormworth.core.util.menu.button.impl.PlaceholderButton; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.npc.api.NPC; +import rip.battle.entity.npc.prompt.NPCChangeSkinPrompt; + +import java.util.Map; + +@RequiredArgsConstructor +public class NPCSkinMenu extends Menu { + + private final NPC npc; + private final EntityPlugin plugin; + + @Override + public String getTitle(Player player) { + return "&eEditing skin for NPC &6" + npc.getName(); + } + + @Override + public int getRows(Player player) { + return 3; + } + + @Override + public Map getButtons(Player player) { + + Map buttons = Maps.newHashMap(); + + buttons.put(0, new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + return new ItemBuilder(Material.BED).setName("&cBack").toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCEditMenu(npc, plugin).open(player); + } + }); + + buttons.put(getSlot(1, 2), new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(Material.PAPER); + + builder.setName("&6Set custom skin"); + + builder.addLore( + "", + "&7Click to set custom skin with a username" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + ChatUtils.beginPrompt(player, new NPCChangeSkinPrompt(plugin, npc), plugin); + } + }); + + buttons.put(getSlot(1, 4), new PlaceholderButton(new ItemBuilder(Material.SKULL_ITEM) + .setName("&6Current Skin") + .setDurability((short) 3) + .setTexture(npc.getSkin() == null ? null : npc.getSkin().getValue()) + .toItemStack())); + + buttons.put(getSlot(1, 6), new Button() { + @Override + public ItemStack getDisplayItem(Player player) { + + ItemBuilder builder = new ItemBuilder(Material.BOOK); + + builder.setName("&eSet skin of current online players"); + + builder.addLore( + "", + "&7Click to open menu and select a player", + "&7to set the skin of the NPC" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + new NPCSkinOnlinePlayersMenu(npc, plugin).open(player); + } + }); + + buttons.put(getSlot(2, 4), new Button() { + + @Override + public ItemStack getDisplayItem(Player player) { + ItemBuilder builder = new ItemBuilder(Material.BARRIER); + + builder.setName("&cRemove skin"); + + builder.addLore( + "", + "&7Click to remove the skin" + ); + + return builder.toItemStack(); + } + + @Override + public void onClick(Player player) { + npc.setSkin(null); + player.playSound(player.getLocation(), Sound.CLICK, 1, 1); + } + }); + return buttons; + } +} diff --git a/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSkinOnlinePlayersMenu.java b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSkinOnlinePlayersMenu.java new file mode 100644 index 0000000..d2c62cb --- /dev/null +++ b/BattleEntity-main/src/main/java/rip/battle/entity/npc/menu/NPCSkinOnlinePlayersMenu.java @@ -0,0 +1,115 @@ +package rip.battle.entity.npc.menu; + +import cc.stormworth.core.util.chat.CC; +import cc.stormworth.core.util.inventory.ItemBuilder; +import cc.stormworth.core.util.menu.button.Button; +import cc.stormworth.core.util.menu.paginated.CenteredPaginatedMenu; +import cc.stormworth.core.util.skin.SkinTexture; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import rip.battle.entity.EntityPlugin; +import rip.battle.entity.npc.api.NPC; + +import java.util.List; +import java.util.Map; + +@RequiredArgsConstructor +public class NPCSkinOnlinePlayersMenu extends CenteredPaginatedMenu { + + private final NPC npc; + private final EntityPlugin plugin; + + @Override + public String getTitle(Player player) { + return "&eEditing skin for NPC &6" + npc.getName(); + } + + @Override + public int getRows(Player player) { + return 3; + } + + @Override + public int getStartSlot(Player player) { + return 9; + } + + @Override + public int getPreviousPageSlot(Player player) { + return 3; + } + + @Override + public int getNextPageSlot(Player player) { + return 5; + } + + @Override + public List