master
loganb1max 2019-06-23 19:27:49 +07:00
parent 2bb4d3b57f
commit c051cf2714
24 changed files with 703 additions and 338 deletions

@ -18,12 +18,17 @@ repositories {
mavenLocal()
maven { url 'https://hub.spigotmc.org/nexus/content/groups/public/' }
maven { url 'https://oss.sonatype.org/content/groups/public/' }
maven { url 'https://jitpack.io' }
}
dependencies {
compileOnly(files('libs/paper-server-1.8.8-R0.1.jar'))
compile('org.projectlombok:lombok:1.16.20')
annotationProcessor ('org.projectlombok:lombok:1.16.20')
compileOnly ('com.github.MilkBowl:VaultAPI:1.7') {
exclude group: 'org.bukkit'
exclude group: 'org.spigot'
}
}
clean {
@ -31,6 +36,6 @@ clean {
}
jar {
archiveName('Minions.jar')
archiveName('MinionsPlus.jar')
destinationDir(file('target'))
}

@ -1,2 +1,2 @@
rootProject.name = 'minions'
rootProject.name = 'minionsplus'

@ -1,28 +0,0 @@
package me.loganb1max.minions;
import lombok.Getter;
import me.loganb1max.minions.command.MinionCommand;
import me.loganb1max.minions.manager.MinionManager;
import org.bukkit.plugin.java.JavaPlugin;
public class MinionsPlugin extends JavaPlugin {
@Getter private static MinionsPlugin instance;
@Getter private MinionManager minionManager;
private MinionCommand minionCommand;
@Override
public void onEnable() {
saveDefaultConfig();
this.minionManager = new MinionManager(this);
this.minionCommand = new MinionCommand();
getCommand("minions").setExecutor(minionCommand);
getCommand("minions").setTabCompleter(minionCommand);
}
@Override
public void onDisable() {
this.minionManager.close();
}
}

@ -1,97 +0,0 @@
package me.loganb1max.minions.menu;
import me.loganb1max.minions.MinionsPlugin;
import me.loganb1max.minions.model.Minion;
import me.loganb1max.minions.util.ItemBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
public class MinionMenu implements Listener {
private final Minion minion;
private final Player player;
private final Inventory inventory;
private final Map<Integer, Consumer<ClickType>> clickHandlerMap = new HashMap<>();
public MinionMenu(final Minion minion, final Player player) {
this.minion = minion;
this.player = player;
Bukkit.getPluginManager().registerEvents(this, MinionsPlugin.getInstance());
this.inventory = Bukkit.createInventory(this.player, 9, "Minion Menu");
bindItem(
minion.getIcon(),
1,
clickType -> { }
);
bindItem(
ItemBuilder.of(Material.GOLD_INGOT)
.name("&6Upgrade")
.lore("&7click to upgrade this minion.")
.build(),
3,
clickType -> {
}
);
bindItem(
ItemBuilder.of(Material.COAL)
.name("&6Deposit Energy")
.lore("")
.build(),
5,
clickType -> {
}
);
bindItem(
ItemBuilder.of(Material.CHEST)
.name("&6Link Chest")
.lore("&7click to link a deposit chest.")
.build(),
7,
clickType -> {
}
);
this.player.openInventory(this.inventory);
}
private void bindItem(final ItemStack item, final int slot, final Consumer<ClickType> consumer) {
this.inventory.setItem(slot, item);
this.clickHandlerMap.remove(slot);
this.clickHandlerMap.put(slot, consumer);
this.player.updateInventory();
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onClose(final InventoryCloseEvent e) {
if (!e.getInventory().equals(this.inventory)) return;
HandlerList.unregisterAll(this);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onClick(final InventoryClickEvent e) {
if (!e.getClickedInventory().equals(this.inventory)) return;
e.setCancelled(true);
this.clickHandlerMap.get(e.getSlot()).accept(e.getClick());
}
}

@ -1,39 +0,0 @@
package me.loganb1max.minions.model.minions;
import me.loganb1max.minions.MinionsPlugin;
import me.loganb1max.minions.model.Minion;
import org.bukkit.Location;
import org.bukkit.block.Block;
import java.util.Set;
import java.util.UUID;
public class FarmerMinion extends Minion {
public FarmerMinion(final UUID owner, final String ownerName) {
super(
MinionsPlugin.getInstance().getConfig().getConfigurationSection("Farmer"),
owner,
ownerName
);
getReplacer().add("%radius%", String.valueOf(getRadius(getLevel())));
}
public FarmerMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
this(owner, ownerName);
setLocation(location);
setEnergy(energy);
setLevel(level);
setLinkedBlocks(linkedBlocks);
findStand();
}
public int getRadius(final int level) {
return getSection().getInt("Levels." + level + ".Radius", 1);
}
@Override
public void tick() {
}
}

@ -1,43 +0,0 @@
package me.loganb1max.minions.model.minions;
import me.loganb1max.minions.MinionsPlugin;
import me.loganb1max.minions.model.Minion;
import org.bukkit.Location;
import org.bukkit.block.Block;
import java.util.Set;
import java.util.UUID;
public class FisherMinion extends Minion {
public FisherMinion(final UUID owner, final String ownerName) {
super(
MinionsPlugin.getInstance().getConfig().getConfigurationSection("Fisher"),
owner,
ownerName
);
getReplacer().add("%radius%", String.valueOf(getRadius(getLevel()))).add("%chanceperblockpersecond%", String.valueOf(getChancePerBlockPerSecond(getLevel())));
}
public FisherMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
this(owner, ownerName);
setLocation(location);
setEnergy(energy);
setLevel(level);
setLinkedBlocks(linkedBlocks);
findStand();
}
public double getChancePerBlockPerSecond(final int level) {
return getSection().getDouble("Levels." + level + ".ChancePerBlockPerSecond", 0.0);
}
public int getRadius(final int level) {
return getSection().getInt("Levels." + level + ".Radius", 1);
}
@Override
public void tick() {
}
}

@ -1,39 +0,0 @@
package me.loganb1max.minions.model.minions;
import me.loganb1max.minions.MinionsPlugin;
import me.loganb1max.minions.model.Minion;
import org.bukkit.Location;
import org.bukkit.block.Block;
import java.util.Set;
import java.util.UUID;
public class MinerMinion extends Minion {
public MinerMinion(final UUID owner, final String ownerName) {
super(
MinionsPlugin.getInstance().getConfig().getConfigurationSection("Miner"),
owner,
ownerName
);
getReplacer().add("%blocklimit%", String.valueOf(getBlockLimit(getLevel())));
}
public MinerMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
this(owner, ownerName);
setLocation(location);
setEnergy(energy);
setLevel(level);
setLinkedBlocks(linkedBlocks);
findStand();
}
public int getBlockLimit(final int level) {
return getSection().getInt("Levels." + level + ".BlockLimit", 1);
}
@Override
public void tick() {
}
}

@ -0,0 +1,61 @@
package me.loganb1max.minionsplus;
import lombok.Getter;
import me.loganb1max.minionsplus.command.MinionCommand;
import me.loganb1max.minionsplus.manager.LinkingManager;
import me.loganb1max.minionsplus.manager.MinionManager;
import me.loganb1max.minionsplus.model.Fuel;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Set;
import java.util.stream.Collectors;
public class MinionsPlus extends JavaPlugin {
@Getter private static MinionsPlus instance;
@Getter private static Economy econ;
@Getter private MinionManager minionManager;
@Getter private LinkingManager linkingManager;
private MinionCommand minionCommand;
@Override
public void onEnable() {
instance = this;
saveDefaultConfig();
setupEconomy();
this.minionManager = new MinionManager(this);
this.linkingManager = new LinkingManager(this);
this.minionCommand = new MinionCommand();
getCommand("minions").setExecutor(minionCommand);
getCommand("minions").setTabCompleter(minionCommand);
}
@Override
public void onDisable() {
this.minionManager.close();
this.linkingManager.close();
}
private boolean setupEconomy() {
if (getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
}
RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
econ = rsp.getProvider();
return econ != null;
}
public Set<Fuel> getFuels() {
return getConfig()
.getConfigurationSection("Fuel")
.getKeys(false)
.stream()
.map(s -> Fuel.fromConfigSection(getConfig().getConfigurationSection("Fuel." + s)))
.collect(Collectors.toSet());
}
}

@ -1,12 +1,13 @@
package me.loganb1max.minions.command;
package me.loganb1max.minionsplus.command;
import com.google.common.collect.ImmutableList;
import me.loganb1max.minions.model.Minion;
import me.loganb1max.minions.model.minions.FarmerMinion;
import me.loganb1max.minions.model.minions.FisherMinion;
import me.loganb1max.minions.model.minions.MinerMinion;
import me.loganb1max.minions.util.ItemUtil;
import me.loganb1max.minions.util.Text;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.model.minions.FarmerMinion;
import me.loganb1max.minionsplus.model.minions.FisherMinion;
import me.loganb1max.minionsplus.model.minions.MinerMinion;
import me.loganb1max.minionsplus.util.ItemUtil;
import me.loganb1max.minionsplus.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -34,7 +35,8 @@ public class MinionCommand implements CommandExecutor, TabCompleter {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("reload")) {
MinionsPlus.getInstance().reloadConfig();
sender.sendMessage(Text.color("&aSuccessfully reloaded config."));
} else {
sendHelp(sender);
}
@ -57,13 +59,13 @@ public class MinionCommand implements CommandExecutor, TabCompleter {
final String type = args[2].toLowerCase();
switch (type) {
case "miner":
minion = new MinerMinion(target);
minion = new MinerMinion(target.getUniqueId(), target.getName());
break;
case "farmer":
minion = new FarmerMinion(target);
minion = new FarmerMinion(target.getUniqueId(), target.getName());
break;
case "fisher":
minion = new FisherMinion(target);
minion = new FisherMinion(target.getUniqueId(), target.getName());
break;
}
@ -85,16 +87,16 @@ public class MinionCommand implements CommandExecutor, TabCompleter {
public List<String> onTabComplete(CommandSender commandSender, Command command, String label, String[] args) {
List<String> toReturn = new ArrayList<>();
switch (args.length) {
case 0:
case 1:
toReturn = ImmutableList.of(
"give",
"reload"
);
break;
case 1:
case 2:
toReturn = Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
break;
case 2:
case 3:
toReturn = ImmutableList.of(
"miner",
"farmer",

@ -0,0 +1,72 @@
package me.loganb1max.minionsplus.manager;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.scheduler.BukkitTask;
import java.util.HashMap;
import java.util.Map;
public class LinkingManager implements Listener {
private final MinionsPlus plugin;
private final BukkitTask timerTask;
private Map<Player, Minion> linkingMap = new HashMap<>();
private Map<Player, Integer> timeMap = new HashMap<>();
public LinkingManager(final MinionsPlus plugin) {
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, this.plugin);
this.timerTask = Bukkit.getScheduler().runTaskTimer(this.plugin, () -> {
for (Map.Entry<Player, Integer> entry : timeMap.entrySet()) {
if (entry.getValue() > 0) entry.setValue(entry.getValue() - 1);
else endLinking(entry.getKey());
}
}, 20, 20);
}
public void close() {
HandlerList.unregisterAll(this);
this.timerTask.cancel();
}
public void beginLinking(final Player player, final Minion minion) {
this.linkingMap.put(player, minion);
this.timeMap.put(player, 15);
player.sendMessage(Text.color("&aYou have begun linking new blocks for " + minion.getName() + ". (15 Seconds)"));
}
private void endLinking(final Player player) {
this.linkingMap.remove(player);
this.timeMap.remove(player);
player.sendMessage(Text.color("&cYou are no longer linking blocks."));
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onLink(final PlayerInteractEvent e) {
if (!this.linkingMap.containsKey(e.getPlayer())) return;
if (!e.hasBlock()) {
e.getPlayer().sendMessage(Text.color("&cYou must click on a block."));
return;
}
final Minion minion = this.linkingMap.get(e.getPlayer());
final Block block = e.getClickedBlock();
if (minion.getLinkedBlocks().contains(block)) {
minion.getLinkedBlocks().remove(block);
e.getPlayer().sendMessage(Text.color("&aSuccessfully unlinked block."));
} else {
minion.getLinkedBlocks().add(block);
e.getPlayer().sendMessage(Text.color("&aSuccessfully linked block."));
}
e.setCancelled(true);
}
}

@ -1,12 +1,15 @@
package me.loganb1max.minions.manager;
package me.loganb1max.minionsplus.manager;
import com.google.gson.*;
import lombok.Getter;
import me.loganb1max.minions.MinionsPlugin;
import me.loganb1max.minions.menu.MinionMenu;
import me.loganb1max.minions.model.Minion;
import me.loganb1max.minions.util.Text;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.menu.MinionMenu;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.model.minions.MinerMinion;
import me.loganb1max.minionsplus.util.ItemUtil;
import me.loganb1max.minionsplus.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.ArmorStand;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -14,6 +17,7 @@ import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.scheduler.BukkitTask;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -27,15 +31,15 @@ import java.util.Set;
public class MinionManager implements Listener {
private final MinionsPlugin plugin;
private final MinionsPlus plugin;
private final BukkitTask animationTask;
private final BukkitTask tickTask;
@Getter private Set<Minion> minions = new HashSet<>();
public MinionManager(final MinionsPlugin plugin) {
public MinionManager(final MinionsPlus plugin) {
this.plugin = plugin;
this.animationTask = Bukkit.getScheduler().runTaskTimer(this.plugin, () -> this.minions.forEach(Minion::animationTick), 10, 10);
this.animationTask = Bukkit.getScheduler().runTaskTimer(this.plugin, () -> this.minions.forEach(Minion::animationTick), 1, 1);
this.tickTask = Bukkit.getScheduler().runTaskTimer(this.plugin, () -> this.minions.forEach(Minion::tick), 20, 20);
Bukkit.getPluginManager().registerEvents(this, this.plugin);
loadMinions();
@ -50,6 +54,7 @@ public class MinionManager implements Listener {
private void loadMinions() {
final File dataFile = new File(this.plugin.getDataFolder(), "minions.json");
if (!dataFile.exists()) return;
final Gson gson = new Gson();
try (final BufferedReader reader = Files.newBufferedReader(dataFile.toPath(), StandardCharsets.UTF_8)) {
JsonObject data = gson.fromJson(reader, JsonObject.class);
@ -60,6 +65,7 @@ public class MinionManager implements Listener {
this.minions.add(minion);
} catch (Exception e) {
this.plugin.getLogger().severe("Failed to load minion.");
e.printStackTrace();
}
}
} catch (IOException e) {
@ -114,4 +120,18 @@ public class MinionManager implements Listener {
});
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlace(PlayerInteractEvent e) {
if (!e.hasItem() || !Minion.isMinion(e.getItem())) return;
e.setCancelled(true);
if (!e.hasBlock()) return;
final Location loc = e.getClickedBlock().getRelative(e.getBlockFace()).getLocation().add(0.5, 0, 0.5);
final Minion minion = Minion.of(e.getItem(), loc);
minion.spawn(loc);
if (minion instanceof MinerMinion) {
this.plugin.getLinkingManager().beginLinking(e.getPlayer(), minion);
}
ItemUtil.consumeItem(e.getPlayer().getInventory(), 1, e.getItem());
}
}

@ -0,0 +1,131 @@
package me.loganb1max.minionsplus.menu;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Fuel;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.util.ItemBuilder;
import me.loganb1max.minionsplus.util.Text;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class MinionMenu implements Listener {
private final Minion minion;
private final Player player;
private final Inventory inventory;
private final Map<Integer, Consumer<ClickType>> clickHandlerMap = new HashMap<>();
public MinionMenu(final Minion minion, final Player player) {
this.minion = minion;
this.player = player;
Bukkit.getPluginManager().registerEvents(this, MinionsPlus.getInstance());
this.inventory = Bukkit.createInventory(this.player, 9, "Minion Menu");
rebind();
this.player.openInventory(this.inventory);
}
public void rebind() {
bindItem(
minion.getIcon(),
1,
clickType -> { }
);
bindItem(
ItemBuilder.of(Material.GOLD_INGOT)
.name("&6Upgrade")
.lore("&7Click to upgrade this minion.")
.lore("")
.lore(this.minion.isMaxLevel() ? "&aMax Level" : "&7Price: &f$" + this.minion.getPrice(minion.getLevel() + 1))
.build(),
3,
clickType -> {
if (this.minion.isMaxLevel()) {
this.player.sendMessage(Text.color("&cThis minion is already max level."));
return;
}
if (!MinionsPlus.getEcon().withdrawPlayer(this.player, this.minion.getPrice(this.minion.getLevel() + 1)).transactionSuccess()) {
this.player.sendMessage(Text.color("&cYou can not afford this upgrade!"));
return;
}
this.minion.levelUp();
this.player.sendMessage(Text.color("&aYou have successfully upgraded this minion."));
rebind();
}
);
bindItem(
ItemBuilder.of(Material.COAL)
.name("&6Deposit Energy")
.lore(MinionsPlus.getInstance().getFuels().stream().map(Fuel::getDisplayString).collect(Collectors.toList()))
.build(),
5,
clickType -> {
double totalGained = 0.0;
Set<Fuel> fuels = MinionsPlus.getInstance().getFuels();
for (int i = 0; i < this.player.getInventory().getSize(); i++) {
final ItemStack item = this.player.getInventory().getItem(i);
if (item == null || item.getType() == Material.AIR) continue;
for (Fuel fuel : fuels) {
if (!fuel.isEqual(item)) continue;
this.minion.gainEnergy(item.getAmount() * fuel.getEnergy());
totalGained += item.getAmount() * fuel.getEnergy();
this.player.getInventory().setItem(i, new ItemStack(Material.AIR));
}
}
this.player.sendMessage(Text.color("&aYou successfully refueled this minion. Added " + totalGained + " energy."));
rebind();
}
);
bindItem(
ItemBuilder.of(Material.CHEST)
.name("&6Link Chest")
.lore("&7Click to link a deposit chest.")
.build(),
7,
clickType -> {
MinionsPlus.getInstance().getLinkingManager().beginLinking(this.player, this.minion);
this.player.closeInventory();
}
);
}
private void bindItem(final ItemStack item, final int slot, final Consumer<ClickType> consumer) {
this.inventory.setItem(slot, item);
this.clickHandlerMap.remove(slot);
this.clickHandlerMap.put(slot, consumer);
this.player.updateInventory();
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onClose(final InventoryCloseEvent e) {
if (!e.getInventory().equals(this.inventory)) return;
HandlerList.unregisterAll(this);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onClick(final InventoryClickEvent e) {
if (e.getSlotType() == InventoryType.SlotType.OUTSIDE) return;
if (!e.getClickedInventory().equals(this.inventory)) return;
e.setCancelled(true);
this.clickHandlerMap.get(e.getSlot()).accept(e.getClick());
}
}

@ -1,21 +1,26 @@
package me.loganb1max.minions.model;
package me.loganb1max.minionsplus.model;
import lombok.AllArgsConstructor;
import me.loganb1max.minions.util.ItemUtil;
import lombok.Getter;
import me.loganb1max.minionsplus.util.ItemUtil;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
@AllArgsConstructor
public class Fuel {
private final String name;
@Getter private final String name;
private final ItemStack itemStack;
private final double energy;
@Getter private final double energy;
public boolean isEqual(final ItemStack item) {
return ItemUtil.compareType(this.itemStack, item);
}
public String getDisplayString() {
return "&7" + this.name + ": &f" + this.energy;
}
public static Fuel fromConfigSection(final ConfigurationSection section) {
final String name = section.getName();
final double energy = section.getDouble("Energy");

@ -1,17 +1,16 @@
package me.loganb1max.minions.model;
package me.loganb1max.minionsplus.model;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import me.loganb1max.minions.MinionsPlugin;
import me.loganb1max.minions.model.minions.FarmerMinion;
import me.loganb1max.minions.model.minions.FisherMinion;
import me.loganb1max.minions.model.minions.MinerMinion;
import me.loganb1max.minions.util.*;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.minions.FarmerMinion;
import me.loganb1max.minionsplus.model.minions.FisherMinion;
import me.loganb1max.minionsplus.model.minions.MinerMinion;
import me.loganb1max.minionsplus.util.*;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -22,20 +21,17 @@ import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Getter
public abstract class Minion {
private final ConfigurationSection section;
private final Replacer replacer;
private final UUID owner;
private final String ownerName;
@Setter(AccessLevel.PROTECTED) private Location location;
@Setter(AccessLevel.PROTECTED) private double energy;
@Setter(AccessLevel.PROTECTED) private int level;
@Setter(AccessLevel.PROTECTED)private Set<Block> linkedBlocks;
@Setter(AccessLevel.PROTECTED) private double energy = 0.0;
@Setter(AccessLevel.PROTECTED) private int level = 1;
@Setter(AccessLevel.PROTECTED)private Set<Block> linkedBlocks = new HashSet<>();
private ArmorStand stand;
@Getter(AccessLevel.NONE)
@ -45,10 +41,6 @@ public abstract class Minion {
this.section = section;
this.owner = owner;
this.ownerName = ownerName;
this.replacer = Replacer.create()
.add("%level%", String.valueOf(getLevel()))
.add("%energy%", String.valueOf(getEnergy()))
.add("%owner%", getOwnerName());
}
protected void findStand() {
@ -70,8 +62,9 @@ public abstract class Minion {
this.stand.setMarker(false);
this.stand.setCustomName(Text.color(getName()));
this.stand.setCustomNameVisible(true);
this.stand.setRightArmPose(this.stand.getRightLegPose().setX(6));
this.equipEquipment(this.stand);
MinionsPlugin.getInstance().getMinionManager().getMinions().add(this);
MinionsPlus.getInstance().getMinionManager().getMinions().add(this);
} else {
this.stand.teleport(location);
}
@ -84,13 +77,13 @@ public abstract class Minion {
this.stand = null;
this.linkedBlocks.clear();
player.getInventory().addItem(this.toItemStack()).forEach((integer, itemStack) -> player.getWorld().dropItemNaturally(player.getLocation(), itemStack));
MinionsPlugin.getInstance().getMinionManager().getMinions().remove(this);
MinionsPlus.getInstance().getMinionManager().getMinions().remove(this);
}
public void animationTick() {
if (this.stand == null) return;
if (this.stand.getRightArmPose().getX() > 300) offset = -0.1;
if (this.stand.getRightArmPose().getX() < 230) offset = 0.1;
if (this.stand.getRightArmPose().getX() < 5) offset = 0.1;
if (this.stand.getRightArmPose().getX() > 6) offset = -0.1;
this.stand.setRightArmPose(this.stand.getRightArmPose().add(offset, 0, 0));
this.stand.setFireTicks(0);
}
@ -119,6 +112,7 @@ public abstract class Minion {
public ItemStack toItemStack() {
ItemStack item = getIcon();
item = ItemUtil.setKeyString(item, "minion-type", getType());
item = ItemUtil.setKeyString(item, "minion-owner", this.owner.toString());
item = ItemUtil.setKeyString(item, "minion-owner-name", this.ownerName);
item = ItemUtil.setKeyInt(item, "minion-level", this.level);
@ -132,19 +126,22 @@ public abstract class Minion {
final String skull = this.section.getString("Item.Skull", null);
final String displayName = this.section.getString("Item.DisplayName");
final List<String> lore = this.section.getStringList("Item.Lore");
ItemStack item = ItemBuilder.of(material)
ItemStack item = null;
if (material == Material.SKULL_ITEM) {
item = SkullCreator.itemFromBase64(skull);
} else {
item = new ItemStack(material);
}
item = ItemBuilder.of(item)
.durability((short) durability)
.name(displayName)
.lore(this.replacer.replace(lore))
.lore(getReplacer().replace(lore))
.build();
if (material == Material.SKULL_ITEM && skull != null) {
item = SkullCreator.itemWithBase64(item, skull);
}
return item;
}
public Set<Block> getLinkedBlocks() {
return ImmutableSet.copyOf(this.linkedBlocks);
return item;
}
public UUID getId() {
@ -168,6 +165,18 @@ public abstract class Minion {
return this.section.getDouble("Levels." + level + ".Price", 0.0);
}
public int getMaxLevel() {
return this.section.getConfigurationSection("Levels").getKeys(false).size();
}
public boolean isMaxLevel() {
return getLevel() == getMaxLevel();
}
public void levelUp() {
this.level++;
}
public JsonElement serialize() {
final Gson gson = new Gson();
final JsonObject object = new JsonObject();
@ -195,7 +204,7 @@ public abstract class Minion {
return object;
}
public static Minion deserialize(final MinionsPlugin plugin, final JsonElement element) {
public static Minion deserialize(final MinionsPlus plugin, final JsonElement element) {
final JsonObject data = element.getAsJsonObject();
final String type = data.get("type").getAsString();
final UUID owner = UUID.fromString(data.get("owner").getAsString());
@ -204,9 +213,16 @@ public abstract class Minion {
final Location location = new Location(Bukkit.getWorld(locData.get("world").getAsString()), locData.get("x").getAsDouble(), locData.get("y").getAsDouble(), locData.get("z").getAsDouble());
final double energy = data.get("energy").getAsDouble();
final int level = data.get("level").getAsInt();
final Set<Block> linkedBlocks = Stream.of(data.get("linkedBlocks").getAsJsonArray())
.map(JsonElement::getAsJsonObject)
.map(jsonObject -> Bukkit.getWorld(jsonObject.get("world").getAsString()).getBlockAt(jsonObject.get("x").getAsInt(), jsonObject.get("y").getAsInt(), jsonObject.get("z").getAsInt())).collect(Collectors.toSet());
final Set<Block> linkedBlocks = new HashSet<>();
for (JsonElement el : data.get("linkedBlocks").getAsJsonArray()) {
JsonObject o = el.getAsJsonObject();
final Block b = Bukkit.getWorld(o.get("world").getAsString()).getBlockAt(
o.get("x").getAsInt(),
o.get("y").getAsInt(),
o.get("z").getAsInt()
);
linkedBlocks.add(b);
}
Minion toReturn = null;
switch (type) {
case "Miner":
@ -222,6 +238,35 @@ public abstract class Minion {
return toReturn;
}
public static boolean isMinion(final ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) return false;
return ItemUtil.hasKey(itemStack, "minion-type");
}
public static Minion of(final ItemStack itemStack, final Location location) {
if (!isMinion(itemStack)) return null;
final String type = ItemUtil.getKeyString(itemStack, "minion-type");
final UUID owner = UUID.fromString(ItemUtil.getKeyString(itemStack, "minion-owner"));
final String ownerName = ItemUtil.getKeyString(itemStack, "minion-owner-name");
final int level = ItemUtil.getKeyInt(itemStack, "minion-level");
final double energy = ItemUtil.getKeyDouble(itemStack, "minion-energy");
Minion toReturn = null;
switch (type) {
case "Miner":
toReturn = new MinerMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
case "Farmer":
toReturn = new FarmerMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
case "Fisher":
toReturn = new FisherMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
}
return toReturn;
}
public abstract void tick();
public abstract Replacer getReplacer();
}

@ -0,0 +1,104 @@
package me.loganb1max.minionsplus.model.minions;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.util.ItemBuilder;
import me.loganb1max.minionsplus.util.Replacer;
import org.bukkit.CropState;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Crops;
import java.util.*;
public class FarmerMinion extends Minion {
public FarmerMinion(final UUID owner, final String ownerName) {
super(
MinionsPlus.getInstance().getConfig().getConfigurationSection("Farmer"),
owner,
ownerName
);
}
public FarmerMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
this(owner, ownerName);
setLocation(location);
setEnergy(energy);
setLevel(level);
setLinkedBlocks(linkedBlocks);
findStand();
}
public int getRadius(final int level) {
return getSection().getInt("Levels." + level + ".Radius", 1);
}
@Override
public void tick() {
if (getEnergy() < getEnergyPerUse(getLevel())) return;
final int radius = getRadius(getLevel());
for (int y = getLocation().getBlockY() + radius; y > getLocation().getBlockY() - radius; y--) {
for (int x = getLocation().getBlockX() - radius; x < getLocation().getBlockX() + radius; x++) {
for (int z = getLocation().getBlockZ() - radius; z < getLocation().getBlockZ() + radius; z++) {
final Block block = getLocation().getWorld().getBlockAt(x, y, z);
final List<ItemStack> drops = new ArrayList<>();
if (block.getType() == Material.POTATO || block.getType() == Material.CARROT || block.getType() == Material.CROPS) {
if (block.getData() != 7) continue;
drops.add(ItemBuilder.of(
block.getType() == Material.CARROT ? Material.CARROT_ITEM
: block.getType() == Material.POTATO ? Material.POTATO_ITEM : Material.WHEAT
).build());
block.setData((byte)0);
}
if (block.getType() == Material.CACTUS || block.getType() == Material.SUGAR_CANE_BLOCK) {
int height = 1;
final Material type = block.getType();
Block rel = block;
while (rel.getRelative(BlockFace.DOWN).getType() == block.getType()) {
height++;
rel.setType(Material.AIR);
rel = rel.getRelative(BlockFace.DOWN);
}
if (height > 1) {
drops.add(ItemBuilder.of(type).amount(height - 1).build());
}
}
if (block.getType() == Material.MELON_BLOCK) {
drops.addAll(block.getDrops());
block.setType(Material.AIR);
}
if (block.getType() == Material.PUMPKIN) {
drops.addAll(block.getDrops());
block.setType(Material.AIR);
}
getLinkedBlocks().stream().filter(b -> b.getState() instanceof InventoryHolder).forEachOrdered(b -> {
InventoryHolder inv = (InventoryHolder) b.getState();
final Collection<ItemStack> remaining = inv.getInventory().addItem(drops.toArray(new ItemStack[] {})).values();
drops.clear();
drops.addAll(remaining);
});
if (!drops.isEmpty()) {
drops.forEach(item -> getLocation().getWorld().dropItemNaturally(getLocation(), item));
}
}
}
}
}
@Override
public Replacer getReplacer() {
return Replacer.create()
.add("%level%", String.valueOf(getLevel()))
.add("%energy%", String.valueOf(getEnergy()))
.add("%owner%", getOwnerName())
.add("%radius%", String.valueOf(getRadius(getLevel())));
}
}

@ -0,0 +1,80 @@
package me.loganb1max.minionsplus.model.minions;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.util.ItemBuilder;
import me.loganb1max.minionsplus.util.Replacer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
public class FisherMinion extends Minion {
public FisherMinion(final UUID owner, final String ownerName) {
super(
MinionsPlus.getInstance().getConfig().getConfigurationSection("Fisher"),
owner,
ownerName
);
}
public FisherMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
this(owner, ownerName);
setLocation(location);
setEnergy(energy);
setLevel(level);
setLinkedBlocks(linkedBlocks);
findStand();
}
public double getChancePerBlockPerSecond(final int level) {
return getSection().getDouble("Levels." + level + ".ChancePerBlockPerSecond", 0.0);
}
public int getRadius(final int level) {
return getSection().getInt("Levels." + level + ".Radius", 1);
}
@Override
public void tick() {
if (getEnergy() < getEnergyPerUse(getLevel())) return;
final int radius = getRadius(getLevel());
final List<ItemStack> drops = new ArrayList<>();
for (int x = getLocation().getBlockX() - radius; x < getLocation().getBlockX() + radius; x++) {
for (int y = getLocation().getBlockY() - radius; y < getLocation().getBlockY() + radius; y++) {
for (int z = getLocation().getBlockZ() - radius; z < getLocation().getBlockZ() + radius; z++) {
final Block block = getLocation().getWorld().getBlockAt(x, y, z);
if (block.getType() != Material.WATER && block.getType() != Material.STATIONARY_WATER) continue;
if (ThreadLocalRandom.current().nextDouble(0.000000, 100.000000) > getChancePerBlockPerSecond(getLevel())) continue;
drops.add(ItemBuilder.of(Material.RAW_FISH).build());
}
}
}
getLinkedBlocks().stream().filter(b -> b.getState() instanceof InventoryHolder).forEachOrdered(b -> {
InventoryHolder inv = (InventoryHolder) b.getState();
final Collection<ItemStack> remaining = inv.getInventory().addItem(drops.toArray(new ItemStack[] {})).values();
drops.clear();
drops.addAll(remaining);
});
if (!drops.isEmpty()) {
drops.forEach(item -> getLocation().getWorld().dropItemNaturally(getLocation(), item));
}
consumeEnergy(getEnergyPerUse(getLevel()));
}
@Override
public Replacer getReplacer() {
return Replacer.create()
.add("%level%", String.valueOf(getLevel()))
.add("%energy%", String.valueOf(getEnergy()))
.add("%owner%", getOwnerName())
.add("%radius%", String.valueOf(getRadius(getLevel())))
.add("%chanceperblockpersecond%", String.valueOf(getChancePerBlockPerSecond(getLevel())));
}
}

@ -0,0 +1,76 @@
package me.loganb1max.minionsplus.model.minions;
import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.util.Replacer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.*;
public class MinerMinion extends Minion {
private static Set<Material> VALID_BLOCKS = new HashSet<>();
static {
VALID_BLOCKS.add(Material.STONE);
VALID_BLOCKS.add(Material.COBBLESTONE);
for (Material mat : Material.values()) {
if (!mat.name().toLowerCase().contains("ore")) continue;
VALID_BLOCKS.add(mat);
}
}
public MinerMinion(final UUID owner, final String ownerName) {
super(
MinionsPlus.getInstance().getConfig().getConfigurationSection("Miner"),
owner,
ownerName
);
}
public MinerMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
this(owner, ownerName);
setLocation(location);
setEnergy(energy);
setLevel(level);
setLinkedBlocks(linkedBlocks);
findStand();
}
public int getBlockLimit(final int level) {
return getSection().getInt("Levels." + level + ".BlockLimit", 1);
}
@Override
public void tick() {
if (getEnergy() < getEnergyPerUse(getLevel())) return;
getLinkedBlocks().stream().filter(block -> !(block.getState() instanceof InventoryHolder)).filter(block -> VALID_BLOCKS.contains(block.getType())).limit(getBlockLimit(getLevel())).forEachOrdered(block -> {
final Collection<ItemStack> drops = block.getDrops();
block.setType(Material.AIR);
getLinkedBlocks().stream().filter(b -> b.getState() instanceof InventoryHolder).forEachOrdered(b -> {
InventoryHolder inv = (InventoryHolder) b.getState();
final Collection<ItemStack> remaining = inv.getInventory().addItem(drops.toArray(new ItemStack[] {})).values();
drops.clear();
drops.addAll(remaining);
});
if (!drops.isEmpty()) {
drops.forEach(item -> getLocation().getWorld().dropItemNaturally(getLocation(), item));
}
});
consumeEnergy(getEnergyPerUse(getLevel()));
}
@Override
public Replacer getReplacer() {
return Replacer.create()
.add("%level%", String.valueOf(getLevel()))
.add("%energy%", String.valueOf(getEnergy()))
.add("%owner%", getOwnerName())
.add("%blocklimit%", String.valueOf(getBlockLimit(getLevel())));
}
}

@ -1,8 +1,10 @@
package me.loganb1max.minions.util;
package me.loganb1max.minionsplus.util;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -14,10 +16,18 @@ public class ItemBuilder {
this.itemStack = new ItemStack(material);
}
public ItemBuilder(final ItemStack itemStack) {
this.itemStack = itemStack;
}
public static ItemBuilder of(final Material material) {
return new ItemBuilder(material);
}
public static ItemBuilder of(final ItemStack itemStack) {
return new ItemBuilder(itemStack);
}
public ItemBuilder amount(final int amount) {
itemStack.setAmount(amount);
return this;
@ -37,7 +47,7 @@ public class ItemBuilder {
public ItemBuilder lore(final String lore) {
ItemMeta meta = itemStack.getItemMeta();
List<String> loreList = meta.getLore();
List<String> loreList = meta.hasLore() ? meta.getLore() : new ArrayList<>();
loreList.add(Text.color(lore));
meta.setLore(loreList);
itemStack.setItemMeta(meta);

@ -1,4 +1,4 @@
package me.loganb1max.minions.util;
package me.loganb1max.minionsplus.util;
import org.bukkit.Color;
import org.bukkit.Material;

@ -1,4 +1,4 @@
package me.loganb1max.minions.util;
package me.loganb1max.minionsplus.util;
import java.util.HashMap;
import java.util.List;

@ -1,4 +1,4 @@
package me.loganb1max.minions.util;
package me.loganb1max.minionsplus.util;
import org.bukkit.Bukkit;
import org.bukkit.Material;

@ -1,4 +1,4 @@
package me.loganb1max.minions.util;
package me.loganb1max.minionsplus.util;
import org.bukkit.ChatColor;

@ -105,15 +105,15 @@ Farmer:
RightHand:
Material: DIAMOND_HOE
Durability: 0
Levels:
'1':
Price: 0.0
EnergyPerAction: 0.5
Radius: 3
'2':
Price: 1000.0
EnergyPerAction: 0.3
Radius: 5
Levels:
'1':
Price: 0.0
EnergyPerAction: 0.5
Radius: 3
'2':
Price: 1000.0
EnergyPerAction: 0.3
Radius: 5
Fisher:
Name: "Fisher Minion"
@ -125,7 +125,7 @@ Fisher:
Lore:
- ""
- "&7Level: %level%"
- "&7Energy: %energy"
- "&7Energy: %energy%"
- "&7Owner: %owner%"
Equipment:
Skull: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjhjOTg2Nzk5YmFmZTcxODRhOGFlMjMzZGI2ZDlhYjhlOWI4NDRmYTlkNGRhNjhmYTNkYzk0YWM4ZmU4MjAifX19
@ -153,14 +153,14 @@ Fisher:
RightHand:
Material: FISHING_ROD
Durability: 0
Levels:
'1':
Price: 0.0
EnergyPerAction: 0.5
Radius: 3
ChancePerBlockPerSecond: 20.0
'2':
Price: 1000.0
EnergyPerAction: 0.3
Radius: 5
ChancePerBlockPerSecond: 50.0
Levels:
'1':
Price: 0.0
EnergyPerAction: 0.5
Radius: 3
ChancePerBlockPerSecond: 20.0
'2':
Price: 1000.0
EnergyPerAction: 0.3
Radius: 5
ChancePerBlockPerSecond: 50.0

@ -1,10 +1,10 @@
name: Minions
main: me.loganb1max.minions.MinionsPlugin
name: MinionsPlus
main: me.loganb1max.minionsplus.MinionsPlus
version: 1.0-SNAPSHOT
description: Minions Plugin for Skyblock Servers
author: loganb1max
load: POSTWORLD
depend: []
depend: [Vault]
commands:
minions:
aliases: [minion]