This commit is contained in:
jascotty2 2019-09-03 15:44:53 -05:00
commit 2d551c05e1
5 changed files with 418 additions and 15 deletions

View File

@ -4,7 +4,7 @@ stages:
variables: variables:
name: "UltimateStacker" name: "UltimateStacker"
path: "/builds/$CI_PROJECT_PATH" path: "/builds/$CI_PROJECT_PATH"
version: "1.9.6" version: "1.9.9"
build: build:
stage: build stage: build

View File

@ -2,24 +2,37 @@ package com.songoda.ultimatestacker.listeners;
import com.songoda.lootables.loot.Drop; import com.songoda.lootables.loot.Drop;
import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.entity.EntityStack;
import com.songoda.ultimatestacker.utils.DropUtils; import com.songoda.ultimatestacker.utils.DropUtils;
import com.songoda.ultimatestacker.utils.ServerVersion;
import com.songoda.ultimatestacker.utils.settings.Setting; import com.songoda.ultimatestacker.utils.settings.Setting;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random;
public class DeathListeners implements Listener { public class DeathListeners implements Listener {
private final UltimateStacker instance; private final UltimateStacker instance;
private Random random;
public DeathListeners(UltimateStacker instance) { public DeathListeners(UltimateStacker instance) {
this.instance = instance; this.instance = instance;
random = new Random();
} }
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@ -33,7 +46,10 @@ public class DeathListeners implements Listener {
for (ItemStack item : event.getDrops()) for (ItemStack item : event.getDrops())
drops.add(new Drop(item)); drops.add(new Drop(item));
} }
event.getDrops().clear(); for (ItemStack item : new ArrayList<>(event.getDrops())) {
if (!shouldDrop(event.getEntity(), item.getType()))
event.getDrops().remove(item);
}
if (instance.getEntityStackManager().isStacked(event.getEntity())) if (instance.getEntityStackManager().isStacked(event.getEntity()))
instance.getEntityStackManager().getStack(event.getEntity()) instance.getEntityStackManager().getStack(event.getEntity())
@ -41,4 +57,95 @@ public class DeathListeners implements Listener {
else else
DropUtils.processStackedDrop(event.getEntity(), drops); DropUtils.processStackedDrop(event.getEntity(), drops);
} }
private boolean shouldDrop(LivingEntity entity, Material material) {
if (entity.getEquipment() != null && entity.getEquipment().getArmorContents().length != 0) {
List<ItemStack> items = new ArrayList<>(Arrays.asList(entity.getEquipment().getArmorContents()));
items.add(entity.getEquipment().getItemInHand());
if (instance.isServerVersionAtLeast(ServerVersion.V1_9))
items.add(entity.getEquipment().getItemInOffHand());
for (ItemStack item : items) {
if (item.getType() == material)
return true;
}
}
if (instance.isServerVersionAtLeast(ServerVersion.V1_11) && entity instanceof ChestedHorse) {
if (((ChestedHorse) entity).getInventory().contains(material))
return true;
}
switch (material.name()) {
case "SADDLE":
return !entity.getType().name().equals("RAVAGER");
case "DIAMOND_HORSE_ARMOR":
case "GOLDEN_HORSE_ARMOR":
case "IRON_HORSE_ARMOR":
case "LEATHER_HORSE_ARMOR":
case "CYAN_CARPET":
case "BLACK_CARPET":
case "BLUE_CARPET":
case "BROWN_CARPET":
case "GRAY_CARPET":
case "GREEN_CARPET":
case "LIGHT_BLUE_CARPET":
case "LIGHT_GRAY_CARPET":
case "LIME_CARPET":
case "MAGENTA_CARPET":
case "ORANGE_CARPET":
case "PINK_CARPET":
case "PURPLE_CARPET":
case "RED_CARPET":
case "WHITE_CARPET":
case "YELLOW_CARPET":
case "CARPET":
case "CHEST":
return true;
default:
return false;
}
}
@EventHandler
public void onEntityHit(EntityDamageByEntityEvent event) {
if (!(event.getDamager() instanceof Player)) return;
if (!instance.getEntityStackManager().isStacked(event.getEntity())) return;
EntityStack stack = instance.getEntityStackManager().getStack(event.getEntity());
if (Setting.KILL_WHOLE_STACK_ON_DEATH.getBoolean() && Setting.REALISTIC_DAMAGE.getBoolean()) {
Player player = (Player) event.getDamager();
ItemStack tool = player.getInventory().getItemInMainHand();
if (tool.getType().getMaxDurability() < 1 || (tool.getItemMeta() != null && (tool.getItemMeta().isUnbreakable()
|| tool.getItemMeta().spigot().isUnbreakable())))
return;
int unbreakingLevel = tool.getEnchantmentLevel(Enchantment.DURABILITY);
Damageable damageable = (Damageable) tool.getItemMeta();
int actualDamage = 0;
for (int i = 0; i < stack.getAmount(); i++)
if (checkUnbreakingChance(unbreakingLevel))
actualDamage++;
damageable.setDamage(damageable.getDamage() + actualDamage-1);
tool.setItemMeta((ItemMeta) damageable);
if (!this.hasEnoughDurability(tool, 1))
player.getInventory().setItemInMainHand(null);
}
}
public boolean hasEnoughDurability(ItemStack tool, int requiredAmount) {
if (!tool.hasItemMeta() || !(tool.getItemMeta() instanceof Damageable) || tool.getType().getMaxDurability() < 1)
return true;
Damageable damageable = (Damageable) tool.getItemMeta();
int durabilityRemaining = tool.getType().getMaxDurability() - damageable.getDamage();
return durabilityRemaining > requiredAmount;
}
public boolean checkUnbreakingChance(int level) {
return (1.0 / (level + 1)) > random.nextDouble();
}
} }

View File

@ -40,7 +40,7 @@ public class LootablesManager {
? entity.getKiller().getItemInHand().getEnchantmentLevel(Enchantment.LOOT_BONUS_MOBS) ? entity.getKiller().getItemInHand().getEnchantmentLevel(Enchantment.LOOT_BONUS_MOBS)
: 0; : 0;
int rerollChance = looting / (looting + 1); int rerollChance = Setting.REROLL.getBoolean() ? looting / (looting + 1) : 0;
for (Loot loot : lootable.getRegisteredLoot()) for (Loot loot : lootable.getRegisteredLoot())
toDrop.addAll(runLoot(entity, loot, rerollChance, looting)); toDrop.addAll(runLoot(entity, loot, rerollChance, looting));
@ -53,9 +53,7 @@ public class LootablesManager {
if (entity.getType() == EntityType.SHEEP) { if (entity.getType() == EntityType.SHEEP) {
modify = (Loot loot2) -> { modify = (Loot loot2) -> {
Material material = loot2.getMaterial(); Material material = loot2.getMaterial();
if (material == (instance.isServerVersionAtLeast(com.songoda.lootables.utils.ServerVersion.V1_13) if (material.name().contains("WOOL") && ((Sheep) entity).getColor() != null) {
? Material.WHITE_WOOL : Material.valueOf("WOOL"))
&& ((Sheep) entity).getColor() != null) {
if (((Sheep) entity).isSheared()) return null; if (((Sheep) entity).isSheared()) return null;
if (instance.isServerVersionAtLeast(com.songoda.lootables.utils.ServerVersion.V1_13)) if (instance.isServerVersionAtLeast(com.songoda.lootables.utils.ServerVersion.V1_13))
loot2.setMaterial(Material.valueOf(((Sheep) entity).getColor() + "_WOOL")); loot2.setMaterial(Material.valueOf(((Sheep) entity).getColor() + "_WOOL"));

View File

@ -0,0 +1,303 @@
package com.songoda.ultimatestacker.utils.settings;
import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.entity.Check;
import com.songoda.ultimatestacker.entity.Split;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public enum Setting {
STACK_SEARCH_TICK_SPEED("Main.Stack Search Tick Speed", 5,
"The speed in which a new stacks will be created.",
"It is advised to keep this number low."),
DISABLED_WORLDS("Main.Disabled Worlds", Arrays.asList("World1", "World2", "World3"),
"Worlds that stacking doesn't happen in."),
STACK_ENTITIES("Entities.Enabled", true,
"Should entities be stacked?"),
NAME_FORMAT_ENTITY("Entities.Name Format", "&f{TYPE} &6{AMT}x",
"The text displayed above an entities head where {TYPE} refers to",
"The entities type and {AMT} is the amount currently stacked."),
SEARCH_RADIUS("Entities.Search Radius", 5,
"The distance entities must be to each other in order to stack."),
MAX_STACK_ENTITIES("Entities.Max Stack Size", 15,
"The max amount of entities in a single stack."),
MIN_STACK_ENTITIES("Entities.Min Stack Amount", 5,
"The minimum amount required before a stack can be formed.",
"Do not set this to lower than 2."),
MAX_PER_TYPE_STACKS_PER_CHUNK("Entities.Max Per Type Stacks Per Chunk", -1,
"The maximum amount of each entity type stack allowed in a chunk."),
STACK_WHOLE_CHUNK("Entities.Stack Whole Chunk", false,
"Should all qualifying entities in each chunk be stacked?",
"This will override the stacking radius."),
ENTITY_HOLOGRAMS("Entities.Holograms Enabled", true,
"Should holograms be displayed above stacked entities?"),
HOLOGRAMS_ON_LOOK_ENTITY("Entities.Only Show Holograms On Look", false,
"Only show nametags above an entities head when looking directly at them."),
CUSTOM_DROPS("Entities.Custom Drops.Enabled", true,
"Should custom drops be enabled?"),
REROLL("Entities.Custom Drops.Reroll", true,
"Increases chance of uncommon drops by making a second attempt to",
"drop if the original attempt failed (Requires the looting enchantment).",
"This is a default Minecraft mechanic."),
KILL_WHOLE_STACK_ON_DEATH("Entities.Kill Whole Stack On Death", false,
"Should killing a stack of entities kill the whole stack or",
"just one out of the stack? If you want only certain entities to be",
"effected by this you can configure it in the entities.yml"),
CLEAR_LAG("Entities.Clear Lag", false,
"When enabled, the plugin will hook into ClearLag and extend the",
"clear task to include stacked entities from this plugin. If this is enabled",
"the built in task will not run."),
INSTANT_KILL("Entities.Instant Kill", Arrays.asList("FALL", "DROWNING", "LAVA", "VOID"),
"Events that will trigger an entire stack to be killed.",
"It should be noted that this is useless if the above setting is true.",
"Any of the following can be added to the list:",
"CONTACT, ENTITY_ATTACK, ENTITY_SWEEP_ATTACK, PROJECTILE",
"SUFFOCATION, FALL, FIRE, FIRE_TICK",
"MELTING, LAVA, DROWNING, BLOCK_EXPLOSION",
"ENTITY_EXPLOSION, VOID, LIGHTNING, SUICIDE",
"STARVATION, POISON, MAGIC, WITHER",
"FALLING_BLOCK, THORNS, DRAGON_BREATH, CUSTOM",
"FLY_INTO_WALL, HOT_FLOOR, CRAMMING, DRYOUT"),
NO_EXP_INSTANT_KILL("Entities.No Exp For Instant Kills", false,
"Should no experience be dropped when an instant kill is performed?"),
STACK_CHECKS("Entities.Stack Checks", Arrays.asList(Check.values()).stream()
.filter(Check::isEnabledByDefault).map(Check::name).collect(Collectors.toList()),
"These are checks that are processed before an entity is stacked.",
"You can add and remove from the list at will.",
"The acceptable check options are:",
"SPAWN_REASON, NERFED, AGE, TICK_AGE, PHANTOM_SIZE",
"IS_TAMED, ANIMAL_OWNER, SKELETON_TYPE",
"ZOMBIE_BABY, SLIME_SIZE, PIG_SADDLE, SHEEP_SHEERED",
"SHEEP_COLOR, WOLF_COLLAR_COLOR, OCELOT_TYPE, HORSE_COLOR",
"HORSE_STYLE, HORSE_CARRYING_CHEST, HORSE_HAS_ARMOR",
"HORSE_HAS_SADDLE, HORSE_JUMP, RABBIT_TYPE, VILLAGER_PROFESSION",
"LLAMA_COLOR, LLAMA_STRENGTH, PARROT_TYPE, PUFFERFISH_STATE",
"TROPICALFISH_PATTERN, TROPICALFISH_BODY_COLOR, TROPICALFISH_PATTERN_COLOR"),
SPLIT_CHECKS("Entities.Split Checks", Arrays.asList(Split.values()).stream()
.map(Split::name).collect(Collectors.toList()),
"These are checks that when achieved will break separate a single entity",
"from a stack."),
KEEP_FIRE("Entities.Keep Fire", true,
"Should fire ticks persist to the next entity when an entity dies?"),
KEEP_POTION("Entities.Keep Potion Effects", true,
"Should potion effects persist to the next entity when an entity dies?"),
CARRY_OVER_LOWEST_HEALTH("Entities.Carry Over Lowest Health", false,
"Should the lowest health be carried over when stacked?",
"This should not be used in collaboration with 'Stack Entity Health'.",
"If it is used this setting will be overrode."),
ONLY_STACK_FROM_SPAWNERS("Entities.Only Stack From Spawners", false,
"Should entities only be stacked if they originate from a spawner?",
"It should be noted that the identifier that tells the plugin",
"if the entity originated from a spawner or not is wiped on",
"server restart."),
STACK_REASONS("Entities.Stack Reasons", Arrays.asList(),
"This will limit mob stacking to mobs who spawned via the listed reasons.",
"This list is ignored if Only Stack From Spawners = true.",
"The following reasons can be added to the list:",
"NATURAL, JOCKEY, CHUNK_GEN, SPAWNER, EGG, SPAWNER_EGG, LIGHTNING, BUILD_SNOWMAN, ",
"BUILD_IRONGOLEM, BUILD_WITHER, VILLAGE_DEFENSE, VILLAGE_INVASION, BREEDING,",
"SLIME_SPLIT, REINFORCEMENTS, NETHER_PORTAL, DISPENSE_EGG, INFECTION,",
"CURED, OCELOT_BABY, SILVERFISH_BLOCK, MOUNT, TRAP, ENDER_PEARL, ",
"SHOULDER_ENTITY, DROWNED, SHEARED, EXPLOSION"
),
CARRY_OVER_METADATA_ON_DEATH("Entities.Carry Over Metadata On Death", true,
"With this enabled any metadata assigned from supported plugins such",
"as EpicSpawners and mcMMO will be preserved when the entity is killed."),
ONLY_STACK_ON_SURFACE("Entities.Only Stack On Surface", true,
"Should entities only be stacked if they are touching the ground",
"or swimming? This does not effect flying entities."),
STACK_ENTITY_HEALTH("Entities.Stack Entity Health", true,
"Should entity health be stacked? When enabled Entity stacks will",
"remember the health of all entities inside of the stack. This",
"works the best with 'Only Stack On Surface enabled' as entities",
"falling out of grinders may stack before hitting the ground."),
ONLY_STACK_FLYING_DOWN("Entities.Only Stack Flying Down", true,
"Should entities that fly only stack with entities that are lower on the",
"Y axis. This is important for grinders so that flying entities don't continuously",
"stack upwards to a higher up entity."),
REALISTIC_DAMAGE("Entities.Use Realistic Weapon Damage", true,
"Should weapons take damage based on the amount of entites in the stack?"),
STACK_ITEMS("Items.Enabled", true,
"Should items be stacked?"),
ITEM_HOLOGRAMS("Items.Holograms Enabled", true,
"Should holograms be displayed above stacked items?"),
ITEM_HOLOGRAM_SINGLE("Items.Show Hologram For Single", true,
"Should holograms be displayed above items when there is only a single",
"item in the stack?"),
ITEM_HOLOGRAM_BLACKLIST("Items.Show Holograms For Blacklisted Items", true,
"Should items that are blacklisted display holograms?"),
MAX_STACK_ITEMS("Items.Max Stack Size", 512,
"The max stack size for items.",
"Currently this can only be set to a max of 120."),
NAME_FORMAT_ITEM("Items.Name Format", "&f{TYPE} &r[&6{AMT}x]",
"The text displayed above a dropped item."),
NAME_FORMAT_RESET("Items.Name Format Reset", true,
"Should color codes in dropped item names be removed?",
"This is added only because it looks smoother in game. This is only visual and",
"doesn't actually effect the item."),
ITEM_BLACKLIST("Items.Blacklist", Collections.singletonList("EGG"),
"Items included in this list will stack to default Minecraft amounts.",
"Material list: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html",
"Leave this empty by using \"blacklist: []\" if you do not wish to disable",
"stacking for any items."),
ITEM_WHITELIST("Items.Whitelist", new ArrayList(),
"Items included in this whitelist will be stacked.",
"Material list: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html",
"Leave this empty by using \"whitelist: []\" if you want everything to be stacked.",
"Items not in this list will act as if they are blacklisted."),
SHOW_STACK_SIZE_SINGLE("Items.Show Stack Size For Single", false,
"When enabled stack sizes for a stack with a single item will",
"not display the stack size. The stack size will be added",
"for stacks containing two or more items."),
SPAWNERS_ENABLED("Spawners.Enabled", true,
"Should spawners be stacked?"),
SPAWNER_HOLOGRAMS("Spawners.Holograms Enabled", true,
"Should holograms be displayed above stacked spawners?"),
EGGS_CONVERT_SPAWNERS("Spawners.Eggs Convert Spawners", true,
"Should eggs convert spawners? If enabled you will",
"still need to give perms for it to work."),
MAX_STACK_SPAWNERS("Spawners.Max Stack Size", 5,
"What should the max a spawner can stack to be?"),
SNEAK_FOR_STACK("Spawners.Sneak To Receive A Stacked Spawner", true,
"Toggle ability to receive a stacked spawner when breaking a spawner while sneaking."),
SPAWNERS_DONT_EXPLODE("Spawners.Prevent Spawners From Exploding", false,
"Should spawners not break when blown up?"),
EXPLOSION_DROP_CHANCE_TNT("Spawners.Chance On TNT Explosion", "100%",
"Chance of a TNT explosion dropping a spawner."),
EXPLOSION_DROP_CHANCE_CREEPER("Spawners.Chance On Creeper Explosion", "100%",
"Chance of a creeper explosion dropping a spawner."),
NAME_FORMAT_SPAWNER("Spawners.Name Format", "&f{TYPE} Spawner &6{AMT}x",
"The text displayed above a stacked spawner where {TYPE} refers to",
"The entities type and {AMT} is the amount currently stacked."),
LANGUGE_MODE("System.Language Mode", "en_US",
"The enabled language file.",
"More language files (if available) can be found in the plugins data folder."),
MYSQL_ENABLED("MySQL.Enabled", false, "Set to 'true' to use MySQL instead of SQLite for data storage."),
MYSQL_HOSTNAME("MySQL.Hostname", "localhost"),
MYSQL_PORT("MySQL.Port", 3306),
MYSQL_DATABASE("MySQL.Database", "your-database"),
MYSQL_USERNAME("MySQL.Username", "user"),
MYSQL_PASSWORD("MySQL.Password", "pass"),
MYSQL_USE_SSL("MySQL.Use SSL", false);
private String setting;
private Object option;
private String[] comments;
Setting(String setting, Object option, String... comments) {
this.setting = setting;
this.option = option;
this.comments = comments;
}
Setting(String setting, Object option) {
this.setting = setting;
this.option = option;
this.comments = null;
}
public static Setting getSetting(String setting) {
List<Setting> settings = Arrays.stream(values()).filter(setting1 -> setting1.setting.equals(setting)).collect(Collectors.toList());
if (settings.isEmpty()) return null;
return settings.get(0);
}
public String getSetting() {
return setting;
}
public Object getOption() {
return option;
}
public String[] getComments() {
return comments;
}
public List<Integer> getIntegerList() {
return UltimateStacker.getInstance().getConfig().getIntegerList(setting);
}
public List<String> getStringList() {
return UltimateStacker.getInstance().getConfig().getStringList(setting);
}
public boolean getBoolean() {
return UltimateStacker.getInstance().getConfig().getBoolean(setting);
}
public int getInt() {
return UltimateStacker.getInstance().getConfig().getInt(setting);
}
public long getLong() {
return UltimateStacker.getInstance().getConfig().getLong(setting);
}
public String getString() {
return UltimateStacker.getInstance().getConfig().getString(setting);
}
public char getChar() {
return UltimateStacker.getInstance().getConfig().getString(setting).charAt(0);
}
public double getDouble() {
return UltimateStacker.getInstance().getConfig().getDouble(setting);
}
}

View File

@ -1,5 +0,0 @@
#Generated by Maven
#Sat Dec 08 20:46:16 CET 2018
version=maven-version-number
groupId=com.songoda
artifactId=UltimateStacker