/*
ExtraHardMode Server Plugin for Minecraft
Copyright (C) 2012 Ryan Hamshire
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.ryanhamshire.ExtraHardMode;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
public class ExtraHardMode extends JavaPlugin
{
//for convenience, a reference to the instance of this plugin
public static ExtraHardMode instance;
//for logging to the console and log file
private static Logger log = Logger.getLogger("Minecraft");
//this handles the config files (messages and plugin options)
public DataStore dataStore;
//for computing random chance
static Random randomNumberGenerator = new Random();
//configuration variables, loaded/saved from a config.yml
public ArrayList<World> config_enabled_worlds; //list of worlds where extra hard mode rules apply
//general monster rules
public int config_moreMonstersMaxY; //max y value for extra monster spawns
public int config_moreMonstersMultiplier; //what to multiply monster spawns by
public int config_monsterSpawnsInLightMaxY; //max y value for monsters to spawn in the light
//monster grinder fix rules
public boolean config_inhibitMonsterGrinders; //whether monster grinders (or "farms") should be inhibited
//world modification rules
public int config_standardTorchMinY; //minimum y for placing standard torches
public boolean config_superHardStone; //whether stone is hardened to encourage cave exploration over tunneling
public boolean config_limitedBlockPlacement; //whether players may place blocks directly underneath themselves
public boolean config_betterTNT; //whether TNT should be more powerful and plentiful
public ArrayList<Material> config_moreFallingBlocks; //which materials beyond sand and gravel should be subject to gravity
public boolean config_limitedTorchPlacement; //whether players are limited to placing torches against specific materials
public boolean config_rainBreaksTorches; //whether rain should break torches
public int config_brokenNetherrackCatchesFirePercent; //percent chance for broken netherrack to start a fire
//zombie rules
public boolean config_zombiesDebilitatePlayers; //whether zombies apply a debuff to players on hit
public int config_zombiesReanimatePercent; //percent chance for a zombie to reanimate after death
//skeleton rules
public int config_skeletonsKnockBackPercent; //percent chance skeletons have a chance to knock back targets with arrows
public int config_skeletonsReleaseSilverfishPercent; //percent chance skeletons will release silverfish instead of firing arrows
public int config_skeletonsDeflectArrowsPercent; //whether or not arrows will pass harmlessly through skeletons
public boolean config_flamingCreepersExplode; //whether creepers explode when caught on fire
//creeper rules
public int config_chargedCreeperSpawnPercent; //percentage of creepers which will spawn charged
public boolean config_chargedCreepersExplodeOnHit; //whether charged creepers explode when damaged
public int config_creepersDropTNTOnDeathPercent; //percentage of creepers which spawn activated TNT on death
//pig zombie rules
public boolean config_alwaysAngryPigZombies; //whether pig zombies are always hostile
public boolean config_fortressPigsDropWart; //whether pig zombies drop nether wart in nether fortresses
//ghast rules
public boolean config_ghastsDeflectArrows; //whether ghasts should deflect arrows and drop extra loot
//magma cube rules
public boolean config_magmaCubesBecomeBlazesOnDamage; //whether damaging a magma cube turns it into a blaze
public int config_flameSlimesSpawnWithNetherBlazePercent; //percentage chance that a blaze spawn will trigger a flame slime spawn as well
//blaze rules
public int config_bonusNetherBlazeSpawnPercent; //percentage of pig zombies which will be replaced with blazes
public boolean config_blazesExplodeOnDeath; //whether blazes explode and spread fire when they die
public int config_nearBedrockBlazeSpawnPercent; //percentage of skeletons near bedrock which will be replaced with blazes
public int config_netherBlazesSplitOnDeathPercent; //percentage chance that a blaze slain in the nether will split into two blazes
public boolean config_blazesDropFireOnDamage; //whether blazes drop fire when damaged
public boolean config_blazesDropBonusLoot; //whether blazes drop extra loot
//spider rules
public int config_bonusUndergroundSpiderSpawnPercent; //percentage of zombies which will be replaced with spiders under sea level
public boolean config_spidersDropWebOnDeath; //whether spiders drop webbing when they die
//enderman rules
public boolean config_improvedEndermanTeleportation; //whether endermen may teleport players
//witch rules
public int config_bonusWitchSpawnPercent; //percentage of surface zombies which spawn as witches
//ender dragon rules
public boolean config_respawnEnderDragon; //whether the ender dragon respawns
public boolean config_enderDragonDropsEgg; //whether it drops an egg when slain
public boolean config_enderDragonDropsVillagerEggs; //whether it drops a pair of villager eggs when slain
public boolean config_enderDragonAdditionalAttacks; //whether the dragon spits fireballs and summons minions
public boolean config_enderDragonCombatAnnouncements; //whether server wide messages will broadcast player victories and defeats
public boolean config_enderDragonNoBuilding; //whether players will be allowed to build in the end
//melons and wheat
public boolean config_weakFoodCrops; //whether food crops die more easily
//mushrooms
public boolean config_noBonemealOnMushrooms; //whether bonemeal may be used on mushrooms
//nether wart
public boolean config_noFarmingNetherWart; //whether nether wart will ever drop more than 1 wart when broken
//sheep (wool)
public boolean config_sheepRegrowWhiteWool; //whether sheep will always regrow white wool
//water
public boolean config_dontMoveWaterSourceBlocks; //whether players may move water source blocks
public boolean config_noSwimmingInArmor; //whether players may swim while wearing armor
//player death
public int config_playerRespawnHealth; //how much health after respawn
public int config_playerRespawnFoodLevel; //how much food bar after respawn
public int config_playerDeathItemStacksForfeitPercent; //percentage of item stacks lost on death
//player damage
public boolean config_enhancedEnvironmentalDamage; //whether players take additional damage and/or debuffs from environmental injuries
public boolean config_extinguishingFireIgnitesPlayers; //whether players catch fire when extinguishing a fire up close
//tree felling
public boolean config_betterTreeChopping; //whether tree logs respect gravity
//explosions disable option, needed to dodge bugs in popular plugins
public boolean config_workAroundExplosionsBugs;
//adds a server log entry
public static void AddLogEntry(String entry)
{
log.info("ExtraHardMode: " + entry);
}
//initializes well... everything
public void onEnable()
{
AddLogEntry("Extra Hard Mode enabled.");
this.dataStore = new DataStore();
instance = this;
//load the config if it exists
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(DataStore.configFilePath));
FileConfiguration outConfig = new YamlConfiguration();
//read configuration settings (note defaults), write back to config file
//enabled worlds defaults
ArrayList<String> defaultEnabledWorldNames = new ArrayList<String>();
List<World> worlds = this.getServer().getWorlds();
for(int i = 0; i < worlds.size(); i++)
{
defaultEnabledWorldNames.add(worlds.get(i).getName());
}
//get enabled world names from the config file
List<String> enabledWorldNames = config.getStringList("ExtraHardMode.Worlds");
if(enabledWorldNames == null || enabledWorldNames.size() == 0)
{
enabledWorldNames = defaultEnabledWorldNames;
}
//validate enabled world names
this.config_enabled_worlds = new ArrayList<World>();
for(int i = 0; i < enabledWorldNames.size(); i++)
{
String worldName = enabledWorldNames.get(i);
World world = this.getServer().getWorld(worldName);
if(world == null)
{
AddLogEntry("Error: There's no world named \"" + worldName + "\". Please update your config.yml.");
}
else
{
this.config_enabled_worlds.add(world);
}
}
//write enabled world names to config file
outConfig.set("ExtraHardMode.Worlds", enabledWorldNames);
this.config_standardTorchMinY = config.getInt("ExtraHardMode.PermanentFlameMinYCoord", 30);
outConfig.set("ExtraHardMode.PermanentFlameMinYCoord", this.config_standardTorchMinY);
this.config_superHardStone = config.getBoolean("ExtraHardMode.HardenedStone", true);
outConfig.set("ExtraHardMode.HardenedStone", this.config_superHardStone);
this.config_enhancedEnvironmentalDamage = config.getBoolean("ExtraHardMode.EnhancedEnvironmentalInjuries", true);
outConfig.set("ExtraHardMode.EnhancedEnvironmentalInjuries", this.config_enhancedEnvironmentalDamage);
this.config_extinguishingFireIgnitesPlayers = config.getBoolean("ExtraHardMode.ExtinguishingFiresIgnitesPlayers", true);
outConfig.set("ExtraHardMode.ExtinguishingFiresIgnitesPlayers", this.config_extinguishingFireIgnitesPlayers);
this.config_betterTNT = config.getBoolean("ExtraHardMode.BetterTNT", true);
outConfig.set("ExtraHardMode.BetterTNT", this.config_betterTNT);
this.config_inhibitMonsterGrinders = config.getBoolean("ExtraHardMode.InhibitMonsterGrinders", true);
outConfig.set("ExtraHardMode.InhibitMonsterGrinders", this.config_inhibitMonsterGrinders);
this.config_limitedBlockPlacement = config.getBoolean("ExtraHardMode.LimitedBlockPlacement", true);
outConfig.set("ExtraHardMode.LimitedBlockPlacement", this.config_limitedBlockPlacement);
this.config_limitedTorchPlacement = config.getBoolean("ExtraHardMode.LimitedTorchPlacement", true);
outConfig.set("ExtraHardMode.LimitedTorchPlacement", this.config_limitedTorchPlacement);
this.config_rainBreaksTorches = config.getBoolean("ExtraHardMode.RainBreaksTorches", true);
outConfig.set("ExtraHardMode.RainBreaksTorches", this.config_rainBreaksTorches);
this.config_brokenNetherrackCatchesFirePercent = config.getInt("ExtraHardMode.NetherrackCatchesFirePercent", 20);
outConfig.set("ExtraHardMode.NetherrackCatchesFirePercent", this.config_brokenNetherrackCatchesFirePercent);
this.config_moreMonstersMaxY = config.getInt("ExtraHardMode.MoreMonsters.MaxYCoord", 55);
outConfig.set("ExtraHardMode.MoreMonsters.MaxYCoord", this.config_moreMonstersMaxY);
this.config_moreMonstersMultiplier = config.getInt("ExtraHardMode.MoreMonsters.Multiplier", 2);
outConfig.set("ExtraHardMode.MoreMonsters.Multiplier", this.config_moreMonstersMultiplier);
this.config_monsterSpawnsInLightMaxY = config.getInt("ExtraHardMode.MonstersSpawnInLightMaxY", 50);
outConfig.set("ExtraHardMode.MonstersSpawnInLightMaxY", this.config_monsterSpawnsInLightMaxY);
this.config_zombiesDebilitatePlayers = config.getBoolean("ExtraHardMode.Zombies.SlowPlayers", true);
outConfig.set("ExtraHardMode.Zombies.SlowPlayers", this.config_zombiesDebilitatePlayers);
this.config_zombiesReanimatePercent = config.getInt("ExtraHardMode.Zombies.ReanimatePercent", 50);
outConfig.set("ExtraHardMode.Zombies.ReanimatePercent", this.config_zombiesReanimatePercent);
this.config_skeletonsKnockBackPercent = config.getInt("ExtraHardMode.Skeletons.ArrowsKnockBackPercent", 30);
outConfig.set("ExtraHardMode.Skeletons.ArrowsKnockBackPercent", this.config_skeletonsKnockBackPercent);
this.config_skeletonsReleaseSilverfishPercent = config.getInt("ExtraHardMode.Skeletons.ReleaseSilverfishPercent", 30);
outConfig.set("ExtraHardMode.Skeletons.ReleaseSilverfishPercent", this.config_skeletonsReleaseSilverfishPercent);
this.config_skeletonsDeflectArrowsPercent = config.getInt("ExtraHardMode.Skeletons.DeflectArrowsPercent", 100);
outConfig.set("ExtraHardMode.Skeletons.DeflectArrowsPercent", this.config_skeletonsDeflectArrowsPercent);
this.config_bonusUndergroundSpiderSpawnPercent = config.getInt("ExtraHardMode.Spiders.BonusUndergroundSpawnPercent", 20);
outConfig.set("ExtraHardMode.Spiders.BonusUndergroundSpawnPercent", this.config_bonusUndergroundSpiderSpawnPercent);
this.config_spidersDropWebOnDeath = config.getBoolean("ExtraHardMode.Spiders.DropWebOnDeath", true);
outConfig.set("ExtraHardMode.Spiders.DropWebOnDeath", this.config_spidersDropWebOnDeath);
this.config_bonusWitchSpawnPercent = config.getInt("ExtraHardMode.Witches.BonusSpawnPercent", 5);
outConfig.set("ExtraHardMode.Witches.BonusSpawnPercent", this.config_bonusWitchSpawnPercent);
this.config_chargedCreeperSpawnPercent = config.getInt("ExtraHardMode.Creepers.ChargedCreeperSpawnPercent", 20);
outConfig.set("ExtraHardMode.Creepers.ChargedCreeperSpawnPercent", this.config_chargedCreeperSpawnPercent);
this.config_creepersDropTNTOnDeathPercent = config.getInt("ExtraHardMode.Creepers.DropTNTOnDeathPercent", 20);
outConfig.set("ExtraHardMode.Creepers.DropTNTOnDeathPercent", this.config_creepersDropTNTOnDeathPercent);
this.config_chargedCreepersExplodeOnHit = config.getBoolean("ExtraHardMode.Creepers.ChargedCreepersExplodeOnDamage", true);
outConfig.set("ExtraHardMode.Creepers.ChargedCreepersExplodeOnDamage", this.config_chargedCreepersExplodeOnHit);
this.config_flamingCreepersExplode = config.getBoolean("ExtraHardMode.Creepers.FireTriggersExplosion", true);
outConfig.set("ExtraHardMode.Creepers.FireTriggersExplosion", this.config_flamingCreepersExplode);
this.config_nearBedrockBlazeSpawnPercent = config.getInt("ExtraHardMode.Blazes.NearBedrockSpawnPercent", 50);
outConfig.set("ExtraHardMode.Blazes.NearBedrockSpawnPercent", this.config_nearBedrockBlazeSpawnPercent);
this.config_bonusNetherBlazeSpawnPercent = config.getInt("ExtraHardMode.Blazes.BonusNetherSpawnPercent", 20);
outConfig.set("ExtraHardMode.Blazes.BonusNetherSpawnPercent", this.config_bonusNetherBlazeSpawnPercent);
this.config_flameSlimesSpawnWithNetherBlazePercent = config.getInt("ExtraHardMode.MagmaCubes.SpawnWithNetherBlazePercent", 100);
outConfig.set("ExtraHardMode.MagmaCubes.SpawnWithNetherBlazePercent", this.config_flameSlimesSpawnWithNetherBlazePercent);
this.config_magmaCubesBecomeBlazesOnDamage = config.getBoolean("ExtraHardMode.MagmaCubes.GrowIntoBlazesOnDamage", true);
outConfig.set("ExtraHardMode.MagmaCubes.GrowIntoBlazesOnDamage", this.config_magmaCubesBecomeBlazesOnDamage);
this.config_blazesExplodeOnDeath = config.getBoolean("ExtraHardMode.Blazes.ExplodeOnDeath", true);
outConfig.set("ExtraHardMode.Blazes.ExplodeOnDeath", this.config_blazesExplodeOnDeath);
this.config_blazesDropFireOnDamage = config.getBoolean("ExtraHardMode.Blazes.DropFireOnDamage", true);
outConfig.set("ExtraHardMode.Blazes.DropFireOnDamage", this.config_blazesDropFireOnDamage);
this.config_blazesDropBonusLoot = config.getBoolean("ExtraHardMode.Blazes.BonusLoot", true);
outConfig.set("ExtraHardMode.Blazes.BonusLoot", this.config_blazesDropBonusLoot);
this.config_netherBlazesSplitOnDeathPercent = config.getInt("ExtraHardMode.Blazes.NetherSplitOnDeathPercent", 25);
outConfig.set("ExtraHardMode.Blazes.NetherSplitOnDeathPercent", this.config_netherBlazesSplitOnDeathPercent);
this.config_alwaysAngryPigZombies = config.getBoolean("ExtraHardMode.PigZombies.AlwaysAngry", true);
outConfig.set("ExtraHardMode.PigZombies.AlwaysAngry", this.config_alwaysAngryPigZombies);
this.config_fortressPigsDropWart = config.getBoolean("ExtraHardMode.PigZombies.DropWartInFortresses", true);
outConfig.set("ExtraHardMode.PigZombies.DropWartInFortresses", this.config_fortressPigsDropWart);
this.config_ghastsDeflectArrows = config.getBoolean("ExtraHardMode.Ghasts.DeflectArrows", true);
outConfig.set("ExtraHardMode.Ghasts.DeflectArrows", this.config_ghastsDeflectArrows);
this.config_improvedEndermanTeleportation = config.getBoolean("ExtraHardMode.Endermen.MayTeleportPlayers", true);
outConfig.set("ExtraHardMode.Endermen.MayTeleportPlayers", this.config_improvedEndermanTeleportation);
this.config_respawnEnderDragon = config.getBoolean("ExtraHardMode.EnderDragon.Respawns", true);
outConfig.set("ExtraHardMode.EnderDragon.Respawns", this.config_respawnEnderDragon);
this.config_enderDragonDropsEgg = config.getBoolean("ExtraHardMode.EnderDragon.DropsEgg", true);
outConfig.set("ExtraHardMode.EnderDragon.DropsEgg", this.config_enderDragonDropsEgg);
this.config_enderDragonDropsVillagerEggs = config.getBoolean("ExtraHardMode.EnderDragon.DropsVillagerEggs", true);
outConfig.set("ExtraHardMode.EnderDragon.DropsVillagerEggs", this.config_enderDragonDropsVillagerEggs);
this.config_enderDragonAdditionalAttacks = config.getBoolean("ExtraHardMode.EnderDragon.HarderBattle", true);
outConfig.set("ExtraHardMode.EnderDragon.HarderBattle", this.config_enderDragonAdditionalAttacks);
this.config_enderDragonCombatAnnouncements = config.getBoolean("ExtraHardMode.EnderDragon.BattleAnnouncements", true);
outConfig.set("ExtraHardMode.EnderDragon.BattleAnnouncements", this.config_enderDragonCombatAnnouncements);
this.config_enderDragonNoBuilding = config.getBoolean("ExtraHardMode.EnderDragon.NoBuildingAllowed", true);
outConfig.set("ExtraHardMode.EnderDragon.NoBuildingAllowed", this.config_enderDragonNoBuilding);
this.config_weakFoodCrops = config.getBoolean("ExtraHardMode.Farming.WeakCrops", true);
outConfig.set("ExtraHardMode.Farming.WeakCrops", this.config_weakFoodCrops);
this.config_noBonemealOnMushrooms = config.getBoolean("ExtraHardMode.Farming.NoBonemealOnMushrooms", true);
outConfig.set("ExtraHardMode.Farming.NoBonemealOnMushrooms", this.config_noBonemealOnMushrooms);
this.config_noFarmingNetherWart = config.getBoolean("ExtraHardMode.Farming.NoFarmingNetherWart", true);
outConfig.set("ExtraHardMode.Farming.NoFarmingNetherWart", this.config_noFarmingNetherWart);
this.config_sheepRegrowWhiteWool = config.getBoolean("ExtraHardMode.Farming.SheepGrowOnlyWhiteWool", true);
outConfig.set("ExtraHardMode.Farming.SheepGrowOnlyWhiteWool", this.config_sheepRegrowWhiteWool);
this.config_dontMoveWaterSourceBlocks = config.getBoolean("ExtraHardMode.Farming.BucketsDontMoveWaterSources", true);
outConfig.set("ExtraHardMode.Farming.BucketsDontMoveWaterSources", this.config_dontMoveWaterSourceBlocks);
this.config_noSwimmingInArmor = config.getBoolean("ExtraHardMode.NoSwimmingWhenHeavy", true);
outConfig.set("ExtraHardMode.NoSwimmingWhenHeavy", this.config_noSwimmingInArmor);
this.config_playerDeathItemStacksForfeitPercent = config.getInt("ExtraHardMode.PlayerDeath.ItemStacksForfeitPercent", 10);
outConfig.set("ExtraHardMode.PlayerDeath.ItemStacksForfeitPercent", this.config_playerDeathItemStacksForfeitPercent);
this.config_playerRespawnHealth = config.getInt("ExtraHardMode.PlayerDeath.RespawnHealth", 15);
outConfig.set("ExtraHardMode.PlayerDeath.RespawnHealth", this.config_playerRespawnHealth);
this.config_playerRespawnFoodLevel = config.getInt("ExtraHardMode.PlayerDeath.RespawnFoodLevel", 15);
outConfig.set("ExtraHardMode.PlayerDeath.RespawnFoodLevel", this.config_playerRespawnFoodLevel);
this.config_betterTreeChopping = config.getBoolean("ExtraHardMode.BetterTreeFelling", true);
outConfig.set("ExtraHardMode.BetterTreeFelling", this.config_betterTreeChopping);
this.config_workAroundExplosionsBugs = config.getBoolean("ExtraHardMode.WorkAroundOtherPluginsExplosionBugs", false);
outConfig.set("ExtraHardMode.WorkAroundOtherPluginsExplosionBugs", this.config_workAroundExplosionsBugs);
//default additional falling blocks
this.config_moreFallingBlocks = new ArrayList<Material>();
this.config_moreFallingBlocks.add(Material.DIRT);
this.config_moreFallingBlocks.add(Material.GRASS);
this.config_moreFallingBlocks.add(Material.COBBLESTONE);
this.config_moreFallingBlocks.add(Material.MOSSY_COBBLESTONE);
this.config_moreFallingBlocks.add(Material.MYCEL);
this.config_moreFallingBlocks.add(Material.JACK_O_LANTERN);
//build a default config entry for those blocks
ArrayList<String> defaultMoreFallingBlocksList = new ArrayList<String>();
for(int i = 0; i < this.config_moreFallingBlocks.size(); i++)
{
defaultMoreFallingBlocksList.add(this.config_moreFallingBlocks.get(i).name());
}
//try to load the list from the config file
List<String> moreFallingBlocksList = config.getStringList("ExtraHardMode.AdditionalFallingBlocks");
//if it fails, use the above default list instead
if(moreFallingBlocksList == null || moreFallingBlocksList.size() == 0)
{
ExtraHardMode.AddLogEntry("Warning: The additional falling blocks list may not be empty. If you don't want any additional falling blocks, list only a material which is never a block, like DIAMOND_SWORD.");
moreFallingBlocksList = defaultMoreFallingBlocksList;
}
//parse this final list of additional falling blocks
this.config_moreFallingBlocks = new ArrayList<Material>();
for(int i = 0; i < moreFallingBlocksList.size(); i++)
{
String blockName = moreFallingBlocksList.get(i);
Material material = Material.getMaterial(blockName);
if(material == null)
{
ExtraHardMode.AddLogEntry("Additional Falling Blocks Configuration: Material not found: " + blockName + ".");
}
else
{
this.config_moreFallingBlocks.add(material);
}
}
//write it back to the config
outConfig.set("ExtraHardMode.AdditionalFallingBlocks", moreFallingBlocksList);
//save config values to file system
try
{
outConfig.save(DataStore.configFilePath);
}
catch(IOException exception)
{
AddLogEntry("Unable to write to the configuration file at \"" + DataStore.configFilePath + "\"");
}
//register for events
PluginManager pluginManager = this.getServer().getPluginManager();
//player events
PlayerEventHandler playerEventHandler = new PlayerEventHandler();
pluginManager.registerEvents(playerEventHandler, this);
//block events
BlockEventHandler blockEventHandler = new BlockEventHandler();
pluginManager.registerEvents(blockEventHandler, this);
//entity events
EntityEventHandler entityEventHandler = new EntityEventHandler();
pluginManager.registerEvents(entityEventHandler, this);
//FEATURE: monsters spawn in the light under a configurable Y level
MoreMonstersTask task = new MoreMonstersTask();
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, task, 1200L, 1200L); //every 60 seconds
}
//handles slash commands
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
{
return true;
}
public void onDisable()
{
AddLogEntry("ExtraHardMode disabled.");
}
//sends a color-coded message to a player
static void sendMessage(Player player, ChatColor color, Messages messageID, String... args)
{
String message = ExtraHardMode.instance.dataStore.getMessage(messageID, args);
sendMessage(player, color, message);
}
//sends a color-coded message to a player
static void sendMessage(Player player, ChatColor color, String message)
{
if(player == null)
{
ExtraHardMode.AddLogEntry(color + message);
}
else
{
//FEATURE: don't spam messages
PlayerData playerData = ExtraHardMode.instance.dataStore.getPlayerData(player.getName());
long now = Calendar.getInstance().getTimeInMillis();
if(!message.equals(playerData.lastMessageSent) || now - playerData.lastMessageTimestamp > 30000)
{
player.sendMessage(color + message);
playerData.lastMessageSent = message;
playerData.lastMessageTimestamp = now;
}
}
}
static void physicsCheck(Block block, int recursionCount, boolean skipCenterBlock)
{
ExtraHardMode.instance.getServer().getScheduler().scheduleSyncDelayedTask(
ExtraHardMode.instance,
new BlockPhysicsCheckTask(block, recursionCount),
5L);
}
//makes a block subject to gravity
static void applyPhysics(Block block)
{
//grass and mycel become dirt when they fall
if(block.getType() == Material.GRASS || block.getType() == Material.MYCEL)
{
block.setType(Material.DIRT);
}
//create falling block
FallingBlock fallingBlock = block.getWorld().spawnFallingBlock(block.getLocation(), block.getTypeId(), block.getData());
fallingBlock.setDropItem(false);
//remove original block
block.setType(Material.AIR);
}
//computes random chance
static boolean random(int percentChance)
{
return randomNumberGenerator.nextInt(101) < percentChance;
}
boolean plantDies(Block block, byte newDataValue)
{
World world = block.getWorld();
if(!ExtraHardMode.instance.config_enabled_worlds.contains(world) || !ExtraHardMode.instance.config_weakFoodCrops) return false;
//not evaluated until the plant is nearly full grown
if(newDataValue <= (byte)6) return false;
Material material = block.getType();
if(material == Material.CROPS || material == Material.MELON_STEM || material == Material.CARROT || material == Material.PUMPKIN_STEM || material == Material.POTATO)
{
int deathProbability = 25;
//plants in the dark always die
if(block.getLightFromSky() < 10)
{
deathProbability = 100 ;
}
else
{
Biome biome = block.getBiome();
//the desert environment is very rough on crops
if(biome == Biome.DESERT || biome == Biome.DESERT_HILLS)
{
deathProbability += 50;
}
//unwatered crops are more likely to die
Block belowBlock = block.getRelative(BlockFace.DOWN);
byte moistureLevel = 0;
if(belowBlock.getType() == Material.SOIL)
{
moistureLevel = belowBlock.getData();
}
if(moistureLevel == 0)
{
deathProbability += 25;
}
}
if(ExtraHardMode.random(deathProbability))
{
return true;
}
}
return false;
}
}