Merge branch 'development'
This commit is contained in:
commit
0c5272e679
17 changed files with 1335 additions and 575 deletions
50
README.md
50
README.md
|
|
@ -1,42 +1,48 @@
|
|||
# Egg Hunt
|
||||
**A plugin for hunting down the dragon egg and stealing it from other players.**
|
||||
|
||||
<img src="https://github.com/HyperSMP/EggHuntPlugin/assets/51202569/c0c860ee-bfa1-480f-baad-12874467416c" width="200" height="200">
|
||||
|
||||
**With this plugin:**
|
||||
# Egg Hunt
|
||||
A plugin for hunting down the dragon egg and stealing it from other players.
|
||||
|
||||
- The dragon egg cannot be stored in an ender chest, bundle, or shulker box.
|
||||
## Plugin Summary
|
||||
|
||||
- The dragon egg cannot be stored in an ender chest.
|
||||
- The egg item will drop on the ground if you leave the game with it in your inventory.
|
||||
- The egg item cannot despawn.
|
||||
- The plugin has an owner system. Taking the egg will give you ownership.
|
||||
- Ownership is tracked through a last-held system- picking up the egg will give you ownership of it.
|
||||
- Dying with the egg, having it stolen, or losing it will change ownership accordingly.
|
||||
- The egg can be located/tracked regardless of whether it's a block, an item, or in an inventory, and in any dimension.
|
||||
- The egg can be located/tracked regardless of whether it's a block, an item, or in an inventory, and across any dimension.
|
||||
|
||||
**Commands:**
|
||||
### Commands
|
||||
- `/eggowner` - displays the name of the player who currently owns the egg
|
||||
- `/locateegg` - displays the current coordinates of the egg, as well as how it's being stored
|
||||
- `/trackegg` - points the compass in your hand towards the egg
|
||||
|
||||
**Customization:**
|
||||
## Customization
|
||||
|
||||
This plugin's configuration file (`config.yml`) allows for several gameplay customizations to accomodate different types of servers.
|
||||
- The egg can be made invulnerable, or can be set to respawn in the end when it gets destroyed
|
||||
- The egg can be made invulnerable, or can be set to respawn in The End when it is destroyed
|
||||
- If set to respawn, the egg can either respawn immediately, or only after the dragon is beaten again
|
||||
- When the egg teleports, it will become "lost", so it won't have an owner until someone finds it again
|
||||
- Dragon eggs that are already stored in a player's ender chest can be excluded from the hunt.
|
||||
- When the egg teleports, it can become "lost", so it will no longer have an owner until a player finds it
|
||||
- Dragon eggs that are already stored in a player's ender chest can be excluded from the hunt
|
||||
- The egg owner is tracked with an entity tag, so you target them with the selector `@a[tag=eggOwner]` in any commands.
|
||||
- Scoreboards track the amount of time each player has owned the dragon egg, and can be configured to track named entities as if those entities actually owned the egg.
|
||||
|
||||
**Installation**
|
||||
- Save the provided .jar file to your server's `/plugins` directory. Alternatively, you can compile the .jar file yourself by cloning this repository to a local directory and running the maven command `mvn package`. The packaged .jar will appear in `/EggHuntPlugin/target/`
|
||||
## Installation
|
||||
- Save the provided .jar file to your server's `/plugins` directory. Alternatively, you can compile the .jar file yourself by cloning this repository to a local directory and running the maven command `mvn package`. The packaged .jar will appear in `/EggHuntPlugin/target/`.
|
||||
- Restart (or `/reload`) the server to generate the `/plugins/EggHunt` directory, which will contain the plugin's config file.
|
||||
- Open `config.yml` in any text editor to change the settings, then restart (or reload) the server to apply the changes.
|
||||
If the dragon egg has already been found, update its location in the plugin by picking up the egg item or by breaking and re-placing the egg block.
|
||||
- If the dragon egg has already been found, update the plugin's record of the egg's location by picking up the egg item or by breaking and re-placing the egg block.
|
||||
|
||||
**Notes for Server Owners:**
|
||||
- Best paired with an anticheat to prevent duplication (unless you are using paperspigot, which disables falling block dupes by default)
|
||||
- The egg location does not update when taken out of an inventory (eg chest) until the inventory is closed, so you should also enable [inventory close](https://github.com/NoCheatPlus/Docs/wiki/%5BInventory%5D-Open) on your anticheat to prevent the player from teleporting away with their inventory open
|
||||
## Notes for Server Owners
|
||||
- Best paired with an anticheat to prevent duplication. (Unless you are using Paper or Spigot, which disable falling block dupes by default)
|
||||
- The egg location does not update when taken out of an inventory (eg chest) until the inventory is closed, so you should also enable [inventory close](https://github.com/NoCheatPlus/Docs/wiki/%5BInventory%5D-Open) on your anticheat to prevent the player from teleporting away with their inventory open.
|
||||
- Only players in creative mode can move the egg into an ender chest.
|
||||
- You can allow players to have dragon eggs in their ender chests that are not tracked. This is enabled by default in the config.yml under "ignore_echest_egg"
|
||||
- Most settings you might need can be changed via the plugin's config file (/EggHunt/config.yml), open an issue if you don't see a setting you want
|
||||
- You can disallow players from using certain commands in this plugin if you are also using a permissions plugin
|
||||
- It is safe to use the Bukkit `/reload` command while this plugin is running
|
||||
- You can allow players to have dragon eggs in their ender chests that are not tracked. This is enabled by default in the config file under "ignore_echest_egg".
|
||||
- Most settings you might need can be changed via the plugin's config file (`/EggHunt/config.yml`). Open an issue on GitHub if you don't see a setting you want.
|
||||
- You can disallow players from using certain commands in this plugin. See the `plugin.yml` file for a list of permissions.
|
||||
- It is safe to use the Bukkit `/reload` command while this plugin is running.
|
||||
- When resetting the world, also delete the `data.yml` file.
|
||||
|
||||
# Reporting Bugs
|
||||
Make sure you are running the latest version of this plugin and read that version's Known Issues list to make sure you aren't reporting a known issue.
|
||||
To report a bug, please open a new [Issue](https://github.com/HyperSMP/EggHuntPlugin/issues) in this repository and fill out the bug report template.
|
||||
|
|
@ -2,29 +2,92 @@ package io.github.J0hnL0cke.egghunt.Controller;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
/**
|
||||
* Misc helper methods relating to player notification
|
||||
*/
|
||||
public class Announcement {
|
||||
public static void announce(String message, Logger logger) {
|
||||
|
||||
private static final String PREFIX_FORMAT_CODE = ChatColor.COLOR_CHAR+"l"; //bold
|
||||
private static final ChatColor PREFIX_COLOR = ChatColor.DARK_PURPLE;
|
||||
private static final ChatColor LOCATION_COLOR = ChatColor.GREEN;
|
||||
private static final ChatColor CORRECT_COLOR = ChatColor.DARK_GREEN;
|
||||
private static final ChatColor INCORRECT_COLOR = ChatColor.RED;
|
||||
private static final ChatColor RESET_CODE = ChatColor.RESET;
|
||||
private static final String RAW_MESSAGE_PREFIX = "[Egg Hunt] ";
|
||||
|
||||
public static void sendMessage(Player p, String message) {
|
||||
p.sendMessage(formatMessage(message));
|
||||
}
|
||||
|
||||
public static String formatLocation(Location destination, Location origin) {
|
||||
//stringify the egg's location
|
||||
int x = destination.getBlockX();
|
||||
int y = destination.getBlockY();
|
||||
int z = destination.getBlockZ();
|
||||
World world = destination.getWorld();
|
||||
|
||||
//whether the two locations are in the same world, or false if origin is null
|
||||
boolean sameWorld = origin != null && origin.getWorld().equals(destination.getWorld());
|
||||
|
||||
String worldName = formatWorld(world, sameWorld);
|
||||
|
||||
String distanceStr = "";
|
||||
if (sameWorld) {
|
||||
double distance = destination.distance(origin);
|
||||
if (!Double.isNaN(distance)) {
|
||||
distanceStr = String.format(" (%d blocks away)", (int)distance);
|
||||
}
|
||||
}
|
||||
|
||||
String loc = String.format("[%d, %d, %d]", x, y, z);
|
||||
|
||||
return String.format("%s%s%s in %s%s", LOCATION_COLOR, loc, RESET_CODE, worldName, distanceStr);
|
||||
}
|
||||
|
||||
public static String formatWorld(World world, boolean correctWorld) {
|
||||
String worldName;
|
||||
switch (world.getEnvironment()) {
|
||||
case NORMAL:
|
||||
worldName = "The Overworld";
|
||||
break;
|
||||
case THE_END:
|
||||
worldName = "The End";
|
||||
break;
|
||||
case NETHER:
|
||||
worldName = "The Nether";
|
||||
break;
|
||||
case CUSTOM:
|
||||
default:
|
||||
worldName = world.getName();
|
||||
}
|
||||
ChatColor color = correctWorld ? CORRECT_COLOR : INCORRECT_COLOR;
|
||||
|
||||
return String.format("%s%s%s", color, worldName, RESET_CODE);
|
||||
}
|
||||
|
||||
public static void announce(String message, LogHandler logger) {
|
||||
List<Player> players = new ArrayList<>(Bukkit.getOnlinePlayers());
|
||||
int playersNotified = 0;
|
||||
|
||||
for (Player player : players)
|
||||
if (player.hasPermission("egghunt.notify")) {
|
||||
playersNotified += 1;
|
||||
player.sendMessage(message);
|
||||
sendMessage(player, message);
|
||||
}
|
||||
|
||||
logger.info(String.format("Told %d player(s) \"%s\"", playersNotified, message));
|
||||
logger.log(String.format("Told %d player(s) \"%s\"", playersNotified, message));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,9 +101,12 @@ public class Announcement {
|
|||
}
|
||||
|
||||
public static void ShowEggEffects(Player p) {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 10, 0);
|
||||
p.playSound(p.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, SoundCategory.MASTER, 10, 0); //min pitch is 0.5
|
||||
ShowEggEffects(p.getLocation());
|
||||
}
|
||||
|
||||
private static String formatMessage(String message) {
|
||||
return String.format("%s%s%s%s%s", PREFIX_FORMAT_CODE, PREFIX_COLOR, RAW_MESSAGE_PREFIX, RESET_CODE, message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,81 +24,42 @@ public class CommandHandler {
|
|||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the given CommandSender
|
||||
*/
|
||||
private void sendMessage(CommandSender sender, String message) {
|
||||
//make the message formatted
|
||||
if (sender instanceof Player) {
|
||||
Announcement.sendMessage((Player) sender, message);
|
||||
} else {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean locateEgg(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (sender.hasPermission("egghunt.locateegg")) {
|
||||
|
||||
final String msgStart = "The dragon egg ";
|
||||
final String msgStart = "The dragon egg";
|
||||
|
||||
Data.Egg_Storage_Type type = data.getEggType();
|
||||
String storageMsg = data.getEggHolderString(); //"is in <x>"
|
||||
|
||||
if (type == Egg_Storage_Type.DNE) {
|
||||
//if the egg does not exist
|
||||
sender.sendMessage(msgStart + "does not exist");
|
||||
Location origin = null; //get location of player that sent the command for distance calculation
|
||||
if(sender instanceof Player){
|
||||
origin = ((Player) sender).getLocation();
|
||||
}
|
||||
|
||||
String locStr = Announcement.formatLocation(data.getEggLocation(), origin);
|
||||
sendMessage(sender, String.format("%s %s at %s.", msgStart, storageMsg, locStr));
|
||||
|
||||
} else {
|
||||
String storageMsg;
|
||||
|
||||
//figure out how the egg is contained
|
||||
if (type == Egg_Storage_Type.BLOCK) {
|
||||
Block eggBlock = data.getEggBlock();
|
||||
|
||||
if (Egg.isEgg(eggBlock)) {
|
||||
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";
|
||||
break;
|
||||
case ITEM_FRAME:
|
||||
case GLOW_ITEM_FRAME:
|
||||
storageMsg = "is in an item frame";
|
||||
break;
|
||||
|
||||
case FALLING_BLOCK:
|
||||
storageMsg = "is a falling block entity";
|
||||
break;
|
||||
|
||||
case PLAYER:
|
||||
storageMsg = String.format("is in the inventory of %s", eggEntity.getName());
|
||||
break;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
} else {
|
||||
sender.sendMessage(NOT_PERMITTED_MSG);
|
||||
sendMessage(sender, NOT_PERMITTED_MSG);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean trackEgg(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage("This command can only be run by a player, use /locateegg instead.");
|
||||
sendMessage(sender, "This command can only be run by a player, use /locateegg instead.");
|
||||
} else {
|
||||
if (sender.hasPermission("egghunt.trackegg")) {
|
||||
Player player = (Player) sender;
|
||||
|
|
@ -114,19 +75,18 @@ public class CommandHandler {
|
|||
compassMeta.setLodestoneTracked(false);
|
||||
compassMeta.setLodestone(eggLoc);
|
||||
heldItem.setItemMeta(compassMeta);
|
||||
sender.sendMessage("Tracking last known dragon egg position.");
|
||||
sendMessage(sender, "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.", eggLoc.getWorld().getName()));
|
||||
sendMessage(sender, String.format("Not in the same dimension as the egg. The egg is in %s.", Announcement.formatWorld(eggLoc.getWorld(), false)));
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage("The dragon egg does not exist.");
|
||||
sendMessage(sender, "The dragon egg does not exist.");
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage("You must be holding a compass to use this command, use /locateegg instead.");
|
||||
sendMessage(sender, "You must be holding a compass to use this command, use /locateegg instead.");
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage(NOT_PERMITTED_MSG);
|
||||
sendMessage(sender, NOT_PERMITTED_MSG);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -135,12 +95,12 @@ public class CommandHandler {
|
|||
private boolean getOwner(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (sender.hasPermission("egghunt.eggowner")) {
|
||||
if (data.getEggOwner() == null) {
|
||||
sender.sendMessage("The dragon egg has not been claimed.");
|
||||
sendMessage(sender, "The dragon egg has not been claimed.");
|
||||
} else {
|
||||
sender.sendMessage(String.format("The dragon egg belongs to %s.", data.getEggOwner().getName()));
|
||||
sendMessage(sender, String.format("The dragon egg belongs to %s.", data.getEggOwner().getName()));
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage(NOT_PERMITTED_MSG);
|
||||
sendMessage(sender, NOT_PERMITTED_MSG);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
package io.github.J0hnL0cke.egghunt.Controller;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
/**
|
||||
* Provides functionality relating to the dragon egg, but does not register any event handlers.
|
||||
* This is a pure fabrication class to simplify functionality used by multiple controllers.
|
||||
*/
|
||||
public class EggController {
|
||||
|
||||
/**
|
||||
* Makes the given entity invulnerable if enabled in the config
|
||||
*/
|
||||
public static void makeEggInvulnerable(Entity entity, Configuration config) {
|
||||
if (config.getEggInvulnerable()) {
|
||||
entity.setInvulnerable(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alerts when the egg is destroyed and respawns it if needed
|
||||
*/
|
||||
public static void eggDestroyed(Configuration config, Data data, LogHandler logger) {
|
||||
logger.log("Egg was destroyed");
|
||||
OfflinePlayer oldOwner = data.getEggOwner();
|
||||
data.resetEggOwner(false, config);
|
||||
data.resetEggLocation();
|
||||
String msg;
|
||||
|
||||
if (config.getRespawnEgg()) {
|
||||
if (config.getRespawnImmediately()) {
|
||||
logger.log("Immediate respawn enabled- respawning egg");
|
||||
respawnEgg(config, data, logger);
|
||||
msg = "The dragon egg was destroyed and has respawned in The End!";
|
||||
if (oldOwner != null) { //prevent spamming of egg destruction
|
||||
}
|
||||
} else {
|
||||
logger.log("Immediate respawn disabled- egg will respawn after next dragon fight");
|
||||
msg = "The dragon egg has been destroyed! It will respawn the next time the Ender Dragon is defeated.";
|
||||
}
|
||||
} else {
|
||||
logger.log("Egg respawn is disabled");
|
||||
msg = "The dragon egg has been destroyed!";
|
||||
|
||||
}
|
||||
|
||||
Announcement.announce(msg, logger);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location above the end fountain where the dragon will respawn
|
||||
*/
|
||||
public static Location getEggRespawnLocation(Configuration config) {
|
||||
//the block above the bedrock fountain where the egg spawns
|
||||
return config.getEndWorld().getEnderDragonBattle().getEndPortalLocation().add(0, 4, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop the egg out of the given player's inventory
|
||||
*/
|
||||
public static void dropEgg(Player player, Data data, Configuration config) {
|
||||
// Check if the player has a dragon egg
|
||||
if (player.getInventory().contains(Material.DRAGON_EGG)) {
|
||||
|
||||
// Set owner and remove
|
||||
data.setEggOwner(player, config); //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 eggDrop = player.getWorld().dropItem(player.getLocation(),
|
||||
new ItemStack(Material.DRAGON_EGG));
|
||||
eggDrop.setVelocity(new Vector(0, 0, 0));
|
||||
data.updateEggLocation(eggDrop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the egg ownership scoreboard tag for the given player if tagging is enabled
|
||||
* Adds the tag if the player is the owner, otherwise removes it
|
||||
*/
|
||||
public static void updateOwnerTag(Player player, Data data, Configuration config) {
|
||||
if (player != null) {
|
||||
if (config.getTagOwner()) {
|
||||
OfflinePlayer owner = data.getEggOwner();
|
||||
//if the given player owns the egg
|
||||
if (owner != null && owner.getUniqueId().equals(player.getUniqueId())) {
|
||||
player.addScoreboardTag(config.getOwnerTagName());
|
||||
} else {
|
||||
player.removeScoreboardTag(config.getOwnerTagName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a new egg item at the given location, sets it to invincible if enabled in the given config.
|
||||
* @return the egg item that was spawned
|
||||
*/
|
||||
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.getEggInvulnerable()) {
|
||||
drop.setInvulnerable(true);
|
||||
}
|
||||
data.updateEggLocation(drop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Respawns the dragon egg in the end
|
||||
*/
|
||||
public static void respawnEgg(Configuration config, Data data, LogHandler logger) {
|
||||
logger.log("Respawning egg");
|
||||
Block eggBlock = getEggRespawnLocation(config).getBlock();
|
||||
eggBlock.setType(Material.DRAGON_EGG);
|
||||
data.updateEggLocation(eggBlock);
|
||||
Announcement.ShowEggEffects(eggBlock.getLocation().add(0.5, 0, 0.5)); //target the center bottom of the block
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,51 +1,48 @@
|
|||
package io.github.J0hnL0cke.egghunt.Controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
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.ComplexEntityPart;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.EnderDragon.Phase;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EnderDragonChangePhaseEvent;
|
||||
import org.bukkit.event.entity.EntityCreatePortalEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
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.server.PluginDisableEvent;
|
||||
import org.bukkit.event.world.PortalCreateEvent;
|
||||
import org.bukkit.event.world.StructureGrowEvent;
|
||||
import org.bukkit.event.world.PortalCreateEvent.CreateReason;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data.Egg_Storage_Type;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Egg;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
/**
|
||||
* Listens for Bukkit events related to destruction of the dragon egg
|
||||
* Prevents destruction or respawns the egg, depending on config settings
|
||||
*/
|
||||
public class EggDestroyListener implements Listener {
|
||||
private Logger logger;
|
||||
private LogHandler logger;
|
||||
private Configuration config;
|
||||
private Data data;
|
||||
|
||||
|
||||
public EggDestroyListener(Logger logger, Configuration config, Data data) {
|
||||
public EggDestroyListener(LogHandler logger, Configuration config, Data data) {
|
||||
this.logger = logger;
|
||||
this.config = config;
|
||||
this.data = data;
|
||||
|
|
@ -59,10 +56,10 @@ public class EggDestroyListener implements Listener {
|
|||
Entity entity = event.getEntity();
|
||||
if (entity.getType().equals(EntityType.DROPPED_ITEM)) {
|
||||
ItemStack item = ((Item)entity).getItemStack();
|
||||
if (Egg.isEgg(item)) {
|
||||
if (Egg.hasEgg(item)) {
|
||||
//make sure item is destroyed to prevent dupes
|
||||
event.getEntity().remove();
|
||||
eggDestroyed();
|
||||
EggController.eggDestroyed(config, data, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -76,12 +73,12 @@ public class EggDestroyListener implements Listener {
|
|||
if (event.getEntity().getType().equals(EntityType.ITEM_FRAME)
|
||||
|| event.getEntity().getType().equals(EntityType.GLOW_ITEM_FRAME)) {
|
||||
ItemFrame frame = (ItemFrame) event.getEntity();
|
||||
if (Egg.isEgg(frame.getItem())) {
|
||||
if (Egg.hasEgg(frame.getItem())) {
|
||||
if (config.getEggInvulnerable()) {
|
||||
logToConsole("canceled explosion of egg item frame");
|
||||
log("canceled explosion of egg item frame");
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
eggDestroyed();
|
||||
EggController.eggDestroyed(config, data, logger);
|
||||
frame.setItem(null); //make sure item is removed
|
||||
}
|
||||
}
|
||||
|
|
@ -97,10 +94,10 @@ public class EggDestroyListener implements Listener {
|
|||
public void onEntityDeath(EntityDeathEvent event) {
|
||||
//if the egg item dies, notify that it has been destroyed
|
||||
if (event.getEntityType().equals(EntityType.DROPPED_ITEM)) {
|
||||
if (Egg.isEgg((ItemStack) event.getEntity())) {
|
||||
if (Egg.hasEgg((ItemStack) event.getEntity())) {
|
||||
//remove just in case to prevent dupes
|
||||
event.getEntity().remove();
|
||||
eggDestroyed();
|
||||
EggController.eggDestroyed(config, data, logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,63 +108,24 @@ public class EggDestroyListener implements Listener {
|
|||
//if the egg does not exist
|
||||
if (config.getEndWorld().getEnderDragonBattle().hasBeenPreviouslyKilled()) {
|
||||
//if the dragon has already been beaten
|
||||
respawnEgg();
|
||||
EggController.respawnEgg(config, data, logger);
|
||||
Announcement.announce("The dragon egg has spawned in the end!", logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop portals from removing the egg
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onCreatePortal(EntityCreatePortalEvent event) {
|
||||
//not specific to any particular creation reason because multiple events could cause the egg to be removed (obby platform regen, gateway portal spawning, stronghold portal activation)
|
||||
boolean egg_affected = false;
|
||||
Location l = null;
|
||||
List<BlockState> blocks = event.getBlocks();
|
||||
logToConsole(String.format("blocks: %s", blocks.toString()));
|
||||
for (BlockState blockState : blocks) {
|
||||
logToConsole(String.format("Block update at %s: from %s to %s", blockState.getLocation(),
|
||||
blockState.getBlock().getType(), blockState.getType()));
|
||||
if (Egg.isEgg(blockState.getBlock())) {
|
||||
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) {
|
||||
if (event.getEntity().getCustomName() != null) {
|
||||
entityName = event.getEntity().getCustomName();
|
||||
}
|
||||
}
|
||||
logToConsole(String.format("%s tried to overwrite egg with a portal", entityName));
|
||||
data.resetEggOwner(false);
|
||||
if (l != null) {
|
||||
data.updateEggLocation(Egg.spawnEggItem(l, config, data));
|
||||
} else {
|
||||
logToConsole("Could not spawn egg item! Invalid block location.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the egg from despawning
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onDespawn(ItemDespawnEvent event) {
|
||||
if (Egg.isEgg(event.getEntity().getItemStack())) {
|
||||
if (Egg.hasEgg(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);
|
||||
logToConsole("Canceled egg despawn");
|
||||
log("Canceled egg despawn");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -176,40 +134,143 @@ public class EggDestroyListener implements Listener {
|
|||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onGrow(StructureGrowEvent event) {
|
||||
boolean destroy = false;
|
||||
if (event.getSpecies().equals(TreeType.RED_MUSHROOM)) {
|
||||
logger.log("Red mushroom grown");
|
||||
List<BlockState> blocks = event.getBlocks();
|
||||
for (BlockState blockState : blocks) {
|
||||
Block block = blockState.getBlock();
|
||||
if (Egg.isEgg(block)) {
|
||||
destroy = true;
|
||||
if (!config.getEggInvulnerable()) { //if egg will be replaced, make sure it gets removed
|
||||
block.setType(Material.AIR);
|
||||
handleBlockStateReplace(blocks);
|
||||
}
|
||||
} 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)) {
|
||||
destroy = true;
|
||||
cont.getInventory().remove(Material.DRAGON_EGG); //make sure egg is removed from container
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent end platform regeneration from overwriting the egg
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPortalCreate(PortalCreateEvent event) {
|
||||
logger.log("Portal created");
|
||||
if (event.getReason().equals(CreateReason.END_PLATFORM)) {
|
||||
|
||||
ArrayList<Block> eggs = findEggs(getBlockListFromBlockStateList(event.getBlocks()));
|
||||
|
||||
//for some reason PortalCreateEvent's block list is not a shallow copy, unlike EntityExplode and StructureGrow Events
|
||||
//that means editing the list does not change which blocks are actually affected by the event
|
||||
//as a workaround, allow egg blocks to be destroyed, but respawn the egg as an item
|
||||
|
||||
for (Block egg : eggs) {
|
||||
EggController.spawnEggItem(egg.getLocation(), config, data);
|
||||
}
|
||||
logger.log("Egg overwritten by the end spawn platform, spawning egg item at block location");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for the dragon destroying the egg by flying into it
|
||||
*/
|
||||
@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
|
||||
e = ((ComplexEntityPart) e).getParent();
|
||||
}
|
||||
|
||||
//preserve the egg on the fountain if it's respawned there
|
||||
//this is an edge case, since the dragon will perch above the egg unless the egg is placed mid-perch or the dragon is pushed into it
|
||||
if (e.getType().equals(EntityType.ENDER_DRAGON)) {
|
||||
if (!config.getEggInvulnerable() && config.getRespawnEgg()) {
|
||||
|
||||
ArrayList<Block> eggs = findEggs(event.blockList());
|
||||
|
||||
for (Block egg : eggs) {
|
||||
if (Egg.isOnlyEgg(egg)) {
|
||||
if (EggController.getEggRespawnLocation(config).getBlock().equals(egg)) {
|
||||
//if the egg is set to respawn, and is overlapped by the dragon at the respawn point,
|
||||
//preserve it rather than letting it be deleted
|
||||
data.resetEggOwner(false, config);
|
||||
event.blockList().remove(egg);
|
||||
//log("prevented dragon destroying respawned egg");
|
||||
//continue on to check if other blocks are the egg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (destroy) {
|
||||
if (config.getEggInvulnerable()) {
|
||||
|
||||
//if dragon is deleting blocks, check if any are the egg
|
||||
handleBlockReplace(event.blockList());
|
||||
|
||||
if(event.blockList().isEmpty()){
|
||||
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);
|
||||
logToConsole(String.format("%s tried to mushroom the dragon egg", p.getName()));
|
||||
}
|
||||
} else {
|
||||
eggDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Block> findEggs(List<Block> blocks){
|
||||
ArrayList<Block> eggs = new ArrayList<>();
|
||||
|
||||
for (Block block : blocks) {
|
||||
if (Egg.hasEgg(block)) {
|
||||
eggs.add(block);
|
||||
}
|
||||
}
|
||||
return eggs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = findEggs(blocks);
|
||||
|
||||
if (!eggs.isEmpty()) {
|
||||
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");
|
||||
EggController.eggDestroyed(config, data, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Block> getBlockListFromBlockStateList(List<BlockState> blockStates) {
|
||||
ArrayList<Block> blocks = new ArrayList<>();
|
||||
|
||||
for (BlockState blockState : blockStates) {
|
||||
blocks.add(blockState.getBlock());
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private void handleBlockStateReplace(List<BlockState> blockStates) {
|
||||
ArrayList<Block> blocks = getBlockListFromBlockStateList(blockStates);
|
||||
|
||||
ArrayList<Block> eggs = findEggs(blocks);
|
||||
|
||||
if (!eggs.isEmpty()) {
|
||||
if (config.getEggInvulnerable()) { //prevent egg destruction
|
||||
for (int i = eggs.size()-1; i >= 0; i--) { //iterate over every egg found backwards
|
||||
int index = blocks.indexOf(eggs.get(i)); //get where the egg is in block list
|
||||
blockStates.remove(index); //remove that item from the blockstate list
|
||||
}
|
||||
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");
|
||||
EggController.eggDestroyed(config, data, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,94 +284,15 @@ public class EggDestroyListener implements Listener {
|
|||
if (config.getEggInvulnerable()) {
|
||||
Entity entity = event.getEntity();
|
||||
if (entity.getType().equals(EntityType.DROPPED_ITEM)) {
|
||||
if (Egg.isEgg((Item) entity)) {
|
||||
if (Egg.hasEgg((Item) entity)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When a portal is updated, check if the egg will be replaced
|
||||
*/
|
||||
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);
|
||||
Location res = checkBlockMaterialFromLocation(config.getEndWorld(), Material.DRAGON_EGG, l1, l2);
|
||||
if (res != null) {
|
||||
portalOverwriteEgg(res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update data and spawn a new egg when the egg is overwritten with a portal
|
||||
*/
|
||||
private void portalOverwriteEgg(Location res) {
|
||||
res.getBlock().setType(Material.AIR);
|
||||
logToConsole("Egg was overwritten with a portal");
|
||||
if (config.getEggInvulnerable()) {
|
||||
logToConsole("Spawning new egg");
|
||||
data.updateEggLocation(Egg.spawnEggItem(res, config, data));
|
||||
} else {
|
||||
eggDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks blocks within the cube created by the given locations.
|
||||
* Returns the first location corresponding to the block found with the given material.
|
||||
* Returns null if no matching block is found or locations are in different worlds.
|
||||
*/
|
||||
private static Location checkBlockMaterialFromLocation(World w, Material m, Location l1, Location l2) {
|
||||
if (l1.getWorld().equals(l2.getWorld())) {
|
||||
for (int x = l1.getBlockX(); x < l2.getBlockX(); x++) {
|
||||
for (int y = l1.getBlockY(); y < l2.getBlockY(); y++) {
|
||||
for (int z = l1.getBlockZ(); z < l2.getBlockZ(); z++) {
|
||||
if (w.getBlockAt(x, y, z).getType().equals(m)) {
|
||||
return new Location(w, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alerts when the egg is destroyed and respawns it if needed
|
||||
*/
|
||||
public void eggDestroyed() {
|
||||
announce("The dragon egg has been destroyed!");
|
||||
data.resetEggOwner(false);
|
||||
|
||||
if (config.getRespawnEgg()) {
|
||||
if (config.getRespawnImmediately()) {
|
||||
respawnEgg();
|
||||
} else {
|
||||
data.resetEggLocation();
|
||||
announce("It will respawn the next time the dragon is defeated");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Respawns the dragon egg in the end
|
||||
*/
|
||||
private void respawnEgg() {
|
||||
Block eggBlock = Egg.respawnEgg(config);
|
||||
data.updateEggLocation(eggBlock);
|
||||
Announcement.ShowEggEffects(eggBlock.getLocation());
|
||||
announce("The dragon egg has spawned in the end!");
|
||||
}
|
||||
|
||||
private void announce(String msg) {
|
||||
Announcement.announce(msg, logger);
|
||||
}
|
||||
|
||||
private void logToConsole(String message) {
|
||||
logger.info(message);
|
||||
private void log(String message) {
|
||||
logger.log(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package io.github.J0hnL0cke.egghunt.Controller;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
|
@ -16,6 +14,7 @@ import org.bukkit.scheduler.BukkitRunnable;
|
|||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Egg;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
public class EventScheduler extends BukkitRunnable {
|
||||
|
||||
|
|
@ -24,9 +23,9 @@ public class EventScheduler extends BukkitRunnable {
|
|||
|
||||
private Data data;
|
||||
private Configuration config;
|
||||
private Logger logger;
|
||||
private LogHandler logger;
|
||||
|
||||
public EventScheduler(Configuration config, Data data, Logger logger) {
|
||||
public EventScheduler(Configuration config, Data data, LogHandler logger) {
|
||||
this.data = data;
|
||||
this.config = config;
|
||||
this.logger = logger;
|
||||
|
|
@ -43,11 +42,12 @@ public class EventScheduler extends BukkitRunnable {
|
|||
logger.warning("Resetting egg location to prevent repeated warnings");
|
||||
data.resetEggLocation();
|
||||
return;
|
||||
} else if (isUnderWorld(data.getEggEntity())) {
|
||||
} else if (isUnderWorld(data.getEggEntity()) && !(data.getEggEntity() instanceof Player)) {
|
||||
logger.log("Egg entity is under the word. Removing egg from entity");
|
||||
Location respawnLoc = data.getEggEntity().getLocation();
|
||||
removeMaterialFromEntity(Material.DRAGON_EGG, data.getEggEntity());
|
||||
if (config.getEggInvulnerable()) {
|
||||
Egg.removeEgg(data.getEggEntity());
|
||||
|
||||
if (config.getEggInvulnerable()) {
|
||||
// get coords for egg to spawn at
|
||||
//get highest block
|
||||
Block highestBlock = respawnLoc.getWorld().getHighestBlockAt(respawnLoc);
|
||||
|
|
@ -58,51 +58,16 @@ public class EventScheduler extends BukkitRunnable {
|
|||
yPos = respawnLoc.getWorld().getSeaLevel();
|
||||
}
|
||||
respawnLoc.setY(yPos);
|
||||
Egg.spawnEggItem(respawnLoc, config, data); //do not need to update data with this location since item spawn event will be called
|
||||
EggController.spawnEggItem(respawnLoc, config, data); //do not need to update data with this location since item spawn event will be called
|
||||
data.resetEggOwner(true, config);
|
||||
} else {
|
||||
eggDestroyed();
|
||||
respawnEgg(respawnLoc);
|
||||
}
|
||||
data.resetEggOwner(true);
|
||||
//alert and respawn if applicable
|
||||
EggController.eggDestroyed(config, data, logger);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEgg(Entity entity) {
|
||||
if (entity instanceof Player) {
|
||||
return ((Player) entity).getInventory().contains(Material.DRAGON_EGG);
|
||||
} else if (entity instanceof LivingEntity) {
|
||||
LivingEntity mob = (((LivingEntity) entity));
|
||||
EntityEquipment inv = mob.getEquipment();
|
||||
if (Egg.isEgg(inv.getItemInMainHand())) {
|
||||
return true;
|
||||
}
|
||||
if (Egg.isEgg(inv.getItemInOffHand())) {
|
||||
return true;
|
||||
}
|
||||
} else if (entity instanceof FallingBlock) {
|
||||
return Egg.isEgg(((FallingBlock) entity));
|
||||
} else if (entity instanceof Item) {
|
||||
return Egg.isEgg((Item) entity);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUnderWorld(Entity entity) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
package io.github.J0hnL0cke.egghunt.Controller;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Container;
|
||||
import org.bukkit.block.DoubleChest;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
|
@ -20,25 +21,26 @@ import org.bukkit.event.inventory.InventoryMoveItemEvent;
|
|||
import org.bukkit.event.inventory.InventoryPickupItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.inventory.AbstractHorseInventory;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Merchant;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Egg;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
/**
|
||||
* Listens for Bukkit events related to inventories
|
||||
*/
|
||||
public class InventoryListener implements Listener {
|
||||
|
||||
private Logger logger;
|
||||
private LogHandler logger;
|
||||
private Configuration config;
|
||||
private Data data;
|
||||
|
||||
public InventoryListener(Logger logger, Configuration config, Data data) {
|
||||
public InventoryListener(LogHandler logger, Configuration config, Data data) {
|
||||
this.logger = logger;
|
||||
this.config = config;
|
||||
this.data = data;
|
||||
|
|
@ -55,10 +57,10 @@ public class InventoryListener implements Listener {
|
|||
ItemStack stack = item.getItemStack();
|
||||
|
||||
// Check if the dropped item is the egg
|
||||
if (Egg.isEgg(stack)) {
|
||||
data.setEggOwner(event.getPlayer());
|
||||
if (Egg.hasEgg(stack)) {
|
||||
data.setEggOwner(event.getPlayer(), config);
|
||||
data.updateEggLocation(item);
|
||||
Egg.makeEggInvulnerable(event.getItemDrop(), config, logger);
|
||||
EggController.makeEggInvulnerable(event.getItemDrop(), config);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,10 +70,10 @@ public class InventoryListener implements Listener {
|
|||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPickupItem(EntityPickupItemEvent event) {
|
||||
// Check if item picked up is an egg
|
||||
if (Egg.isEgg(event.getItem())) {
|
||||
if (Egg.hasEgg(event.getItem())) {
|
||||
data.updateEggLocation(event.getEntity());
|
||||
if (event.getEntity() instanceof Player) {
|
||||
data.setEggOwner((Player) event.getEntity());
|
||||
data.setEggOwner((Player) event.getEntity(), config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,7 +87,7 @@ public class InventoryListener implements Listener {
|
|||
// Check if the dragon egg was picked up
|
||||
ItemStack item = event.getItem().getItemStack();
|
||||
|
||||
if (Egg.isEgg(item)) {
|
||||
if (Egg.hasEgg(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)) {
|
||||
|
|
@ -108,14 +110,14 @@ public class InventoryListener implements Listener {
|
|||
if (otherInv.getType().equals(InventoryType.ENDER_CHEST)) {
|
||||
if (config.getDropEnderchestedEgg() && player.getGameMode() != GameMode.CREATIVE) {
|
||||
if (otherInv.contains(Material.DRAGON_EGG)) {
|
||||
ItemStack egg = otherInv.getItem(otherInv.first(Material.DRAGON_EGG));
|
||||
ItemStack egg = otherInv.getItem(otherInv.first(Material.DRAGON_EGG)); //TODO make this work with bundles/shulkers
|
||||
Location playerLoc = player.getLocation();
|
||||
otherInv.remove(egg);
|
||||
Item i = playerLoc.getWorld().dropItem(playerLoc, egg); //TODO use drop item function
|
||||
console_log(String.format(
|
||||
log(String.format(
|
||||
"Dropped the dragon egg on the ground since %s had it in their ender chest.",
|
||||
player.getName()));
|
||||
console_log(
|
||||
log(
|
||||
"Set ignore_echest_egg to \"true\" in the config file to disable this feature.");
|
||||
data.updateEggLocation(i);
|
||||
}
|
||||
|
|
@ -126,24 +128,40 @@ public class InventoryListener implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (player.getInventory().contains(Material.DRAGON_EGG)) {
|
||||
if (Egg.hasEgg(player.getInventory())) {
|
||||
//if the player has the egg in their inventory, it will stay there
|
||||
data.updateEggLocation(player);
|
||||
data.setEggOwner(player);
|
||||
data.setEggOwner(player, config);
|
||||
|
||||
} else if (otherInv.contains(Material.DRAGON_EGG)) {
|
||||
} else if (Egg.hasEgg(otherInv)) {
|
||||
|
||||
if (otherInv.getType() != InventoryType.PLAYER) { //TODO check how this affects player viewing own inventory (egg on head/offhand?)
|
||||
|
||||
if (!(otherInv.getHolder() instanceof Merchant)) { //chest boat/llama but not villager/wandering trader
|
||||
//this is a container (chest, furnace, hopper minecart, etc), so the egg will remain here when the inventory is closed
|
||||
data.updateEggLocation(otherInv);
|
||||
InventoryHolder holder = otherInv.getHolder();
|
||||
|
||||
if (holder instanceof Entity) {
|
||||
if (holder instanceof Merchant) { //villager/wandering trader
|
||||
//items will not be stored in this inventory, and will instead revert to the player
|
||||
logger.log("inventory close- inside merchant entity (reverts to player)");
|
||||
data.updateEggLocation(player);
|
||||
|
||||
} else {
|
||||
//this is an entity that stores items (hopper minecart, chest boat, llama, etc), so the egg will remain here when the inventory is closed
|
||||
logger.log("inventory close- inside non-merchant entity");
|
||||
data.updateEggLocation(otherInv);
|
||||
}
|
||||
|
||||
} else { //this inventory holder is a block
|
||||
if (holder instanceof Container || holder instanceof DoubleChest) { //DoubleChest implements InventoryHolder directly instead of implementing Container
|
||||
//this is a container (furnace, chest boat, etc), so the egg will stay here
|
||||
logger.log("inventory close- inside container block");
|
||||
data.updateEggLocation(otherInv);
|
||||
} else {
|
||||
//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
|
||||
logger.log("inventory close- inside non-container block (reverts to player)");
|
||||
data.updateEggLocation(player);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -155,8 +173,8 @@ public class InventoryListener implements Listener {
|
|||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onInventoryMove(InventoryMoveItemEvent event) {
|
||||
//check if the item being moved is the egg
|
||||
if (Egg.isEgg(event.getItem())) {
|
||||
if (event.getDestination().firstEmpty() != -1 || event.getDestination().contains(Material.DRAGON_EGG)) {
|
||||
if (Egg.hasEgg(event.getItem())) {
|
||||
if (event.getDestination().firstEmpty() != -1 || Egg.hasEgg(event.getDestination())) {
|
||||
data.updateEggLocation(event.getDestination());
|
||||
}
|
||||
}
|
||||
|
|
@ -164,7 +182,7 @@ public class InventoryListener implements Listener {
|
|||
|
||||
|
||||
/**
|
||||
* Stop players from holding the egg in their cursor then dragging to drop it into an ender chest or shulker box.
|
||||
* Stop players from holding the egg in their cursor then dragging to drop it into an ender chest (or shulker box).
|
||||
*
|
||||
* Note: Due to limitations with the API, this prevents dragging the egg when viewing an ender chest or shulker box,
|
||||
* even if the egg is only dragged over slots in the player's inventory.
|
||||
|
|
@ -173,11 +191,11 @@ public class InventoryListener implements Listener {
|
|||
public void onInventoryDragConsider(InventoryDragEvent event) {
|
||||
InventoryType inv = event.getInventory().getType(); //this only gets the currently viewed ("top") inventory, which is not necessairly where the items are dragged in/over
|
||||
if (event.getWhoClicked().getGameMode() != GameMode.CREATIVE) {
|
||||
if (inv.equals(InventoryType.ENDER_CHEST) || inv.equals(InventoryType.SHULKER_BOX)) {
|
||||
boolean holdEgg = Egg.isEgg(event.getOldCursor());
|
||||
if (inv.equals(InventoryType.ENDER_CHEST) || (inv.equals(InventoryType.SHULKER_BOX) && !config.getCanPackageEgg())) {
|
||||
boolean holdEgg = Egg.hasEgg(event.getOldCursor());
|
||||
if (holdEgg) {
|
||||
event.setCancelled(true);
|
||||
console_log(String.format("Stopped %s from dragging egg while viewing shulker/ender chest",
|
||||
log(String.format("Stopped %s from dragging egg while viewing shulker/ender chest",
|
||||
event.getWhoClicked().getName()));
|
||||
}
|
||||
}
|
||||
|
|
@ -185,17 +203,17 @@ public class InventoryListener implements Listener {
|
|||
}
|
||||
|
||||
/**
|
||||
* Stop players from storing the egg in an ender chest or shulker box.
|
||||
* Also stops the player from putting the egg into a bundle regardless of open inventory.
|
||||
* Stop players from storing the egg in an ender chest (or shulker box).
|
||||
* Also stops the player from putting the egg into a bundle if configured regardless of open inventory.
|
||||
* TODO refactor into multiple smaller listeners
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInventoryMoveConsider(InventoryClickEvent event) {
|
||||
InventoryType inv = event.getInventory().getType();
|
||||
if (event.getWhoClicked().getGameMode() != GameMode.CREATIVE) {
|
||||
if (inv.equals(InventoryType.ENDER_CHEST) || inv.equals(InventoryType.SHULKER_BOX)) {
|
||||
boolean hoverEgg = Egg.isEgg(event.getCurrentItem());
|
||||
boolean holdEgg = Egg.isEgg(event.getCursor());
|
||||
if (inv.equals(InventoryType.ENDER_CHEST) || (inv.equals(InventoryType.SHULKER_BOX) && !config.getCanPackageEgg())) {
|
||||
boolean hoverEgg = Egg.hasEgg(event.getCurrentItem());
|
||||
boolean holdEgg = Egg.hasEgg(event.getCursor());
|
||||
Boolean clickedContainer = null;
|
||||
if (event.getClickedInventory() != null) {
|
||||
clickedContainer = event.getClickedInventory().equals(event.getInventory());
|
||||
|
|
@ -207,7 +225,7 @@ public class InventoryListener implements Listener {
|
|||
boolean cancel = false;
|
||||
|
||||
if (clickedContainer == null){
|
||||
logger.info(event.getAction().toString());
|
||||
log(event.getAction().toString());
|
||||
} else if (clickedContainer) {
|
||||
//player clicked the container
|
||||
switch (event.getAction()) {
|
||||
|
|
@ -247,7 +265,7 @@ public class InventoryListener implements Listener {
|
|||
if (cancel) {
|
||||
//if the item clicked was the egg
|
||||
event.setCancelled(true);
|
||||
console_log(String.format("Stopped %s from moving egg to shulker/ender chest",
|
||||
log(String.format("Stopped %s from moving egg to shulker/ender chest",
|
||||
event.getWhoClicked().getName()));
|
||||
}
|
||||
}
|
||||
|
|
@ -263,9 +281,9 @@ public class InventoryListener implements Listener {
|
|||
if (event.getClickedInventory().equals(event.getInventory())) {
|
||||
//make sure the destination is the ender chest
|
||||
//this allows hotkeying the egg around in the player's inventory
|
||||
if (Egg.isEgg(item)) {
|
||||
if (Egg.hasEgg(item)) {
|
||||
event.setCancelled(true);
|
||||
console_log(String.format("Stopped %s from hotkeying egg to shulker/ender chest",
|
||||
log(String.format("Stopped %s from hotkeying egg to shulker/ender chest",
|
||||
event.getWhoClicked().getName()));
|
||||
}
|
||||
}
|
||||
|
|
@ -273,20 +291,21 @@ public class InventoryListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
//prevent using bundles on the egg in *any* inventory
|
||||
//prevent using bundles on the egg in any inventory
|
||||
if(event.getCurrentItem() != null){
|
||||
if(event.getCursor()!=null){
|
||||
|
||||
ItemStack clicked=event.getCurrentItem();
|
||||
ItemStack cursor=event.getCursor();
|
||||
|
||||
if ((Egg.isEgg(cursor) && clicked.getType() == Material.BUNDLE)
|
||||
|| (Egg.isEgg(clicked) && cursor.getType() == Material.BUNDLE)) {
|
||||
if ((Egg.hasEgg(cursor) && clicked.getType() == Material.BUNDLE )
|
||||
|| (Egg.hasEgg(clicked) && cursor.getType() == Material.BUNDLE)) {
|
||||
if (!config.getCanPackageEgg()) {
|
||||
event.setCancelled(true);
|
||||
console_log(String.format("Stopped %s from bundling the egg",
|
||||
log(String.format("Stopped %s from bundling the egg",
|
||||
event.getWhoClicked().getName()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -294,19 +313,22 @@ public class InventoryListener implements Listener {
|
|||
|
||||
/**
|
||||
* Stop players from pushing the egg into a shulker using a hopper/hopper minecart
|
||||
* Only works if this setting is enabled in the config
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPushConsider(InventoryMoveItemEvent event) {
|
||||
//nice try, but it won't work
|
||||
if (!config.getCanPackageEgg()) {
|
||||
if (event.getDestination().getType().equals(InventoryType.SHULKER_BOX)) {
|
||||
if (Egg.isEgg(event.getItem())) {
|
||||
if (Egg.hasEgg(event.getItem())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void console_log(String message) {
|
||||
logger.info(message);
|
||||
private void log(String message) {
|
||||
logger.log(message);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ import org.bukkit.entity.*;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockDispenseEvent;
|
||||
import org.bukkit.event.block.BlockFromToEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.*;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
|
@ -17,21 +19,19 @@ import org.bukkit.inventory.PlayerInventory;
|
|||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Egg;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data.Egg_Storage_Type;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
/**
|
||||
* Listens to miscellaneous Bukkit events
|
||||
*/
|
||||
public class MiscListener implements Listener {
|
||||
|
||||
private Logger logger;
|
||||
private LogHandler logger;
|
||||
private Configuration config;
|
||||
private Data data;
|
||||
|
||||
|
||||
public MiscListener(Logger logger, Configuration config, Data data) {
|
||||
public MiscListener(LogHandler logger, Configuration config, Data data) {
|
||||
this.logger = logger;
|
||||
this.config = config;
|
||||
this.data = data;
|
||||
|
|
@ -48,18 +48,25 @@ public class MiscListener implements Listener {
|
|||
data.saveData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the player's entity tag when they join
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
EggController.updateOwnerTag(player, data, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Egg.dropEgg(player, data);
|
||||
EggController.dropEgg(player, data, config);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Track the egg droping as an item.
|
||||
* Note: No handler to check if the falling egg entity drops an item, so we have to check every item spawn
|
||||
|
|
@ -69,9 +76,10 @@ public class MiscListener implements Listener {
|
|||
// Check if the spawned item is the egg
|
||||
Item item = event.getEntity();
|
||||
|
||||
if (Egg.isEgg(item)) {
|
||||
if (Egg.hasEgg(item)) {
|
||||
data.updateEggLocation(item);
|
||||
Egg.makeEggInvulnerable(event.getEntity(), config, logger);
|
||||
EggController.makeEggInvulnerable(event.getEntity(), config);
|
||||
log("made entity invulnerable");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,10 +87,29 @@ public class MiscListener implements Listener {
|
|||
* Handle the egg being placed as a block
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onBlockPlace (BlockPlaceEvent event) {
|
||||
if (Egg.isEgg(event.getBlock())) {
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
if (Egg.hasEgg(event.getBlock())) {
|
||||
data.updateEggLocation(event.getBlock());
|
||||
data.setEggOwner(event.getPlayer());
|
||||
data.setEggOwner(event.getPlayer(), config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the egg being dispensed when inside a shulker box
|
||||
* TODO allow this to happen and just update the position of the egg
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onBlockDispense(BlockDispenseEvent event) {
|
||||
|
||||
if (event.getBlock().getType().equals(Material.DISPENSER)) {
|
||||
if (Egg.hasEgg(event.getItem())) {
|
||||
//if egg or egg container will be dispensed by a dispenser
|
||||
if (Egg.isShulker(event.getItem().getType())) {
|
||||
//if the item is a shulker box holding the egg (will be dispensed as a block)
|
||||
event.setCancelled(true);
|
||||
//log("Prevented shulker containing the egg from being dispensed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,11 +125,11 @@ public class MiscListener implements Listener {
|
|||
Allay allay = (Allay) event.getRightClicked();
|
||||
|
||||
if (!(allay.getEquipment().getItemInMainHand().getType().equals(Material.AIR))) { //if allay has an item
|
||||
if (Egg.isEgg(allay.getEquipment().getItemInMainHand())
|
||||
if (Egg.hasEgg(allay.getEquipment().getItemInMainHand())
|
||||
&& playerInv.getItemInMainHand().getType().equals(Material.AIR)) {
|
||||
//interaction with empty main hand will remove the egg from the allay and put it in the player's inventory
|
||||
data.updateEggLocation(event.getPlayer());
|
||||
data.setEggOwner(event.getPlayer());
|
||||
data.setEggOwner(event.getPlayer(), config);
|
||||
|
||||
}
|
||||
break; //allay has an item, giving it the egg is not possible
|
||||
|
|
@ -118,9 +145,9 @@ public class MiscListener implements Listener {
|
|||
}
|
||||
|
||||
if (!heldItem.getType().equals(Material.AIR)) { //if item in either hand
|
||||
if (Egg.isEgg(heldItem)) {
|
||||
if (Egg.hasEgg(heldItem)) {
|
||||
data.updateEggLocation(event.getRightClicked());
|
||||
data.setEggOwner(event.getPlayer());
|
||||
data.setEggOwner(event.getPlayer(), config);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,20 +161,20 @@ public class MiscListener implements Listener {
|
|||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onSpread(BlockFromToEvent event) {
|
||||
if (Egg.isEgg(event.getBlock())) {
|
||||
if (Egg.hasEgg(event.getBlock())) {
|
||||
data.updateEggLocation(event.getToBlock());
|
||||
|
||||
if (!config.getAccurateLocation()) {
|
||||
//TODO disable accuracy here
|
||||
console_log("The egg teleported, showing players the egg's location before teleport");
|
||||
//log("The egg teleported, showing players the egg's location before teleport");
|
||||
} else {
|
||||
console_log("The egg teleported, showing players the egg's up-to-date location");
|
||||
//log("The egg teleported, showing players the egg's up-to-date location");
|
||||
}
|
||||
|
||||
if (config.resetOwnerOnTeleport()) {
|
||||
if (data.getEggOwner() != null) {
|
||||
announce(String.format("The dragon egg has teleported. %s is no longer the owner.", data.getEggOwner().getName()));
|
||||
data.resetEggOwner(false);
|
||||
data.resetEggOwner(false, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -161,15 +188,15 @@ public class MiscListener implements Listener {
|
|||
//check if this is dealing with a falling block, since EntityChangeBlockEvent is generic
|
||||
if (event.getEntityType() == EntityType.FALLING_BLOCK) {
|
||||
//if the falling block is the egg
|
||||
if (Egg.isEgg((FallingBlock)event.getEntity())) {
|
||||
if (Egg.hasEgg((FallingBlock)event.getEntity())) {
|
||||
|
||||
console_log("Gravity event involving dragon egg occured");
|
||||
log("Gravity event involving dragon egg occured");
|
||||
|
||||
if (event.getBlock().getType() == Material.AIR) {
|
||||
//egg lands
|
||||
data.updateEggLocation(event.getBlock());
|
||||
|
||||
} else if (Egg.isEgg(event.getBlock())) {
|
||||
} else if (Egg.hasEgg(event.getBlock())) {
|
||||
//egg begins falling
|
||||
data.updateEggLocation(event.getEntity());
|
||||
}
|
||||
|
|
@ -184,8 +211,8 @@ public class MiscListener implements Listener {
|
|||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
if (!event.getKeepInventory() && event.getEntity().getInventory().contains(Material.DRAGON_EGG)) {
|
||||
data.resetEggOwner(false);
|
||||
if (!event.getKeepInventory() && Egg.hasEgg(event.getEntity().getInventory())) {
|
||||
data.resetEggOwner(false, config);
|
||||
|
||||
//change the death message
|
||||
String deathmsg = event.getDeathMessage();
|
||||
|
|
@ -207,8 +234,8 @@ public class MiscListener implements Listener {
|
|||
Announcement.announce(msg, logger);
|
||||
}
|
||||
|
||||
private void console_log(String message) {
|
||||
logger.info(message);
|
||||
private void log(String message) {
|
||||
logger.log(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
package io.github.J0hnL0cke.egghunt.Controller;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.Instant;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scoreboard.Criteria;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.RenderType;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.ScoreboardManager;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
/**
|
||||
* Handles interactions with the scoreboard api
|
||||
*/
|
||||
public class ScoreboardController {
|
||||
|
||||
private static ScoreboardController thisHandler;
|
||||
|
||||
private Data data;
|
||||
private Configuration config;
|
||||
private LogHandler logger;
|
||||
private ScoreboardManager manager;
|
||||
private Scoreboard board;
|
||||
private Objective eggMinutes;
|
||||
private Objective eggSeconds;
|
||||
private Instant lastUpdate;
|
||||
private static final String EGG_MINUTES_KEY = "eggOwnedMinutes";
|
||||
private static final String EGG_SECONDS_KEY = "eggOwnedSeconds";
|
||||
|
||||
public static ScoreboardController getScoreboardHandler(Data data, Configuration configuration, LogHandler logger) {
|
||||
if (thisHandler == null) {
|
||||
thisHandler = new ScoreboardController(data, configuration, logger);
|
||||
}
|
||||
return thisHandler;
|
||||
}
|
||||
|
||||
private ScoreboardController(Data data, Configuration config, LogHandler logger) {
|
||||
this.data = data;
|
||||
this.config = config;
|
||||
this.logger = logger;
|
||||
|
||||
if (config.getKeepScore()) {
|
||||
logger.log("Scorekeeping is enabled, loading scoreboard...");
|
||||
loadData();
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveData(LogHandler logger) {
|
||||
if (thisHandler == null) {
|
||||
logger.warning("ScoreboardController has not been initalized before attempting to save!");
|
||||
} else {
|
||||
thisHandler.updateScores();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
manager = Bukkit.getScoreboardManager();
|
||||
board = manager.getMainScoreboard(); //possibly switch to new board? would need to save/load independently of server
|
||||
|
||||
eggSeconds = getOrMakeObjective(EGG_SECONDS_KEY, "Seconds owning egg");
|
||||
eggMinutes = getOrMakeObjective(EGG_MINUTES_KEY, "Minutes owning egg");
|
||||
|
||||
lastUpdate = Instant.now();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the score for the current egg owner
|
||||
*
|
||||
* For accurate scoring, this should be updated at least every time egg ownership changes, and
|
||||
* every time the plugin is enabled/disabled
|
||||
* @param data
|
||||
*/
|
||||
public void updateScores() {
|
||||
if (config.getKeepScore() && data.getEggType()!= Data.Egg_Storage_Type.DNE) {
|
||||
logger.log("Updating scoreboard");
|
||||
|
||||
if (data.getEggType() == Data.Egg_Storage_Type.ENTITY) {
|
||||
Entity eggEntity = data.getEggEntity();
|
||||
if (config.getNamedEntitiesGetScore()) {
|
||||
if (eggEntity.getCustomName() != null) {
|
||||
incrementScoring(eggEntity.getCustomName()); //prioritize the named entity for scoring
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OfflinePlayer owner = data.getEggOwner();
|
||||
if (owner != null) {
|
||||
incrementScoring(owner.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void incrementScoring(String entityName) {
|
||||
//YOU WILL REMEMBER ME! REMEMBER ME FOR
|
||||
//ChronoUnit.CENTURIES
|
||||
|
||||
Instant newUpdate = Instant.now(); //when writing tests, switch this to using an injected Clock instance
|
||||
|
||||
long seconds = ChronoUnit.SECONDS.between(lastUpdate, newUpdate); //this is the floored duration in minutes
|
||||
int convertedSeconds = Long.valueOf(seconds).intValue();
|
||||
|
||||
addScore(entityName, eggSeconds, convertedSeconds); //add to eggSeconds
|
||||
|
||||
int mins = Math.floorDiv(getScore(entityName, eggSeconds), 60); //convert seconds into minutes
|
||||
setScore(entityName, eggMinutes, mins); //update eggMinutes
|
||||
|
||||
lastUpdate = newUpdate; //update lastUpdate time
|
||||
}
|
||||
|
||||
public Objective getOrMakeObjective(String key, String displayName) {
|
||||
Objective obj = board.getObjective(key);
|
||||
if (obj == null) {
|
||||
logger.info(String.format("No scoreboard objective \"%s\" found, creating new objective", key));
|
||||
obj = board.registerNewObjective(key, Criteria.DUMMY, displayName, RenderType.INTEGER);
|
||||
}
|
||||
|
||||
if (!obj.isModifiable()) {
|
||||
String msg = "Could not modify objective \"%s\"! Make sure objective criteria is set to dummy!";
|
||||
logger.warning(String.format(msg, obj.getName()));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void addScore(String name, Objective obj, int score) {
|
||||
if (score != 0) { //avoid adding the entity to the scoreboard if adding 0
|
||||
Score s = obj.getScore(name);
|
||||
s.setScore(s.getScore() + score);
|
||||
}
|
||||
}
|
||||
|
||||
private void setScore(String name, Objective obj, int score) {
|
||||
Score s = obj.getScore(name);
|
||||
s.setScore(score);
|
||||
}
|
||||
|
||||
private int getScore(String name, Objective obj) {
|
||||
Score s = obj.getScore(name);
|
||||
return s.getScore();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,15 +9,21 @@ import io.github.J0hnL0cke.egghunt.Persistence.ConfigFileDAO;
|
|||
* Retrieve settings for this plugin
|
||||
*/
|
||||
public class Configuration {
|
||||
boolean eggInvulnerable; /** whether to make the egg immune to damage */
|
||||
boolean respawnEgg; /** whether the egg should respawn when destroyed */
|
||||
boolean respawnImmediately; /** if respawning the egg, whether it should immediately respawn in-place or whether it should generate after next dragon fight */
|
||||
boolean resetOwnerOnTeleport; /** whether the egg should become "lost" when it is teleported */
|
||||
boolean accurateLocation;
|
||||
boolean dropEnderchestedEgg; /** whether an existing egg already in an ender chest should be forced out or stuck there */
|
||||
World endWorld; /** the name of the world that counts as the end on this server */
|
||||
private boolean debug; /** whether to show debug information in console log */
|
||||
private boolean eggInvulnerable; /** whether to make the egg immune to damage */
|
||||
private boolean respawnEgg; /** whether the egg should respawn when destroyed */
|
||||
private boolean respawnImmediately; /** if respawning the egg, whether it should immediately respawn in-place or whether it should generate after next dragon fight */
|
||||
private boolean resetOwnerOnTeleport; /** whether the egg should become "lost" when it is teleported */
|
||||
private boolean accurateLocation;
|
||||
private boolean dropEnderchestedEgg; /** whether an existing egg already in an ender chest should be forced out or stuck there */
|
||||
private boolean canPackageEgg; /** whether the egg can be stored in a shulker box or bundle */
|
||||
private boolean tagOwner; /** whether to apply a tag to the owner of the egg */
|
||||
private boolean keepScore; /** whether to create and increment a scoreboard for time holding the egg */
|
||||
private boolean namedEntitiesGetScore; /** whether entities with custom names are counted on the scoreboard when holding the egg */
|
||||
private World endWorld; /** the name of the world that counts as the end on this server */
|
||||
private String ownerTagName; /** the name of the tag to apply to the owner, if enabled */
|
||||
|
||||
public static String defaultEnd = "world_end"; /** default end world name for most spigot servers */
|
||||
public static final String DEFAULT_END = "world_end"; /** default end world name for most spigot servers */
|
||||
|
||||
ConfigFileDAO fileDao;
|
||||
|
||||
|
|
@ -29,16 +35,26 @@ public class Configuration {
|
|||
private void loadData() {
|
||||
|
||||
//load config settings
|
||||
debug = fileDao.readBool("debug");
|
||||
eggInvulnerable = fileDao.readBool("egg_inv");
|
||||
respawnEgg = fileDao.readBool("resp_egg");
|
||||
respawnImmediately = fileDao.readBool("resp_imm");
|
||||
resetOwnerOnTeleport = fileDao.readBool("reset_owner");
|
||||
accurateLocation = fileDao.readBool("accurate_loc");
|
||||
dropEnderchestedEgg = fileDao.readBool("drop_enderchested_egg");
|
||||
canPackageEgg = fileDao.readBool("can_package_egg");
|
||||
tagOwner = fileDao.readBool("tag_owner");
|
||||
keepScore = fileDao.readBool("keep_score");
|
||||
namedEntitiesGetScore = fileDao.readBool("named_entities_keep_score");
|
||||
|
||||
ownerTagName = fileDao.read("owner_tag_name", null);
|
||||
endWorld = Bukkit.getServer().getWorld(fileDao.read("end", DEFAULT_END));
|
||||
|
||||
endWorld = Bukkit.getServer().getWorld(fileDao.read("end", defaultEnd));
|
||||
}
|
||||
|
||||
public boolean getDebugEnabled() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
public boolean getEggInvulnerable() {
|
||||
return eggInvulnerable;
|
||||
|
|
@ -63,9 +79,30 @@ public class Configuration {
|
|||
return dropEnderchestedEgg;
|
||||
}
|
||||
|
||||
public boolean getCanPackageEgg() {
|
||||
return false; //canPackageEgg; TODO implement checks for this
|
||||
}
|
||||
|
||||
public boolean getTagOwner() {
|
||||
return tagOwner;
|
||||
}
|
||||
|
||||
public boolean getKeepScore() {
|
||||
return keepScore;
|
||||
}
|
||||
|
||||
public boolean getNamedEntitiesGetScore() {
|
||||
return namedEntitiesGetScore;
|
||||
}
|
||||
|
||||
public String getOwnerTagName(){
|
||||
return ownerTagName;
|
||||
}
|
||||
|
||||
public World getEndWorld() {
|
||||
return endWorld;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package io.github.J0hnL0cke.egghunt.Model;
|
|||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
|
|
@ -14,6 +13,8 @@ import org.bukkit.inventory.Inventory;
|
|||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Controller.Announcement;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.EggController;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.ScoreboardController;
|
||||
import io.github.J0hnL0cke.egghunt.Persistence.DataFileDAO;
|
||||
|
||||
/**
|
||||
|
|
@ -22,7 +23,7 @@ import io.github.J0hnL0cke.egghunt.Persistence.DataFileDAO;
|
|||
public class Data {
|
||||
|
||||
private DataFileDAO dataDao;
|
||||
private Logger logger;
|
||||
private LogHandler logger;
|
||||
|
||||
public enum Egg_Storage_Type {
|
||||
ENTITY,
|
||||
|
|
@ -38,8 +39,10 @@ public class Data {
|
|||
private Entity entity;
|
||||
private UUID entityFallback;
|
||||
|
||||
private static final String BUG_STR = "THIS MAY BE A BUG! Please report it at https://github.com/HyperSMP/EggHuntPlugin/issues";
|
||||
|
||||
public Data(DataFileDAO dataDao, Logger logger) {
|
||||
|
||||
public Data(DataFileDAO dataDao, LogHandler logger) {
|
||||
this.dataDao = dataDao;
|
||||
this.logger = logger;
|
||||
loadData();
|
||||
|
|
@ -56,14 +59,38 @@ public class Data {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current storage type for the dragon egg
|
||||
* When getting the corresponding entity or block, that object is guaranteed to be non-null
|
||||
*/
|
||||
public Egg_Storage_Type getEggType() {
|
||||
if ((storedAs == Egg_Storage_Type.BLOCK && block == null)
|
||||
|| (storedAs == Egg_Storage_Type.ENTITY && entity == null)) {
|
||||
//make sure object is non-null
|
||||
String msg = String.format(
|
||||
"Unable to find egg! storedAs = %s but corresponding object is null!\nResetting storedAs to prevent further errors",
|
||||
storedAs.toString());
|
||||
resetEggLocation();
|
||||
logger.warning(msg);
|
||||
}
|
||||
|
||||
return storedAs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity currently associated with the dragon egg
|
||||
* This should only be used after checking the egg is stored as an entity
|
||||
* The provided entity should (but is not guaranteed to) contain the egg
|
||||
*/
|
||||
public Entity getEggEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block currently associated with the dragon egg
|
||||
* This should only be used after checking the egg is stored as a block
|
||||
* The provided block should (but is not guaranteed to) contain the egg
|
||||
*/
|
||||
public Block getEggBlock() {
|
||||
return block;
|
||||
}
|
||||
|
|
@ -121,6 +148,59 @@ public class Data {
|
|||
return UUID.fromString(uuid);
|
||||
}
|
||||
|
||||
private void validateData() {
|
||||
logger.log("Data loaded. Validating loaded data...");
|
||||
//make sure data was properly loaded
|
||||
|
||||
switch (storedAs) {
|
||||
case BLOCK:
|
||||
if (block == null) {
|
||||
logger.warning("Could not locate egg block!");
|
||||
resetEggLocation();
|
||||
} else if (!Egg.hasEgg(block)) {
|
||||
logger.warning("Saved egg block does not actually contain the egg! Was the egg moved while the plugin was disabled?");
|
||||
logger.warning(BUG_STR);
|
||||
} else {
|
||||
log("Successfully found dragon egg block.");
|
||||
}
|
||||
break;
|
||||
case ENTITY:
|
||||
if (entity == null) {
|
||||
logger.warning("Could not locate the egg entity!");
|
||||
resetEggLocation();
|
||||
} else if (!Egg.hasEgg(entity)) {
|
||||
logger.warning("Saved egg entity does not actually contain the egg! Was the egg moved while the plugin was disabled?");
|
||||
logger.warning(BUG_STR);
|
||||
} else {
|
||||
log("Successfully found dragon egg entity.");
|
||||
}
|
||||
break;
|
||||
case DNE:
|
||||
log("Dragon egg has not been claimed.");
|
||||
}
|
||||
|
||||
if (owner != null) {
|
||||
OfflinePlayer p = Bukkit.getOfflinePlayer(owner);
|
||||
if (p == null) {
|
||||
logger.warning("Could not find player with the saved UUID! Resetting egg owner to prevent errors.");
|
||||
logger.warning(BUG_STR);
|
||||
resetEggOwner(false, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (entity == null && storedAs.equals(Egg_Storage_Type.ENTITY)) {
|
||||
logger.warning("Could not locate the egg entity!");
|
||||
resetEggLocation();
|
||||
} else if (block == null && storedAs.equals(Egg_Storage_Type.BLOCK)) {
|
||||
logger.warning("Could not locate egg block!");
|
||||
resetEggLocation();
|
||||
} else if (storedAs.equals(Egg_Storage_Type.DNE)) {
|
||||
log("Dragon egg has not been claimed.");
|
||||
} else {
|
||||
log("Successfully found dragon egg.");
|
||||
}
|
||||
}
|
||||
|
||||
public void loadData() {
|
||||
owner = dataDao.readUUID("owner", null);
|
||||
block = deserializeBlock(dataDao.readLocation("block", null));
|
||||
|
|
@ -131,28 +211,19 @@ public class Data {
|
|||
|
||||
if (storageString == 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.");
|
||||
"If this is the first time this plugin has run, it is safe to ignore this warning.");
|
||||
storedAs = Egg_Storage_Type.DNE;
|
||||
saveData();
|
||||
} else {
|
||||
storedAs = Egg_Storage_Type.valueOf(storageString);
|
||||
|
||||
//make sure data was properly loaded
|
||||
if (entity == null && storedAs.equals(Egg_Storage_Type.ENTITY)) {
|
||||
logger.warning("Could not locate the egg entity!");
|
||||
resetEggLocation();
|
||||
} else if (block == null && storedAs.equals(Egg_Storage_Type.BLOCK)) {
|
||||
logger.warning("Could not locate egg block!");
|
||||
resetEggLocation();
|
||||
} else if (storedAs.equals(Egg_Storage_Type.DNE)) {
|
||||
logger.info("Dragon egg has not been claimed.");
|
||||
} else {
|
||||
logger.info("Successfully found dragon egg.");
|
||||
}
|
||||
validateData();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveData() {
|
||||
ScoreboardController.saveData(logger);
|
||||
|
||||
dataDao.writeUUID("owner", owner);
|
||||
dataDao.writeLocation("block", serializeBlock(block));
|
||||
dataDao.writeUUID("entity", serializeEntity(entity));
|
||||
|
|
@ -170,35 +241,57 @@ public class Data {
|
|||
dataDao.save();
|
||||
}
|
||||
|
||||
public void setEggOwner(Player player) {
|
||||
setEggOwner(player.getUniqueId());
|
||||
public void setEggOwner(Player player, Configuration config) {
|
||||
setEggOwner(player.getUniqueId(), config);
|
||||
}
|
||||
|
||||
private void setEggOwner(UUID playerUUID) {
|
||||
if (!playerUUID.equals(owner)) { //only announce if the egg has actually changed posession
|
||||
owner = playerUUID;
|
||||
Announcement.announce(
|
||||
String.format("%s has claimed the dragon egg!", Bukkit.getOfflinePlayer(owner).getName()), logger);
|
||||
private void setEggOwner(UUID playerUUID, Configuration config) {
|
||||
if (!playerUUID.equals(owner)) { //only update if the egg has actually changed posession
|
||||
ScoreboardController.saveData(logger);
|
||||
UUID oldOwner = owner;
|
||||
owner = playerUUID; //set new owner
|
||||
String ownerName = Bukkit.getOfflinePlayer(owner).getName();
|
||||
String msg;
|
||||
|
||||
//if the old owner is online, remove their scoreboard tag
|
||||
if (oldOwner != null) {
|
||||
EggController.updateOwnerTag(Bukkit.getPlayer(oldOwner), this, config);
|
||||
String oldOwnerName = Bukkit.getOfflinePlayer(oldOwner).getName();
|
||||
msg = String.format("%s has stolen the dragon egg from %s!", ownerName, oldOwnerName);
|
||||
|
||||
} else {
|
||||
msg = String.format("%s has claimed the dragon egg!", ownerName);
|
||||
}
|
||||
|
||||
Announcement.announce(msg, logger);
|
||||
|
||||
Player p = Bukkit.getPlayer(playerUUID);
|
||||
if (p != null) { //make sure player is online
|
||||
Announcement.ShowEggEffects(p);
|
||||
EggController.updateOwnerTag(p, this, config); //update the scoreboard tag of the new owner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resetEggOwner(boolean announce) {
|
||||
if (announce) { //TODO move announcements somewhere else?
|
||||
public void resetEggOwner(boolean announce, Configuration config) {
|
||||
ScoreboardController.saveData(logger);
|
||||
if (owner != null) {
|
||||
Announcement.announce(String.format("%s no longer owns the dragon egg", Bukkit.getOfflinePlayer(owner).getName()), logger);
|
||||
Player oldOwner = Bukkit.getPlayer(owner);
|
||||
if (announce) { //TODO move announcements somewhere else?
|
||||
String ownerName = Bukkit.getOfflinePlayer(owner).getName();
|
||||
Announcement.announce(String.format("%s no longer owns the dragon egg", ownerName), logger);
|
||||
}
|
||||
}
|
||||
logger.info("Egg owner has been reset");
|
||||
owner = null;
|
||||
|
||||
log("Egg owner reset");
|
||||
owner = null;
|
||||
if (config != null) {
|
||||
EggController.updateOwnerTag(oldOwner, this, config); //update tag after setting owner to null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resetEggLocation() {
|
||||
log("Egg no longer exists");
|
||||
log("Egg location reset");
|
||||
block = null;
|
||||
entity = null;
|
||||
storedAs = Egg_Storage_Type.DNE;
|
||||
|
|
@ -208,20 +301,11 @@ public class Data {
|
|||
approxLocation = block.getLocation();
|
||||
this.block = block;
|
||||
entity = null;
|
||||
storedAs=Egg_Storage_Type.BLOCK;
|
||||
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"));
|
||||
break;
|
||||
|
||||
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()));
|
||||
log("The egg is "+getEggHolderString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateEggLocation(Entity holderEntity) {
|
||||
approxLocation = holderEntity.getLocation();
|
||||
|
|
@ -229,47 +313,17 @@ public class Data {
|
|||
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()));
|
||||
break;
|
||||
|
||||
case FALLING_BLOCK:
|
||||
log(String.format("The egg is a falling block"));
|
||||
break;
|
||||
|
||||
case DROPPED_ITEM:
|
||||
log(String.format("The egg is a dropped item"));
|
||||
break;
|
||||
|
||||
case ITEM_FRAME:
|
||||
case GLOW_ITEM_FRAME:
|
||||
log(String.format("The egg is an item frame"));
|
||||
break;
|
||||
|
||||
case ARMOR_STAND:
|
||||
log(String.format("The egg is held by an armor stand"));
|
||||
break;
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
}
|
||||
log("The egg is "+getEggHolderString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public void updateEggLocation(Inventory inv) {
|
||||
//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 (inv.getHolder() instanceof Entity){
|
||||
// Hopper minecart, llama, or some other entity has the egg
|
||||
for (Entity e : inv.getLocation().getWorld().getEntities()) {
|
||||
for (Entity e : inv.getLocation().getChunk().getEntities()) {
|
||||
//search all entities in the world
|
||||
if (e instanceof InventoryHolder) {
|
||||
if (inv.getHolder().equals((InventoryHolder) e)) {
|
||||
|
|
@ -279,16 +333,83 @@ public class Data {
|
|||
}
|
||||
}
|
||||
}
|
||||
log("could not find correct inventoryHolder entity!");
|
||||
logger.warning("Could not find the correct InventoryHolder entity for this Inventory! Are you using custom inventories?");
|
||||
logger.warning(BUG_STR);
|
||||
|
||||
} else {
|
||||
// Hopper picked up the egg
|
||||
updateEggLocation(inv.getLocation().getBlock()); //TODO check if this cast works or if .getLocation().getBlock() is needed
|
||||
// Block contains the egg
|
||||
updateEggLocation(inv.getLocation().getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a human-readable string describing where the dragon egg is
|
||||
* Will always start with "is <x>" unless the message is "does not exist"
|
||||
*/
|
||||
public String getEggHolderString() {
|
||||
Egg_Storage_Type type = getEggType();
|
||||
|
||||
String storageMsg;
|
||||
|
||||
if (type == Egg_Storage_Type.DNE) { //egg does not exist
|
||||
storageMsg = "does not exist";
|
||||
|
||||
} else { //egg exists
|
||||
|
||||
if (type == Egg_Storage_Type.BLOCK) {
|
||||
Block eggBlock = getEggBlock();
|
||||
|
||||
if (Egg.isOnlyEgg(eggBlock)) { //egg is an egg block
|
||||
storageMsg = "is a block";
|
||||
|
||||
} else { //egg is in a block
|
||||
//inside a container, so provide the name of the container
|
||||
storageMsg = String.format("is inside of a(n) %s", eggBlock.getType().toString());
|
||||
}
|
||||
|
||||
} else { //egg is in an entity
|
||||
|
||||
Entity eggEntity = getEggEntity();
|
||||
|
||||
switch (eggEntity.getType()) {
|
||||
case PLAYER:
|
||||
storageMsg = String.format("is in the inventory of %s", entity.getName());
|
||||
break;
|
||||
|
||||
case FALLING_BLOCK:
|
||||
storageMsg = String.format("is a falling block");
|
||||
break;
|
||||
|
||||
case DROPPED_ITEM:
|
||||
storageMsg = String.format("is a dropped item");
|
||||
break;
|
||||
|
||||
case ITEM_FRAME:
|
||||
case GLOW_ITEM_FRAME:
|
||||
storageMsg = String.format("is an item frame");
|
||||
break;
|
||||
|
||||
case ARMOR_STAND:
|
||||
storageMsg = String.format("is held by an armor stand");
|
||||
break;
|
||||
|
||||
default:
|
||||
//stored in the inventory of a non-player entity (zombie, hopper minecart, etc)
|
||||
if (entity.getCustomName() != null) {
|
||||
storageMsg = String.format("is held by a(n) %s named \"%s\"",
|
||||
entity.getType().toString(),
|
||||
entity.getName());
|
||||
} else {
|
||||
storageMsg = String.format("is held by a(n) %s", entity.getType().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return storageMsg;
|
||||
}
|
||||
|
||||
private void log(String msg) {
|
||||
logger.info(msg);
|
||||
logger.log(msg);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,79 +1,280 @@
|
|||
package io.github.J0hnL0cke.egghunt.Model;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Container;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.bukkit.inventory.meta.BundleMeta;
|
||||
|
||||
/**
|
||||
* Provides methods related to the dragon egg
|
||||
* Provides methods related to checking for or removing the dragon egg
|
||||
*/
|
||||
public class Egg {
|
||||
|
||||
private static Material egg = Material.DRAGON_EGG;
|
||||
|
||||
/**
|
||||
* Makes the given entity invulnerable if enabled in the config
|
||||
* Checks if the given ItemStack is a container that is holding the dragon egg. Also returns false if the provided stack is null.
|
||||
* @param stack ItemStack to check
|
||||
* @return True if the stack is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static void makeEggInvulnerable(Entity entity, Configuration config, Logger logger) {
|
||||
if (config.getEggInvulnerable()) {
|
||||
entity.setInvulnerable(true);
|
||||
logger.info("made drop invulnerable");
|
||||
public static boolean containsEgg(ItemStack stack) {
|
||||
if (stack == null) {
|
||||
return false;
|
||||
}
|
||||
if (isShulker(stack.getType())) { //check if shulker
|
||||
BlockStateMeta meta = (BlockStateMeta) stack.getItemMeta();
|
||||
ShulkerBox box = (ShulkerBox) meta.getBlockState();
|
||||
return hasEgg(box.getInventory());
|
||||
|
||||
} else if (stack.getType().equals(Material.BUNDLE)) { //check if bundle
|
||||
BundleMeta bundle = (BundleMeta) stack.getItemMeta();
|
||||
return hasEgg(bundle);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the dragon egg in the end world specified by the given config.
|
||||
* @return The new egg block.
|
||||
* Check if the given material is any color of shulker box
|
||||
*/
|
||||
public static Block respawnEgg(Configuration config) {
|
||||
Block newEggLoc = config.getEndWorld().getEnderDragonBattle().getEndPortalLocation().add(0, 4, 0).getBlock();
|
||||
newEggLoc.setType(Material.DRAGON_EGG);
|
||||
return newEggLoc;
|
||||
public static boolean isShulker(Material material) {
|
||||
if (material == null) {
|
||||
return false;
|
||||
}
|
||||
return Tag.SHULKER_BOXES.getValues().contains(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop the egg out of the given player's inventory
|
||||
* Checks if the given Block is a container that is holding the dragon egg. Also returns false if the provided block is null.
|
||||
* @param block Block to check
|
||||
* @return True if the block is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static void dropEgg(Player player, Data data) {
|
||||
// Check if the player has a dragon egg
|
||||
if (player.getInventory().contains(Material.DRAGON_EGG)) {
|
||||
|
||||
// Set owner and remove
|
||||
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 = player.getWorld().dropItem(player.getLocation(),
|
||||
new ItemStack(Material.DRAGON_EGG));
|
||||
data.updateEggLocation(egg_drop);
|
||||
public static boolean containsEgg(Block block) {
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
BlockState state = block.getState();
|
||||
if (state instanceof Container) {
|
||||
Container cont = (Container) state;
|
||||
return hasEgg(cont.getInventory());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean removeEgg(Entity entity) {
|
||||
//TODO update for containers
|
||||
if (entity instanceof Player) {
|
||||
if (hasEgg(((Player) entity).getInventory())) {
|
||||
Player player = (Player)entity;
|
||||
player.getInventory().remove(egg);
|
||||
}
|
||||
} else if (entity instanceof LivingEntity) {
|
||||
LivingEntity mob = (((LivingEntity) entity));
|
||||
EntityEquipment inv = mob.getEquipment();
|
||||
if (hasEgg(inv.getItemInMainHand())) {
|
||||
inv.setItemInMainHand(null);
|
||||
return true;
|
||||
} else if (hasEgg(inv.getItemInOffHand())) {
|
||||
inv.setItemInOffHand(null);
|
||||
return true;
|
||||
}
|
||||
} else if (entity instanceof FallingBlock) {
|
||||
FallingBlock block = (FallingBlock) entity;
|
||||
if (hasEgg(block)) {
|
||||
block.remove();
|
||||
return true;
|
||||
}
|
||||
} else if (entity instanceof Item) {
|
||||
Item item = (Item) entity;
|
||||
if (hasEgg(item)) {
|
||||
item.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean removeEgg(Block block) {
|
||||
if (hasEgg(block)) {
|
||||
block.setType(Material.AIR);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a new egg item at the given location, sets it to invincible if enabled in the given config.
|
||||
* This should trigger the item drop event, so it should not be necessary to immediately update the data file with the returned item.
|
||||
* @return the egg item that was spawned
|
||||
* Check if the given Material is the dragon egg. Also returns false if the provided material is null.
|
||||
* @param material Material to check
|
||||
* @return True if the stack material is a dragon egg, otherwise false
|
||||
*/
|
||||
public static Item 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.getEggInvulnerable()) {
|
||||
drop.setInvulnerable(true);
|
||||
public static boolean isEgg(Material material) {
|
||||
if (material == null) {
|
||||
return false;
|
||||
}
|
||||
return drop;
|
||||
return material.equals(egg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given Entity is holding the dragon egg. Also returns false if the provided entity is null.
|
||||
* @param entity
|
||||
* @return True if the entity is holding the dragon egg or a container that is holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(Entity entity) {
|
||||
if (entity instanceof Player) {
|
||||
return Egg.hasEgg(((Player) entity).getInventory()); //Handles entire player check, including inventory, equipment, and custom slots
|
||||
}
|
||||
|
||||
//Some entities can be instances of both LivingEntity and InventoryHolder (villager, allay, etc)
|
||||
//therefore, check both inventory and equipment separately for the egg
|
||||
if (entity instanceof LivingEntity) {
|
||||
LivingEntity mob = (((LivingEntity) entity));
|
||||
EntityEquipment inv = mob.getEquipment();
|
||||
if (Egg.hasEgg(inv.getArmorContents())) {
|
||||
return true;
|
||||
} else if (Egg.hasEgg(inv.getItemInMainHand()) || Egg.hasEgg(inv.getItemInOffHand())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity instanceof InventoryHolder) {
|
||||
if (Egg.hasEgg(((InventoryHolder) entity).getInventory())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity instanceof FallingBlock) {
|
||||
return Egg.hasEgg(((FallingBlock) entity));
|
||||
} else if (entity instanceof Item) {
|
||||
return Egg.hasEgg(((Item) entity));
|
||||
} else if (entity instanceof ItemFrame) {
|
||||
return Egg.hasEgg(((ItemFrame) entity).getItem());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any of the given ItemStacks are the dragon egg or are holding the egg. Also returns false if the provided list is null.
|
||||
* @param stack list of ItemStacks to check
|
||||
* @return True if any of the stacks' material is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(ItemStack[] stacks) {
|
||||
if (stacks == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ItemStack item : stacks) {
|
||||
if (Egg.hasEgg(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given ItemStack is the dragon egg or is holding the egg. Also returns false if the provided stack is null.
|
||||
* @param stack ItemStack to check
|
||||
* @return True if the stack material is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(ItemStack stack) {
|
||||
if (stack == null) {
|
||||
return false;
|
||||
}
|
||||
return isEgg(stack.getType()) || containsEgg(stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Inventory contains the dragon egg or a container holding the egg. Also returns false if the provided inventory is null.
|
||||
* @param inventory Inventory to check
|
||||
* @return True if the inventory contains the a dragon egg item or an item holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(Inventory inventory) {
|
||||
if (inventory == null) {
|
||||
return false;
|
||||
}
|
||||
return hasEgg(inventory.getContents());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given PlayerInventory contains the dragon egg or a container holding the egg. Also returns false if the provided inventory is null.
|
||||
* Note: Player inventories can contain extra content slots on top of normal inventory contents
|
||||
* @param inventory PlayerInventory to check
|
||||
* @return True if the inventory contains the a dragon egg item or an item holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(PlayerInventory inventory) {
|
||||
if (inventory == null) {
|
||||
return false;
|
||||
}
|
||||
for (ItemStack stack : inventory.getExtraContents()) {
|
||||
if (hasEgg(stack)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return hasEgg((Inventory)inventory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Item is the dragon egg or is holding the egg. Also returns false if the provided item is null.
|
||||
* @param item Item to check
|
||||
* @return True if the item material is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(Item item) {
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
return isEgg(item.getItemStack().getType()) || containsEgg(item.getItemStack());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Block is the dragon egg or is holding the egg. Also returns false if the provided block is null.
|
||||
* @param block Block to check
|
||||
* @return True if the block material is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(Block block) {
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
return isEgg(block.getType()) || containsEgg(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given FallingBlock is the dragon egg or is holding the egg. Also returns false if the provided block is null.
|
||||
* @param block FallingBlock to check
|
||||
* @return True if the block material is a dragon egg or holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(FallingBlock block) {
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
return isEgg(block.getBlockData().getMaterial()); //don't check containsEgg because shulker can't be falling block
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given BundleMeta contains the dragon egg or a container holding the egg. Also returns false if the provided bundle is null.
|
||||
* @param bundle Bundle to check
|
||||
* @return True if the bundle contains either the dragon egg or a container (another bundle) holding the egg, otherwise false
|
||||
*/
|
||||
public static boolean hasEgg(BundleMeta bundle) {
|
||||
for (ItemStack stack : bundle.getItems()) {
|
||||
if (hasEgg(stack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,7 +282,7 @@ public class Egg {
|
|||
* @param stack ItemStack to check
|
||||
* @return True if the stack material is a dragon egg, otherwise false
|
||||
*/
|
||||
public static boolean isEgg(ItemStack stack) {
|
||||
public static boolean isOnlyEgg(ItemStack stack) {
|
||||
if (stack == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -93,7 +294,7 @@ public class Egg {
|
|||
* @param item Item to check
|
||||
* @return True if the item material is a dragon egg, otherwise false
|
||||
*/
|
||||
public static boolean isEgg(Item item) {
|
||||
public static boolean isOnlyEgg(Item item) {
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -105,7 +306,7 @@ public class Egg {
|
|||
* @param block Block to check
|
||||
* @return True if the block material is a dragon egg, otherwise false
|
||||
*/
|
||||
public static boolean isEgg(Block block) {
|
||||
public static boolean isOnlyEgg(Block block) {
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -117,11 +318,24 @@ public class Egg {
|
|||
* @param block FallingBlock to check
|
||||
* @return True if the block material is a dragon egg, otherwise false
|
||||
*/
|
||||
public static boolean isEgg(FallingBlock block) {
|
||||
public static boolean isOnlyEgg(FallingBlock block) {
|
||||
if (block == null) {
|
||||
return false;
|
||||
}
|
||||
return block.getBlockData().getMaterial().equals(egg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Inventory contains the dragon egg. Also returns false if the provided inventory is null.
|
||||
* @param inventory Inventory to check
|
||||
* @return True if the inventorry contains a dragon egg, otherwise false
|
||||
*/
|
||||
public static boolean hasOnlyEgg(Inventory inventory) {
|
||||
if (inventory == null) {
|
||||
return false;
|
||||
}
|
||||
return inventory.contains(Material.DRAGON_EGG);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
package io.github.J0hnL0cke.egghunt.Model;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class LogHandler {
|
||||
private Logger logger;
|
||||
private boolean debug = false;
|
||||
|
||||
/**
|
||||
* Provides loggging functionality
|
||||
* Debugging requires increasing the logging level, since the console never listens to logs below INFO
|
||||
* due to how parent loggers are hardcoded
|
||||
*/
|
||||
public LogHandler(Logger logger) {
|
||||
this.logger = logger;
|
||||
|
||||
log("Logging ready");
|
||||
}
|
||||
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
if (debug) {
|
||||
log("Debugging is ON");
|
||||
}
|
||||
}
|
||||
|
||||
public void log(String msg, Level loggingLevel) {
|
||||
logger.log(loggingLevel, msg);
|
||||
}
|
||||
|
||||
public void log(String msg) {
|
||||
log(msg, debug ? Level.INFO : Level.CONFIG);
|
||||
}
|
||||
|
||||
public void info(String msg) {
|
||||
log(msg, Level.INFO);
|
||||
}
|
||||
|
||||
public void warning(String msg) {
|
||||
log(msg, Level.WARNING);
|
||||
}
|
||||
|
||||
public void severe(String msg) {
|
||||
log(msg, Level.SEVERE);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
package io.github.J0hnL0cke.egghunt.Persistence;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.io.File;
|
||||
|
||||
|
|
@ -15,6 +12,8 @@ import org.bukkit.configuration.file.FileConfiguration;
|
|||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
|
||||
public class DataFileDAO {
|
||||
|
||||
public static final String DATA_FILE = "data.yml";
|
||||
|
|
@ -22,17 +21,16 @@ public class DataFileDAO {
|
|||
private static DataFileDAO thisDao;
|
||||
private FileConfiguration fileConfig;
|
||||
private File file;
|
||||
private LogHandler logger;
|
||||
|
||||
JavaPlugin plugin;
|
||||
|
||||
private DataFileDAO(JavaPlugin plugin){
|
||||
this.plugin = plugin;
|
||||
private DataFileDAO(JavaPlugin plugin, LogHandler logger) {
|
||||
this.logger = logger;
|
||||
loadData(plugin, DATA_FILE);
|
||||
}
|
||||
|
||||
public static DataFileDAO getDataDAO(JavaPlugin plugin){
|
||||
public static DataFileDAO getDataDAO(JavaPlugin plugin, LogHandler logger){
|
||||
if(thisDao == null){
|
||||
thisDao = new DataFileDAO(plugin);
|
||||
thisDao = new DataFileDAO(plugin, logger);
|
||||
}
|
||||
return thisDao;
|
||||
}
|
||||
|
|
@ -58,7 +56,7 @@ public class DataFileDAO {
|
|||
try {
|
||||
fileConfig.save(file);
|
||||
} catch (IOException e) {
|
||||
Bukkit.getServer().getLogger().severe(String.format("Could not save data file!"));
|
||||
logger.severe(String.format("Could not save data file!"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package io.github.J0hnL0cke.egghunt;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
|
@ -10,14 +8,17 @@ import org.bukkit.plugin.PluginManager;
|
|||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import io.github.J0hnL0cke.egghunt.Controller.Announcement;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.CommandHandler;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.EggController;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.EggDestroyListener;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.MiscListener;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.ScoreboardController;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.EventScheduler;
|
||||
import io.github.J0hnL0cke.egghunt.Controller.InventoryListener;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Configuration;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Data;
|
||||
import io.github.J0hnL0cke.egghunt.Model.Egg;
|
||||
import io.github.J0hnL0cke.egghunt.Model.LogHandler;
|
||||
import io.github.J0hnL0cke.egghunt.Persistence.ConfigFileDAO;
|
||||
import io.github.J0hnL0cke.egghunt.Persistence.DataFileDAO;
|
||||
|
||||
|
|
@ -28,27 +29,32 @@ public final class egghunt extends JavaPlugin {
|
|||
CommandHandler commandHandler;
|
||||
|
||||
BukkitTask belowWorldTask;
|
||||
Logger logger;
|
||||
LogHandler logger;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
logger = getLogger();
|
||||
log("Enabling EggHunt...");
|
||||
//create logger instance
|
||||
logger = new LogHandler(getLogger());
|
||||
|
||||
logger.info("Enabling EggHunt..."); //server already provides an enable message
|
||||
saveDefaultConfig();
|
||||
|
||||
//create model instances using dependency injection
|
||||
config = new Configuration(new ConfigFileDAO(this));
|
||||
data = new Data(DataFileDAO.getDataDAO(this), getLogger());
|
||||
data = new Data(DataFileDAO.getDataDAO(this, logger), logger);
|
||||
|
||||
logger.setDebug(config.getDebugEnabled());
|
||||
|
||||
//create controller instances
|
||||
MiscListener miscListener = new MiscListener(getLogger(), config, data);
|
||||
ScoreboardController scoreboardController = ScoreboardController.getScoreboardHandler(data, config, logger);
|
||||
MiscListener miscListener = new MiscListener(logger, config, data);
|
||||
InventoryListener inventoryListener = new InventoryListener(logger, config, data);
|
||||
EggDestroyListener destroyListener = new EggDestroyListener(logger, config, data);
|
||||
EventScheduler scheduler = new EventScheduler(config, data, logger);
|
||||
commandHandler = new CommandHandler(data);
|
||||
|
||||
//register event handlers
|
||||
log("Registering event listeners...");
|
||||
logger.log("Registering event listeners...");
|
||||
PluginManager manager = getServer().getPluginManager();
|
||||
manager.registerEvents(miscListener, this);
|
||||
manager.registerEvents(inventoryListener, this);
|
||||
|
|
@ -56,35 +62,36 @@ public final class egghunt extends JavaPlugin {
|
|||
|
||||
//schedule tasks
|
||||
//TODO: disable task when not in use
|
||||
log("Scheduling below world task...");
|
||||
logger.log("Scheduling task...");
|
||||
belowWorldTask = scheduler.runTaskTimer(this, 20, 20);
|
||||
|
||||
log("Done!");
|
||||
logger.info("EggHunt enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
log("onDisable has been invoked, disabling eggHunt.");
|
||||
logger.log("Preparing to disable EggHunt..."); //server already provides a disable message
|
||||
if (data != null) {
|
||||
//if a player has the egg in their inventory,
|
||||
//drop it on the ground in case the server is closing
|
||||
Entity eggHolder = data.getEggEntity();
|
||||
if (eggHolder != null) {
|
||||
if (eggHolder instanceof Player) {
|
||||
log("egg is held by a player, dropping egg...");
|
||||
logger.log("Egg is held by a player, dropping egg...");
|
||||
Player p = (Player) eggHolder;
|
||||
Egg.dropEgg(p, data);
|
||||
EggController.dropEgg(p, data, config);
|
||||
//in case the server isn't restarting, let the player know what happend
|
||||
p.sendMessage("The dragon egg was dropped from your inventory");
|
||||
Announcement.sendMessage(p, "The dragon egg was dropped from your inventory");
|
||||
}
|
||||
}
|
||||
log("saving data...");
|
||||
logger.log("Saving data...");
|
||||
data.saveData();
|
||||
}
|
||||
logger.log("Disabling task...");
|
||||
if (belowWorldTask!=null) {
|
||||
belowWorldTask.cancel();
|
||||
}
|
||||
log("Plugin disabled.");
|
||||
logger.info("EggHunt disabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -92,8 +99,6 @@ public final class egghunt extends JavaPlugin {
|
|||
return commandHandler.onCommand(sender, cmd, label, args);
|
||||
}
|
||||
|
||||
private void log(String msg) {
|
||||
logger.info(msg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#If enabled, logs extra debugging information to the console. This information will appear in logs regardless of debug setting.
|
||||
debug: true
|
||||
|
||||
#Name of your end world, usually to "world_the_end" on spigot
|
||||
end: world_the_end
|
||||
|
||||
#Whether the egg teleporting causes the owner to no longer count as the owner of the egg
|
||||
reset_owner: true
|
||||
#Whether to tell players the new location of the egg (true) or the previous location of the egg (false) when it teleports
|
||||
#!!! not yet implemented !!!
|
||||
#accurate_loc: false
|
||||
|
||||
#Whether the egg should be invulnerable to damage
|
||||
egg_inv: false
|
||||
|
|
@ -13,6 +13,21 @@ egg_inv: false
|
|||
resp_egg: true
|
||||
#Whether the egg respawns immediately (true) or after a new dragon is spawned and killed (false) after the egg is destroyed
|
||||
resp_imm: false
|
||||
|
||||
#Whether to drop any eggs that players have in their ender chest onto the ground.
|
||||
#Setting this to false will prevent the player from removing that egg from their ender chest.
|
||||
drop_enderchested_egg: false
|
||||
|
||||
#Whether to apply an entity tag to the egg owner (works like `/tag <playerName> add <tagName>`)
|
||||
#Tag is updated when egg ownership changes and on player login
|
||||
tag_owner: true
|
||||
#The name of the tag to apply. Selected like: `/tell @a[tag=<tagName>] <message>`
|
||||
#If changing this while the egg is claimed, remove the old tag by running `/tag <playerName> remove <oldTagName>`
|
||||
owner_tag_name: eggOwner
|
||||
|
||||
#Whether to create and update scoreboards for time holding the dragon egg
|
||||
#Scoreboards are updated when the egg changes ownership and when the world saves
|
||||
#When editing the scores, modify the board tracking seconds. Other times are calculated based on that time
|
||||
keep_score: true
|
||||
#Whether entities with custom names are counted on the scoreboard instead of the owner when holding the egg
|
||||
named_entities_keep_score: false
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
name: EggHunt
|
||||
main: io.github.J0hnL0cke.egghunt.egghunt
|
||||
website: https://github.com/HyperSMP/EggHuntPlugin
|
||||
version: 1.20.1
|
||||
api-version: '1.20'
|
||||
|
||||
|
|
@ -34,13 +35,18 @@ permissions:
|
|||
children:
|
||||
egghunt.locateegg: true
|
||||
egghunt.trackegg: true
|
||||
egghunt.eggowner: true
|
||||
egghunt.notify: true
|
||||
default: true
|
||||
egghunt.locateegg:
|
||||
description: Allows you to locate the dragon egg using /locateegg
|
||||
default: true
|
||||
egghunt.trackegg:
|
||||
description: Allows you to track the egg with a compass using /trackegg
|
||||
default: true
|
||||
egghunt.eggowner:
|
||||
description: Allows you to query the egg's current owner
|
||||
default: true
|
||||
egghunt.notify:
|
||||
description: Receive a chat message when the egg is claimed, stolen, lost, or destroyed
|
||||
default: true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue