Completely rewrote how data is stored

Massively simplified the way data is stored and rewrote all controllers to use the new data structure. Added much-needed helper methods to the controllers, simplified any complicated methods in the controllers, rewrote inventoryClose checks to be more flexible, replaced some comments with docstrings, moved data-related functionality in the controller to the Data class, renamed DAOs to FileDAO, and changed void-related egg respawning
This commit is contained in:
J0nasL 2023-06-28 04:52:57 -04:00
parent 4e7f2e99ba
commit e39818b608
11 changed files with 612 additions and 527 deletions

View file

@ -12,10 +12,10 @@ public class Announcement {
public static void announce(String message, Logger logger) {
List<Player> players = new ArrayList<>(Bukkit.getOnlinePlayers());
for (Player player: players)
if (player.hasPermission("egghunt.notify")) {
((CommandSender) player).sendMessage(message);
}
for (Player player : players)
if (player.hasPermission("egghunt.notify")) {
((CommandSender) player).sendMessage(message);
}
logger.info(String.format("Told %d players %s", players.size(), message));
}

View file

@ -1,17 +1,17 @@
package io.github.J0hnL0cke.egghunt.Controller;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.CompassMeta;
import io.github.J0hnL0cke.egghunt.Model.Data;
import io.github.J0hnL0cke.egghunt.Model.Data.Egg_Storage_Type;
public class CommandHandler {
@ -25,43 +25,66 @@ public class CommandHandler {
private boolean locateEgg(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.hasPermission("egghunt.locateegg")) {
String eggContainer = "";
switch (data.stored_as) {
case BLOCK:
eggContainer = "has been placed";
break;
case CONTAINER_INV:
eggContainer = "is in a "
.concat(data.loc.getBlock().getType().toString().toLowerCase());
break;
case ENTITY_INV:
eggContainer = "is in the inventory of ".concat(data.stored_entity.getName());
break;
case ITEM:
eggContainer = "is an item";
break;
default:
eggContainer = "does not exist";
break;
final String msgStart = "The dragon egg ";
Data.Egg_Storage_Type type = data.getEggType();
if (type == Egg_Storage_Type.DNE) {
//if the egg does not exist
sender.sendMessage(msgStart + "does not exist");
} else {
String storageMsg;
//figure out how the egg is contained
if (type == Egg_Storage_Type.BLOCK) {
Block eggBlock = data.getEggBlock();
if (eggBlock.getType() == Material.DRAGON_EGG) {
storageMsg = "has been placed";
} else {
//egg is inside a container, provide the name of the container
storageMsg = String.format(" is inside of a(n) %s", eggBlock.getType().toString());
}
} else {
Entity eggEntity = data.getEggEntity();
switch (eggEntity.getType()) {
case DROPPED_ITEM: {
storageMsg = "is a dropped item";
}
case ITEM_FRAME: {
storageMsg = "is in an item frame";
}
case FALLING_BLOCK: {
storageMsg = "is a falling block entity";
}
case PLAYER: {
storageMsg = String.format("is in the inventory of %s", eggEntity.getName());
}
default: {
storageMsg = String.format("is held by a(n) %s", eggEntity.getType().toString());
if (eggEntity.getCustomName() != null) {
storageMsg += String.format(" named %s", eggEntity.getCustomName());
}
}
}
}
//stringify the egg's location
Location locMsg = data.getEggLocation();
int x = locMsg.getBlockX();
int y = locMsg.getBlockY();
int z = locMsg.getBlockZ();
String world = locMsg.getWorld().getName();
String locStr = String.format(" at %d, %d, %d in %s", x, y, z, world);
sender.sendMessage(String.format("The dragon egg %s %s.", storageMsg, locStr));
}
String egg_loc_str = ""; // make this empty so if egg does not exist, it remains blank
if (data.stored_as != Data.Egg_Storage_Type.DNE) {
Location egg_loc = data.getEggLocation();
// May occasionally produce a NullPointerException, assert that it wont
assert egg_loc != null;
int egg_x = egg_loc.getBlockX();
int egg_y = egg_loc.getBlockY();
int egg_z = egg_loc.getBlockZ();
String egg_world = egg_loc.getWorld().getName();
egg_loc_str = String.format(" at %d, %d, %d in %s", egg_x, egg_y, egg_z, egg_world);
}
sender.sendMessage("The dragon egg ".concat(eggContainer).concat(egg_loc_str).concat("."));
} else {
sender.sendMessage(NOT_PERMITTED_MSG);
}
@ -74,29 +97,28 @@ public class CommandHandler {
} else {
if (sender.hasPermission("egghunt.trackegg")) {
Player player = (Player) sender;
// roundabout way of getting the item the player is holding in their hotbar
ItemStack held_item = player.getInventory().getItemInMainHand();
if (held_item.getType().equals(Material.COMPASS)) {
// get the item the player is holding
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (heldItem.getType().equals(Material.COMPASS)) {
if (data.stored_as != Data.Egg_Storage_Type.DNE) {
Location egg_loc = data.getEggLocation();
if (player.getWorld().equals(egg_loc.getWorld())) {
if (data.getEggType() != Data.Egg_Storage_Type.DNE) {
Location eggLoc = data.getEggLocation();
if (player.getWorld().equals(eggLoc.getWorld())) {
CompassMeta meta = (CompassMeta) held_item.getItemMeta();
meta.setLodestoneTracked(false);
meta.setLodestone(egg_loc);
held_item.setItemMeta(meta);
sender.sendMessage("Compass set to track last known dragon egg position.");
CompassMeta compassMeta = (CompassMeta) heldItem.getItemMeta();
compassMeta.setLodestoneTracked(false);
compassMeta.setLodestone(eggLoc);
heldItem.setItemMeta(compassMeta);
sender.sendMessage("Tracking last known dragon egg position.");
} else {
sender.sendMessage("Not in the same dimension as the egg.");
sender.sendMessage(String.format("The egg is in %s.", egg_loc.getWorld().getName()));
sender.sendMessage(String.format("The egg is in %s.", eggLoc.getWorld().getName()));
}
} else {
sender.sendMessage("The dragon egg does not exist.");
}
} else {
sender.sendMessage(
"You must be holding a compass to use this command, use /locateegg instead.");
sender.sendMessage("You must be holding a compass to use this command, use /locateegg instead.");
}
} else {
sender.sendMessage(NOT_PERMITTED_MSG);
@ -107,12 +129,10 @@ public class CommandHandler {
private boolean getOwner(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.hasPermission("egghunt.eggowner")) {
if (data.owner == null) {
sender.sendMessage("The dragon egg is currently unclaimed");
if (data.getEggOwner() == null) {
sender.sendMessage("The dragon egg has not been claimed.");
} else {
sender.sendMessage(String.format("The dragon egg belongs to %s.",
get_username_from_uuid(data.owner)));
sender.sendMessage("Don't steal it!");
sender.sendMessage(String.format("The dragon egg belongs to %s.", data.getEggOwner().getName()));
}
} else {
sender.sendMessage(NOT_PERMITTED_MSG);
@ -192,8 +212,4 @@ public class CommandHandler {
// if no command is found
return false;
}
public static String get_username_from_uuid(UUID id) {
return Bukkit.getOfflinePlayer(id).getName();
}
}

View file

@ -9,6 +9,7 @@ import org.bukkit.TreeType;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Container;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -60,26 +61,27 @@ public class EggHuntListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onAutosave(WorldSaveEvent event) {
//TODO: save data when autosave happens
//TODO: don't save data until an autosave happens
data.saveData();
}
// Handle egg removal and drop upon player logoff
//TODO: check if item spawn and item drop are overlapping, and check which can be replaced
// Drop egg if a player logs off with it in their inventory
//TODO: check if item spawn and item drop events overlap, and check which can be replaced
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onLogoff(PlayerQuitEvent event) {
Player player = event.getPlayer();
// Check if the player has a dragon egg
if (player.getInventory().contains(Material.DRAGON_EGG)) {
// Set owner and remove
setEggOwner(player);
data.setEggOwner(player); //TODO is this necessary? player will likely already be owner
player.getInventory().remove(Material.DRAGON_EGG);
// Drop it on the floor and set its location
//TODO use drop egg method in EggRespawn
Item egg_drop = event.getPlayer().getWorld().dropItem(player.getLocation(), new ItemStack(Material.DRAGON_EGG));
setEggLocation(egg_drop, Data.Egg_Storage_Type.ITEM);
data.updateEggLocation(egg_drop);
}
}
@ -91,10 +93,10 @@ public class EggHuntListener implements Listener {
ItemStack stack=item.getItemStack();
// Check if the dropped item is the egg
if(stack.getType().equals(Material.DRAGON_EGG)) {
setEggOwner(event.getPlayer());
setEggLocation(item, Egg_Storage_Type.ITEM);
setEggInv(event.getItemDrop());
if(isEgg(stack)) {
data.setEggOwner(event.getPlayer());
data.updateEggLocation(item);
makeEggInvulnerable(event.getItemDrop());
}
}
@ -105,23 +107,18 @@ public class EggHuntListener implements Listener {
// Check if the spawned item is the egg
Item item = event.getEntity();
if (item.getItemStack().getType().equals(Material.DRAGON_EGG)) {
setEggLocation(item, Egg_Storage_Type.ITEM);
setEggInv(event.getEntity());
if (isEgg(item)) {
data.updateEggLocation(item);
makeEggInvulnerable(event.getEntity());
}
}
// Handle the egg being held in an entity's inventory
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPickupItem(EntityPickupItemEvent event) {
// Check if item dropped is an egg
if(event.getItem().getItemStack().getType().equals(Material.DRAGON_EGG)) {
if (event.getEntity() instanceof Player) {
setEggOwner((Player) event.getEntity());
}
setEggLocation(event.getEntity(), Egg_Storage_Type.ENTITY_INV);
if(isEgg(event.getItem())) {
data.updateEggLocation(event.getEntity());
}
}
@ -132,160 +129,146 @@ public class EggHuntListener implements Listener {
// Check if the dragon egg was picked up
ItemStack item = event.getItem().getItemStack();
if (item.getType().equals(Material.DRAGON_EGG)){
if (event.getInventory().firstEmpty()!=-1 || event.getInventory().contains(Material.DRAGON_EGG)) {
if (event.getInventory().getHolder() instanceof Entity){
// Hopper minecart picked up the egg
setEggLocation((Entity)event.getInventory().getHolder(), Egg_Storage_Type.ENTITY_INV);
} else {
//hopper picked up the egg
setEggLocation(event.getInventory().getLocation(), Egg_Storage_Type.CONTAINER_INV);
}
if (isEgg(item)) {
//check if the inventory has open space
//TODO test this with edge cases for hopper pull/push
if (event.getInventory().firstEmpty() != -1 || event.getInventory().contains(Material.DRAGON_EGG)) {
data.updateEggLocation(event.getInventory());
}
}
}
/**
* When the player closes an inventory,
* check the player and the inventory for the egg when the inventory closes.
* This removes the need to check specifics about a player's clicks in an inventory
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryClose(InventoryCloseEvent event) {
//some storage, like anvils, can't actually store items, only hold them while the inventory is open
//since they don't revert to the player's inventory in the same tick, assume that the player, not the block, has the egg
boolean always_revert_to_player;
switch (event.getInventory().getType()) {
case ANVIL:
case CARTOGRAPHY:
case CRAFTING:
case ENCHANTING:
case GRINDSTONE:
case LECTERN:
case LOOM:
case MERCHANT:
case STONECUTTER:
case WORKBENCH:
always_revert_to_player=true;
break;
default:
always_revert_to_player=false;
break;
}
//check the player and the inventory for the egg when the inventory closes
//should replace the need to check specifics about a player's clicks in an inventory
Player player = (Player) event.getPlayer();
Inventory others = event.getInventory();
Inventory otherInv = event.getInventory();
if (player.getInventory().contains(Material.DRAGON_EGG) || (others.contains(Material.DRAGON_EGG) && always_revert_to_player)){
setEggLocation(player, Egg_Storage_Type.ENTITY_INV);
setEggOwner(player);
if (player.getInventory().contains(Material.DRAGON_EGG)) {
//if the player has the egg in their inventory, it will stay there
data.updateEggLocation(player);
data.setEggOwner(player);
} else if (others.getType()!= InventoryType.PLAYER) {
} else if (otherInv.contains(Material.DRAGON_EGG)) {
//check if the other inventory has the egg
if (others.contains(Material.DRAGON_EGG)) {
if (otherInv.getType() != InventoryType.PLAYER) { //TODO check how this affects player viewing own inventory (egg on head/offhand?)
if (otherInv.getHolder() instanceof Container) { //TODO test this works
//this is a container (chest, furnace, hopper minecart, etc), so the egg will remain here when the inventory is closed
data.updateEggLocation(otherInv);
if (others.getHolder() instanceof Entity) {
setEggLocation((Entity) others.getHolder(), Egg_Storage_Type.ENTITY_INV);
} else if (others.getType().equals(InventoryType.ENDER_CHEST)) {
//force any eggs in the ender chest to be dropped
if (config.getDropEnderchestedEgg() && player.getGameMode()!=GameMode.CREATIVE) {
ItemStack egg=others.getItem(others.first(Material.DRAGON_EGG));
egg.setAmount(1);
Location player_loc=player.getLocation();
others.remove(egg);
Item i=player_loc.getWorld().dropItemNaturally(player_loc, egg);
console_log(String.format("%s has the dragon egg in their ender chest, dropping it on the ground...", player.getName()));
console_log("Set ignore_echest_egg to \"true\" in the config file to disable this feature.");
setEggLocation(i, data.stored_as);
}
} else {
setEggLocation(others.getLocation(), Egg_Storage_Type.CONTAINER_INV);
}
//this is not a container (anvil, crafting table, villager, etc), so it will move back to the player's inventory
//note- if the player's inventory is full, it will instead drop as an item, which will trigger the item drop event
//force an egg in the ender chest to be dropped if enabled in config and if the player is not in creative
if (otherInv.getType().equals(InventoryType.ENDER_CHEST) && config.getDropEnderchestedEgg() && player.getGameMode() != GameMode.CREATIVE) {
ItemStack egg = otherInv.getItem(otherInv.first(Material.DRAGON_EGG));
Location playerLoc = player.getLocation();
otherInv.remove(egg);
Item i = playerLoc.getWorld().dropItem(playerLoc, egg); //TODO use drop item function
console_log(String.format(
"Dropped the dragon egg on the ground since %s had it in their ender chest.",
player.getName()));
console_log(
"Set ignore_echest_egg to \"true\" in the config file to disable this feature.");
data.updateEggLocation(i);
} else {
//the egg will appear in the player's inventory
data.updateEggLocation(player);
}
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryMove (InventoryMoveItemEvent event) {
//called when an inventory item is moved between blocks (hoppers, dispensers, etc)
//check if the item being moved is the egg
if (event.getItem().getType().equals(Material.DRAGON_EGG)) {
if (event.getDestination().firstEmpty()!=-1 || event.getDestination().contains(Material.DRAGON_EGG)) {
if (event.getDestination().getHolder() instanceof Entity) {
setEggLocation((Entity)event.getDestination().getHolder(), Egg_Storage_Type.ENTITY_INV);
}
else {
setEggLocation(event.getDestination().getLocation(), Egg_Storage_Type.CONTAINER_INV);
}
if (isEgg(event.getItem())) {
if (event.getDestination().firstEmpty() != -1 || event.getDestination().contains(Material.DRAGON_EGG)) {
data.updateEggLocation(event.getDestination());
}
}
}
//This function handles the egg being placed as a block
/**
* Handle the egg being placed as a block
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPlace (BlockPlaceEvent event) {
if (event.getBlock().getType().equals(Material.DRAGON_EGG)) {
setEggLocation(event.getBlock().getLocation(), Egg_Storage_Type.BLOCK);
setEggOwner(event.getPlayer());
if (isEgg(event.getBlock())) {
data.updateEggLocation(event.getBlock());
data.setEggOwner(event.getPlayer());
}
}
//This function handles the egg being placed in an item frame
/**
* Handle the egg being placed in an item frame
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInteract(PlayerInteractEntityEvent event) {
if(event.getRightClicked() instanceof ItemFrame) {
if (event.getRightClicked() instanceof ItemFrame) {
PlayerInventory player_inv = event.getPlayer().getInventory();
if(player_inv.getItemInMainHand().getType().equals(Material.DRAGON_EGG) || player_inv.getItemInOffHand().getType().equals(Material.DRAGON_EGG)) {
setEggLocation(event.getRightClicked(), Egg_Storage_Type.ENTITY_INV);
setEggOwner(event.getPlayer());
if (isEgg(player_inv.getItemInMainHand()) || isEgg(player_inv.getItemInOffHand())) {
data.updateEggLocation(event.getRightClicked());
data.setEggOwner(event.getPlayer());
}
}
}
//This function handles the egg teleporting
/**
* Handle the egg teleporting
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSpread(BlockFromToEvent event) {
if (event.getBlock().getType().equals(Material.DRAGON_EGG)) {
Block block;
if (config.getAccurateLocation()) {
block=event.getToBlock();
console_log("The egg teleported, location is set to show location after teleport");
} else {
block=event.getBlock();
if (isEgg(event.getBlock())) {
data.updateEggLocation(event.getToBlock());
if (!config.getAccurateLocation()) {
//TODO disable accuracy here
console_log("The egg teleported, location is set to show location before teleport");
} else {
console_log("The egg teleported, location is set to show location after teleport");
}
if (config.resetOwnerOnTeleport()) {
if (data.owner!=null) {
announce(String.format("The dragon egg has teleported. %s is no longer the owner.", get_username_from_uuid(data.owner)));
resetEggOwner(false);
if (data.getEggOwner()!=null) {
announce(String.format("The dragon egg has teleported. %s is no longer the owner.", data.getEggOwner().getName()));
data.resetEggOwner(false);
}
}
setEggLocation(block.getLocation(), Egg_Storage_Type.BLOCK);
}
}
//This function handles the egg as a falling block entity
/**
* Handle the egg as a falling block entity
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onFallingBlock(final EntityChangeBlockEvent event){
//check if this is dealing with a falling block
//check if this is dealing with a falling block, since EntityChangeBlockEvent is generic
if (event.getEntityType() == EntityType.FALLING_BLOCK) {
//check if the falling block is the egg
if (((FallingBlock)event.getEntity()).getBlockData().getMaterial().equals(Material.DRAGON_EGG)) {
//if the falling block is the egg
if (isEgg((FallingBlock)event.getEntity())) {
console_log("Gravity event involving dragon egg occured");
//block lands
if (event.getBlock().getType()==Material.AIR) {
setEggLocation(event.getBlock().getLocation(), Egg_Storage_Type.BLOCK);
}
//block begins falling
else if (event.getBlock().getType()==Material.DRAGON_EGG) {
//TODO: make falling block entities a separate storage type
setEggLocation(event.getEntity(),Egg_Storage_Type.ENTITY_INV);
if (event.getBlock().getType() == Material.AIR) {
//egg lands
data.updateEggLocation(event.getBlock());
} else if (event.getBlock().getType() == Material.DRAGON_EGG) {
//egg begins falling
data.updateEggLocation(event.getEntity());
}
}
}
@ -294,10 +277,10 @@ public class EggHuntListener implements Listener {
//if the egg item takes damage, call eggDestroyed
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityDamageEvent(EntityDamageEvent event) {
Entity entity=event.getEntity();
Entity entity = event.getEntity();
if (entity.getType().equals(EntityType.DROPPED_ITEM)) {
ItemStack item = ((Item)entity).getItemStack();
if (item.getType().equals(Material.DRAGON_EGG)) {
if (isEgg(item)) {
//make sure item is destroyed to prevent dupes
event.getEntity().remove();
eggDestroyed();
@ -305,23 +288,29 @@ public class EggHuntListener implements Listener {
}
}
//when the dragon dies, spawn the egg
//if the egg dies, call egg destroyed
/**
* Notifies that the egg is destroyed if the egg item dies
* Also respawns the egg when the dragon is killed
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityDeath(EntityDeathEvent event) {
//if the egg should respawn, and it does not exist, and the dragon is killed, and the dragon has already been killed, respawn the egg
if (event.getEntityType().equals(EntityType.DROPPED_ITEM)) {
if (((ItemStack)event.getEntity()).getType().equals(Material.DRAGON_EGG)) {
event.getEntity().remove();
eggDestroyed();
}
}
//if the egg item dies, notify that it has been destroyed
if (event.getEntityType().equals(EntityType.DROPPED_ITEM)) {
if (isEgg((ItemStack) event.getEntity())) {
//remove just in case to prevent dupes
event.getEntity().remove();
eggDestroyed();
}
}
//if the dragon is killed, respawn the egg
if (config.getRespawnEgg()) {
if (data.stored_as.equals(Egg_Storage_Type.DNE)) {
if (data.getEggType() == Egg_Storage_Type.DNE) {
//
if (event.getEntityType().equals(EntityType.ENDER_DRAGON)) {
//dragon is killed
if (config.getEndWorld().getEnderDragonBattle().hasBeenPreviouslyKilled()) {
if (config.getEndWorld().getEnderDragonBattle().hasBeenPreviouslyKilled()) {
//dragon has already been beaten
spawnEggBlock();
}
}
@ -329,8 +318,6 @@ public class EggHuntListener implements Listener {
}
}
//stop portals from removing the egg
@EventHandler(priority = EventPriority.MONITOR)
public void onCreatePortal(EntityCreatePortalEvent event) {
@ -339,16 +326,18 @@ public class EggHuntListener implements Listener {
Location l = null;
List<BlockState> blocks=event.getBlocks();
console_log(String.format("blocks: %s",blocks.toString()));
for (BlockState blockState: blocks) {
console_log(String.format("Block update at %s: from %s to %s", data.serializeLocation(blockState.getLocation()),blockState.getBlock().getType(),blockState.getType()));
if (blockState.getBlock().getType().equals(Material.DRAGON_EGG)) {
egg_affected=true;
l=blockState.getLocation();
//extra check to make sure egg is removed
blockState.getBlock().setType(Material.AIR);
}
}
for (BlockState blockState : blocks) {
console_log(String.format("Block update at %s: from %s to %s", blockState.getLocation(),
blockState.getBlock().getType(), blockState.getType()));
if (blockState.getBlock().getType().equals(Material.DRAGON_EGG)) {
egg_affected = true;
l = blockState.getLocation();
//extra check to make sure egg is removed
blockState.getBlock().setType(Material.AIR);
}
}
if (egg_affected) {
String entityName="Unknown entity";
if (event.getEntity()!=null) {
@ -357,11 +346,11 @@ public class EggHuntListener implements Listener {
}
}
console_log(String.format("%s tried to overwrite egg with a portal",entityName));
resetEggOwner(true);
data.resetEggOwner(true);
if (l!=null) {
spawnEggItem(l);
EggRespawn.spawnEggItem(l, config, data);
} else {
console_log("Could not spawn egg item! Invalid location.");
console_log("Could not spawn egg item! Invalid block location.");
}
}
@ -372,7 +361,7 @@ public class EggHuntListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onDespawn (ItemDespawnEvent event) {
//if the egg is going to despawn, cancel it
if (event.getEntity().getItemStack().getType().equals(Material.DRAGON_EGG)) {
if (isEgg(event.getEntity().getItemStack())) {
event.setCancelled(true);
//set the age back to 1 so it doesn't try to despawn every tick
event.getEntity().setTicksLived(1);
@ -383,51 +372,54 @@ public class EggHuntListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerDeath(PlayerDeathEvent event) {
if (!event.getKeepInventory() && event.getEntity().getInventory().contains(Material.DRAGON_EGG)) {
resetEggOwner(false);
String deathmsg = event.getDeathMessage();
data.resetEggOwner(false);
if (deathmsg == null) {
deathmsg="";
}
if (deathmsg.length() > 0) {
//change the death message
String deathmsg = event.getDeathMessage();
if (deathmsg == null || deathmsg.isBlank()) {
announce(String.format("%s died and lost the dragon egg!", event.getEntity().getDisplayName()));
} else {
if (deathmsg.endsWith(".")) {
deathmsg= deathmsg.substring(0,deathmsg.length() - 1);
deathmsg = deathmsg.substring(0, deathmsg.length() - 1);
}
event.setDeathMessage(String.format("%s and lost the dragon egg!", deathmsg));
} else {
announce(String.format("%s died and lost the dragon egg!", event.getEntity().getDisplayName()));
}
}
}
//stop mushrooms from removing the egg
/**
* stop mushrooms from removing the egg
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onGrow(StructureGrowEvent event) {
boolean cancel=false;
if (event.getSpecies().equals(TreeType.BROWN_MUSHROOM) || event.getSpecies().equals(TreeType.RED_MUSHROOM)) {
List<BlockState> blocks=event.getBlocks();
for (BlockState block : blocks) {
if (block.getBlock().getType().equals(Material.DRAGON_EGG)) {
cancel=true;
break;
}
}
if (cancel) {
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);
console_log(String.format("%s tried to mushroom the dragon egg", p.getName()));
}
}
}
boolean cancel = false;
if (event.getSpecies().equals(TreeType.BROWN_MUSHROOM) || event.getSpecies().equals(TreeType.RED_MUSHROOM)) {
List<BlockState> blocks = event.getBlocks();
for (BlockState block : blocks) {
if (isEgg(block.getBlock())) {
cancel = true;
break;
}
}
if (cancel) {
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);
console_log(String.format("%s tried to mushroom the dragon egg", p.getName()));
}
}
}
}
//TODO: 1.17: also exclude bundles
// stop players from echesting the egg or storing it in a shulker box
/**
* stop players from storing the egg in an ender chest or shulker box
* TODO: 1.17+: also exclude bundles
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryMoveConsider(InventoryClickEvent event) {
InventoryType inv = event.getInventory().getType();
@ -435,17 +427,17 @@ public class EggHuntListener implements Listener {
if (inv.equals(InventoryType.ENDER_CHEST) || inv.equals(InventoryType.SHULKER_BOX)) {
//check if the item clicked was the egg
if (event.getCurrentItem() != null) {
if (event.getCurrentItem().getType().equals(Material.DRAGON_EGG)) {
if (isEgg(event.getCurrentItem())) {
event.setCancelled(true);
console_log(String.format("Stopped %s from moving egg to ender chest",
event.getWhoClicked().getName()));
}
}
//Don't allow hotkeying either
//don't allow hotkeying either
if (event.getClick().equals(ClickType.NUMBER_KEY)) {
ItemStack item = event.getWhoClicked().getInventory().getItem(event.getHotbarButton());
if (item != null) {
if (item.getType().equals(Material.DRAGON_EGG)) {
if (isEgg(item)) {
event.setCancelled(true);
console_log(String.format("Stopped %s from hotkeying egg to ender chest",
event.getWhoClicked().getName()));
@ -456,12 +448,14 @@ public class EggHuntListener implements Listener {
}
}
//stop players from pushing the egg into a shulker using a hopper/hopper minecart
/**
* stop players from pushing the egg into a shulker using a hopper/hopper minecart
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void onPushConsider (InventoryMoveItemEvent event) {
//nice try, but it won't work
if (event.getDestination().getType().equals(InventoryType.SHULKER_BOX)){
if (event.getItem().getType().equals(Material.DRAGON_EGG)) {
if (isEgg(event.getItem())) {
event.setCancelled(true);
}
}
@ -474,8 +468,7 @@ public class EggHuntListener implements Listener {
if (config.getEggInvincible()) {
Entity entity=event.getEntity();
if (entity.getType().equals(EntityType.DROPPED_ITEM)) {
ItemStack item = ((Item)entity).getItemStack();
if (item.getType().equals(Material.DRAGON_EGG)) {
if (isEgg((Item)entity)) {
event.setCancelled(true);
}
}
@ -485,7 +478,8 @@ public class EggHuntListener implements Listener {
//Helper methods
//When a portal is updated, check if the egg will be replaced
private void checkPortalBlocks(){
private void checkPortalBlocks() {
//TODO there has to be a better way to do this
//Check end platform
Location l1=new Location(config.getEndWorld(),102,48,2);
Location l2=new Location(config.getEndWorld(),98,51,-2);
@ -493,22 +487,31 @@ public class EggHuntListener implements Listener {
if (res!=null) {
portalOverwriteEgg(res);
}
}
private void portalOverwriteEgg(Location res) {
res.getBlock().setType(Material.AIR);
console_log("Prevented egg overwrite with a portal");
resetEggOwner(true);
data.resetEggOwner(true); //TODO see if this can be used to spam chat, update if needed
if (config.getEggInvincible()) {
spawnEggItem(res);
EggRespawn.spawnEggItem(res, config, data);
} else {
eggDestroyed();
}
}
//Checks various blocks for the given material
/**
* Checks various blocks for the given material
* @param w world the position is in
* @param m material to check
* @param x1 starting x pos
* @param x2 ending x pos
* @param y1 starting y pos
* @param y2 ending y pos
* @param z1 starting z pos
* @param z2 ending z pos
* @return
*/
private static Location checkBlockMaterial(World w, Material m, int x1, int x2, int y1, int y2, int z1, int z2) {
for (int x=x1; x<x2; x++) {
for (int y=y1; y<y2; y++) {
@ -526,104 +529,60 @@ public class EggHuntListener implements Listener {
return checkBlockMaterial(w,m,l1.getBlockX(),l1.getBlockY(),l1.getBlockZ(),l2.getBlockX(),l2.getBlockY(),l2.getBlockZ());
}
//Calls CheckBlockMaterial with deltas
/**
* Calls CheckBlockMaterial with deltas
*/
private static Location checkDeltaBlockMaterial(World w, Material m, int x, int dx, int y, int dy, int z, int dz) {
return (checkBlockMaterial(w, m, x, x+dx, y, y+dy, z, z+dz));
}
private void resetEggOwner(boolean announce) {
if (announce) {
if (data.owner!=null) {
announce(String.format("%s no longer owns the dragon egg", get_username_from_uuid(data.owner)));
}
}
console_log("Reset egg owner");
data.owner=null;
data.saveData();
}
private void setEggOwner(Player player) {
console_log(player.getName().concat(" has the egg."));
String formatStr;
//check if ownership switched
//make sure owner has actually changed so getting the egg again doesn't unnecessairly update the db
if (data.owner != null && !player.getUniqueId().equals(data.owner)) {
formatStr = "%s has stolen the dragon egg!";
} else if (data.owner == null) {
formatStr = "%s has claimed the dragon egg!";
} else {
return;
}
//update owner and announce to players
data.owner=player.getUniqueId();
data.saveData();
announce(String.format(formatStr, player.getName()));
}
private void setEggLocation(Location egg_loc, Egg_Storage_Type store_type) {
data.loc=egg_loc;
data.stored_entity=null;
data.stored_as=store_type;
console_log(String.format("The egg has moved to block %s as %s", egg_loc, store_type.toString()));
data.saveData();
}
private void setEggLocation(Entity entity, Egg_Storage_Type store_type) {
data.loc=null;
data.stored_entity=entity;
data.stored_as=store_type;
console_log(String.format("The egg has moved to entity %s (%s) as %s", entity, entity.getLocation(), store_type.toString()));
data.saveData();
}
private void setEggInv(Entity egg_stack) {
private void makeEggInvulnerable(Entity egg_stack) {
if (config.getEggInvincible()) {
egg_stack.setInvulnerable(true);
console_log("made drop invulnerable");
}
}
private void eggDestroyed() {
public void eggDestroyed() {
announce("The dragon egg has been destroyed!");
resetEggOwner(false);
data.owner=null;
data.stored_as=Egg_Storage_Type.DNE;
data.loc=null;
data.stored_entity=null;
data.saveData();
data.resetEggOwner(false);
if (config.getRespawnEgg()) {
if (config.getRespawnImmediately()) {
spawnEggBlock();
} else {
} else {
data.resetEggLocation();
announce("It will respawn the next time the dragon is defeated");
}
}
}
private void spawnEggBlock() {
Location new_egg_loc=config.getEndWorld().getEnderDragonBattle().getEndPortalLocation().add(0, 4, 0);
new_egg_loc.getBlock().setType(Material.DRAGON_EGG);
setEggLocation(new_egg_loc,Egg_Storage_Type.BLOCK);
Block newEggLoc=config.getEndWorld().getEnderDragonBattle().getEndPortalLocation().add(0, 4, 0).getBlock();
data.updateEggLocation(newEggLoc);
announce("The dragon egg has spawned in the end!");
}
public void spawnEggItem(Location loc){
ItemStack egg=new ItemStack(Material.DRAGON_EGG);
egg.setAmount(1);
Item drop=loc.getWorld().dropItem(loc, egg);
drop.setGravity(false);
drop.setGlowing(true);
drop.setVelocity(new Vector().setX(0).setY(0).setZ(0));
if (config.getEggInvincible()) {
drop.setInvulnerable(true);
}
setEggLocation(drop, Egg_Storage_Type.ITEM);
private boolean isEgg(ItemStack stack) {
return stack.getType().equals(Material.DRAGON_EGG);
}
private boolean isEgg(Item item) {
return item.getType().equals(Material.DRAGON_EGG);
}
private boolean isEgg(Block block) {
return block.getType().equals(Material.DRAGON_EGG);
}
private boolean isEgg(FallingBlock block) {
return block.getBlockData().getMaterial().equals(Material.DRAGON_EGG);
}
private ItemStack makeEgg() {
return new ItemStack(Material.DRAGON_EGG);
}
private void announce(String msg) {
Announcement.announce(msg, logger);
}
@ -632,7 +591,4 @@ public class EggHuntListener implements Listener {
logger.info(message);
}
}

View file

@ -0,0 +1,25 @@
package io.github.J0hnL0cke.egghunt.Controller;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import io.github.J0hnL0cke.egghunt.Model.Configuration;
import io.github.J0hnL0cke.egghunt.Model.Data;
public class EggRespawn {
public static void spawnEggItem(Location loc, Configuration config, Data data){
ItemStack egg=new ItemStack(Material.DRAGON_EGG);
egg.setAmount(1);
Item drop=loc.getWorld().dropItem(loc, egg);
drop.setGravity(false);
drop.setGlowing(true);
drop.setVelocity(new Vector().setX(0).setY(0).setZ(0));
if (config.getEggInvincible()) {
drop.setInvulnerable(true);
}
data.updateEggLocation(drop);
}
}

View file

@ -1,5 +1,7 @@
package io.github.J0hnL0cke.egghunt.Controller;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@ -23,31 +25,58 @@ public class EventScheduler extends BukkitRunnable {
private Data data;
private Configuration config;
private Logger logger;
public EventScheduler(Configuration config, Data data) {
public EventScheduler(Configuration config, Data data, Logger logger) {
this.data = data;
this.config = config;
this.logger = logger;
}
@Override
public void run() {
// check if the entity storing the egg has fallen out of the world
if (data.stored_as.equals(Data.Egg_Storage_Type.ENTITY_INV)) {
Entity entity = data.stored_entity;
if (entity != null) {
// TODO: check if this check is needed
if (hasEgg(entity)) {
if (isUnderWorld(entity)) {
removeEgg(entity);
//TODO handle launching egg into void faster than the timer tick
//TODO first check if chunk is loaded
if (data.getEggType() == Data.Egg_Storage_Type.ENTITY) {
if (isUnderWorld(data.getEggEntity())) {
Location respawnLoc = data.getEggEntity().getLocation();
removeMaterialFromEntity(Material.DRAGON_EGG, data.getEggEntity());
if (config.getEggInvincible()) {
// get coords for egg to spawn at
//get highest block
Block highestBlock = respawnLoc.getWorld().getHighestBlockAt(respawnLoc);
int yPos = highestBlock.getY();
//if no highest block, default to sea level (world height / 2)
if (highestBlock.isEmpty()) {
yPos = respawnLoc.getWorld().getMaxHeight() / 2;
}
respawnLoc.setY(yPos);
EggRespawn.spawnEggItem(respawnLoc, config, data);
} else {
eggDestroyed();
respawnEgg(respawnLoc);
}
data.resetEggOwner(true);
}
} else if (data.stored_as.equals(Data.Egg_Storage_Type.ITEM)) {
Entity item = data.stored_entity;
if (item != null) {
if (isUnderWorld(item)) {
removeEgg(item);
}
}
}
private void eggDestroyed() {
Announcement.announce("The dragon egg has been destroyed!", logger);
data.resetEggOwner(false);
}
private void respawnEgg(Location respawnLoc) {
if (config.getRespawnEgg()) {
if (config.getRespawnImmediately()) {
} else {
data.resetEggLocation();
Announcement.announce("It will respawn the next time the dragon is defeated", logger);
}
}
}
@ -76,35 +105,29 @@ public class EventScheduler extends BukkitRunnable {
return entity.getLocation().getY() < UNDER_WORLD_HEIGHT;
}
public void removeEgg(Entity container) {
Location l = container.getLocation();
removeMaterialFromEntity(Material.DRAGON_EGG, container);
if (config.getEggInvincible()) {
// get coords for egg to spawn at
// TODO: handle negative y coords in 1.17
Block block_pos = l.getWorld().getHighestBlockAt(l);
int y_pos = block_pos.getY();
if (block_pos.isEmpty()) {
y_pos = l.getWorld().getMaxHeight()/2; //respawn around sea level (world height / 2) if no blocks underneath
}
l.setY(y_pos);
EggHuntListener.spawnEggItem(l);
} else {
EggHuntListener.eggDestroyed();
}
EggHuntListener.resetEggOwner(true);
}
public void removeMaterialFromEntity(Material m, Entity entity) {
data.stored_as = Data.Egg_Storage_Type.DNE;
if (entity instanceof Player) {
Player player = (Player) entity;
player.getInventory().remove(m);
} else if (entity instanceof LivingEntity) {
switch (entity.getType()) {
case PLAYER: {
Player player = (Player) entity;
player.getInventory().remove(m);
return;
}
case DROPPED_ITEM: {
((Item) entity).remove();
return;
}
case FALLING_BLOCK: {
((FallingBlock) entity).remove();
return;
}
default: {
}
}
if (entity instanceof LivingEntity) {
LivingEntity live = (LivingEntity) entity;
EntityEquipment equipment = ((LivingEntity) entity).getEquipment();
if (equipment != null) {
// TODO: consider all armor slots, not just hands
if (equipment.getItemInMainHand().getType().equals(m)) {
equipment.setItemInMainHand(null);
}
@ -112,10 +135,6 @@ public class EventScheduler extends BukkitRunnable {
equipment.setItemInOffHand(null);
}
}
} else if (entity instanceof Item) {
((Item) entity).remove();
} else if (entity instanceof FallingBlock) {
((FallingBlock) entity).remove();
}
}

View file

@ -3,7 +3,7 @@ package io.github.J0hnL0cke.egghunt.Model;
import org.bukkit.Bukkit;
import org.bukkit.World;
import io.github.J0hnL0cke.egghunt.Persistence.ConfigDAO;
import io.github.J0hnL0cke.egghunt.Persistence.ConfigFileDAO;
/**
* Retrieve settings for this plugin
@ -19,9 +19,9 @@ public class Configuration {
public static String defaultEnd = "world_end"; /** default end world name for most spigot servers */
ConfigDAO fileDao;
ConfigFileDAO fileDao;
public Configuration(ConfigDAO fileDao) {
public Configuration(ConfigFileDAO fileDao) {
this.fileDao = fileDao;
loadData();
}

View file

@ -6,154 +6,216 @@ import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import io.github.J0hnL0cke.egghunt.Persistence.DataDAO;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import io.github.J0hnL0cke.egghunt.Controller.Announcement;
import io.github.J0hnL0cke.egghunt.Persistence.DataFileDAO;
/**
* Retrieve and store this plugin's data
* Retrieves and stores this plugin's data
*/
public class Data {
private DataDAO dataDao;
private DataFileDAO dataDao;
private Logger logger;
public enum Egg_Storage_Type {
ITEM,
ENTITY,
BLOCK,
ENTITY_INV,
CONTAINER_INV,
DNE, //egg does not exist
}
public Location loc;
public Entity stored_entity;
public UUID owner;
public Egg_Storage_Type stored_as;
private Location approxLocation;
private UUID owner;
private Egg_Storage_Type storedAs;
private Block block;
private Entity entity;
public Data(DataDAO dataDAO, Logger logger) {
public Data(DataFileDAO dataDAO, Logger logger) {
dataDAO = this.dataDao;
loadData();
//TODO figure out a better schema for getting/setting egg data than making everything public
}
public Location getEggLocation() {
if (stored_as != Egg_Storage_Type.DNE) {
boolean is_entity;
if (storedAs == Egg_Storage_Type.DNE) {
return null;
} else if (storedAs == Egg_Storage_Type.BLOCK) {
return block.getLocation();
} else if (storedAs == Egg_Storage_Type.ENTITY) {
return entity.getLocation();
}
return null;
}
switch (stored_as) {
case BLOCK:
case CONTAINER_INV:
is_entity=false;
break;
case ENTITY_INV:
case ITEM:
is_entity=true;
break;
default:
throw new java.lang.Error("Unknown egg storage type when calling getEggLocation()"); //fail loudly instead of silently, you're welcome
}
return is_entity ? stored_entity.getLocation() : loc;
}
return null;
}
public Egg_Storage_Type getEggType() {
return storedAs;
}
public Entity getEggEntity() {
return entity;
}
public Block getEggBlock() {
return block;
}
public OfflinePlayer getEggOwner() {
return Bukkit.getOfflinePlayer(owner);
}
public void loadData() {
//load egg location
//load stored_as
stored_as=dataDao.read("stored_as", Egg_Storage_Type.class, Egg_Storage_Type.DNE);
//load owner
owner=dataDao.read("owner", UUID.class, null);
//load loc
//TODO major refactor to this
String loc_str=dataDao.read("loc", String.class, null);
boolean needs_loc_str = stored_as == Egg_Storage_Type.BLOCK
|| stored_as == Egg_Storage_Type.CONTAINER_INV;
if (loc_str!=null) {
String[] loc_arr=loc_str.split(":");
if (loc_arr.length==4) {
World w = Bukkit.getServer().getWorld(loc_arr[0]);
double x = Double.parseDouble(loc_arr[1]);
double y = Double.parseDouble(loc_arr[2]);
double z = Double.parseDouble(loc_arr[3]);
loc=new Location(w,x,y,z);
} else {
logger.warning("Invalid block location string");
}
} else {
if (needs_loc_str) {
logger.warning("Location string was null when it should have a value");
}
loc=null;
}
//load stored_entity
String stored_entity=dataDao.read("stored_entity", String.class, null);
boolean needs_stored_entity=stored_as==Egg_Storage_Type.ENTITY_INV || stored_as==Egg_Storage_Type.ITEM;
if (stored_entity!=null) {
UUID id=UUID.fromString(stored_entity);
this.stored_entity=Bukkit.getEntity(id);
//if the entity is not found
if (this.stored_entity==null && needs_stored_entity) {
logger.warning("Could not locate entity from saved UUID");
}
} else {
stored_entity=null;
if (needs_stored_entity) {
logger.warning("Stored entity was null when it should have a value");
}
}
owner = dataDao.read("owner", UUID.class, null);
block = dataDao.read("block", Block.class, null);
entity = dataDao.read("entity", Entity.class, null);
approxLocation = dataDao.read("lastLocation", Location.class, null);
storedAs = dataDao.read("storedAs", Egg_Storage_Type.class, null);
if (storedAs == null) {
logger.warning("Could not correctly load egg location data! Was this plugin's data folder deleted?\n" +
"If this is the first time this plugin has run, it is safe to ignore this error.");
storedAs = Egg_Storage_Type.DNE;
saveData();
}
}
public void saveData() {
//save loc
dataDao.write("loc", loc);
//save stored_entity
dataDao.write("stored_entity", stored_entity);
//save block/entity name to DB
String name;
switch (stored_as) {
case BLOCK: name="block";
break;
case CONTAINER_INV: name=loc.getBlock().getType().toString();
break;
case DNE: name=null;
break;
case ENTITY_INV:
String entityName=stored_entity.getName();
String entityType=stored_entity.getType().toString();
name=String.format("%s:%s",entityType,entityName);
break;
case ITEM: name="item";
break;
default: throw new java.lang.Error("Unknown egg storage type");
}
//save stored_as
if (stored_as!=null) {
dataDao.write("stored_as", stored_as.name());
} else {
dataDao.write("stored_as", Egg_Storage_Type.DNE.name());
}
//save owner
public void saveData() {
dataDao.write("owner", owner);
//save timestamp
dataDao.write("timestamp", LocalDateTime.now().toString());
dataDao.write("block", block);
dataDao.write("entity", entity);
dataDao.write("lastLocation", approxLocation);
dataDao.write("storedAs", storedAs);
//save timestamp
dataDao.write("FileWriteTime", LocalDateTime.now().toString());
//write to file
dataDao.save();
}
}
public String serializeLocation(Location loc) {
return loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ();
}
@Deprecated
private String locationToString(Location loc) {
return loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ();
}
public void setEggOwner(Player player) {
setEggOwner(player.getUniqueId());
}
private void setEggOwner(UUID playerUUID) {
owner = playerUUID;
}
public void resetEggOwner(boolean announce) {
if (announce) { //TODO move announcements somewhere else?
if (owner != null) {
Announcement.announce(String.format("%s no longer owns the dragon egg", Bukkit.getOfflinePlayer(owner)), logger);
}
}
logger.info("Egg owner has been reset");
owner = null;
saveData();
}
public void resetEggLocation() {
log("Egg no longer exists");
block = null;
entity = null;
storedAs = Egg_Storage_Type.DNE;
saveData();
}
public void updateEggLocation(Block block) {
approxLocation = block.getLocation();
this.block = block;
entity = null;
storedAs=Egg_Storage_Type.BLOCK;
switch (block.getType()) {
case DRAGON_EGG: {
//egg is stored as a block
log(String.format("The egg is placed as a block"));
}
default: {
//egg is stored within the inventory of a tile entity (chest, hopper, furnace, etc)
log(String.format("The egg is in a(n) %s", block.getType()));
}
}
saveData();
}
public void updateEggLocation(Entity holderEntity) {
approxLocation = holderEntity.getLocation();
entity = holderEntity;
block = null;
storedAs = Egg_Storage_Type.ENTITY;
switch (holderEntity.getType()) {
case PLAYER: {
//TODO Switch posession here
log(String.format("The egg is in the inventory of the player \"%s\"", entity.getName()));
}
case FALLING_BLOCK: {
log(String.format("The egg is a falling block"));
}
case DROPPED_ITEM: {
log(String.format("The egg is a dropped item"));
}
case ITEM_FRAME: {
log(String.format("The egg is an item frame"));
}
case ARMOR_STAND: {
log(String.format("The egg is held by an armor stand"));
}
default:
//stored in the inventory of a non-player entity (zombie, hopper minecart, etc)
if (entity.getCustomName() != null) {
log(String.format("The egg is held by a(n) %s named \"%s\"", entity.getType().toString(),
entity.getName()));
} else {
log(String.format("The egg is held by a(n) %s", entity.getType().toString()));
}
}
saveData();
}
public void updateEggLocation(Inventory holder) {
//likely to be called when a generic inventory is the most info given for what picked up an item, like on hopper collect event
//if more info is available (such as Entity or Block instance), better to pass that instead, although this should still work
if (holder instanceof Entity){
// Hopper minecart (or some other entity) picked up the egg
updateEggLocation((Entity)holder);
} else {
// Hopper picked up the egg
updateEggLocation((Block)holder); //TODO check if this cast works or if .getLocation().getBlock() is needed
}
}
private void log(String msg) {
logger.info(msg);
}
}

View file

@ -5,11 +5,11 @@ import org.bukkit.plugin.java.JavaPlugin;
/**
* Reads and writes key/value pairs to/from the plugin's config.yml file
*/
public class ConfigDAO {
public class ConfigFileDAO {
JavaPlugin plugin;
public ConfigDAO(JavaPlugin plugin) {
public ConfigFileDAO(JavaPlugin plugin) {
this.plugin = plugin;
}

View file

@ -8,24 +8,24 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
public class DataDAO {
public class DataFileDAO {
public static final String DATA_FILE = "data.yml";
private static DataDAO thisDao;
private static DataFileDAO thisDao;
private FileConfiguration fileConfig;
private File file;
JavaPlugin plugin;
private DataDAO(JavaPlugin plugin){
private DataFileDAO(JavaPlugin plugin){
this.plugin = plugin;
loadData(plugin, DATA_FILE);
}
public static DataDAO getDataDAO(JavaPlugin plugin){
public static DataFileDAO getDataDAO(JavaPlugin plugin){
if(thisDao == null){
thisDao = new DataDAO(plugin);
thisDao = new DataFileDAO(plugin);
}
return thisDao;
}

View file

@ -1,5 +1,7 @@
package io.github.J0hnL0cke.egghunt;
import java.util.logging.Logger;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
@ -10,8 +12,8 @@ import io.github.J0hnL0cke.egghunt.Controller.EggHuntListener;
import io.github.J0hnL0cke.egghunt.Controller.EventScheduler;
import io.github.J0hnL0cke.egghunt.Model.Configuration;
import io.github.J0hnL0cke.egghunt.Model.Data;
import io.github.J0hnL0cke.egghunt.Persistence.ConfigDAO;
import io.github.J0hnL0cke.egghunt.Persistence.DataDAO;
import io.github.J0hnL0cke.egghunt.Persistence.ConfigFileDAO;
import io.github.J0hnL0cke.egghunt.Persistence.DataFileDAO;
public final class egghunt extends JavaPlugin {
@ -21,45 +23,50 @@ public final class egghunt extends JavaPlugin {
EventScheduler schedule;
EggHuntListener listener;
BukkitTask belowWorldTask;
BukkitTask belowWorldTask;
Logger logger;
@Override
public void onEnable() {
getLogger().info("onEnable has been invoked, starting EggHunt.");
logger = getLogger();
log("onEnable has been invoked, starting EggHunt.");
saveDefaultConfig();
//create model instances using dependency injection
config = new Configuration(new ConfigDAO(this));
data = new Data(DataDAO.getDataDAO(this), getLogger());
config = new Configuration(new ConfigFileDAO(this));
data = new Data(DataFileDAO.getDataDAO(this), getLogger());
//create controller instances
listener = new EggHuntListener(getLogger(), config, data);
schedule = new EventScheduler(config, data);
schedule = new EventScheduler(config, data, logger);
//register event handlers
getLogger().info("registering event listeners.");
log("registering event listeners.");
getServer().getPluginManager().registerEvents(listener, this);
//schedule tasks
//TODO: disable task when not in use
getLogger().info("Scheduling below world task");
log("Scheduling below world task");
belowWorldTask = schedule.runTaskTimer(this, 20, 20);
getLogger().info("Done!");
log("Done!");
}
@Override
public void onDisable() {
getLogger().info("onDisable has been invoked.");
log("onDisable has been invoked.");
if (belowWorldTask!=null) {
belowWorldTask.cancel();
}
getLogger().info("Done!");
log("Plugin disabled.");
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
return commandHandler.onCommand(sender, cmd, label, args);
}
}
private void log(String msg) {
logger.info(msg);
}
}

View file

@ -1,4 +1,4 @@
#name of your end world, defaults to "world_the_end" on spigot
#name of your end world, usually to "world_the_end" on spigot
end: world_the_end
#whether the egg teleporting resets the owner to none