minions-plus/src/main/java/pw/hamzantal/minionsplus/model/Minion.java

302 lines
11 KiB
Java

package pw.hamzantal.minionsplus.model;
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 pw.hamzantal.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.minions.*;
import me.loganb1max.minionsplus.util.*;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import pw.hamzantal.minionsplus.model.minions.*;
import pw.hamzantal.minionsplus.util.*;
import java.text.DecimalFormat;
import java.util.*;
@Getter
public abstract class Minion {
private final ConfigurationSection section;
private final UUID owner;
private final String ownerName;
@Setter(AccessLevel.PROTECTED) private Location location;
@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)
private double offset = 0.1;
public Minion(final ConfigurationSection section, final UUID owner, final String ownerName) {
this.section = section;
this.owner = owner;
this.ownerName = ownerName;
}
protected void findStand() {
if (this.stand != null) return;
this.location.getChunk().load();
this.location.getWorld().getNearbyEntities(this.location, 0.5, 0.5, 0.5).stream().filter(entity -> entity instanceof ArmorStand && !entity.getCustomName().isEmpty()).findFirst().ifPresent(entity -> {
this.stand = (ArmorStand) entity;
});
}
public void spawn(final Location location) {
this.location = location;
if (this.stand == null) {
this.stand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
this.stand.setSmall(true);
this.stand.setBasePlate(false);
this.stand.setGravity(false);
this.stand.setCanPickupItems(false);
this.stand.setRemoveWhenFarAway(false);
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);
MinionsPlus.getInstance().getMinionManager().getMinions().add(this);
} else {
this.stand.teleport(location);
}
}
public void despawn(final Player player) {
if (this.stand == null) return;
this.location = null;
this.stand.remove();
this.stand = null;
this.linkedBlocks.clear();
player.getInventory().addItem(this.toItemStack()).forEach((integer, itemStack) -> player.getWorld().dropItemNaturally(player.getLocation(), itemStack));
MinionsPlus.getInstance().getMinionManager().getMinions().remove(this);
}
public void animationTick() {
if (this.stand == null) return;
if (this.stand.getRightArmPose().getX() < 5) offset = 0.1;
if (this.stand.getRightArmPose().getX() > 6) offset = -0.1;
if (this.energy > 0) this.stand.setRightArmPose(this.stand.getRightArmPose().add(offset, 0, 0));
final DecimalFormat format = new DecimalFormat("#.#");
this.stand.setCustomName(Text.color(getName() + " &8[&f" + format.format(getEnergy()) + "&8]"));
this.stand.setFireTicks(0);
}
public double gainEnergy(final double amount) {
return this.energy += amount;
}
public double consumeEnergy(final double amount) {
return this.energy -= amount;
}
public void equipEquipment(final ArmorStand stand) {
final String skull = this.section.getString("Equipment.Skull", "");
ItemStack skullItem = SkullCreator.itemFromBase64(skull);
stand.setHelmet(skullItem);
final ItemStack chestplate = ItemUtil.fromConfigSection(this.section.getConfigurationSection("Equipment.Chestplate"));
stand.setChestplate(chestplate);
final ItemStack leggings = ItemUtil.fromConfigSection(this.section.getConfigurationSection("Equipment.Leggings"));
stand.setLeggings(leggings);
final ItemStack boots = ItemUtil.fromConfigSection(this.section.getConfigurationSection("Equipment.Boots"));
stand.setBoots(boots);
final ItemStack rightHand = ItemUtil.fromConfigSection(this.section.getConfigurationSection("Equipment.RightHand"));
stand.setItemInHand(rightHand);
}
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);
item = ItemUtil.setKeyDouble(item, "minion-energy", this.energy);
return item;
}
public ItemStack getIcon() {
final Material material = Material.getMaterial(this.section.getString("Item.Material"));
final int durability = this.section.getInt("Item.Durability");
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 = 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(getReplacer().replace(lore))
.build();
return item;
}
public UUID getId() {
if (this.stand == null) return null;
return this.stand.getUniqueId();
}
public String getType() {
return this.section.getName();
}
public String getName() {
return this.section.getString("Name");
}
public double getEnergyPerUse(final int level) {
return this.section.getDouble("Levels." + level + ".EnergyPerAction", 0.0);
}
public double getPrice(final int level) {
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();
object.addProperty("type", getType());
object.addProperty("owner", this.owner.toString());
object.addProperty("ownerName", this.ownerName);
final JsonObject loc = new JsonObject();
loc.addProperty("world", this.location.getWorld().getName());
loc.addProperty("x", this.location.getX());
loc.addProperty("y", this.location.getY());
loc.addProperty("z", this.location.getZ());
object.add("location", loc);
object.addProperty("energy", this.energy);
object.addProperty("level", this.level);
final List<JsonElement> linked = new ArrayList<>();
this.linkedBlocks.forEach(block -> {
JsonObject b = new JsonObject();
b.addProperty("world", block.getWorld().getName());
b.addProperty("x", block.getX());
b.addProperty("y", block.getY());
b.addProperty("z", block.getZ());
linked.add(b);
});
object.add("linkedBlocks", gson.toJsonTree(linked));
return object;
}
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());
final String ownerName = data.get("ownerName").getAsString();
final JsonObject locData = data.get("location").getAsJsonObject();
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 = 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":
toReturn = new MinerMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
case "Farmer":
toReturn = new FarmerMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
case "Fisher":
toReturn = new FisherMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
case "Seller":
toReturn = new SellerMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
case "Butcher":
toReturn = new ButcherMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
case "Collector":
toReturn = new CollectorMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
case "Breeder":
toReturn = new BreederMinion(owner, ownerName, location, energy, level, linkedBlocks);
break;
}
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;
case "Seller":
toReturn = new SellerMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
case "Butcher":
toReturn = new ButcherMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
case "Collector":
toReturn = new CollectorMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
case "Breeder":
toReturn = new BreederMinion(owner, ownerName, location, energy, level, new HashSet<>());
break;
}
return toReturn;
}
public abstract void tick();
public abstract Replacer getReplacer();
}