Improvements to egg overwrite handling

Affects mushroom growing and dragon deleting blocks. Made dragon deletion handling better and removed redundant mushroom handling

Made removeEgg() a static method
This commit is contained in:
J0nasL 2023-07-17 05:06:07 -04:00
parent 9ace49f84d
commit 7d0b5da979
2 changed files with 100 additions and 66 deletions

View file

@ -1,5 +1,6 @@
package io.github.J0hnL0cke.egghunt.Controller;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
@ -26,8 +27,10 @@ import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.ItemDespawnEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.units.qual.C;
import io.github.J0hnL0cke.egghunt.Model.Configuration;
import io.github.J0hnL0cke.egghunt.Model.Data;
@ -135,82 +138,105 @@ public class EggDestroyListener implements Listener {
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onGrow(StructureGrowEvent event) {
boolean destroy = false;
if (event.getSpecies().equals(TreeType.RED_MUSHROOM)) {
List<BlockState> blocks = event.getBlocks();
for (BlockState blockState : blocks) {
Block block = blockState.getBlock();
if (Egg.hasEgg(block)) {
destroy = true;
if (!config.getEggInvulnerable()) { //if egg will be replaced, make sure it gets removed
block.setType(Material.AIR);
}
} else {
if (blockState instanceof Container) { //TODO exclude item frames, which aren't destroyed by this
Container cont = (Container) blockState;
if (cont.getInventory().contains(Material.DRAGON_EGG)) { //TODO update for egg in shulker/bundle
destroy = true;
cont.getInventory().remove(Material.DRAGON_EGG); //make sure egg is removed from container
}
}
}
}
if (destroy) {
if (config.getEggInvulnerable()) {
event.setCancelled(true);
Player p = event.getPlayer();
if (p != null) {
p.playSound(p.getLocation(), Sound.BLOCK_ANVIL_LAND, 1, 1);
p.sendMessage("Cannot grow mushroom: obstructed by dragon egg");
p.setCooldown(Material.BONE_MEAL, 100);
log(String.format("%s tried to mushroom the dragon egg", p.getName()));
}
} else {
eggDestroyed();
}
}
}
}
/**
* Cancel events that damage the egg item if enabled in config
* Note: cannot cancel damage to item frames, since damage is used to remove an item but is not called when burned/exploded
* TODO: figure out if this is still needed, since when active, egg is set to be invlunerable
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onConsiderEntityDamageEvent(EntityDamageEvent event) {
if (config.getEggInvulnerable()) {
Entity entity = event.getEntity();
if (entity.getType().equals(EntityType.DROPPED_ITEM)) {
if (Egg.hasEgg((Item) entity)) {
event.setCancelled(true);
}
}
handleBlockStateReplace(blocks);
//TODO need to handle egg respawn, since it could be immediately destroyed by the dragon after respawning
}
}
/**
* Listens for the dragon destroying the egg by flying into it
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onDragonDeleteBlock(final EntityExplodeEvent event) {
//check if this event is dealing with the dragon, since the event is very generic
Entity e = event.getEntity();
if (e instanceof ComplexEntityPart) { //if a part of a multi-part entity like the dragon, get the whole dragon
if (e instanceof ComplexEntityPart) {
//if a part of a multi-part entity like the dragon, get the whole dragon
e = ((ComplexEntityPart) e).getParent();
}
if (e.getType().equals(EntityType.ENDER_DRAGON)) {
for (Block b : event.blockList()) {
if (Egg.hasEgg(b)) {
//TODO need both a monitor and a HIGHEST check here to cancel the event
b.setType(Material.AIR);
//if dragon is deleting blocks, check if any are the egg
handleBlockReplace(event.blockList());
}
}
//TODO can't do normal respawn, since it might respawn where dragon is already perched
eggDestroyed();
/**
* Looks through the provided blocks to see if the dragon egg is affected
* Notifies that the egg is destroyed or prevents its destruction
* @param blocks
*/
private void handleBlockReplace(List<Block> blocks) {
ArrayList<Block> eggs = new ArrayList<>();
Boolean foundEgg = false;
for (Block block : blocks) {
if (Egg.hasEgg(block)) {
foundEgg = true;
eggs.add(block);
}
}
if (foundEgg) {
if (config.getEggInvulnerable()) { //prevent egg destruction
for (Block b : eggs) {
blocks.remove(b); //remove egg from list of blocks to delete
}
log("Prevented egg from being replaced");
} else { //if egg will be replaced, make sure it gets removed
for (Block b : eggs) {
Egg.removeEgg(b); //delete egg
}
log("Dragon egg was replaced");
eggDestroyed();
}
}
}
private void handleBlockStateReplace(List<BlockState> blockStates) {
//TODO refactor to merge these together without preventing shallow copy
ArrayList<BlockState> eggs = new ArrayList<>();
Boolean foundEgg = false;
for (BlockState blockState : blockStates) {
if (Egg.hasEgg(blockState.getBlock())) {
foundEgg = true;
eggs.add(blockState);
}
}
if (foundEgg) {
if (config.getEggInvulnerable()) { //prevent egg destruction
for (BlockState b : eggs) {
blockStates.remove(b); //remove egg from list of blocks to delete
}
log("Prevented egg from being replaced");
} else { //if egg will be replaced, make sure it gets removed
for (BlockState b : eggs) {
Egg.removeEgg(b.getBlock()); //delete egg
}
log("Dragon egg was replaced");
eggDestroyed();
}
}
}
/**
* Cancel events that damage the egg item if enabled in config
* Note: cannot cancel damage to item frames, since damage is used to remove an item but is not called when burned/exploded
* TODO: figure out if this is still needed, since when active, egg is set to be invlunerable
*/
@EventHandler(priority = EventPriority.HIGHEST)
public ArrayList<Block> onConsiderEntityDamageEvent(EntityDamageEvent event) {
if (config.getEggInvulnerable()) {
Entity entity = event.getEntity();
if (entity.getType().equals(EntityType.DROPPED_ITEM)) {
if (Egg.hasEgg((Item) entity)) {
event.setCancelled(true);
}
}
}

View file

@ -174,30 +174,30 @@ public class Egg {
}
public boolean removeEgg(Entity entity) {
public static boolean removeEgg(Entity entity) {
if (entity instanceof Player) {
if (Egg.hasEgg(((Player) entity).getInventory())) {
if (hasEgg(((Player) entity).getInventory())) {
//TODO
}
} else if (entity instanceof LivingEntity) {
LivingEntity mob = (((LivingEntity) entity));
EntityEquipment inv = mob.getEquipment();
if (Egg.hasEgg(inv.getItemInMainHand())) {
if (hasEgg(inv.getItemInMainHand())) {
inv.setItemInMainHand(null);
return true;
} else if (Egg.hasEgg(inv.getItemInOffHand())) {
} else if (hasEgg(inv.getItemInOffHand())) {
inv.setItemInOffHand(null);
return true;
}
} else if (entity instanceof FallingBlock) {
FallingBlock block = (FallingBlock) entity;
if (Egg.hasEgg(block)) {
if (hasEgg(block)) {
block.remove();
return true;
}
} else if (entity instanceof Item) {
Item item = (Item) entity;
if (Egg.hasEgg(item)) {
if (hasEgg(item)) {
item.remove();
return true;
}
@ -205,6 +205,14 @@ public class Egg {
return false;
}
public static boolean removeEgg(Block block) {
if (hasEgg(block)) {
block.setType(Material.AIR);
return true;
}
return false;
}
/**
* Check if the given Material is the dragon egg. Also returns false if the provided material is null.
* @param material Material to check