Custom ItemStacks and more refactoring

This commit is contained in:
Minecon724 2024-09-21 09:57:15 +02:00
parent 35922959ff
commit 0f73cdec84
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
7 changed files with 161 additions and 78 deletions

View file

@ -1,8 +1,8 @@
package eu.m724.giants;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@ -11,6 +11,7 @@ import org.bukkit.util.Vector;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
@ -69,23 +70,26 @@ public class Configuration {
}
}
for (String line : config.getStringList("drops")) {
String[] parts = line.split(":");
for (Map<?, ?> dropMap : config.getMapList("drops")) {
try {
Material material = Material.getMaterial(parts[0]);
if (material == null) {
throw new IllegalArgumentException("Invalid Material");
ItemStack itemStack;
if (dropMap.containsKey("itemStack")) {
itemStack = (ItemStack) dropMap.get("itemStack");
} else {
Material material = Material.getMaterial((String) dropMap.get("material"));
if (material == null) {
throw new IllegalArgumentException("Invalid Material");
}
itemStack = new ItemStack(material, 1);
}
int min = Integer.parseInt(parts[1]);
int max = Integer.parseInt(parts[2]);
float chance = Integer.parseInt(parts[3]) / 100f; // TODO is there even a point
Drop drop = new Drop(material, min, max, chance);
drops.add(drop);
int min = (int) dropMap.get("quantityMin");
int max = (int) dropMap.get("quantityMax");
float chance = (int) dropMap.get("chance");
drops.add(new Drop(itemStack, min, max, chance));
} catch (IllegalArgumentException e) {
logger.warning("Parsing a drop failed:");
logger.warning(line);
logger.warning(e.getMessage());
}
}

View file

@ -1,16 +1,25 @@
package eu.m724.giants;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.concurrent.ThreadLocalRandom;
public class Drop {
public final Material material;
public final ItemStack itemStack;
public final int min, max;
public final float chance;
public Drop(Material material, int min, int max, float chance) {
this.material = material;
public Drop(ItemStack itemStack, int min, int max, float chance) {
this.itemStack = itemStack;
this.min = min;
this.max = max;
this.chance = chance;
}
public ItemStack generateItemStack() {
int amount = ThreadLocalRandom.current().nextInt(min, max + 1);
ItemStack itemStack = this.itemStack.clone();
itemStack.setAmount(amount);
return itemStack;
}
}

View file

@ -17,14 +17,15 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
// TODO move ai stuff to another class
/**
* A processor class that processes giants
*/
public class GiantProcessor implements Listener {
private static final int VERSION = 1;
private final JavaPlugin plugin;
private final Configuration configuration;
private final Logger logger;
@ -43,36 +44,38 @@ public class GiantProcessor implements Listener {
}
void start() {
new BukkitRunnable() {
@Override
public void run() {
for (Husk husk : Set.copyOf(trackedHusks)) {
if (husk.isValid()) {
Location location = husk.getLocation();
Entity giant = husk.getVehicle();
if (configuration.ai) {
new BukkitRunnable() {
@Override
public void run() {
for (Husk husk : Set.copyOf(trackedHusks)) {
if (husk.isValid()) {
Location location = husk.getLocation();
Entity giant = husk.getVehicle();
if (giant instanceof Giant) {
if (giant.isValid()) { // TODO reconsider
giant.getWorld().getNearbyEntities(
giant.getBoundingBox().expand(configuration.attackReach),
e -> (e instanceof Player && !e.isInvulnerable())
).forEach(p -> ((Player) p).damage(configuration.attackDamage, giant));
giant.setRotation(location.getYaw(), location.getPitch());
if (giant instanceof Giant) {
if (giant.isValid()) { // TODO reconsider
giant.getWorld().getNearbyEntities(
giant.getBoundingBox().expand(configuration.attackReach),
e -> (e instanceof Player && !e.isInvulnerable())
).forEach(p -> ((Player) p).damage(configuration.attackDamage, giant));
giant.setRotation(location.getYaw(), location.getPitch());
}
} else {
// no vehicle means the giant doesn't exist anymore and the husk should also not exist
husk.setHealth(0);
trackedHusks.remove(husk);
logger.fine("Husk killed because Giant died at " + husk.getLocation());
}
} else {
// no vehicle means the giant doesn't exist anymore and the husk should also not exist
husk.setHealth(0);
trackedHusks.remove(husk);
logger.fine("Husk killed because Giant died at " + husk.getLocation());
logger.fine("Husk unloaded at " + husk.getLocation());
}
} else {
trackedHusks.remove(husk);
logger.fine("Husk unloaded at " + husk.getLocation());
}
}
}
}.runTaskTimer(plugin, configuration.attackDelay, 0L);
}.runTaskTimer(plugin, configuration.attackDelay, 0L);
}
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@ -86,8 +89,7 @@ public class GiantProcessor implements Listener {
new PotionEffect(PotionEffectType.INVISIBILITY, Integer.MAX_VALUE, 1).apply(passenger);
passenger.setInvulnerable(true);
passenger.setPersistent(true);
// TODO I was considering making the value plugin version to track and correct changes
passenger.getPersistentDataContainer().set(huskKey, PersistentDataType.BOOLEAN, true);
passenger.getPersistentDataContainer().set(huskKey, PersistentDataType.INTEGER, VERSION);
entity.addPassenger(passenger);
trackedHusks.add((Husk) passenger);
@ -157,7 +159,7 @@ public class GiantProcessor implements Listener {
logger.fine("Rolling a drop");
if (drop.chance > random.nextFloat()) {
ItemStack is = new ItemStack(drop.material, random.nextInt(drop.min, drop.max + 1));
ItemStack is = drop.generateItemStack();
entity.getWorld().dropItemNaturally(location, is);
logger.fine("Dropped " + is);

View file

@ -0,0 +1,80 @@
package eu.m724.giants;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class GiantsCommand implements CommandExecutor {
private final GiantsPlugin plugin;
public GiantsCommand(GiantsPlugin plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
sender.sendMessage("Giants " + plugin.getDescription().getVersion());
return true;
}
String action = args[0];
if (!sender.hasPermission("giants.command." + action)) {
sender.sendMessage("You don't have permission to use this command, or it doesn't exist.");
return true;
}
Player player = sender instanceof Player ? (Player) sender : null;
if (action.equals("spawn")) {
if (player != null) {
plugin.spawnGiant(player.getLocation());
sender.sendMessage("Spawned a Giant");
} else {
sender.sendMessage("Only players can use this command.");
}
} else if (action.equals("serialize")) {
if (player != null) {
ItemStack itemStack = player.getInventory().getItemInMainHand();
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> map = new LinkedHashMap<>();
map.put("chance", 1);
map.put("quantityMin", itemStack.getAmount());
map.put("quantityMax", itemStack.getAmount());
map.put("itemStack", itemStack);
list.add(map);
YamlConfiguration yamlConfiguration = new YamlConfiguration();
yamlConfiguration.set("v", list);
yamlConfiguration.setInlineComments("v", List.of("Copy the below content to your config.yml"));
long now = System.currentTimeMillis();
String name = "item-" + now + ".yml";
try {
yamlConfiguration.save(new File(plugin.getDataFolder(), name));
sender.sendMessage("Saved to plugins/Giants/" + name + ". To add it as a drop, see instructions in the file.");
} catch (IOException e) {
e.printStackTrace();
sender.sendMessage("Error saving file. See console for details.");
}
} else {
sender.sendMessage("Only players can use this command.");
}
}
return true;
}
}

View file

@ -1,12 +1,9 @@
package eu.m724.giants;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Giant;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
@ -25,23 +22,11 @@ public class GiantsPlugin extends JavaPlugin implements CommandExecutor {
configuration.load();
getCommand("spawngiant").setExecutor(this);
getCommand("giants").setExecutor(new GiantsCommand(this));
giantProcessor.start();
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
try {
Player player = (Player) sender;
giantProcessor.spawnGiant(player.getLocation());
} catch (ClassCastException e) {
sender.sendMessage("Only players can use this command.");
}
return true;
}
// TODO api, untested
/**

View file

@ -1,12 +1,9 @@
# Notes:
# To have no values in a list, remove every value below it and change to [] like `effects: []`
# If disabled, the giant won't move (but it will still attack)
# If disabled, the giant will not move or attack
ai: true
# See above
attack: true
# In hearts, 0.5 is half a heart
attackDamage: 1.0
@ -27,7 +24,8 @@ expandUp: 0
# 0 is 0% (no zombie becomes a giant), 1 is 100% (every zombie becomes a giant), so the default 0.005 is 0.5%
chance: 0.005
# Which worlds not to spawn Giants in
# Worlds that Giants will not spawn in naturally.
# You can still use the command to spawn
blacklist:
- "world_nether"
- "world_the_end"
@ -42,10 +40,14 @@ effects:
- "HEALTH_BOOST:10"
# Custom drops
# material:min quantity:max quantity:chance
# material: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
# min and max are inclusive
# unlike above, chance is an integer from 0 to 100
# metadata can't be set yet
# Adding metadata (enchantments, lore etc) is possible. See https://www.spigotmc.org/resources/giants.99600/field?field=documentation
drops:
- "APPLE:1:3:25" # 25% of the time, drop 1 to 3 apples
- material: STICK # See https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
chance: 0.75 # 75% chance to drop 1-3 apples
quantityMin: 1 # inclusive
quantityMax: 3 # inclusive
- material: WOODEN_SWORD
chance: 0.05 # 5%
quantityMin: 1
quantityMax: 1

View file

@ -7,11 +7,12 @@ website: https://www.spigotmc.org/resources/giants.99600/
load: STARTUP
commands:
spawngiant:
description: Spawns a Giant at your location.
permission: giants.spawngiant
permission-message: You do not have permission to use this command.
giants:
description: Utility command for Giants
permissions:
giants.spawngiant:
description: Permits /spawngiant
giants.command.spawn:
description: Permits /giants spawn
default: op
giants.command.serialize:
description: Permits /giants serialize
default: op