diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..9887763d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,25 @@ +# Editorconfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +indent_style = tab +indent_size = 4 +end_of_line = lf +insert_final_newline = true +continuation_indent_size = 8 + +[*.java] +indent_style = tab +indent_size = 4 + +[*.xml] +indent_style = tab +indent_size = 2 + +[*.yml] +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore index 4190d768..98c7bbdd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,283 @@ -.gitignore -/target \ No newline at end of file + +# Created by https://www.gitignore.io/api/java,batch,linux,macos,maven,windows,eclipse,intellij+all +# Edit at https://www.gitignore.io/?templates=java,batch,linux,macos,maven,windows,eclipse,intellij+all + +### Batch ### +# BatchFiles +*.bat +*.cmd +*.btm + +### Eclipse ### + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +### Eclipse Patch ### +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Annotation Processing +.apt_generated + +.sts4-cache/ + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +<<<<<<< HEAD +# End of https://www.gitignore.io/api/java,batch,linux,macos,maven,windows,intellij+all + + +#Eclipse stuff +/target/ +.classpath +.settings/** +.project +/logs/ +dependency-reduced-pom.xml +/target/ + +/bin/ +======= +# End of https://www.gitignore.io/api/java,batch,linux,macos,maven,windows,eclipse,intellij+all +>>>>>>> civclassic/master diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index f2640e61..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -sign the Contributor License Agreement diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..e8fe96e7 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,46 @@ +@Library('civ_pipeline_lib')_ + +pipeline { + agent any + tools { + maven 'Maven 3.6.3' + jdk 'Java 8' + } + environment { + civ_dependent_plugins = "FactoryMod JukeAlert RailSwitch SimpleAdminHacks Bastion" + } + stages { + stage ('Build') { + steps { + civ_build_plugin() + } + } + stage ('Archive binaries') { + steps { + civ_archive_artifacts() + } + } + stage ('Archive javadoc') { + steps { + civ_archive_javadoc() + } + } + stage ('Aggregate reports') { + steps { + civ_aggregate_reports() + } + } + } + + post { + always { + civ_post_always() + } + success { + civ_post_success() + } + failure { + civ_post_failure() + } + } +} diff --git a/README.md b/README.md index 79a50aa0..cc0333e7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Citadel -Jenkins Build Server can be found: http://build.civcraft.co/job/Citadel-master/ +Citadel Jenkins Build Server can be found here: https://build.devotedmc.com/job/Citadel-master/ -Java Docs: http://build.civcraft.co/job/Citadel-master/javadoc/ +Basic new player tutorial: https://www.reddit.com/r/Devoted/wiki/plugins/citadel + +If you need help installing Citadel, follow this guide: https://github.com/ProgrammerDan/civcraft-vm + +https://www.devotedmc.com/citadel.html diff --git a/config.yml b/config.yml deleted file mode 100644 index 50023e5c..00000000 --- a/config.yml +++ /dev/null @@ -1,105 +0,0 @@ -# material is the bukkit name for the material. -# requirements is the amount of the material needed to create a reinforcement. -# return is the amount of material to return. -# percent_chance is the chance to return the block. Scales with damage. -# scale_amount is, if maturation is enabled, the amount extra to damage a block if it is not fully matured. The forumla for calculating the extra damage is 1/(1-((time left of maturation) / (default amount of time for maturation))) * scale. So if a block has 5 minutes left of maturation on a 10 minute default period with a scale of 3 we do 1/(5 / 10) * 3 = 6 damage. Setting scale amount to 0 disables this function. -internal_logging: true -command_logging: true -break_logging: true -reinf_logging: false -reinforcements: - diamond: - material: DIAMOND - requirements: 1 - return: 1 - percent_chance: 100 - hit_points: 1800 -# mature time is in minutes - mature_time: 1440 - acid_time: 1440 - scale_amount: 1 - lore: -# Delete the comment char to use lore. Three spaces are required -# after lore. You can add multiple lines by adding - -# - Some string representation required for this reinforcement. - iron: - material: IRON_INGOT - requirements: 1 - return: 1 - percent_chance: 100 - hit_points: 250 - mature_time: 60 - acid_time: 60 - scale_amount: 1 - lore: - stone: - material: STONE - requirements: 1 - return: 1 - percent_chance: 100 - hit_points: 25 - mature_time: 10 - acid_time: 10 - scale_amount: 1 - lore: - bedrock: - material: BEDROCK - requirements: 1 - return: 0 - percent_chance: 100 - hit_points: 147483646 - mature_time: 147483646 - acid_time: 147483646 - scale_amount: 1 - lore: -#natural_reinforcements: - #diamond_ore: - #material: DIAMOND_ORE - #hit_points: 60 -non_reinforceables: - - BEDROCK - - ENDER_PORTAL_FRAME - - SAPLING - - LONG_GRASS - - DEAD_BUSH - - PISTON_EXTENSION - - PISTON_MOVING_PIECE - - RED_ROSE - - YELLOW_FLOWER - - BROWN_MUSHROOM - - RED_MUSHROOM - - TNT - - CROPS - - FIRE - - SNOW - - ICE - - CACTUS - - SUGAR_CANE_BLOCK - - PORTAL - - CAKE_BLOCK - - PUMPKIN_STEM - - MELON_STEM - - VINE - - NETHER_WARTS - - ENDER_PORTAL -reset_player_state: 300 -enable_maturation: true -# The max amount of reinforcements to keep loaded -max_cache_size: 20000 -# The amount of minutes to keep a reinforcement loaded -max_cache_load_time: 10 -redstone_distance: 7 -acidblock_material: GOLD_BLOCK -# If set to true then instead of dropping the reinforcement a block with the specified reinforcement value will be dropped. -drop_reinforced_block: false -save_interval_ticks: 500 -# reinforcement_damageMultiplier is m where BlockDamage = 2 ^ (n/m) where n is equal to the number of days the group has been inactive -reinforcement_damageMultiplier: 7 -mysql: - hostname: "localhost" - port: 3306 - dbname: "bukkit" - username: "bukkit" - password: "" -# Shows reinforcement information as percentile value -show_health_as_percent: false diff --git a/plugin.yml b/plugin.yml deleted file mode 100644 index 243fb595..00000000 --- a/plugin.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: ${project.name} -main: vg.civcraft.mc.citadel.Citadel -version: ${project.version} -author: Rourke750 -depend: [NameLayer, CivModCore] -softdepend: [Mercury, BetterShards] -description: Citadel allows you to make blocks difficult to break. When a block is reinforced, it must be broken many times before it is destroyed. -commands: - ctr: - aliases: [ctreinforce] - ctacid: - ctf: - aliases: [ctfortify] - ctb: - aliases: [ctbypass] - cti: - aliases: [ctinformation] - ctin: - aliases: [ctinsecure] - ctm: - aliases: [ctmaterials] - cto: - aliases: [ctoff] - cts: - aliases: [ctstats] - permission: citadel.admin - ctur: - permission: citadel.admin - ctar: - permission: citadel.admin - aliases: [ctareareinforce] - ctsl: - permission: citadel.admin - aliases: [ctsetlogging] -permissions: - citadel.admin: - default: op - citadel.admin.accesssecurable: - default: op diff --git a/pom.xml b/pom.xml index f03d91f1..94cb9605 100644 --- a/pom.xml +++ b/pom.xml @@ -1,83 +1,64 @@ - 4.0.0 + + + com.github.civclassic + civclassic-parent + 1.0.0 + + vg.civcraft.mc.citadel Citadel jar - 3.5.0 + 4.1.1D Citadel - https://github.com/Civcraft/Citadel - - - - - - maven-compiler-plugin - 2.3.2 - - 1.8 - 1.8 - - - - - - ${basedir}/src + https://github.com/civclassic/Citadel - - - ${basedir} - - LICENSE.txt - *.yml - - true - - - - org.spigotmc - spigot-api - 1.9.2-R0.1-SNAPSHOT + com.destroystokyo.paper + paper-api + 1.16.4-R0.1-SNAPSHOT + provided vg.civcraft.mc.civmodcore CivModCore - 1.3.2 + 1.8.2D provided - vg.civcraft.mc.namelayer - NameLayer - 2.7 - provided - + vg.civcraft.mc.namelayer + namelayer-mc + 3.0.0 + provided + - vg.civcraft.mc.bettershards - BetterShards - 1.4 + vg.civcraft.mc.namelayer + namelayer-core + 3.0.0 provided - vg.civcraft.mc.mercury - Mercury - 1.2.0 + com.gmail.filoghost.holographicdisplays + holographicdisplays-api + 2.4.5 provided - civcraft-repo - http://build.civcraft.co:8080/plugin/repository/everything/ + codemc-repo + https://repo.codemc.io/repository/maven-public/ - spigot-repo - https://hub.spigotmc.org/nexus/content/groups/public/ + civ-github-repo + https://raw.githubusercontent.com/CivClassic/artifacts/master/ - diff --git a/src/main/java/vg/civcraft/mc/citadel/Citadel.java b/src/main/java/vg/civcraft/mc/citadel/Citadel.java new file mode 100644 index 00000000..88ab457a --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/Citadel.java @@ -0,0 +1,156 @@ +package vg.civcraft.mc.citadel; + +import java.util.logging.Logger; + +import org.bukkit.Bukkit; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.listener.BlockListener; +import vg.civcraft.mc.citadel.listener.EntityListener; +import vg.civcraft.mc.citadel.listener.InventoryListener; +import vg.civcraft.mc.citadel.listener.ModeListener; +import vg.civcraft.mc.citadel.listener.RedstoneListener; +import vg.civcraft.mc.citadel.model.AcidManager; +import vg.civcraft.mc.citadel.model.CitadelChunkData; +import vg.civcraft.mc.citadel.model.CitadelDAO; +import vg.civcraft.mc.citadel.model.CitadelSettingManager; +import vg.civcraft.mc.citadel.model.HologramManager; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementTypeManager; +import vg.civcraft.mc.civmodcore.ACivMod; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.api.BlockBasedChunkMetaView; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.api.ChunkMetaAPI; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableBasedDataObject; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableStorageEngine; +import vg.civcraft.mc.namelayer.mc.NameLayerPlugin; + +public class Citadel extends ACivMod { + + private static Citadel instance; + + public static Citadel getInstance() { + return instance; + } + + private Logger logger; + private ReinforcementManager reinManager; + private CitadelConfigManager config; + private AcidManager acidManager; + private ReinforcementTypeManager typeManager; + private HologramManager holoManager; + private CitadelSettingManager settingManager; + private CitadelDAO dao; + private CitadelPermissionHandler permHandler; + + private PlayerStateManager stateManager; + + /** + * @return Acid block manager + */ + public AcidManager getAcidManager() { + return acidManager; + } + + public CitadelConfigManager getConfigManager() { + return config; + } + + public ReinforcementManager getReinforcementManager() { + return reinManager; + } + + public ReinforcementTypeManager getReinforcementTypeManager() { + return typeManager; + } + + public CitadelSettingManager getSettingManager() { + return settingManager; + } + + public PlayerStateManager getStateManager() { + return stateManager; + } + + public HologramManager getHologramManager() { + return holoManager; + } + + public CitadelPermissionHandler getPermissionHandler() { + return permHandler; + } + + CitadelDAO getDAO() { + return dao; + } + + @Override + public void onDisable() { + reinManager.shutDown(); + HandlerList.unregisterAll(this); + Bukkit.getScheduler().cancelTasks(this); + } + + public void reload() { + onDisable(); + onEnable(); + } + + @Override + public void onEnable() { + super.onEnable(); + instance = this; + logger = getLogger(); + if (!Bukkit.getPluginManager().isPluginEnabled("NameLayer")) { + logger.info("Citadel is shutting down because it could not find NameLayer"); + Bukkit.shutdown(); + return; + } + config = new CitadelConfigManager(this); + if (!config.parse()) { + logger.severe("Errors in config file, shutting down"); + Bukkit.shutdown(); + return; + } + typeManager = new ReinforcementTypeManager(); + config.getReinforcementTypes().forEach(t -> typeManager.register(t)); + dao = new CitadelDAO(this.logger, config.getDatabase()); + if (!dao.updateDatabase()) { + logger.severe("Errors setting up database, shutting down"); + Bukkit.shutdown(); + return; + } + BlockBasedChunkMetaView> chunkMetaData = + ChunkMetaAPI.registerBlockBasedPlugin(this, () -> new CitadelChunkData(false, dao),dao, true); + if (chunkMetaData == null) { + logger.severe("Errors setting up chunk metadata API, shutting down"); + Bukkit.shutdown(); + return; + } + reinManager = new ReinforcementManager(chunkMetaData); + stateManager = new PlayerStateManager(); + acidManager = new AcidManager(config.getAcidMaterials()); + settingManager = new CitadelSettingManager(); + Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> { + if (Bukkit.getPluginManager().isPluginEnabled("HolographicDisplays")) { + holoManager = new HologramManager(settingManager); + logger.info("HolographicDisplays is loaded, holograms available"); + } + else { + logger.info("HolographicDisplays is not loaded, no holograms available"); + }}); + permHandler = new CitadelPermissionHandler(NameLayerPlugin.getInstance().getGroupTracker().getPermissionTracker()); + registerListeners(); + } + + /** + * Registers the listeners for Citadel. + */ + private void registerListeners() { + getServer().getPluginManager().registerEvents(new BlockListener(this), this); + getServer().getPluginManager().registerEvents(new EntityListener(), this); + getServer().getPluginManager().registerEvents(new InventoryListener(), this); + getServer().getPluginManager().registerEvents(new ModeListener(this), this); + getServer().getPluginManager().registerEvents(new RedstoneListener(config.getMaxRedstoneDistance()), this); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/CitadelConfigManager.java b/src/main/java/vg/civcraft/mc/citadel/CitadelConfigManager.java new file mode 100644 index 00000000..5e29efb8 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/CitadelConfigManager.java @@ -0,0 +1,206 @@ +package vg.civcraft.mc.citadel; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementEffect; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.ACivMod; +import vg.civcraft.mc.civmodcore.CoreConfigManager; +import vg.civcraft.mc.civmodcore.dao.ManagedDatasource; +import vg.civcraft.mc.civmodcore.util.ConfigParsing; +import vg.civcraft.mc.civmodcore.util.TextUtil; + +public class CitadelConfigManager extends CoreConfigManager { + + private ManagedDatasource database; + private List reinforcementTypes; + private List acidMaterials; + + private List globalBlackList; + + private boolean logHostileBreaks; + private boolean logFriendlyBreaks; + private boolean logDamage; + private boolean logCreation; + private boolean logMessages; + + private long globalDecayTimer; + private double globalDecayMultiplier; + + private double redstoneRange; + + private boolean hangersInheritReinforcements; + + public CitadelConfigManager(ACivMod plugin) { + super(plugin); + } + + public List getAcidMaterials() { + return acidMaterials; + } + + public List getBlacklistedMaterials() { + return globalBlackList; + } + + public ManagedDatasource getDatabase() { + return database; + } + + public double getMaxRedstoneDistance() { + return redstoneRange; + } + + public boolean doHangersInheritReinforcements() { + return hangersInheritReinforcements; + } + + private ReinforcementEffect getReinforcementEffect(ConfigurationSection config) { + if (config == null) { + return null; + } + Particle effect; + try { + String effectName = config.getString("type"); + effect = Particle.valueOf(effectName); + } catch (IllegalArgumentException e) { + logger.warning("Invalid effect at: " + config.getCurrentPath()); + return null; + } + float offSet = (float) config.getDouble("offset", 0); + float offsetX = (float) config.getDouble("offsetX", offSet); + float offsetY = (float) config.getDouble("offsetY", offSet); + float offsetZ = (float) config.getDouble("offsetZ", offSet); + float speed = (float) config.getDouble("speed", 1); + int amount = config.getInt("particleCount", 50); + return new ReinforcementEffect(effect, offsetX, offsetY, offsetZ, speed, amount); + } + + public List getReinforcementTypes() { + return reinforcementTypes; + } + + public boolean logCreation() { + return logCreation; + } + + public boolean logDamage() { + return logDamage; + } + + public boolean logFriendlyBreaks() { + return logFriendlyBreaks; + } + + public boolean logHostileBreaks() { + return logHostileBreaks; + } + + public boolean logMessages() { + return logMessages; + } + + private void parseAcidMaterials(ConfigurationSection config) { + acidMaterials = parseMaterialList(config, "acidblock_material"); + if (acidMaterials == null) { + logger.info("No valid acid materials found in config"); + acidMaterials = new LinkedList<>(); + } + for (Material mat : acidMaterials) { + logger.info("Adding " + mat.toString() + " as valid acid material"); + } + } + + @Override + protected boolean parseInternal(ConfigurationSection config) { + database = (ManagedDatasource) config.get("database"); + globalBlackList = parseMaterialList(config, "non_reinforceables"); + parseAcidMaterials(config); + logHostileBreaks = config.getBoolean("logHostileBreaks", true); + logFriendlyBreaks = config.getBoolean("logFriendlyBreaks", true); + logDamage = config.getBoolean("logDamage", false); + logCreation = config.getBoolean("logCreation", true); + logMessages = config.getBoolean("logMessages", true); + redstoneRange = config.getDouble("redstoneDistance", 3); + globalDecayMultiplier = config.getDouble("global_decay_multiplier", 2.0); + globalDecayTimer = ConfigParsing.parseTime(config.getString("global_decay_timer", "0")); + parseReinforcementTypes(config.getConfigurationSection("reinforcements")); + hangersInheritReinforcements = config.getBoolean("hangers_inherit_reinforcement", false); + return true; + } + + private ReinforcementType parseReinforcementType(ConfigurationSection config) { + if (!config.isItemStack("item")) { + logger.warning( + "Reinforcement config at " + config.getCurrentPath() + " had no valid item entry, it was ignored"); + return null; + } + ItemStack item = config.getItemStack("item"); + ReinforcementEffect creationEffect = getReinforcementEffect(config.getConfigurationSection("creation_effect")); + ReinforcementEffect damageEffect = getReinforcementEffect(config.getConfigurationSection("damage_effect")); + ReinforcementEffect destructionEffect = getReinforcementEffect( + config.getConfigurationSection("destruction_effect")); + long gracePeriod = ConfigParsing.parseTime(config.getString("grace_period", "0"), TimeUnit.MILLISECONDS); + long maturationTime = ConfigParsing.parseTime(config.getString("mature_time", "0"), TimeUnit.MILLISECONDS); + long acidTime = ConfigParsing.parseTime(config.getString("acid_time", "-1"), TimeUnit.MILLISECONDS); + int acidPriority = config.getInt("acid_priority", 0); + String name = config.getString("name"); + double maturationScale = config.getInt("scale_amount", 1); + float health = (float) config.getDouble("hit_points", 100); + double returnChance = config.getDouble("return_chance", 1.0); + List reinforceables = parseMaterialList(config, "reinforceables"); + List nonReinforceables = parseMaterialList(config, "non_reinforceables"); + short id = (short) config.getInt("id", -1); + long decayTimer = ConfigParsing + .parseTime(config.getString("decay_timer", String.valueOf(globalDecayTimer / 1000L) + "s")); + double decayMultiplier = config.getDouble("decay_multiplier", globalDecayMultiplier); + double multiplerOnDeletedGroup = config.getDouble("deleted_group_multipler", 4); + int legacyId = config.getInt("legacy_id", -1); + if (name == null) { + logger.warning("No name specified for reinforcement type at " + config.getCurrentPath()); + name = item.getType().name(); + } + if (id == -1) { + logger.warning("Reinforcement type at " + config.getCurrentPath() + " had no id, it was ignored"); + return null; + } + if (reinforceables != null && nonReinforceables != null) { + logger.warning("Both blacklist and whitelist specified for reinforcement type at " + config.getCurrentPath() + + ". This does not make sense and the type will be ignored"); + return null; + } + logger.info("Parsed reinforcement type " + name + " for item " + item.toString() + ", returnChance: " + + returnChance + ", maturationTime: " + TextUtil.formatDuration(maturationTime, TimeUnit.MILLISECONDS) + + ", acidTime: " + TextUtil.formatDuration(acidTime, TimeUnit.MILLISECONDS) + ", gracePeriod: " + + gracePeriod + ", id: " + id); + return new ReinforcementType(health, returnChance, item, maturationTime, acidTime, acidPriority, maturationScale, gracePeriod, + creationEffect, damageEffect, destructionEffect, reinforceables, nonReinforceables, id, name, + globalBlackList, decayTimer, decayMultiplier, multiplerOnDeletedGroup, legacyId); + } + + private void parseReinforcementTypes(ConfigurationSection config) { + reinforcementTypes = new LinkedList<>(); + if (config == null) { + logger.info("No reinforcement types found in config"); + return; + } + for (String key : config.getKeys(false)) { + if (!config.isConfigurationSection(key)) { + logger.warning("Ignoring invalid entry " + key + " at " + config.getCurrentPath()); + continue; + } + ReinforcementType type = parseReinforcementType(config.getConfigurationSection(key)); + if (type != null) { + reinforcementTypes.add(type); + } + } + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/CitadelPermissionHandler.java b/src/main/java/vg/civcraft/mc/citadel/CitadelPermissionHandler.java new file mode 100644 index 00000000..870aeacd --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/CitadelPermissionHandler.java @@ -0,0 +1,105 @@ +package vg.civcraft.mc.citadel; + +import vg.civcraft.mc.namelayer.core.DefaultPermissionLevel; +import vg.civcraft.mc.namelayer.core.PermissionTracker; +import vg.civcraft.mc.namelayer.core.PermissionType; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +public class CitadelPermissionHandler { + + private final static String CHEST_PERM = "CONTAINER_ACCESS"; + private final static String BYPASS_PERM = "BYPASS_REINFORCEMENT"; + private final static String CROPS_PERM = "HARVEST_CROPS"; + private final static String INSECURE_PERM = "INSECURE_REINFORCEMENT"; + private final static String REINFORCE_PERM = "REINFORCE"; + private final static String DOOR_PERM = "USE_DOORS"; + private final static String ACID_PERM = "USE_ACID_BLOCKS"; + private final static String INFO_PERM = "USE_INFORMATION_MODE"; + private final static String REPAIR_PERM = "ALLOW_REPAIR_REINFORCEMENT"; + private final static String MODIFY_PERM = "ALLOW_MODIFYING_BLOCKS"; + private final static String BEACON_PERM = "USE_BEACONS"; + private final static String HANGING_PLACE_BREAK_PERM = "ALLOWS_CHANGING_HANGING_BLOCKS"; + private final static String ITEM_FRAME_HANDLE_PERM = "ALLOWS_HANDLING_ITEM_FRAMES"; + private final static String ITEM_FRAME_ROTATE_PERM = "ALLOWS_ROTATING_ITEM_FRAMES"; + + private PermissionTracker permTracker; + + public CitadelPermissionHandler(PermissionTracker permTracker) { + this.permTracker = permTracker; + setup(); + } + + private static void setup() { + GroupAPI.registerPermission(REINFORCE_PERM, DefaultPermissionLevel.MOD, "Allows reinforcing blocks on this group"); + GroupAPI.registerPermission(ACID_PERM, DefaultPermissionLevel.MOD, "Allows activating acid blocks reinforced on this group"); + GroupAPI.registerPermission(INFO_PERM, DefaultPermissionLevel.MEMBER, "Allows viewing information on reinforcements reinforced on this group"); + GroupAPI.registerPermission(BYPASS_PERM, DefaultPermissionLevel.MOD, "Allows bypassing reinforcements reinforced on this group"); + GroupAPI.registerPermission(REPAIR_PERM, DefaultPermissionLevel.MOD, "Allows repairing reinforcements reinforced on this group"); + GroupAPI.registerPermission(DOOR_PERM, DefaultPermissionLevel.MEMBER, "Allows opening doors reinforced on this group"); + GroupAPI.registerPermission(CHEST_PERM, DefaultPermissionLevel.MEMBER, "Allows opening containers like chests reinforced on this group"); + GroupAPI.registerPermission(CROPS_PERM, DefaultPermissionLevel.MEMBER, "Allows harvesting crops growing on soil reinforced on this group"); + GroupAPI.registerPermission(INSECURE_PERM, DefaultPermissionLevel.MEMBER, "Allows toggling the insecure flag on reinforcements"); + GroupAPI.registerPermission(MODIFY_PERM, DefaultPermissionLevel.MOD, "Allows modifying reinforced blocks like flipping levers, stripping logs etc"); + GroupAPI.registerPermission(BEACON_PERM, DefaultPermissionLevel.MEMBER, "Allow changing beacon effects"); + GroupAPI.registerPermission(HANGING_PLACE_BREAK_PERM, DefaultPermissionLevel.MOD, "Allows placing/breaking hanging entities on reinforced blocks"); + GroupAPI.registerPermission(ITEM_FRAME_HANDLE_PERM, DefaultPermissionLevel.MOD, "Allows the placing/removal of items into/from Item Frames"); + GroupAPI.registerPermission(ITEM_FRAME_ROTATE_PERM, DefaultPermissionLevel.MEMBER, "Allows the rotation of items placed within Item Frames"); + } + + public PermissionType getModifyBlocks() { + return permTracker.getPermission(MODIFY_PERM); + } + + public PermissionType getChests() { + return permTracker.getPermission(CHEST_PERM); + } + + public PermissionType getDoors() { + return permTracker.getPermission(DOOR_PERM); + } + + public PermissionType getBypass() { + return permTracker.getPermission(BYPASS_PERM); + } + + public PermissionType getReinforce() { + return permTracker.getPermission(REINFORCE_PERM); + } + + public PermissionType getAcidblock() { + return permTracker.getPermission(ACID_PERM); + } + + public PermissionType getCrops() { + return permTracker.getPermission(CROPS_PERM); + } + + public PermissionType getInsecure() { + return permTracker.getPermission(INSECURE_PERM); + } + + public PermissionType getInfo() { + return permTracker.getPermission(INFO_PERM); + } + + public PermissionType getRepair() { + return permTracker.getPermission(REPAIR_PERM); + } + + public PermissionType getBeacon() { + return permTracker.getPermission(BEACON_PERM); + } + + public PermissionType getHangingPlaceBreak() { + return permTracker.getPermission(HANGING_PLACE_BREAK_PERM); + } + + public PermissionType getItemFramePutTake() { + return permTracker.getPermission(ITEM_FRAME_HANDLE_PERM); + } + + public PermissionType getItemFrameRotate() { + return permTracker.getPermission(ITEM_FRAME_ROTATE_PERM); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java b/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java new file mode 100644 index 00000000..8dfb62d2 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/CitadelUtility.java @@ -0,0 +1,153 @@ +package vg.civcraft.mc.citadel; + +import java.util.logging.Level; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.itemHandling.ItemMap; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +/** + * Just a useful class with general and misplaced methods that can be called + * from anywhere. + * + */ +public class CitadelUtility { + + private CitadelUtility() { + } + + public static boolean isPlant(Block plant) { + switch (plant.getType()) { + case DANDELION: + case POPPY: + case BLUE_ORCHID: + case ALLIUM: + case AZURE_BLUET: + case ORANGE_TULIP: + case RED_TULIP: + case PINK_TULIP: + case WHITE_TULIP: + case OXEYE_DAISY: + case ACACIA_SAPLING: + case BIRCH_SAPLING: + case DARK_OAK_SAPLING: + case JUNGLE_SAPLING: + case OAK_SAPLING: + case SPRUCE_SAPLING: + case WHEAT: + case CARROTS: + case POTATOES: + case BEETROOTS: + case MELON_STEM: + case PUMPKIN_STEM: + case ATTACHED_MELON_STEM: + case ATTACHED_PUMPKIN_STEM: + case NETHER_WART: + case SUGAR_CANE: + case CACTUS: + case SUNFLOWER: + case LILAC: + case PEONY: + case TWISTING_VINES: + case TWISTING_VINES_PLANT: + case WEEPING_VINES: + case WEEPING_VINES_PLANT: + case KELP: + case KELP_PLANT: + return true; + default: + return false; + } + } + + public static void sendAndLog(CommandSender receiver, ChatColor color, String message) { + receiver.sendMessage(color + message); + if (Citadel.getInstance().getConfigManager().logMessages()) { + Citadel.getInstance().getLogger().log(Level.INFO, "Sent {0} reply {1}", + new Object[] { receiver.getName(), message }); + } + } + + public static void debugLog(String msg) { + if (Citadel.getInstance().getConfigManager().isDebugEnabled()) { + Citadel.getInstance().getLogger().info(msg); + } + } + + public static boolean consumeReinforcementItems(Player player, ReinforcementType type, boolean consumeExtra) { + ItemMap toRemove = new ItemMap(type.getItem()); + if (consumeExtra) { + toRemove.addItemAmount(type.getItem(), 1); + } + if (!toRemove.removeSafelyFrom(player.getInventory())) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "Failed to remove items needed for " + type.getName() + " reinforcement from your inventory"); + Citadel.getInstance().getStateManager().setState(player, null); + return false; + } + return true; + } + + public static boolean attemptReinforcementCreation(Block block, ReinforcementType type, Group group, + Player player) { + // check if player still has permission + if (!GroupAPI.hasPermission(player.getUniqueId(), group, + Citadel.getInstance().getPermissionHandler().getReinforce())) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You seem to have lost permission to reinforce on " + group.getName()); + Citadel.getInstance().getStateManager().setState(player, null); + return true; + } + block = ReinforcementLogic.getResponsibleBlock(block); + // check if reinforcement already exists + Reinforcement existingRein = Citadel.getInstance().getReinforcementManager().getReinforcement(block); + if (existingRein != null) { + // something like a slab, we just ignore this + return false; + } + // check if reinforcement can reinforce that block + if (!type.canBeReinforced(block.getType())) { + CitadelUtility.sendAndLog(player, ChatColor.RED, type.getName() + " can not reinforce " + block.getType()); + return true; + } + ItemMap playerItems = new ItemMap(player.getInventory()); + if (player.getInventory().getItemInOffHand() != null) { + playerItems.addItemStack(player.getInventory().getItemInOffHand()); + } + // check inventory + int available = playerItems.getAmount(type.getItem()); + int required = type.getItem().getAmount(); + boolean consumeExtra = block.getType() == type.getItem().getType(); + if (consumeExtra) { + //make sure they're not trying to reinforce with the single block thats also being placed + required++; + } + if (available < required) { + Citadel.getInstance().getStateManager().setState(player, null); + CitadelUtility.sendAndLog(player, ChatColor.RED, "You have no items left to reinforce with " + type.getName()); + return true; + } + Reinforcement newRein = ReinforcementLogic.callReinforcementCreationEvent(player, block, type, group); + if (newRein == null) { + return true; + } + // remove from inventory + if (!CitadelUtility.consumeReinforcementItems(player, type, consumeExtra)) { + return true; + } + // create reinforcement + if (Citadel.getInstance().getConfigManager().logCreation()) { + Citadel.getInstance().getLogger().info(player.getName() + " created reinforcement with " + type.getName() + + " for " + block.getType().toString() + " at " + block.getLocation().toString()); + } + ReinforcementLogic.createReinforcement(newRein); + return false; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/ReinforcementLogic.java b/src/main/java/vg/civcraft/mc/citadel/ReinforcementLogic.java new file mode 100644 index 00000000..b63408f2 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/ReinforcementLogic.java @@ -0,0 +1,343 @@ +package vg.civcraft.mc.citadel; + +import java.util.Objects; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.type.Bed; +import org.bukkit.block.data.type.Chest; +import org.bukkit.block.data.type.CoralWallFan; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; + +import vg.civcraft.mc.citadel.events.ReinforcementCreationEvent; +import vg.civcraft.mc.citadel.events.ReinforcementDestructionEvent; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.api.BlockAPI; +import vg.civcraft.mc.namelayer.core.Group; + +public final class ReinforcementLogic { + + private ReinforcementLogic() { + } + + /** + * Inserts a new reinforcements into the cache, queues it for persistence and + * plays particle effects for creation + * + * @param rein Reinforcement just created + */ + public static void createReinforcement(Reinforcement rein) { + Citadel.getInstance().getReinforcementManager().putReinforcement(rein); + if (rein.getType().getCreationEffect() != null) { + rein.getType().getCreationEffect().playEffect(rein); + } + } + + public static Reinforcement callReinforcementCreationEvent(Player player, Block block, ReinforcementType type, + Group group) { + Reinforcement rein = new Reinforcement(block.getLocation(), type, group); + ReinforcementCreationEvent event = new ReinforcementCreationEvent(player, rein); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return null; + } + return rein; + } + + public static void damageReinforcement(Reinforcement rein, float damage, Entity source) { + float futureHealth = rein.getHealth() - damage; + if (futureHealth <= 0) { + ReinforcementDestructionEvent event = new ReinforcementDestructionEvent(rein, damage, source); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } + futureHealth = Math.min(futureHealth, rein.getType().getHealth()); + rein.setHealth(futureHealth); + if (rein.isBroken()) { + if (rein.getType().getDestructionEffect() != null) { + rein.getType().getDestructionEffect().playEffect(rein); + } + } else { + if (rein.getType().getDamageEffect() != null) { + rein.getType().getDamageEffect().playEffect(rein); + } + } + } + + public static float getDamageApplied(Reinforcement reinforcement) { + float damageAmount = 1.0F; + if (!reinforcement.isMature()) { + double timeExisted = System.currentTimeMillis() - reinforcement.getCreationTime(); + double progress = timeExisted / reinforcement.getType().getMaturationTime(); + damageAmount /= progress; + damageAmount *= reinforcement.getType().getMaturationScale(); + } + damageAmount *= getDecayDamage(reinforcement); + return damageAmount; + } + + public static double getDecayDamage(Reinforcement reinforcement) { + if (reinforcement.getGroup() != null) { + //long lastRefresh = reinforcement.getGroup().getActivityTimeStamp(); //TODO + long lastRefresh = System.currentTimeMillis(); + return reinforcement.getType().getDecayDamageMultipler(lastRefresh); + } else { + return reinforcement.getType().getDeletedGroupMultiplier(); + } + } + + public static Reinforcement getReinforcementAt(Location location) { + return Citadel.getInstance().getReinforcementManager().getReinforcement(location); + } + + public static Reinforcement getReinforcementProtecting(Block block) { + if (!BlockAPI.isValidBlock(block)) { + return null; + } + Reinforcement reinforcement = getReinforcementAt(block.getLocation()); + if (reinforcement != null) { + return reinforcement; + } + switch (block.getType()) { + // Chests are awkward since you can place both sides of a double chest + // independently, which isn't true for + // beds, plants, or doors, so this needs to be accounted for and + // "getResponsibleBlock()" isn't appropriate + // for the following logic: that both sides protect each other; that if either + // block is reinforced, then + // the chest as a whole remains protected. + case CHEST: + case TRAPPED_CHEST: { + Chest chest = (Chest) block.getBlockData(); + BlockFace facing = chest.getFacing(); + switch (chest.getType()) { + case LEFT: { + BlockFace face = BlockAPI.turnClockwise(facing); + return getReinforcementAt(block.getLocation().add(face.getDirection())); + } + case RIGHT: { + BlockFace face = BlockAPI.turnAntiClockwise(facing); + return getReinforcementAt(block.getLocation().add(face.getDirection())); + } + default: { + return null; + } + } + } + default: { + Block responsible = getResponsibleBlock(block); + if (Objects.equals(block, responsible)) { + return null; + } + return getReinforcementAt(responsible.getLocation()); + } + } + } + + /** + * Some blocks, crops in particular, can not be reinforced but instead have + * their reinforcement behavior tied to a source block. This method will get + * that source block, which may be the given block itself. It does not look at + * reinforcement data at all, it merely applies logic based on block type and + * physics checks + * + * @param block Block to get responsible block for + * @return Block which reinforcement would protect the given block + */ + + public static Block getResponsibleBlock(Block block) { + // Do not put [double] chests in here. + switch (block.getType()) { + case DANDELION: + case POPPY: + case BLUE_ORCHID: + case ALLIUM: + case AZURE_BLUET: + case ORANGE_TULIP: + case RED_TULIP: + case PINK_TULIP: + case WHITE_TULIP: + case OXEYE_DAISY: + case ACACIA_SAPLING: + case BIRCH_SAPLING: + case DARK_OAK_SAPLING: + case JUNGLE_SAPLING: + case OAK_SAPLING: + case SPRUCE_SAPLING: + case WARPED_FUNGUS: + case CRIMSON_FUNGUS: + case BAMBOO_SAPLING: + case WHEAT: + case CARROTS: + case POTATOES: + case BEETROOTS: + case SWEET_BERRY_BUSH: + case MELON_STEM: + case PUMPKIN_STEM: + case ATTACHED_MELON_STEM: + case ATTACHED_PUMPKIN_STEM: + case WARPED_ROOTS: + case CRIMSON_ROOTS: + case NETHER_SPROUTS: + case WITHER_ROSE: + case LILY_OF_THE_VALLEY: + case CORNFLOWER: + case SEA_PICKLE: + case FERN: + case KELP: + case GRASS: + case SEAGRASS: + case TUBE_CORAL: + case TUBE_CORAL_FAN: + case BRAIN_CORAL: + case BRAIN_CORAL_FAN: + case BUBBLE_CORAL: + case BUBBLE_CORAL_FAN: + case FIRE_CORAL: + case FIRE_CORAL_FAN: + case HORN_CORAL: + case HORN_CORAL_FAN: + case DEAD_TUBE_CORAL: + case DEAD_TUBE_CORAL_FAN: + case DEAD_BRAIN_CORAL: + case DEAD_BRAIN_CORAL_FAN: + case DEAD_BUBBLE_CORAL: + case DEAD_BUBBLE_CORAL_FAN: + case DEAD_FIRE_CORAL: + case DEAD_FIRE_CORAL_FAN: + case DEAD_HORN_CORAL: + case DEAD_HORN_CORAL_FAN: + case NETHER_WART: { + return block.getRelative(BlockFace.DOWN); + } + case TWISTING_VINES: { + // scan downwards for first different block + Block below = block.getRelative(BlockFace.DOWN); + while (below.getType() == block.getType() || below.getType() == Material.TWISTING_VINES_PLANT) { + below = below.getRelative(BlockFace.DOWN); + } + return below; + } + case SUGAR_CANE: + case BAMBOO: + case ROSE_BUSH: + case TWISTING_VINES_PLANT: + case CACTUS: + case SUNFLOWER: + case LILAC: + case TALL_GRASS: + case LARGE_FERN: + case TALL_SEAGRASS: + case KELP_PLANT: + case PEONY: { + // scan downwards for first different block + Block below = block.getRelative(BlockFace.DOWN); + while (below.getType() == block.getType()) { + below = below.getRelative(BlockFace.DOWN); + } + return below; + } + case ACACIA_DOOR: + case BIRCH_DOOR: + case DARK_OAK_DOOR: + case IRON_DOOR: + case SPRUCE_DOOR: + case JUNGLE_DOOR: + case WARPED_DOOR: + case CRIMSON_DOOR: + case OAK_DOOR: { + if (block.getRelative(BlockFace.UP).getType() != block.getType()) { + // block is upper half of a door + return block.getRelative(BlockFace.DOWN); + } + return block; + } + case BLACK_BED: + case BLUE_BED: + case BROWN_BED: + case CYAN_BED: + case GRAY_BED: + case GREEN_BED: + case MAGENTA_BED: + case LIME_BED: + case ORANGE_BED: + case PURPLE_BED: + case PINK_BED: + case WHITE_BED: + case LIGHT_GRAY_BED: + case LIGHT_BLUE_BED: + case RED_BED: + case YELLOW_BED: { + Bed bed = (Bed) block.getBlockData(); + if (bed.getPart() == Bed.Part.HEAD) { + return block.getRelative(bed.getFacing().getOppositeFace()); + } + return block; + } + case TUBE_CORAL_WALL_FAN: + case BRAIN_CORAL_WALL_FAN: + case BUBBLE_CORAL_WALL_FAN: + case FIRE_CORAL_WALL_FAN: + case HORN_CORAL_WALL_FAN: + case DEAD_TUBE_CORAL_WALL_FAN: + case DEAD_BRAIN_CORAL_WALL_FAN: + case DEAD_BUBBLE_CORAL_WALL_FAN: + case DEAD_FIRE_CORAL_WALL_FAN: + case DEAD_HORN_CORAL_WALL_FAN: { + CoralWallFan cwf = (CoralWallFan) block.getBlockData(); + return block.getRelative(cwf.getFacing().getOppositeFace()); + } + case WEEPING_VINES: { + // scan upwards + Block above = block.getRelative(BlockFace.UP); + while (above.getType() == block.getType() || above.getType() == Material.WEEPING_VINES_PLANT) { + above = above.getRelative(BlockFace.UP); + } + return above; + } + case WEEPING_VINES_PLANT: { + // scan upwards + Block above = block.getRelative(BlockFace.UP); + while (above.getType() == block.getType()) { + above = above.getRelative(BlockFace.UP); + } + return above; + } + default: { + return block; + } + } + } + + /** + * Checks if at the given block is a container, which is not insecure and which + * the player can not access due to missing perms + * + * @param player the player attempting to access stuff + * @param block Block to check for + * @return True if the player can not do something like placing an adjacent + * chest or comparator, false otherwise + */ + public static boolean isPreventingBlockAccess(Player player, Block block) { + if (block == null) { + return false; + } + if (block.getState() instanceof InventoryHolder) { + Reinforcement rein = getReinforcementProtecting(block); + if (rein == null || rein.isInsecure()) { + return false; + } + return !rein.hasPermission(player, Citadel.getInstance().getPermissionHandler().getChests()); + } + return false; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/ReinforcementManager.java b/src/main/java/vg/civcraft/mc/citadel/ReinforcementManager.java new file mode 100644 index 00000000..eac8dca9 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/ReinforcementManager.java @@ -0,0 +1,55 @@ +package vg.civcraft.mc.citadel; + +import org.bukkit.Location; +import org.bukkit.block.Block; + +import vg.civcraft.mc.citadel.model.CitadelChunkData; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.api.BlockBasedChunkMetaView; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableBasedDataObject; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableStorageEngine; + +public class ReinforcementManager { + + private BlockBasedChunkMetaView> chunkMetaData; + + ReinforcementManager( + BlockBasedChunkMetaView> chunkMetaData) { + this.chunkMetaData = chunkMetaData; + } + + /** + * Gets the reinforcement at the given location if one exists + * + * @param location Location to get reinforcement for + * @return Reinforcement at the location or null if no reinforcement exists + * there + */ + public Reinforcement getReinforcement(Location location) { + return (Reinforcement) chunkMetaData.get(location); + } + + /** + * Gets the reinforcement for the given block if one exists + * + * @param block Block to get reinforcement for + * @return Reinforcement for the block or null if no reinforcement exists there + */ + public Reinforcement getReinforcement(Block block) { + return getReinforcement(block.getLocation()); + } + + /** + * Inserts the given reinforcement into the tracking. If a reinforcement already + * exists at the same location it will be replaced. + * + * @param reinforcement Reinforcement to insert + */ + public void putReinforcement(Reinforcement reinforcement) { + chunkMetaData.put(reinforcement); + } + + void shutDown() { + chunkMetaData.disable(); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Acid.java b/src/main/java/vg/civcraft/mc/citadel/command/Acid.java new file mode 100644 index 00000000..965bf080 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Acid.java @@ -0,0 +1,132 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Container; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.BlockIterator; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.events.ReinforcementAcidBlockedEvent; +import vg.civcraft.mc.citadel.model.AcidManager; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.api.MaterialAPI; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.civmodcore.util.TextUtil; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +@CivCommand(id = "ctacid") +public class Acid extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player p = (Player) sender; + Iterator itr = new BlockIterator(p, 40); // Within 2.5 chunks + AcidManager acidMan = Citadel.getInstance().getAcidManager(); + boolean foundAny = false; + while (itr.hasNext()) { + Block block = itr.next(); + if (MaterialAPI.isAir(block.getType()) || !(block.getType().isSolid()) || !(block.getType().isOccluding())) { + continue; + } + if (!acidMan.isPossibleAcidBlock(block)) { + if (!foundAny) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "That block is not a valid acid block"); + } + return true; + } + Reinforcement reinforcement = ReinforcementLogic.getReinforcementAt(block.getLocation()); + if (reinforcement == null) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "That block is not reinforced."); + return true; + } + if (!GroupAPI.hasPermission(p, reinforcement.getGroup(), Citadel.getInstance().getPermissionHandler().getAcidblock())) { + CitadelUtility.sendAndLog(p, ChatColor.RED, + "You do not have sufficient permission to use acid blocks on this group."); + return true; + } + long neededTime = acidMan.getRemainingAcidMaturationTime(reinforcement); + if (neededTime > 0) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "That acid block will be mature in " + + TextUtil.formatDuration(neededTime, TimeUnit.MILLISECONDS)); + return true; + } + Block topFace = block.getRelative(BlockFace.UP); + if (MaterialAPI.isAir(topFace.getType())) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "There is no block above to acid block."); + return true; + } + Reinforcement topRein = ReinforcementLogic.getReinforcementProtecting(topFace); + if (topRein == null) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "The block above doesn't have a reinforcement."); + return true; + } + if (!acidMan.canAcidBlock(reinforcement.getType(), topRein.getType())) { + CitadelUtility.sendAndLog(p, ChatColor.RED, + reinforcement.getType().getName() + " can not acid away " + topRein.getType().getName()); + return true; + } + ReinforcementAcidBlockedEvent event = new ReinforcementAcidBlockedEvent(p, reinforcement, topRein); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + if (Citadel.getInstance().getConfigManager().isDebugEnabled()) { + Citadel.getInstance().getLogger().log(Level.INFO, + "Acid block event cancelled for acid at " + reinforcement.getLocation()); + } + return true; + } + + if (Citadel.getInstance().getConfigManager().logHostileBreaks()) { + Citadel.getInstance().getLogger().log(Level.INFO, "Acid at {0} broke {1} at {2}, activated by {3}", + new Object[] { block.getLocation(), topFace.getType(), topFace.getLocation(), p.getName() }); + } + foundAny = true; + reinforcement.setHealth(-1); + // play particles for top block + ReinforcementLogic.damageReinforcement(topRein, topRein.getHealth() + 1, p); + block.breakNaturally(); + p.getWorld().dropItemNaturally(reinforcement.getLocation(), reinforcement.getType().getItem()); + if (!acidContainerBlock(topFace)) { + topFace.breakNaturally(); + } + } + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } + + /** + * Checks if a containers contents can be dropped + * @param block Container being acid blocked + * @return true if contents have been successfully dropped + */ + + public boolean acidContainerBlock(Block block) { + if (!(block instanceof Container)) { + return false; + } + Container container = (Container) block.getBlockData(); + ItemStack[] items = container.getInventory().getContents(); + container.getInventory().clear(); + for (ItemStack item : items) { + block.getWorld().dropItemNaturally(block.getLocation(), item); + } + return true; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/AdvancedFortification.java b/src/main/java/vg/civcraft/mc/citadel/command/AdvancedFortification.java new file mode 100644 index 00000000..d53fbbd5 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/AdvancedFortification.java @@ -0,0 +1,100 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; +import vg.civcraft.mc.citadel.playerstate.AdvancedFortificationState; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; +import vg.civcraft.mc.namelayer.mc.commands.NameLayerTabCompletion; + +@CivCommand(id = "cta") +public class AdvancedFortification extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + PlayerStateManager stateManager = Citadel.getInstance().getStateManager(); + AbstractPlayerState currentState = stateManager.getState(player); + AdvancedFortificationState advFortState = null; + if (currentState instanceof AdvancedFortificationState) { + advFortState = (AdvancedFortificationState) currentState; + if (args.length == 0) { + stateManager.setState(player, null); + return true; + } + } + ItemStack mainHand = player.getInventory().getItemInMainHand(); + if (mainHand.getType() == Material.AIR) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You need to hold an item in your main hand to specify the block type to reinforce"); + return true; + } + ItemStack offHand = player.getInventory().getItemInOffHand(); + if (offHand.getType() == Material.AIR) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You need to hold a reinforcement item in your off hand"); + return true; + } + ReinforcementType type = Citadel.getInstance().getReinforcementTypeManager().getByItemStack(offHand); + if (type == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You can not reinforce with the item in your off hand"); + return true; + } + if (!type.canBeReinforced(mainHand.getType())) { + CitadelUtility.sendAndLog(player, ChatColor.AQUA, + type.getName() + ChatColor.RED + " can not reinforce " + mainHand.getType().name()); + return true; + } + Group group = null; + if (args.length == 0) { + group = GroupAPI.getDefaultGroup(player); + if (group == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You don't have a default group and can thus not use this command without specifying a group"); + return true; + } + } else { + group = GroupAPI.getGroup(args[0]); + } + if (group == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "The group " + args[0] + " does not exist."); + return true; + } + boolean hasAccess = GroupAPI.hasPermission(player.getUniqueId(), group, Citadel.getInstance().getPermissionHandler().getReinforce()); + if (!hasAccess) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You do not have permission to reinforce on " + group.getName()); + return true; + } + if (advFortState == null) { + advFortState = new AdvancedFortificationState(player); + stateManager.setState(player, advFortState); + } + advFortState.addSetup(mainHand, type, group); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + if (args.length == 0) + return NameLayerTabCompletion.completeGroupName("", (Player) sender); + else if (args.length == 1) + return NameLayerTabCompletion.completeGroupName(args[0], (Player) sender); + else { + return new ArrayList<>(); + } + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/AreaReinforce.java b/src/main/java/vg/civcraft/mc/citadel/command/AreaReinforce.java new file mode 100644 index 00000000..785c81e0 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/AreaReinforce.java @@ -0,0 +1,103 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; +import vg.civcraft.mc.namelayer.mc.commands.NameLayerCommand; + +@CivCommand(id = "ctar") +public class AreaReinforce extends NameLayerCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Must be a player to perform this command."); + return true; + } + Player p = (Player) sender; + UUID uuid = resolveUUID(sender); + ReinforcementType reinType = Citadel.getInstance().getReinforcementTypeManager() + .getByItemStack(p.getInventory().getItemInMainHand()); + if (reinType == null) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "The item you are holding is not a possible reinforcement"); + return true; + } + Group group = null; + if (args.length == 6) { + group = GroupAPI.getDefaultGroup(p); + if (group == null) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "You need to set a default group \n Use /nlsdg to do so"); + return true; + } + } else { + group = GroupAPI.getGroup(args [0]); + } + if (group == null) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "The group " + args[0] + " does not exist."); + return true; + } + // no additional group permission check here because the player is + // admin/op anyway + int xMin, yMin, zMin, xMax, yMax, zMax; + int offset = args.length == 7 ? 1 : 0; + try { + int x1 = Integer.parseInt(args[offset]); + int y1 = Integer.parseInt(args[offset + 1]); + int z1 = Integer.parseInt(args[offset + 2]); + int x2 = Integer.parseInt(args[offset + 3]); + int y2 = Integer.parseInt(args[offset + 4]); + int z2 = Integer.parseInt(args[offset + 5]); + xMin = Math.min(x1, x2); + yMin = Math.min(y1, y2); + zMin = Math.min(z1, z2); + xMax = Math.max(x1, x2); + yMax = Math.max(y1, y2); + zMax = Math.max(z1, z2); + } catch (NumberFormatException e) { + CitadelUtility.sendAndLog(p, ChatColor.RED, "One of the arguments you provided was not a number"); + return false; + } + int count = 0; + for (int x = xMin; x <= xMax; x++) { + for (int y = yMin; y <= yMax; y++) { + for (int z = zMin; z <= zMax; z++) { + Block current = p.getWorld().getBlockAt(x, y, z); + if (!reinType.canBeReinforced(current.getType())) { + continue; + } + Block protecting = ReinforcementLogic.getResponsibleBlock(current); + if (!current.getLocation().equals(protecting.getLocation())) { + continue; + } + count++; + Reinforcement rein = ReinforcementLogic.callReinforcementCreationEvent(p, current, reinType, group); + if (rein != null) { + ReinforcementLogic.createReinforcement(rein); + } + } + } + } + + CitadelUtility.sendAndLog(p, ChatColor.GREEN, "Successfully created " + count + "reinforcements"); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Bypass.java b/src/main/java/vg/civcraft/mc/citadel/command/Bypass.java new file mode 100644 index 00000000..5bf57c74 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Bypass.java @@ -0,0 +1,38 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.civmodcore.playersettings.impl.BooleanSetting; + +@CivCommand(id = "ctb") +public class Bypass extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + BooleanSetting setting = Citadel.getInstance().getSettingManager().getBypass(); + boolean enabled = setting.getValue(player); + if (enabled) { + CitadelUtility.sendAndLog(player, ChatColor.GREEN, "Bypass mode has been disabled."); + } else { + CitadelUtility.sendAndLog(player, ChatColor.GREEN, + "Bypass mode has been enabled. You will be able to break reinforced blocks if you are on the group."); + } + setting.toggleValue(player.getUniqueId()); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/EasyMode.java b/src/main/java/vg/civcraft/mc/citadel/command/EasyMode.java new file mode 100644 index 00000000..ef45fc1c --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/EasyMode.java @@ -0,0 +1,38 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.civmodcore.playersettings.impl.BooleanSetting; + +@CivCommand(id = "cte") +public class EasyMode extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + BooleanSetting setting = Citadel.getInstance().getSettingManager().getEasyMode(); + boolean enabled = setting.getValue(player); + if (enabled) { + CitadelUtility.sendAndLog(player, ChatColor.GREEN, "Easy reinforcing mode has been disabled."); + } else { + CitadelUtility.sendAndLog(player, ChatColor.GREEN, + "Easy reinforcing mode has been enabled. You will be able to reinforce to your default group by placing blocks while having a reinforcement material in your off hand."); + } + setting.toggleValue(player.getUniqueId()); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Fortification.java b/src/main/java/vg/civcraft/mc/citadel/command/Fortification.java new file mode 100644 index 00000000..ead9915c --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Fortification.java @@ -0,0 +1,91 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelPermissionHandler; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; +import vg.civcraft.mc.citadel.playerstate.FortificationState; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; +import vg.civcraft.mc.namelayer.mc.commands.NameLayerTabCompletion; + +@CivCommand(id = "ctf") +public class Fortification extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + PlayerStateManager stateManager = Citadel.getInstance().getStateManager(); + AbstractPlayerState currentState = stateManager.getState(player); + if (args.length == 0 && currentState instanceof FortificationState) { + stateManager.setState(player, null); + return true; + } + ReinforcementType type = Citadel.getInstance().getReinforcementTypeManager() + .getByItemStack(player.getInventory().getItemInMainHand()); + if (type == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You can not reinforce with this item"); + stateManager.setState(player, null); + return true; + } + + Group group = null; + if (args.length == 0) { + group = GroupAPI.getDefaultGroup(player); + if (group == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You need to fortify to a group! Try /fortify groupname. \n Or use /create groupname if you don't have a group yet."); + return true; + } + } else { + group = GroupAPI.getGroup(args[0]); + } + if (group == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "The group " + args[0] + " does not exist."); + stateManager.setState(player, null); + return true; + } + boolean hasAccess = GroupAPI.hasPermission(player.getUniqueId(), group, + Citadel.getInstance().getPermissionHandler().getReinforce()); + if (!hasAccess) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You do not have permission to reinforce on " + group.getName()); + stateManager.setState(player, null); + return true; + } + if (currentState instanceof FortificationState) { + FortificationState fortState = (FortificationState) currentState; + if (fortState.getGroup() == group && fortState.getType() == type) { + stateManager.setState(player, null); + return true; + } + } + stateManager.setState(player, new FortificationState(player, type, group)); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) + return null; + + if (args.length == 0) + return NameLayerTabCompletion.completeGroupName("", (Player) sender); + else if (args.length == 1) + return NameLayerTabCompletion.completeGroupName(args[0], (Player) sender); + else { + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Information.java b/src/main/java/vg/civcraft/mc/citadel/command/Information.java new file mode 100644 index 00000000..84b94b6c --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Information.java @@ -0,0 +1,32 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.civmodcore.playersettings.impl.BooleanSetting; + +@CivCommand(id = "cti") +public class Information extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + BooleanSetting ctiSetting = Citadel.getInstance().getSettingManager().getInformationMode(); + ctiSetting.toggleValue(player.getUniqueId()); + player.sendMessage(ChatColor.GREEN + "Toggled reinforcement information mode " + ChatColor.YELLOW + + (ctiSetting.getValue(player.getUniqueId()) ? "on" : "off")); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Insecure.java b/src/main/java/vg/civcraft/mc/citadel/command/Insecure.java new file mode 100644 index 00000000..46ab8d4a --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Insecure.java @@ -0,0 +1,37 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; +import vg.civcraft.mc.citadel.playerstate.InsecureState; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; + +@CivCommand(id = "ctin") +public class Insecure extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + PlayerStateManager stateManager = Citadel.getInstance().getStateManager(); + AbstractPlayerState currentState = Citadel.getInstance().getStateManager().getState(player); + if (currentState instanceof InsecureState) { + stateManager.setState(player, null); + } else { + stateManager.setState(player, new InsecureState(player)); + } + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Off.java b/src/main/java/vg/civcraft/mc/citadel/command/Off.java new file mode 100644 index 00000000..6b70940c --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Off.java @@ -0,0 +1,37 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.model.CitadelSettingManager; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; + +@CivCommand(id = "cto") +public class Off extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Citadel.getInstance().getStateManager().setState((Player) sender, null); + CitadelSettingManager settings = Citadel.getInstance().getSettingManager(); + UUID uuid = ((Player) sender).getUniqueId(); + if (settings.getInformationMode().getValue(uuid) && settings.shouldCtoDisableCti(uuid)) { + settings.getInformationMode().setValue(uuid, false); + } + if (settings.getBypass().getValue(uuid) && settings.shouldCtoDisableCtb(uuid)) { + settings.getBypass().setValue(uuid, false); + } + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new ArrayList<>(); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/PatchMode.java b/src/main/java/vg/civcraft/mc/citadel/command/PatchMode.java new file mode 100644 index 00000000..796beea3 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/PatchMode.java @@ -0,0 +1,37 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.LinkedList; +import java.util.List; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; +import vg.civcraft.mc.citadel.playerstate.PatchState; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; + +@CivCommand(id = "ctp") +public class PatchMode extends StandaloneCommand{ + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + PlayerStateManager stateManager = Citadel.getInstance().getStateManager(); + AbstractPlayerState currentState = Citadel.getInstance().getStateManager().getState(player); + if (currentState instanceof PatchState) { + stateManager.setState(player, null); + } else { + stateManager.setState(player, new PatchState(player)); + } + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new LinkedList<>(); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Reinforce.java b/src/main/java/vg/civcraft/mc/citadel/command/Reinforce.java new file mode 100644 index 00000000..44e5692c --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Reinforce.java @@ -0,0 +1,78 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.citadel.playerstate.ReinforcingState; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; +import vg.civcraft.mc.namelayer.mc.commands.NameLayerTabCompletion; + +@CivCommand(id = "ctr") +public class Reinforce extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + Group group = null; + if (args.length == 0) { + group = GroupAPI.getDefaultGroup(player); + if (group == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You need to reinforce to a group! Try /reinforce groupname. \n Or use /create groupname if you don't have a group yet."); + return true; + } + } else { + group = GroupAPI.getGroup(args[0]); + } + PlayerStateManager stateManager = Citadel.getInstance().getStateManager(); + if (group == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "The group " + args[0] + " does not exist."); + stateManager.setState(player, null); + return true; + } + boolean hasAccess = GroupAPI.hasPermission(player.getUniqueId(), group, + Citadel.getInstance().getPermissionHandler().getReinforce()); + if (!hasAccess) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You do not have permission to reinforce on " + group.getName()); + stateManager.setState(player, null); + return true; + } + AbstractPlayerState currentState = Citadel.getInstance().getStateManager().getState(player); + if (currentState instanceof ReinforcingState) { + ReinforcingState reinState = (ReinforcingState) currentState; + if (reinState.getGroup() == group) { + stateManager.setState(player, null); + return true; + } + } + stateManager.setState(player, new ReinforcingState(player, group)); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) + return null; + + if (args.length == 0) + return NameLayerTabCompletion.completeGroupName("", (Player) sender); + else if (args.length == 1) + return NameLayerTabCompletion.completeGroupName(args[0], (Player) sender); + else { + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java b/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java new file mode 100644 index 00000000..6fd611c3 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/ReinforcementsGUI.java @@ -0,0 +1,63 @@ +package vg.civcraft.mc.citadel.command; + +import java.text.DecimalFormat; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.api.ItemAPI; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; +import vg.civcraft.mc.civmodcore.inventorygui.DecorationStack; +import vg.civcraft.mc.civmodcore.inventorygui.IClickable; +import vg.civcraft.mc.civmodcore.inventorygui.MultiPageView; +import vg.civcraft.mc.civmodcore.util.TextUtil; + +@CivCommand(id = "ctdl") +public class ReinforcementsGUI extends StandaloneCommand { + + private DecimalFormat format = new DecimalFormat("##.##"); + + @Override + public boolean execute(CommandSender sender, String[] arg1) { + List types = new LinkedList<>( + Citadel.getInstance().getReinforcementTypeManager().getAllTypes()); + // sort ascending by health + Collections.sort(types, (o1, o2) -> Double.compare(o1.getHealth(), o2.getHealth())); + List clicks = new LinkedList<>(); + for (ReinforcementType type : types) { + ItemStack is = type.getItem().clone(); + ItemAPI.setDisplayName(is, ChatColor.AQUA + type.getName()); + ItemAPI.addLore(is, ChatColor.GREEN + "Health: " + format.format(type.getHealth())); + ItemAPI.addLore(is, ChatColor.GOLD + "Maturation time: " + + TextUtil.formatDuration(type.getMaturationTime(), TimeUnit.MILLISECONDS)); + if (type.getAcidTime() > 0) { + ItemAPI.addLore(is, ChatColor.GOLD + "Acid maturation time: " + + TextUtil.formatDuration(type.getAcidTime(), TimeUnit.MILLISECONDS)); + } else { + ItemAPI.addLore(is, ChatColor.GOLD + "Can not be used for acid"); + } + ItemAPI.addLore(is, + ChatColor.WHITE + "Return chance: " + format.format(type.getReturnChance() * 100.0) + " %"); + IClickable click = new DecorationStack(is); + clicks.add(click); + } + MultiPageView pageView = new MultiPageView((Player) sender, clicks, ChatColor.BLUE + "Reinforcements", true); + pageView.showScreen(); + return true; + } + + @Override + public List tabComplete(CommandSender arg0, String[] arg1) { + return null; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/command/Reload.java b/src/main/java/vg/civcraft/mc/citadel/command/Reload.java new file mode 100644 index 00000000..41836fbc --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/command/Reload.java @@ -0,0 +1,28 @@ +package vg.civcraft.mc.citadel.command; + +import java.util.LinkedList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.civmodcore.command.CivCommand; +import vg.civcraft.mc.civmodcore.command.StandaloneCommand; + +@CivCommand(id = "citadelreload") +public class Reload extends StandaloneCommand { + + @Override + public boolean execute(CommandSender sender, String[] args) { + Citadel.getInstance().reload(); + sender.sendMessage(ChatColor.GREEN + "Reloaded Citadel"); + return true; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) { + return new LinkedList<>(); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcedBlockBreak.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcedBlockBreak.java new file mode 100644 index 00000000..4e41a892 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcedBlockBreak.java @@ -0,0 +1,40 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.block.BlockBreakEvent; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a reinforcement is destroyed and the block reinforced is going to drop + * + */ +public class ReinforcedBlockBreak extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private BlockBreakEvent blockEvent; + + public ReinforcedBlockBreak(Player who, Reinforcement reinforcement, BlockBreakEvent event) { + super(who, reinforcement); + this.blockEvent = event; + } + + /** + * @return The BlockBreakEvent which caused the destrution of the reinforcement + */ + public BlockBreakEvent getWrappedBlockBreakEvent() { + return blockEvent; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementAcidBlockedEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementAcidBlockedEvent.java new file mode 100644 index 00000000..dae2711d --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementAcidBlockedEvent.java @@ -0,0 +1,39 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a block is destroyed by an acid block + * + */ +public class ReinforcementAcidBlockedEvent extends ReinforcementEvent { + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private Reinforcement acidBlock; + + public ReinforcementAcidBlockedEvent(Player player, Reinforcement acidBlock, Reinforcement destroyedBlock) { + super(player, destroyedBlock); + this.acidBlock = acidBlock; + } + + /** + * Gets the reinforcement of the acid block. + * + * @return Acid block reinforcement + */ + public Reinforcement getAcidBlockReinforcement() { + return acidBlock; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} \ No newline at end of file diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementBypassEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementBypassEvent.java new file mode 100644 index 00000000..d8deda15 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementBypassEvent.java @@ -0,0 +1,29 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a player bypasses a reinforcement they have access to + * + */ +public class ReinforcementBypassEvent extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + public ReinforcementBypassEvent(Player who, Reinforcement reinforcement) { + super(who, reinforcement); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementChangeTypeEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementChangeTypeEvent.java new file mode 100644 index 00000000..cf886970 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementChangeTypeEvent.java @@ -0,0 +1,40 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; + +/** + * Called when a reinforcements type is changed + * + */ +public class ReinforcementChangeTypeEvent extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private ReinforcementType newType; + + public ReinforcementChangeTypeEvent(Player p, Reinforcement rein, ReinforcementType newType) { + super(p, rein); + this.newType = newType; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + /** + * + * @return Future reinforcement type + */ + public ReinforcementType getNewType() { + return newType; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementCreationEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementCreationEvent.java new file mode 100644 index 00000000..41b9ec6f --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementCreationEvent.java @@ -0,0 +1,28 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a new reinforcement is created + * + */ +public class ReinforcementCreationEvent extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + public ReinforcementCreationEvent(Player p, Reinforcement rein) { + super(p, rein); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementDamageEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementDamageEvent.java new file mode 100644 index 00000000..67e7cdd5 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementDamageEvent.java @@ -0,0 +1,49 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a reinforcement is damaged by a player, but not when it is damaged by other entities or natural causes + * + */ +public class ReinforcementDamageEvent extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private float damageDone; + + public ReinforcementDamageEvent(Player player, Reinforcement rein, float damageDone) { + super(player, rein); + this.damageDone = damageDone; + } + + /** + * Gets the total damage done by this damaging event + * + * @return Total damage + */ + public float getDamageDone() { + return damageDone; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + /** + * Sets the total damage done + * + * @param damageDone Damage to do + */ + public void setDamageDone(float damageDone) { + this.damageDone = damageDone; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementDestructionEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementDestructionEvent.java new file mode 100644 index 00000000..abd8e17a --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementDestructionEvent.java @@ -0,0 +1,71 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Entity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a reinforcement is forcefully destroyed, meaning it is removed + * and was not bypassed + * + */ +public class ReinforcementDestructionEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private boolean isCancelled; + private Reinforcement reinforcement; + private float finalDamage; + private Entity source; + + public ReinforcementDestructionEvent(Reinforcement reinforcement, float finalDamage, Entity source) { + this.finalDamage = finalDamage; + this.reinforcement = reinforcement; + this.source = source; + } + + /** + * @return Source of the final damage dealt to the reinforcement. May be a + * player, creeper, fireball etc. or possibly null + */ + public Entity getSource() { + return source; + } + + /** + * @return Reinforcement destroyed + */ + public Reinforcement getReinforcement() { + return reinforcement; + } + + /** + * @return How much damage was dealt in the killing blow to the reinforcement + */ + public float getFinalDamage() { + return finalDamage; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return isCancelled; + } + + @Override + public void setCancelled(boolean value) { + isCancelled = value; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementEvent.java new file mode 100644 index 00000000..ab67c062 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementEvent.java @@ -0,0 +1,36 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.player.PlayerEvent; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +public abstract class ReinforcementEvent extends PlayerEvent implements Cancellable { + + protected Reinforcement reinforcement; + protected boolean isCancelled; + + public ReinforcementEvent(Player who, Reinforcement reinforcement) { + super(who); + this.reinforcement = reinforcement; + isCancelled = false; + } + + /** + * @return Reinforcement involved in this event + */ + public Reinforcement getReinforcement() { + return reinforcement; + } + + @Override + public boolean isCancelled() { + return isCancelled; + } + + @Override + public void setCancelled(boolean value) { + isCancelled = value; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementGroupChangeEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementGroupChangeEvent.java new file mode 100644 index 00000000..3cc8a937 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementGroupChangeEvent.java @@ -0,0 +1,37 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.namelayer.core.Group; + +/** + * Called when the group a reinforcement is on is changed + * + */ +public class ReinforcementGroupChangeEvent extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private Group newGroup; + + public ReinforcementGroupChangeEvent(Player who, Reinforcement reinforcement, Group newGroup) { + super(who, reinforcement); + this.newGroup = newGroup; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public Group getNewGroup() { + return newGroup; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementModeSwitchEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementModeSwitchEvent.java new file mode 100644 index 00000000..78c30c51 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementModeSwitchEvent.java @@ -0,0 +1,62 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; + +/** + * Called when a player changes his reinforcement mode. Not called when the + * player attempt to switch, but stays in the same mode + * + */ +public class ReinforcementModeSwitchEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + private AbstractPlayerState oldState; + private AbstractPlayerState newState; + private boolean isCancelled; + + public ReinforcementModeSwitchEvent(Player who, AbstractPlayerState oldState, AbstractPlayerState newState) { + super(who); + this.oldState = oldState; + this.newState = newState; + isCancelled = false; + } + + /** + * @return Reinforcement mode before the change + */ + public AbstractPlayerState getOldMode() { + return oldState; + } + + /** + * @return Reinforcement mode after the change + */ + public AbstractPlayerState getNewMode() { + return newState; + } + + @Override + public boolean isCancelled() { + return isCancelled; + } + + @Override + public void setCancelled(boolean value) { + isCancelled = value; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementRepairEvent.java b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementRepairEvent.java new file mode 100644 index 00000000..87dc94fa --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/events/ReinforcementRepairEvent.java @@ -0,0 +1,29 @@ +package vg.civcraft.mc.citadel.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +/** + * Called when a reinforcement is repaired in patch mode + * + */ +public class ReinforcementRepairEvent extends ReinforcementEvent { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + public ReinforcementRepairEvent(Player who, Reinforcement reinforcement) { + super(who, reinforcement); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/listener/BlockListener.java b/src/main/java/vg/civcraft/mc/citadel/listener/BlockListener.java new file mode 100644 index 00000000..6f44c48e --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/listener/BlockListener.java @@ -0,0 +1,402 @@ +package vg.civcraft.mc.citadel.listener; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Container; +import org.bukkit.block.data.Openable; +import org.bukkit.block.data.type.Comparator; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.api.BlockAPI; +import vg.civcraft.mc.civmodcore.api.MaterialAPI; +import vg.civcraft.mc.civmodcore.util.DoubleInteractFixer; + +public class BlockListener implements Listener { + + private static final Material matfire = Material.FIRE; + + private DoubleInteractFixer interactFixer; + + public BlockListener(Citadel plugin) { + this.interactFixer = new DoubleInteractFixer(plugin); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void blockBreakEvent(BlockBreakEvent event) { + Citadel.getInstance().getStateManager().getState(event.getPlayer()).handleBreakBlock(event); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void blockPlaceEvent(BlockPlaceEvent event) { + Citadel.getInstance().getStateManager().getState(event.getPlayer()).handleBlockPlace(event); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void blockBurn(BlockBurnEvent bbe) { + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(bbe.getBlock()); + if (reinforcement == null) { + return; + } + bbe.setCancelled(true); + Block block = bbe.getBlock(); + // Basic essential fire protection + if (block.getRelative(0, 1, 0).getType() == matfire) { + block.getRelative(0, 1, 0).setType(Material.AIR); + } // Essential + // Extended fire protection (recommend) + if (block.getRelative(1, 0, 0).getType() == matfire) { + block.getRelative(1, 0, 0).setType(Material.AIR); + } + if (block.getRelative(-1, 0, 0).getType() == matfire) { + block.getRelative(-1, 0, 0).setType(Material.AIR); + } + if (block.getRelative(0, -1, 0).getType() == matfire) { + block.getRelative(0, -1, 0).setType(Material.AIR); + } + if (block.getRelative(0, 0, 1).getType() == matfire) { + block.getRelative(0, 0, 1).setType(Material.AIR); + } + if (block.getRelative(0, 0, -1).getType() == matfire) { + block.getRelative(0, 0, -1).setType(Material.AIR); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void blockPhysEvent(BlockPhysicsEvent event) { + Block block = event.getBlock(); + if (block.getType().hasGravity()) { + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + if (rein != null) { + event.setCancelled(true); + } + } + + } + + // Stop comparators from being placed unless the reinforcement is insecure + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void comparatorPlaceCheck(BlockPlaceEvent event) { + // We only care if they are placing a comparator + if (event.getBlockPlaced().getType() != Material.COMPARATOR) { + return; + } + Comparator comparator = (Comparator) event.getBlockPlaced().getBlockData(); + Block block = event.getBlockPlaced().getRelative(comparator.getFacing().getOppositeFace()); + // Check if the comparator is placed against something with an inventory + if (ReinforcementLogic.isPreventingBlockAccess(event.getPlayer(), block)) { + event.setCancelled(true); + CitadelUtility.sendAndLog(event.getPlayer(), ChatColor.RED, + "You can not place this because it'd allow bypassing a nearby reinforcement"); + return; + } + // Comparators can also read through a single opaque block + if (block.getType().isOccluding()) { + if (ReinforcementLogic.isPreventingBlockAccess(event.getPlayer(), + block.getRelative(comparator.getFacing().getOppositeFace()))) { + event.setCancelled(true); + CitadelUtility.sendAndLog(event.getPlayer(), ChatColor.RED, + "You can not place this because it'd allow bypassing a nearby reinforcement"); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void interact(PlayerInteractEvent pie) { + if (pie.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (interactFixer.checkInteracted(pie.getPlayer(), pie.getClickedBlock())) { + return; + } + } else if (pie.getAction() != Action.LEFT_CLICK_BLOCK) { + return; + } + Citadel.getInstance().getStateManager().getState(pie.getPlayer()).handleInteractBlock(pie); + } + + // prevent placing water inside of reinforced blocks + @EventHandler(priority = EventPriority.LOW) + public void liquidDumpEvent(PlayerBucketEmptyEvent event) { + Block block = event.getBlockClicked().getRelative(event.getBlockFace()); + if (block.getType() == Material.AIR || block.getType().isSolid()) { + return; + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + if (rein != null) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockFromToEvent(BlockFromToEvent event) { + // prevent water/lava from spilling reinforced blocks away + if (event.getToBlock().getY() < 0) { + return; + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(event.getToBlock()); + if (rein != null) { + event.setCancelled(true); + } + } + + // prevent breaking reinforced blocks through plant growth + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onStructureGrow(StructureGrowEvent event) { + for (BlockState block_state : event.getBlocks()) { + if (ReinforcementLogic.getReinforcementProtecting(block_state.getBlock()) != null) { + event.setCancelled(true); + return; + } + } + } + + // prevent opening reinforced things + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void openContainer(PlayerInteractEvent e) { + if (!e.hasBlock()) { + return; + } + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(e.getClickedBlock()); + if (rein == null) { + return; + } + if (e.getClickedBlock().getState() instanceof Container) { + if (!rein.hasPermission(e.getPlayer(), Citadel.getInstance().getPermissionHandler().getChests())) { + e.setCancelled(true); + String msg = String.format("%s is locked with %s%s", e.getClickedBlock().getType().name(), + ChatColor.AQUA, rein.getType().getName()); + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, msg); + } + return; + } + if (e.getClickedBlock().getBlockData() instanceof Openable) { + if (!rein.hasPermission(e.getPlayer(), Citadel.getInstance().getPermissionHandler().getDoors())) { + e.setCancelled(true); + String msg = String.format("%s is locked with %s%s", e.getClickedBlock().getType().name(), + ChatColor.AQUA, rein.getType().getName()); + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, msg); + } + } + } + + // prevent players from upgrading a chest into a double chest to bypass the + // single chests reinforcement + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void preventBypassChestAccess(BlockPlaceEvent e) { + Material mat = e.getBlock().getType(); + if (mat != Material.CHEST && mat != Material.TRAPPED_CHEST) { + return; + } + for (Block rel : BlockAPI.getPlanarSides(e.getBlock())) { + if (rel.getType() == mat && ReinforcementLogic.isPreventingBlockAccess(e.getPlayer(), rel)) { + e.setCancelled(true); + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, + "You can not place this because it'd allow bypassing a nearby reinforcement"); + break; + } + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void removeReinforcedAir(BlockPlaceEvent e) { + if (!MaterialAPI.isAir(e.getBlockReplacedState().getType())) { + return; + } + Reinforcement rein = Citadel.getInstance().getReinforcementManager().getReinforcement(e.getBlock()); + if (rein != null) { + rein.setHealth(-1); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void preventStrippingLogs(PlayerInteractEvent pie) { + if (!pie.hasBlock()) { + return; + } + if (pie.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + Block block = pie.getClickedBlock(); + if (!MaterialAPI.isLog(block.getType())) { + return; + } + EquipmentSlot hand = pie.getHand(); + if (hand != EquipmentSlot.HAND && hand != EquipmentSlot.OFF_HAND) { + return; + } + ItemStack relevant; + Player p = pie.getPlayer(); + if (hand == EquipmentSlot.HAND) { + relevant = p.getInventory().getItemInMainHand(); + } else { + relevant = p.getInventory().getItemInOffHand(); + } + if (!MaterialAPI.isAxe(relevant.getType())) { + return; + } + Reinforcement rein = Citadel.getInstance().getReinforcementManager().getReinforcement(block); + if (rein == null) { + return; + } + if (!rein.hasPermission(p, Citadel.getInstance().getPermissionHandler().getModifyBlocks())) { + p.sendMessage(ChatColor.RED + "You do not have permission to modify this block"); + pie.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void preventTilingGrass(PlayerInteractEvent pie) { + if (!pie.hasBlock()) { + return; + } + if (pie.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + Block block = pie.getClickedBlock(); + if (block.getType() != Material.GRASS_BLOCK) { + return; + } + EquipmentSlot hand = pie.getHand(); + if (hand != EquipmentSlot.HAND && hand != EquipmentSlot.OFF_HAND) { + return; + } + ItemStack relevant; + Player p = pie.getPlayer(); + if (hand == EquipmentSlot.HAND) { + relevant = p.getInventory().getItemInMainHand(); + } else { + relevant = p.getInventory().getItemInOffHand(); + } + if (!MaterialAPI.isShovel(relevant.getType())) { + return; + } + Reinforcement rein = Citadel.getInstance().getReinforcementManager().getReinforcement(block); + if (rein == null) { + return; + } + if (!rein.hasPermission(p, Citadel.getInstance().getPermissionHandler().getModifyBlocks())) { + p.sendMessage(ChatColor.RED + "You do not have permission to modify this block"); + pie.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void preventTillingDirtIntoFarmland(PlayerInteractEvent pie) { + if (!pie.hasBlock()) { + return; + } + if (pie.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + Block block = pie.getClickedBlock(); + Material type = block.getType(); + if (type != Material.GRASS_BLOCK && type != Material.DIRT && type != Material.COARSE_DIRT + && type != Material.GRASS_PATH) { + return; + } + EquipmentSlot hand = pie.getHand(); + if (hand != EquipmentSlot.HAND && hand != EquipmentSlot.OFF_HAND) { + return; + } + ItemStack relevant; + Player p = pie.getPlayer(); + if (hand == EquipmentSlot.HAND) { + relevant = p.getInventory().getItemInMainHand(); + } else { + relevant = p.getInventory().getItemInOffHand(); + } + if (!MaterialAPI.isHoe(relevant.getType())) { + return; + } + Reinforcement rein = Citadel.getInstance().getReinforcementManager().getReinforcement(block); + if (rein == null) { + return; + } + if (!rein.hasPermission(p, Citadel.getInstance().getPermissionHandler().getModifyBlocks())) { + p.sendMessage(ChatColor.RED + "You do not have permission to modify this block"); + pie.setCancelled(true); + } + } + + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void preventHarvestingHoney(PlayerInteractEvent pie) { + if (!pie.hasBlock()) { + return; + } + if (pie.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + Block block = pie.getClickedBlock(); + Material type = block.getType(); + if (type != Material.BEE_NEST && type != Material.BEEHIVE) { + return; + } + EquipmentSlot hand = pie.getHand(); + if (hand != EquipmentSlot.HAND && hand != EquipmentSlot.OFF_HAND) { + return; + } + ItemStack relevant; + Player p = pie.getPlayer(); + if (hand == EquipmentSlot.HAND) { + relevant = p.getInventory().getItemInMainHand(); + } else { + relevant = p.getInventory().getItemInOffHand(); + } + if (relevant.getType() != Material.SHEARS && relevant.getType() != Material.GLASS_BOTTLE) { + return; + } + Reinforcement rein = Citadel.getInstance().getReinforcementManager().getReinforcement(block); + if (rein == null) { + return; + } + if (!rein.hasPermission(p, Citadel.getInstance().getPermissionHandler().getModifyBlocks())) { + p.sendMessage(ChatColor.RED + "You do not have permission to harvest this block"); + pie.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = false) + public void openBeacon(PlayerInteractEvent pie) { + if (!pie.hasBlock()) { + return; + } + if (pie.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + if (pie.getClickedBlock().getType() != Material.BEACON) { + return; + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(pie.getClickedBlock()); + if (rein == null) { + return; + } + if (!rein.hasPermission(pie.getPlayer(), Citadel.getInstance().getPermissionHandler().getBeacon())) { + pie.setCancelled(true); + String msg = String.format("%s is locked with %s%s", pie.getClickedBlock().getType().name(), ChatColor.AQUA, + rein.getType().getName()); + CitadelUtility.sendAndLog(pie.getPlayer(), ChatColor.RED, msg); + } + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/listener/EntityListener.java b/src/main/java/vg/civcraft/mc/citadel/listener/EntityListener.java new file mode 100644 index 00000000..7b2a9bf2 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/listener/EntityListener.java @@ -0,0 +1,300 @@ +package vg.civcraft.mc.citadel.listener; + +import static vg.civcraft.mc.civmodcore.util.NullCoalescing.castOrNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Hanging; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityBreakDoorEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerJoinEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.api.ItemAPI; + +public class EntityListener implements Listener { + + // prevent zombies from breaking reinforced doors + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void breakDoor(EntityBreakDoorEvent ebde) { + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(ebde.getBlock()); + if (rein != null) { + ReinforcementLogic.damageReinforcement(rein, ReinforcementLogic.getDamageApplied(rein), ebde.getEntity()); + if (!rein.isBroken()) { + ebde.setCancelled(true); + } + } + } + + // For some ungodly reason, when you break a block below a block with gravity, it spawns a FallingBlock entity + // that then attempts to change the block. To prevent this change from ticking damage and creating a ghost block + // the entity needs to have its gravity disabled so it immediately lands. + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onFallingBlockSpawn(EntitySpawnEvent event) { + if (event.getEntityType() != EntityType.FALLING_BLOCK) { + return; + } + Block block = event.getLocation().getBlock(); + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + if (rein == null) { + return; + } + Entity entity = event.getEntity(); + entity.setGravity(false); + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void changeBlock(EntityChangeBlockEvent ecbe) { + Block block = ecbe.getBlock(); + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + // Do not allow a falling block entity to damage reinforcements. + if (rein == null || ecbe.getEntityType() == EntityType.FALLING_BLOCK) { + return; + } + ReinforcementLogic.damageReinforcement(rein, ReinforcementLogic.getDamageApplied(rein), ecbe.getEntity()); + if (rein.isBroken()) { + return; + } + ecbe.setCancelled(true); + } + + // apply explosion damage to reinforcements + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void explode(EntityExplodeEvent eee) { + Iterator iterator = eee.blockList().iterator(); + // we can edit the result by removing blocks from the list + while (iterator.hasNext()) { + Block block = iterator.next(); + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + if (rein == null) { + continue; + } + ReinforcementLogic.damageReinforcement(rein, ReinforcementLogic.getDamageApplied(rein), eee.getEntity()); + if (!rein.isBroken()) { + iterator.remove(); + } + } + } + + private List getGolemBlocks(EntityType type, Block base) { + ArrayList blocks = new ArrayList<>(); + blocks.add(base); + base = base.getRelative(BlockFace.UP); + blocks.add(base); + if (type == EntityType.IRON_GOLEM) { + for (BlockFace face : new BlockFace[] { BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, + BlockFace.WEST }) { + Block arm = base.getRelative(face); + if (arm.getType() == Material.IRON_BLOCK) + blocks.add(arm); + } + } + base = base.getRelative(BlockFace.UP); + blocks.add(base); + return blocks; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void playerJoinEvent(PlayerJoinEvent event) { + Player p = event.getPlayer(); + final UUID uuid = p.getUniqueId(); + //TODO figure out decay again + } + + // prevent creating golems from reinforced blocks + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void spawn(CreatureSpawnEvent cse) { + EntityType type = cse.getEntityType(); + if (type != EntityType.IRON_GOLEM && type != EntityType.SNOWMAN && type != EntityType.WITHER + && type != EntityType.SILVERFISH) { + return; + } + for (Block block : getGolemBlocks(type, cse.getLocation().getBlock())) { + Reinforcement reinforcement = Citadel.getInstance().getReinforcementManager().getReinforcement(block); + if (reinforcement != null) { + cse.setCancelled(true); + } + } + } + + // ------------------------------------------------------------ + // Hanging Entities + // ------------------------------------------------------------ + + @EventHandler(priority = EventPriority.HIGHEST) + public void hangingPlaceEvent(HangingPlaceEvent event) { + if (!Citadel.getInstance().getConfigManager().doHangersInheritReinforcements()) { + return; + } + Player player = event.getPlayer(); + if (player == null) { + return; + } + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(event.getBlock()); + if (reinforcement == null) { + return; + } + if (reinforcement.isInsecure()) { + return; + } + if (reinforcement.hasPermission(player, Citadel.getInstance().getPermissionHandler().getHangingPlaceBreak())) { + return; + } + player.sendMessage(ChatColor.RED + "You cannot place those on blocks you don't have permissions for."); + event.setCancelled(true); + Bukkit.getScheduler().runTaskLater(Citadel.getInstance(), player::updateInventory, 1L); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void hangingEntityBreakEvent(HangingBreakByEntityEvent event) { + if (!Citadel.getInstance().getConfigManager().doHangersInheritReinforcements()) { + return; + } + switch (event.getCause()) { + // Allow it to break if: + // 1) The host block broke + // 2) A block was placed over it + // 3) A plugin broke it + case OBSTRUCTION: + case PHYSICS: + case DEFAULT: + case EXPLOSION: + return; + case ENTITY: { + Player player = castOrNull(Player.class, event.getRemover()); + if (player == null) { + break; + } + Hanging entity = event.getEntity(); + Block host = entity.getLocation().getBlock().getRelative(entity.getAttachedFace()); + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(host); + if (reinforcement == null) { + return; + } + if (reinforcement.isInsecure()) { + return; + } + if (reinforcement.hasPermission(player, Citadel.getInstance().getPermissionHandler().getHangingPlaceBreak())) { + return; + } + player.sendMessage(ChatColor.RED + "The host block is protecting this."); + //break; + } + } + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void HangingBreakEvent(HangingBreakEvent event) { + if (!Citadel.getInstance().getConfigManager().doHangersInheritReinforcements()) { + return; + } + if (event.getCause() != HangingBreakEvent.RemoveCause.EXPLOSION){ + return; + } + Hanging entity = event.getEntity(); + Block host = entity.getLocation().getBlock().getRelative(entity.getAttachedFace()); + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(host); + if (reinforcement == null) { + return; + } + if (reinforcement.isInsecure()) { + return; + } + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void entityDamageEvent(EntityDamageByEntityEvent event) { + if (!Citadel.getInstance().getConfigManager().doHangersInheritReinforcements()) { + return; + } + Hanging entity = castOrNull(Hanging.class, event.getEntity()); + if (entity == null) { + return; + } + Player player = castOrNull(Player.class, event.getDamager()); + if (player == null) { + event.setCancelled(true); + return; + } + Block host = entity.getLocation().getBlock().getRelative(entity.getAttachedFace()); + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(host); + if (reinforcement == null) { + return; + } + if (entity instanceof ItemFrame) { + if (ItemAPI.isValidItem(((ItemFrame) entity).getItem())) { + if (reinforcement.isInsecure()) { + return; + } + if (reinforcement.hasPermission(player, Citadel.getInstance().getPermissionHandler().getItemFramePutTake())) { + return; + } + } + } + player.sendMessage(ChatColor.RED + "The host block is protecting this."); + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void playerEntityInteractEvent(PlayerInteractEntityEvent event) { + if (!Citadel.getInstance().getConfigManager().doHangersInheritReinforcements()) { + return; + } + Hanging entity = castOrNull(Hanging.class, event.getRightClicked()); + if (entity == null) { + return; + } + Block host = entity.getLocation().getBlock().getRelative(entity.getAttachedFace()); + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(host); + if (reinforcement == null) { + return; + } + Player player = event.getPlayer(); + if (entity instanceof ItemFrame) { + if (reinforcement.isInsecure()) { + return; + } + // If the Item Frame already has an item, then the only possible action is rotation + if (ItemAPI.isValidItem(((ItemFrame) entity).getItem())) { + if (reinforcement.hasPermission(player, Citadel.getInstance().getPermissionHandler().getItemFrameRotate())) { + return; + } + } + // If the Item Frame is empty, then the only possible action is placement + if (reinforcement.hasPermission(player, Citadel.getInstance().getPermissionHandler().getItemFramePutTake())) { + return; + } + } + player.sendMessage(ChatColor.RED + "You do not have permission to alter that."); + event.setCancelled(true); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/listener/InventoryListener.java b/src/main/java/vg/civcraft/mc/citadel/listener/InventoryListener.java new file mode 100644 index 00000000..86f305b3 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/listener/InventoryListener.java @@ -0,0 +1,130 @@ +package vg.civcraft.mc.citadel.listener; + +import org.bukkit.Location; +import org.bukkit.block.Chest; +import org.bukkit.block.Container; +import org.bukkit.block.DoubleChest; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.api.WorldAPI; + +public class InventoryListener implements Listener { + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onInventoryMoveItemEvent(InventoryMoveItemEvent event) { + Inventory fromInventory = event.getSource(); + InventoryHolder fromHolder = fromInventory.getHolder(); + boolean isFromBlock = fromHolder instanceof Container; + boolean fromAtChunkBorder = false; + Location fromLocation = null; + if (isFromBlock) { + fromLocation = fromInventory.getLocation(); + fromAtChunkBorder = isAtChunkBorder(fromLocation); + if (fromAtChunkBorder && !WorldAPI.isBlockLoaded(fromLocation)) { + event.setCancelled(true); + return; + } + } + + Inventory destInventory = event.getDestination(); + InventoryHolder destHolder = destInventory.getHolder(); + boolean isDestBlock = destHolder instanceof Container; + boolean destAtChunkBorder = false; + Location destLocation = null; + if (isDestBlock) { + destLocation = destInventory.getLocation(); + destAtChunkBorder = isAtChunkBorder(destLocation); + if (destAtChunkBorder && !WorldAPI.isBlockLoaded(destLocation)) { + event.setCancelled(true); + return; + } + } else { + if (!isFromBlock) { + // neither is a block, just ignore entirely + return; + } + } + + // Determine the reinforcement of the source + Reinforcement fromReinforcement = null; + if (isFromBlock) { + if (fromAtChunkBorder && fromHolder instanceof DoubleChest) { + DoubleChest doubleChest = (DoubleChest) fromHolder; + Location chestLocation = ((Chest) doubleChest.getLeftSide()).getLocation(); + Location otherLocation = ((Chest) doubleChest.getRightSide()).getLocation(); + // [LagFix] If either side of the double chest is not loaded then the + // reinforcement cannot be retrieved + // [LagFix] without necessarily loading the chunk to check against reinforcement + // logic, therefore this + // [LagFix] should err on the side of caution and prevent the transfer. + if (!WorldAPI.isBlockLoaded(chestLocation) || !WorldAPI.isBlockLoaded(otherLocation)) { + event.setCancelled(true); + return; + } + } + fromReinforcement = ReinforcementLogic.getReinforcementProtecting(fromLocation.getBlock()); + } + // Determine the reinforcement of the destination + Reinforcement destReinforcement = null; + if (isDestBlock) { + if (destAtChunkBorder && destHolder instanceof DoubleChest) { + DoubleChest doubleChest = (DoubleChest) destHolder; + Location chestLocation = ((Chest) doubleChest.getLeftSide()).getLocation(); + Location otherLocation = ((Chest) doubleChest.getRightSide()).getLocation(); + // [LagFix] If either side of the double chest is not loaded then the + // reinforcement cannot be retrieved + // [LagFix] without necessarily loading the chunk to check against reinforcement + // logic, therefore this + // [LagFix] should err on the side of caution and prevent the transfer. + if (!WorldAPI.isBlockLoaded(chestLocation) || !WorldAPI.isBlockLoaded(otherLocation)) { + event.setCancelled(true); + return; + } + } + destReinforcement = ReinforcementLogic.getReinforcementProtecting(destLocation.getBlock()); + } + // Allow the transfer if neither are reinforced + if (fromReinforcement == null && destReinforcement == null) { + return; + } + // Allow the transfer if the destination is un-reinforced and the source is + // insecure + if (destReinforcement == null) { + if (!fromReinforcement.isInsecure()) { + event.setCancelled(true); + } + return; + } + // Allow the transfer if the source is un-reinforced and the destination is + // insecure + if (fromReinforcement == null) { + if (!destReinforcement.isInsecure()) { + event.setCancelled(true); + } + return; + } + // Allow the transfer if both the source and destination are insecure + if (fromReinforcement.isInsecure() && destReinforcement.isInsecure()) { + return; + } + // Allow the transfer if both the source and destination are on the same group + if (fromReinforcement.getGroupId() == destReinforcement.getGroupId()) { + return; + } + event.setCancelled(true); + } + + private static boolean isAtChunkBorder(Location location) { + int xShif = location.getBlockX() & 15; + int zShif = location.getBlockZ() & 15; + return xShif == 0 || xShif == 15 || zShif == 0 || zShif == 15; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java b/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java new file mode 100644 index 00000000..fb5b1520 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/listener/ModeListener.java @@ -0,0 +1,281 @@ +package vg.civcraft.mc.citadel.listener; + +import java.text.DecimalFormat; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.events.ReinforcementModeSwitchEvent; +import vg.civcraft.mc.citadel.model.AcidManager; +import vg.civcraft.mc.citadel.model.CitadelSettingManager; +import vg.civcraft.mc.citadel.model.HologramManager; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.playerstate.AbstractPlayerState; +import vg.civcraft.mc.citadel.playerstate.PlayerStateManager; +import vg.civcraft.mc.civmodcore.playersettings.PlayerSetting; +import vg.civcraft.mc.civmodcore.playersettings.SettingChangeListener; +import vg.civcraft.mc.civmodcore.playersettings.impl.DisplayLocationSetting; +import vg.civcraft.mc.civmodcore.scoreboard.bottom.BottomLine; +import vg.civcraft.mc.civmodcore.scoreboard.bottom.BottomLineAPI; +import vg.civcraft.mc.civmodcore.scoreboard.side.CivScoreBoard; +import vg.civcraft.mc.civmodcore.scoreboard.side.ScoreBoardAPI; +import vg.civcraft.mc.civmodcore.util.DoubleInteractFixer; +import vg.civcraft.mc.civmodcore.util.TextUtil; + +public class ModeListener implements Listener { + + private static final DecimalFormat commaFormat = new DecimalFormat("#.##"); + private static final DecimalFormat roundingFormat = new DecimalFormat("0"); + + private DoubleInteractFixer interactFixer; + private BottomLine ctiBottomLine; + private CivScoreBoard ctiBoard; + private BottomLine ctbBottomLine; + private CivScoreBoard ctbBoard; + private BottomLine reinBottomLine; + private CivScoreBoard reinBoard; + private CitadelSettingManager settingMan; + private PlayerStateManager stateMan; + + public ModeListener(Citadel citadel) { + interactFixer = new DoubleInteractFixer(citadel); + this.stateMan = citadel.getStateManager(); + this.ctiBottomLine = BottomLineAPI.createBottomLine("ctiDisplay", 3); + this.ctiBoard = ScoreBoardAPI.createBoard("ctiDisplay"); + this.ctbBottomLine = BottomLineAPI.createBottomLine("ctbDisplay", 3); + this.ctbBoard = ScoreBoardAPI.createBoard("ctbDisplay"); + this.reinBottomLine = BottomLineAPI.createBottomLine("ctreinDisplay", 3); + this.reinBoard = ScoreBoardAPI.createBoard("ctreinDisplay"); + this.settingMan = Citadel.getInstance().getSettingManager(); + settingMan.getInformationMode().registerListener(new SettingChangeListener() { + @Override + public void handle(UUID player, PlayerSetting setting, Boolean oldValue, Boolean newValue) { + setCtiOverlay(Bukkit.getPlayer(player), newValue); + } + }); + settingMan.getInformationLocationSetting().registerListener(new SettingChangeListener() { + @Override + public void handle(UUID player, PlayerSetting setting, String oldValue, String newValue) { + setCtiOverlay(Bukkit.getPlayer(player), settingMan.getInformationMode().getValue(player)); + } + }); + settingMan.getBypass().registerListener(new SettingChangeListener() { + @Override + public void handle(UUID player, PlayerSetting setting, Boolean oldValue, Boolean newValue) { + setCtbOverlay(Bukkit.getPlayer(player), newValue); + } + }); + settingMan.getBypassLocationSetting().registerListener(new SettingChangeListener() { + @Override + public void handle(UUID player, PlayerSetting setting, String oldValue, String newValue) { + setCtbOverlay(Bukkit.getPlayer(player), settingMan.getBypass().getValue(player)); + } + }); + settingMan.getModeLocationSetting().registerListener(new SettingChangeListener() { + + @Override + public void handle(UUID player, PlayerSetting setting, String oldValue, String newValue) { + setReinModeOverlay(Bukkit.getPlayer(player), stateMan.getState(Bukkit.getPlayer(player))); + } + }); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void modeChange(ReinforcementModeSwitchEvent event) { + setReinModeOverlay(event.getPlayer(), event.getNewMode()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void playerLogin(PlayerJoinEvent e) { + setCtiOverlay(e.getPlayer(), settingMan.getInformationMode().getValue(e.getPlayer())); + setCtbOverlay(e.getPlayer(), settingMan.getBypass().getValue(e.getPlayer())); + setReinModeOverlay(e.getPlayer(), stateMan.getState(e.getPlayer())); + } + + private void setCtiOverlay(Player player, boolean state) { + updateDisplaySetting(player, settingMan.getInformationLocationSetting(), state, ChatColor.GOLD + "CTI", + ctiBottomLine, ctiBoard); + } + + private void setCtbOverlay(Player player, boolean state) { + updateDisplaySetting(player, settingMan.getBypassLocationSetting(), state, ChatColor.AQUA + "CTB", + ctbBottomLine, ctbBoard); + } + + private void setReinModeOverlay(Player player, AbstractPlayerState state) { + if (state == null) { + return; + } + updateDisplaySetting(player, settingMan.getModeLocationSetting(), true, state.getOverlayText(), reinBottomLine, + reinBoard); + } + + private static void updateDisplaySetting(Player player, DisplayLocationSetting locSetting, boolean state, String text, + BottomLine bottomLine, CivScoreBoard scoreBoard) { + if (player == null) { + return; + } + if (text == null) { + state = false; + } + if (!state) { + // always clean up, value might have been changed + bottomLine.removePlayer(player); + scoreBoard.hide(player); + } else { + if (locSetting.showOnActionbar(player.getUniqueId())) { + bottomLine.updatePlayer(player, text); + } + if (locSetting.showOnSidebar(player.getUniqueId())) { + scoreBoard.set(player, text); + } + } + } + + public static ChatColor getDamageColor(double relativeHealth) { + if (relativeHealth >= 1.0) { + return ChatColor.GREEN; + } else if (relativeHealth >= 0.75) { + return ChatColor.DARK_GREEN; + } else if (relativeHealth >= 0.5) { + return ChatColor.YELLOW; + } else if (relativeHealth >= 0.25) { + return ChatColor.RED; + } else { + return ChatColor.DARK_RED; + } + } + + public static String formatHealth(Reinforcement rein) { + double broken = rein.getHealth() / rein.getType().getHealth(); + ChatColor color; + if (broken >= 1.0) { + color = ChatColor.GREEN; + } else if (broken >= 0.75) { + color = ChatColor.DARK_GREEN; + } else if (broken >= 0.5) { + color = ChatColor.YELLOW; + } else if (broken >= 0.25) { + color = ChatColor.RED; + } else { + color = ChatColor.DARK_RED; + } + return String.format("%s%s%% (%s/%s)", color.toString(), + commaFormat.format(rein.getHealth() / rein.getType().getHealth() * 100), + roundingFormat.format(rein.getHealth()), roundingFormat.format(rein.getType().getHealth())); + } + + public static String formatProgress(long start, long timeNeeded, String text) { + long timeTaken = System.currentTimeMillis() - start; + timeTaken = Math.min(timeTaken, timeNeeded); + double progress = Math.min(1.0, ((double) timeTaken) / ((double) timeNeeded)); + return String.format("%s%% %s %s", commaFormat.format(progress * 100), text, + TextUtil.formatDuration(timeNeeded - timeTaken, TimeUnit.MILLISECONDS)); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void handleInteractBlock(PlayerInteractEvent e) { + if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (interactFixer.checkInteracted(e.getPlayer(), e.getClickedBlock())) { + return; + } + } else if (e.getAction() != Action.LEFT_CLICK_BLOCK) { + return; + } + if (!settingMan.getInformationMode().getValue(e.getPlayer())) { + return; + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(e.getClickedBlock()); + Player player = e.getPlayer(); + boolean showChat = settingMan.shouldShowChatInCti(player.getUniqueId()); + if (rein == null) { + if (showChat) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.YELLOW, "Not reinforced"); + } + return; + } + if (player.getGameMode() == GameMode.CREATIVE && e.getAction() == Action.LEFT_CLICK_BLOCK) { + e.setCancelled(true); + } + boolean showHolo = settingMan.shouldShowHologramInCti(player.getUniqueId()); + if (!rein.hasPermission(player, Citadel.getInstance().getPermissionHandler().getInfo())) { + if (showChat) { + Citadel.getInstance().getSettingManager().sendCtiEnemyMessage(player, rein); + } + if (showHolo) { + showHolo(rein, player); + } + return; + } + if (showChat) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("Reinforced at %s%s health with %s%s %son %s%s ", formatHealth(rein), + ChatColor.GREEN, ChatColor.AQUA, rein.getType().getName(), ChatColor.GREEN, ChatColor.LIGHT_PURPLE, + rein.getGroup().getName())); + if (!rein.isMature()) { + sb.append(ChatColor.GOLD); + sb.append(formatProgress(rein.getCreationTime(), rein.getType().getMaturationTime(), "mature")); + sb.append(" "); + } + if (rein.isInsecure()) { + sb.append(ChatColor.AQUA); + sb.append("(Insecure)"); + } + if (ReinforcementLogic.getDecayDamage(rein) != 1) { + String ctiDecayAmountFormat = commaFormat.format(ReinforcementLogic.getDecayDamage(rein)); + sb.append(String.format("%s (Decayed x%s)", ChatColor.LIGHT_PURPLE, ctiDecayAmountFormat)); + } + AcidManager acidMan = Citadel.getInstance().getAcidManager(); + if (acidMan.isPossibleAcidBlock(e.getClickedBlock())) { + sb.append(ChatColor.GOLD); + long remainingTime = acidMan.getRemainingAcidMaturationTime(rein); + if (remainingTime == 0) { + sb.append("Acid ready"); + } else { + sb.append(formatProgress(rein.getCreationTime(), rein.getType().getAcidTime(), "acid timer")); + } + } + CitadelUtility.sendAndLog(player, ChatColor.GREEN, sb.toString().trim()); + } + if (showHolo) { + showHolo(rein, player); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = false) + public void onBlockBreak(BlockBreakEvent event) { + // refresh hologram + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(event.getBlock()); + if (rein == null) { + return; + } + Player player = event.getPlayer(); + boolean showHolo = Citadel.getInstance().getSettingManager().shouldShowHologramInCti(player.getUniqueId()); + if (!showHolo) { + return; + } + showHolo(rein, player); + } + + private static void showHolo(Reinforcement rein, Player player) { + HologramManager holoManager = Citadel.getInstance().getHologramManager(); + if (holoManager != null) { + holoManager.showInfoHolo(rein, player); + } + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/listener/RedstoneListener.java b/src/main/java/vg/civcraft/mc/citadel/listener/RedstoneListener.java new file mode 100644 index 00000000..9ac55d8d --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/listener/RedstoneListener.java @@ -0,0 +1,214 @@ +package vg.civcraft.mc.citadel.listener; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Openable; +import org.bukkit.block.data.type.Door; +import org.bukkit.block.data.type.Switch; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.api.BlockAPI; + +public class RedstoneListener implements Listener { + + private static boolean isAuthorizedPlayerNear(Reinforcement reinforcement, double distance) { + Location reinLocation = reinforcement.getLocation(); + + if (reinLocation.getWorld() == null) { + return false; + } + + // distance is radius, not diameter + double diameter = distance * 2; + Collection entities = reinLocation.getWorld().getNearbyEntities(reinLocation, diameter, diameter, + diameter, + e -> e instanceof Player && !e.isDead() + && reinforcement.hasPermission(e.getUniqueId(), Citadel.getInstance().getPermissionHandler().getDoors()) + && e.getLocation().distanceSquared(reinLocation) <= diameter * diameter); + return !entities.isEmpty(); + } + + private double maxRedstoneDistance; + + private Map> authorizations; + + public RedstoneListener(double maxRedstoneDistance) { + this.maxRedstoneDistance = maxRedstoneDistance; + this.authorizations = new HashMap<>(); + Bukkit.getScheduler().scheduleSyncRepeatingTask(Citadel.getInstance(), () -> authorizations.clear(), 1, 1); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void pistonExtend(BlockPistonExtendEvent bpee) { + for (Block block : bpee.getBlocks()) { + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(block); + if (reinforcement != null) { + bpee.setCancelled(true); + break; + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void pistonRetract(BlockPistonRetractEvent bpre) { + for (Block block : bpre.getBlocks()) { + Reinforcement reinforcement = ReinforcementLogic.getReinforcementProtecting(block); + if (reinforcement != null) { + bpre.setCancelled(true); + break; + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void pressButton(PlayerInteractEvent e) { + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + if (!(e.getClickedBlock().getBlockData() instanceof Switch)) { + return; + } + Switch button = (Switch) (e.getClickedBlock().getBlockData()); + Block buttonBlock = e.getClickedBlock(); + Block attachedBlock; + // needs special handling because buttons attached to ceiling and ground can be + // turned in which case the facing direction indicates this direction + switch (button.getAttachedFace()) { + case CEILING: + attachedBlock = e.getClickedBlock().getRelative(BlockFace.UP); + break; + case FLOOR: + attachedBlock = e.getClickedBlock().getRelative(BlockFace.DOWN); + break; + case WALL: + attachedBlock = e.getClickedBlock().getRelative(button.getFacing().getOppositeFace()); + break; + default: + Citadel.getInstance().getLogger().warning("Could not handle button face " + button.getAttachedFace()); + return; + } + // prepare all sides of button itself + setupAdjacentDoors(e.getPlayer(), buttonBlock, button.getFacing().getOppositeFace()); + // prepare all sides of the block attached to + setupAdjacentDoors(e.getPlayer(), attachedBlock, button.getFacing()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void redstonePower(BlockRedstoneEvent bre) { + // prevent doors from being opened by redstone + if (bre.getNewCurrent() <= 0 || bre.getOldCurrent() > 0) { + return; + } + Block block = bre.getBlock(); + BlockData blockData = block.getBlockData(); + if (!(blockData instanceof Openable)) { + return; + } + Openable openable = (Openable) blockData; + if (openable.isOpen()) { + return; + } + if (blockData instanceof Door) { + // we always store the activation for the lower half of a door + Door door = (Door) blockData; + if (door.getHalf() == Bisected.Half.TOP) { + block = block.getRelative(BlockFace.DOWN); + } + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + if (rein == null) { + return; + } + if (rein.isInsecure()) { + boolean playerNearby = isAuthorizedPlayerNear(rein, maxRedstoneDistance); + if (!playerNearby) { + bre.setNewCurrent(bre.getOldCurrent()); + } + return; + } + List playersActivating = authorizations.get(block.getLocation()); + if (playersActivating == null) { + bre.setNewCurrent(bre.getOldCurrent()); + return; + } + for (UUID uuid : playersActivating) { + if (rein.hasPermission(uuid, Citadel.getInstance().getPermissionHandler().getDoors())) { + // single valid perm is enough to open + return; + } + } + // noone valid found nearby, so deny + bre.setNewCurrent(bre.getOldCurrent()); + } + + private void setupAdjacentDoors(Player player, Block block, BlockFace skip) { + for (Entry entry : BlockAPI.getAllSidesMapped(block).entrySet()) { + if (entry.getKey() == skip) { + continue; + } + Block rel = entry.getValue(); + BlockData blockData = rel.getBlockData(); + if (!(blockData instanceof Openable)) { + continue; + } + Location locationToSave; + if (blockData instanceof Door) { + Door door = (Door) blockData; + if (door.getHalf() == Bisected.Half.TOP) { + // block is upper half of a door + locationToSave = rel.getRelative(BlockFace.DOWN).getLocation(); + } else { + // already the lower half of the door + locationToSave = rel.getLocation(); + } + } else { + locationToSave = rel.getLocation(); + } + List existingAuths = authorizations.computeIfAbsent(locationToSave, k -> new LinkedList<>()); + existingAuths.add(player.getUniqueId()); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void stepPressurePlate(PlayerInteractEvent e) { + if (e.getAction() != Action.PHYSICAL) { + return; + } + Material mat = e.getClickedBlock().getType(); + if (mat != Material.STONE_PRESSURE_PLATE && mat != Material.POLISHED_BLACKSTONE_PRESSURE_PLATE && + mat != Material.LIGHT_WEIGHTED_PRESSURE_PLATE && mat != Material.HEAVY_WEIGHTED_PRESSURE_PLATE + && !Tag.WOODEN_PRESSURE_PLATES.isTagged(mat)) { + return; + } + setupAdjacentDoors(e.getPlayer(), e.getClickedBlock(), BlockFace.EAST_SOUTH_EAST); + // block below + setupAdjacentDoors(e.getPlayer(), e.getClickedBlock().getRelative(BlockFace.DOWN), BlockFace.UP); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java b/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java new file mode 100644 index 00000000..67c6645b --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/model/AcidManager.java @@ -0,0 +1,56 @@ +package vg.civcraft.mc.citadel.model; + +import java.util.Collection; +import java.util.Set; +import java.util.TreeSet; + +import org.bukkit.Material; +import org.bukkit.block.Block; + +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; + +public class AcidManager { + + private Set material; + + public AcidManager(Collection acidMats) { + this.material = new TreeSet<>(acidMats); + } + + /** + * Checks if acid blocking is enabled for this reinforcement type + * + * @param acidBlock acid Reinforcement type to check for + * @param victim victim block Reinforcement type + * @return True if the reinforcement type can acid block other reinforcements + * and has an acid timer configured + */ + public boolean canAcidBlock(ReinforcementType acidBlock, ReinforcementType victim) { + return acidBlock.getAcidPriority() >= victim.getAcidPriority(); + } + + /** + * Gets remaining time needed to mature acid block in milli seconds. If the acid + * is ready 0 will be returned + * + * @param rein Reinforcement to check for + * @return Remaining time in milli seconds or 0 if the acid is ready + */ + public long getRemainingAcidMaturationTime(Reinforcement rein) { + long totalTime = rein.getType().getAcidTime(); + return Math.max(0, totalTime - rein.getAge()); + } + + /** + * Checks if the given valid is of a material registered as valid acid material + * + * @param b Block to check for + * @return True if the block material is suited for being an acid block + */ + public boolean isPossibleAcidBlock(Block b) { + if (b == null) { + return false; + } + return material.contains(b.getType()); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/model/CitadelChunkData.java b/src/main/java/vg/civcraft/mc/citadel/model/CitadelChunkData.java new file mode 100644 index 00000000..d812c729 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/model/CitadelChunkData.java @@ -0,0 +1,11 @@ +package vg.civcraft.mc.citadel.model; + +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableBasedBlockChunkMeta; + +public class CitadelChunkData extends TableBasedBlockChunkMeta { + + public CitadelChunkData(boolean isNew, CitadelDAO storage) { + super(isNew, storage); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/model/CitadelDAO.java b/src/main/java/vg/civcraft/mc/citadel/model/CitadelDAO.java new file mode 100644 index 00000000..d4f3dd35 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/model/CitadelDAO.java @@ -0,0 +1,335 @@ +package vg.civcraft.mc.citadel.model; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.Callable; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.inventory.meta.ItemMeta; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementTypeManager; +import vg.civcraft.mc.civmodcore.CivModCorePlugin; +import vg.civcraft.mc.civmodcore.dao.ManagedDatasource; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.XZWCoord; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.BlockBasedChunkMeta; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableBasedBlockChunkMeta; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableStorageEngine; +import vg.civcraft.mc.civmodcore.locations.global.WorldIDManager; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +public class CitadelDAO extends TableStorageEngine { + + public CitadelDAO(Logger logger, ManagedDatasource db) { + super(logger, db); + } + + @Override + public void registerMigrations() { + db.registerMigration(15, false, + "CREATE TABLE IF NOT EXISTS reinforcement (rein_id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY," + + "x int(11) NOT NULL, y int(11) NOT NULL, z int(11) NOT NULL, chunk_x int(11) NOT NULL, chunk_z int(11) NOT NULL," + + "world varchar(255) NOT NULL, material_id int(11) NOT NULL, durability varchar(10) NOT NULL, insecure tinyint(1) NOT NULL," + + "group_id int(11) NOT NULL, maturation_time int(11) NOT NULL, rein_type_id int(11) NOT NULL, lore varchar(255) DEFAULT NULL," + + "acid_time int(11) NOT NULL)"); + db.registerMigration(16, false, new Callable() { + + @Override + public Boolean call() throws Exception { + try (Connection insertConn = db.getConnection(); + PreparedStatement selectRein = insertConn.prepareStatement( + "select x,y,z,chunk_x,chunk_z,world,material_id,durability,insecure,group_id,maturation_time,lore from reinforcement order by rein_id asc"); + ResultSet rs = selectRein.executeQuery()) { + PreparedStatement insertRein = insertConn.prepareStatement( + "insert into ctdl_reinforcements (chunk_x, chunk_z, world_id, x_offset, y, z_offset, type_id, " + + "health, group_id, insecure, creation_time) values(?,?,?, ?,?,?, ?,?,?,?,?);"); + try (PreparedStatement deleteExisting = insertConn + .prepareStatement("delete from ctdl_reinforcements")) { + // in case this migration failed before some of the data might already have + // migrated, which we want to undo + deleteExisting.execute(); + } + + WorldIDManager worldMan = CivModCorePlugin.getInstance().getWorldIdManager(); + Map> reinTypes = new TreeMap<>(); + for (ReinforcementType type : Citadel.getInstance().getReinforcementTypeManager().getAllTypes()) { + List withType = reinTypes.computeIfAbsent(type.getLegacyId(), + s -> new ArrayList<>()); + withType.add(type); + } + int batchCounter = 0; + while (rs.next()) { + byte x = (byte) BlockBasedChunkMeta.modulo(rs.getInt(1)); + short y = (short) rs.getInt(2); + byte z = (byte) BlockBasedChunkMeta.modulo(rs.getInt(3)); + int chunkX = rs.getInt(4); + int chunkZ = rs.getInt(5); + String worldName = rs.getString(6); + int materialId = rs.getInt(7); + String durability = rs.getString(8); + boolean insecure = rs.getBoolean(9); + int groupId = rs.getInt(10); + int maturationTime = rs.getInt(11); + String lore = rs.getString(12); + + short worldID = worldMan.getInternalWorldIdByName(worldName); + if (worldID == -1) { + logger.severe("Failed to find world id for world with name " + worldName); + return false; + } + float healthFloat = Float.parseFloat(durability); + List withType = reinTypes.get(materialId); + if (withType == null) { + logger.severe( + "Failed to find material mapping for reinforcement with material id " + materialId); + return false; + } + ReinforcementType type = null; + if (withType.size() == 1) { + type = withType.get(0); + } else { + boolean hasLore = lore != null; + for (ReinforcementType compType : withType) { + ItemMeta meta = compType.getItem().getItemMeta(); + if (hasLore == meta.hasLore()) { + if (!hasLore || meta.getLore().get(0).equals(lore)) { + type = compType; + break; + } + } + } + if (type == null) { + logger.severe("Failed to find material mapping for reinforcement with material id " + + materialId + " and lore " + lore); + return false; + } + } + // previously we stored the timestamp at which the reinforcement will be mature + // in minutes since unix epoch + // No, I do not know why + long creationTime = maturationTime - (type.getMaturationTime() / 60_000); + // some rows have a maturation time of 0, no idea why + creationTime = Math.max(creationTime, 1); + creationTime *= 60_000; + + insertRein.setInt(1, chunkX); + insertRein.setInt(2, chunkZ); + insertRein.setShort(3, worldID); + insertRein.setByte(4, x); + insertRein.setShort(5, y); + insertRein.setByte(6, z); + insertRein.setShort(7, type.getID()); + insertRein.setFloat(8, healthFloat); + insertRein.setInt(9, groupId); + insertRein.setBoolean(10, insecure); + insertRein.setTimestamp(11, new Timestamp(creationTime)); + insertRein.addBatch(); + if (batchCounter > 10000) { + batchCounter = 0; + insertRein.executeBatch(); + } + batchCounter++; + } + insertRein.executeBatch(); + } + return true; + } + }, "create table if not exists ctdl_reinforcements (chunk_x int not null, chunk_z int not null, world_id smallint unsigned not null, " + + "x_offset tinyint unsigned not null, y smallint not null, z_offset tinyint unsigned not null, " + + "type_id smallint unsigned not null, health float not null, group_id int not null, insecure boolean not null default false," + + "creation_time timestamp not null default now(), index reinChunkLookUp(chunk_x, chunk_z, world_id), primary key " + + "(chunk_x, chunk_z, world_id, x_offset, y ,z_offset))"); + } + + /** + * Gets a single reinforcement at the given location without inserting it into + * the tracking + * + * @return Reinforcement loaded from the database + */ + @Override + public Reinforcement getForLocation(int x, int y, int z, short worldID, short pluginID) { + int chunkX = BlockBasedChunkMeta.toChunkCoord(x); + int chunkZ = BlockBasedChunkMeta.toChunkCoord(z); + ReinforcementTypeManager typeMan = Citadel.getInstance().getReinforcementTypeManager(); + try (Connection insertConn = db.getConnection(); + PreparedStatement selectRein = insertConn + .prepareStatement("select type_id, group_id, creation_time, health, insecure " + + "from ctdl_reinforcements where chunk_x = ? and chunk_z = ? and world_id = ? and x_offset = ? and y = ? and z_offset = ?;");) { + selectRein.setInt(1, chunkX); + selectRein.setInt(2, chunkZ); + selectRein.setShort(3, worldID); + selectRein.setByte(4, (byte) BlockBasedChunkMeta.modulo(x)); + selectRein.setShort(5, (short) y); + selectRein.setByte(6, (byte) BlockBasedChunkMeta.modulo(z)); + try (ResultSet rs = selectRein.executeQuery()) { + if (!rs.next()) { + return null; + } + short typeID = rs.getShort(1); + ReinforcementType type = typeMan.getById(typeID); + if (type == null) { + logger.log(Level.SEVERE, "Failed to load reinforcement with type id " + typeID); + return null; + } + int groupID = rs.getInt(2); + long creationTime = rs.getTimestamp(3).getTime(); + float health = rs.getFloat(4); + boolean insecure = rs.getBoolean(5); + World world = CivModCorePlugin.getInstance().getWorldIdManager().getWorldByInternalID(worldID); + Location loc = new Location(world, x, y, z); + return new Reinforcement(loc, type, groupID, creationTime, health, insecure, false); + } + } catch (SQLException e) { + logger.log(Level.SEVERE, "Failed to load reinforcement from db: ", e); + return null; + } + } + + @Override + public void insert(Reinforcement data, XZWCoord coord) { + try (Connection insertConn = db.getConnection(); + PreparedStatement insertRein = insertConn.prepareStatement( + "insert into ctdl_reinforcements (chunk_x, chunk_z, world_id, x_offset, y, z_offset, type_id, " + + "health, group_id, insecure, creation_time) values(?,?,?, ?,?,?, ?,?,?,?,?);");) { + insertRein.setInt(1, coord.getX()); + insertRein.setInt(2, coord.getZ()); + insertRein.setShort(3, coord.getWorldID()); + insertRein.setByte(4, (byte) BlockBasedChunkMeta.modulo(data.getLocation().getBlockX())); + insertRein.setShort(5, (short) data.getLocation().getBlockY()); + insertRein.setByte(6, (byte) BlockBasedChunkMeta.modulo(data.getLocation().getBlockZ())); + insertRein.setShort(7, data.getType().getID()); + insertRein.setFloat(8, data.getHealth()); + insertRein.setInt(9, data.getGroupId()); + insertRein.setBoolean(10, data.isInsecure()); + insertRein.setTimestamp(11, new Timestamp(data.getCreationTime())); + insertRein.execute(); + } catch (SQLException e) { + logger.log(Level.SEVERE, "Failed to insert reinforcement into db: ", e); + } + } + + @Override + public void update(Reinforcement data, XZWCoord coord) { + try (Connection insertConn = db.getConnection(); + PreparedStatement updateRein = insertConn.prepareStatement( + "update ctdl_reinforcements set type_id = ?, health = ?, group_id = ?, insecure = ?, creation_time = ? where " + + "chunk_x = ? and chunk_z = ? and world_id = ? and x_offset = ? and y = ? and z_offset = ?;");) { + updateRein.setShort(1, data.getType().getID()); + updateRein.setFloat(2, data.getHealth()); + updateRein.setInt(3, data.getGroupId()); + updateRein.setBoolean(4, data.isInsecure()); + updateRein.setTimestamp(5, new Timestamp(data.getCreationTime())); + updateRein.setInt(6, coord.getX()); + updateRein.setInt(7, coord.getZ()); + updateRein.setShort(8, coord.getWorldID()); + updateRein.setByte(9, (byte) BlockBasedChunkMeta.modulo(data.getLocation().getBlockX())); + updateRein.setShort(10, (short) data.getLocation().getBlockY()); + updateRein.setByte(11, (byte) BlockBasedChunkMeta.modulo(data.getLocation().getBlockZ())); + updateRein.execute(); + } catch (SQLException e) { + logger.log(Level.SEVERE, "Failed to update reinforcement in db: ", e); + } + } + + @Override + public void delete(Reinforcement data, XZWCoord coord) { + try (Connection insertConn = db.getConnection(); + PreparedStatement deleteRein = insertConn.prepareStatement( + "delete from ctdl_reinforcements where chunk_x = ? and chunk_z = ? and world_id = ? and " + + "x_offset = ? and y = ? and z_offset = ?;");) { + deleteRein.setInt(1, coord.getX()); + deleteRein.setInt(2, coord.getZ()); + deleteRein.setShort(3, coord.getWorldID()); + deleteRein.setByte(4, (byte) BlockBasedChunkMeta.modulo(data.getLocation().getBlockX())); + deleteRein.setShort(5, (short) data.getLocation().getBlockY()); + deleteRein.setByte(6, (byte) BlockBasedChunkMeta.modulo(data.getLocation().getBlockZ())); + deleteRein.execute(); + } catch (SQLException e) { + logger.log(Level.SEVERE, "Failed to delete reinforcement from db: ", e); + } + } + + @Override + public void fill(TableBasedBlockChunkMeta chunkData, Consumer insertFunction) { + int preMultipliedX = chunkData.getChunkCoord().getX() * 16; + int preMultipliedZ = chunkData.getChunkCoord().getZ() * 16; + ReinforcementTypeManager typeMan = Citadel.getInstance().getReinforcementTypeManager(); + World world = chunkData.getChunkCoord().getWorld(); + Set groupIDs = new TreeSet<>(); + try (Connection insertConn = db.getConnection(); + PreparedStatement selectRein = insertConn.prepareStatement( + "select x_offset, y, z_offset, type_id, group_id, creation_time, health, insecure " + + "from ctdl_reinforcements where chunk_x = ? and chunk_z = ? and world_id = ?;");) { + selectRein.setInt(1, chunkData.getChunkCoord().getX()); + selectRein.setInt(2, chunkData.getChunkCoord().getZ()); + selectRein.setShort(3, chunkData.getChunkCoord().getWorldID()); + try (ResultSet rs = selectRein.executeQuery()) { + while (rs.next()) { + int xOffset = rs.getByte(1); + int x = xOffset + preMultipliedX; + int y = rs.getShort(2); + int zOffset = rs.getByte(3); + int z = zOffset + preMultipliedZ; + Location location = new Location(world, x, y, z); + short typeID = rs.getShort(4); + ReinforcementType type = typeMan.getById(typeID); + if (type == null) { + logger.log(Level.SEVERE, "Failed to load reinforcement with type id " + typeID); + continue; + } + int groupID = rs.getInt(5); + groupIDs.add(groupID); + long creationTime = rs.getTimestamp(6).getTime(); + float health = rs.getFloat(7); + boolean insecure = rs.getBoolean(8); + Reinforcement rein = new Reinforcement(location, type, groupID, creationTime, health, insecure, + false); + insertFunction.accept(rein); + } + } + } catch (SQLException e) { + logger.log(Level.SEVERE, "Failed to load reinforcement from db: ", e); + } + groupIDs.forEach(GroupAPI::requestToBeCached); + } + + @Override + public Collection getAllDataChunks() { + List result = new ArrayList<>(); + try (Connection insertConn = db.getConnection(); + PreparedStatement selectChunks = insertConn.prepareStatement( + "select chunk_x, chunk_z, world_id from ctdl_reinforcements group by chunk_x, chunk_z, world_id"); + ResultSet rs = selectChunks.executeQuery()) { + while (rs.next()) { + int chunkX = rs.getInt(1); + int chunkZ = rs.getInt(2); + short worldID = rs.getShort(3); + result.add(new XZWCoord(chunkX, chunkZ, worldID)); + } + } catch (SQLException e) { + logger.log(Level.SEVERE, "Failed to select populated chunks from db: ", e); + } + return result; + } + + @Override + public boolean stayLoaded() { + return false; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/model/CitadelSettingManager.java b/src/main/java/vg/civcraft/mc/citadel/model/CitadelSettingManager.java new file mode 100644 index 00000000..f7752ab5 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/model/CitadelSettingManager.java @@ -0,0 +1,219 @@ +package vg.civcraft.mc.citadel.model; + +import java.text.DecimalFormat; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.listener.ModeListener; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.playersettings.PlayerSettingAPI; +import vg.civcraft.mc.civmodcore.playersettings.gui.MenuSection; +import vg.civcraft.mc.civmodcore.playersettings.impl.BooleanSetting; +import vg.civcraft.mc.civmodcore.playersettings.impl.BoundedIntegerSetting; +import vg.civcraft.mc.civmodcore.playersettings.impl.CommandReplySetting; +import vg.civcraft.mc.civmodcore.playersettings.impl.DecimalFormatSetting; +import vg.civcraft.mc.civmodcore.playersettings.impl.DisplayLocationSetting; +import vg.civcraft.mc.civmodcore.playersettings.impl.DisplayLocationSetting.DisplayLocation; +import vg.civcraft.mc.civmodcore.playersettings.impl.StringSetting; + +public class CitadelSettingManager { + + private BooleanSetting byPass; + private BooleanSetting informationMode; + private BooleanSetting showChatMsgInCti; + private BooleanSetting showHologramInCti; + private BooleanSetting easyMode; + private BooleanSetting ctoDisableCti; + private BooleanSetting ctoDisableCtb; + + private BoundedIntegerSetting hologramDuration; + + private CommandReplySetting ctiNotReinforced; + // private CommandReplySetting ctiAllied; + private CommandReplySetting ctiEnemy; + // private CommandReplySetting modeSwitch; + private DecimalFormatSetting ctiPercentageHealth; + private DecimalFormatSetting ctiReinforcementHealth; + private DecimalFormatSetting ctiDecayMultiplier; + private StringSetting ctiDecay; + private DisplayLocationSetting ctbLocationSetting; + private DisplayLocationSetting modeLocationSetting; + private DisplayLocationSetting ctiLocationSetting; + + public CitadelSettingManager() { + initSettings(); + } + + public DisplayLocationSetting getBypassLocationSetting() { + return ctbLocationSetting; + } + + public DisplayLocationSetting getModeLocationSetting() { + return modeLocationSetting; + } + + public DisplayLocationSetting getInformationLocationSetting() { + return ctiLocationSetting; + } + + public BooleanSetting getBypass() { + return byPass; + } + + public BooleanSetting getInformationMode() { + return informationMode; + } + + public BooleanSetting getEasyMode() { + return easyMode; + } + + public boolean shouldShowChatInCti(UUID uuid) { + return showChatMsgInCti.getValue(uuid); + } + + public boolean shouldCtoDisableCti(UUID uuid) { + return ctoDisableCti.getValue(uuid); + } + + public boolean shouldCtoDisableCtb(UUID uuid) { + return ctoDisableCtb.getValue(uuid); + } + + public boolean shouldShowHologramInCti(UUID uuid) { + return showHologramInCti.getValue(uuid); + } + + public boolean isInEasyMode(UUID uuid) { + return easyMode.getValue(uuid); + } + + public int getHologramDuration(UUID uuid) { + return hologramDuration.getValue(uuid); + } + + void initSettings() { + MenuSection menu = PlayerSettingAPI.getMainMenu().createMenuSection("Citadel", + "Citadel and reinforcement related settings", new ItemStack(Material.IRON_INGOT)); + byPass = new BooleanSetting(Citadel.getInstance(), true, "Bypass", "citadelBypass", + "Allows you to bypass reinforcements you have permission for and break them in a single break"); + PlayerSettingAPI.registerSetting(byPass, menu); + + informationMode = new BooleanSetting(Citadel.getInstance(), false, "Information mode", "citadelInformationMode", + "Displays information about reinforced blocks when interacting with them"); + PlayerSettingAPI.registerSetting(informationMode, menu); + + easyMode = new BooleanSetting(Citadel.getInstance(), false, "Easy reinforcing mode", "citadelEasyMode", + "Allows automatically reinforcing to your default group with reinforcement materials from your off hand"); + PlayerSettingAPI.registerSetting(easyMode, menu); + + showChatMsgInCti = new BooleanSetting(Citadel.getInstance(), true, "Show chat message in information mode", + "citadelCtiShowChatMsg", "Should chat messages be shown in reinforcement information mode"); + PlayerSettingAPI.registerSetting(showChatMsgInCti, menu); + + showHologramInCti = new BooleanSetting(Citadel.getInstance(), true, "Show holograms in information mode", + "citadelCtiShowHologram", "Should holograms be shown in reinforcement information mode"); + PlayerSettingAPI.registerSetting(showHologramInCti, menu); + + hologramDuration = new BoundedIntegerSetting(Citadel.getInstance(), 5000, "Hologram visibility duration", + "citadelHologramCullTimer", new ItemStack(Material.CLOCK), + "How long should holograms in information mode remain visible, measured in milli seconds", false, 1000, + 30000); + PlayerSettingAPI.registerSetting(hologramDuration, menu); + + ctbLocationSetting = new DisplayLocationSetting(Citadel.getInstance(), DisplayLocation.NONE, "Bypass display location" + , "citadelBypassDisplayLocation", new ItemStack(Material.GOLDEN_PICKAXE), "bypass"); + PlayerSettingAPI.registerSetting(ctbLocationSetting, menu); + + ctiLocationSetting = new DisplayLocationSetting(Citadel.getInstance(), DisplayLocation.SIDEBAR, "Information mode display location" + , "citadelInfoModeDisplayLocation", new ItemStack(Material.BOOKSHELF), "reinforcement info mode"); + PlayerSettingAPI.registerSetting(ctiLocationSetting, menu); + + modeLocationSetting = new DisplayLocationSetting(Citadel.getInstance(), DisplayLocation.SIDEBAR, "Citadel mode display location" + , "citadelReinModeDisplayLocation", new ItemStack(Material.NETHER_STAR), "Citadel mode"); + PlayerSettingAPI.registerSetting(modeLocationSetting, menu); + + ctoDisableCtb = new BooleanSetting(Citadel.getInstance(), false, "/cto disable /ctb", + "citadelCtoDisableCtb", "Should /cto disable Bypass mode (/ctb)"); + PlayerSettingAPI.registerSetting(ctoDisableCtb, menu); + + ctoDisableCti = new BooleanSetting(Citadel.getInstance(), true, "/cto disable /cti", + "citadelCtoDisableCti", "Should /cto disable Information mode (/cti)"); + PlayerSettingAPI.registerSetting(ctoDisableCti, menu); + + MenuSection commandSection = menu.createMenuSection("Command replies", + "Allows configuring the replies received when interacting with reinforcements or Citadel commands. For advanced users only"); + + ctiNotReinforced = new CommandReplySetting(Citadel.getInstance(), ChatColor.YELLOW + "Not reinforced", + "CTI Message Unreinforced", "citadel_cti_unreinforced", new ItemStack(Material.YELLOW_TERRACOTTA), + "The message received when interacting with an unreinforced block in Information Mode"); + PlayerSettingAPI.registerSetting(ctiNotReinforced, commandSection); + + ctiPercentageHealth = new DecimalFormatSetting(Citadel.getInstance(), new DecimalFormat("#.##"), + "Reinforcement Percentage Health Format", "citadel_cti_percentage_health", + new ItemStack(Material.KNOWLEDGE_BOOK), + "Decimal format used for displaying a percentage value for reinforcement health", 100.0 / 3); + PlayerSettingAPI.registerSetting(ctiPercentageHealth, commandSection); + + ctiReinforcementHealth = new DecimalFormatSetting(Citadel.getInstance(), new DecimalFormat("0"), + "Reinforcement Health Format", "citadel_cti_health", new ItemStack(Material.KNOWLEDGE_BOOK), + "Decimal format used for displaying a reinforcements health", 100.0 / 3); + PlayerSettingAPI.registerSetting(ctiReinforcementHealth, commandSection); + + ctiDecayMultiplier = new DecimalFormatSetting(Citadel.getInstance(), new DecimalFormat("#.##"), + "Reinforcement Decay Multiplier Format", "citadel_cti_decay_multiplier", + new ItemStack(Material.KNOWLEDGE_BOOK), + "Decimal format used for displaying the decay multiplier of a reinforcement", 100.0 / 3); + PlayerSettingAPI.registerSetting(ctiDecayMultiplier, commandSection); + + ctiDecay = new StringSetting(Citadel.getInstance(), " (Decayed x%%decay%%)", + "Reinforcement Decay Format", "citadel_cti_decay", new ItemStack(Material.KNOWLEDGE_BOOK), + "String format used for displaying the decay of a reinforcement"); + PlayerSettingAPI.registerSetting(ctiDecay, commandSection); + + ctiEnemy = new CommandReplySetting(Citadel.getInstance(), + ChatColor.RED + "Reinforced at %%health_color%%%%perc_health%%% (%%health%%/%%max_health%%)" + + ChatColor.RED + " health with " + ChatColor.AQUA + "%%type%%" + ChatColor.LIGHT_PURPLE + "%%decay_string%%", + "CTI Message Enemy", "citadel_cti_enemy", new ItemStack(Material.RED_TERRACOTTA), + "The message received when interacting with enemy reinforcements"); + ctiEnemy.registerArgument("perc_health", "33.33", "the percentage health of the reinforcement"); + ctiEnemy.registerArgument("max_health", "50", "the maximum health of the reinforcement"); + ctiEnemy.registerArgument("health", "25", "the current health of the reinforcement"); + ctiEnemy.registerArgument("type", "Stone", "the type of the reinforcement"); + ctiEnemy.registerArgument("health_color", ModeListener.getDamageColor(0.5).toString(), + "a color representing the reinforcement health"); + ctiEnemy.registerArgument("decay_string", "", "the decay of the reinforcement"); + PlayerSettingAPI.registerSetting(ctiEnemy, commandSection); + } + + public void sendCtiEnemyMessage(Player player, Reinforcement reinforcement) { + Map args = new TreeMap<>(); + ReinforcementType type = reinforcement.getType(); + String percFormat = ctiPercentageHealth.getValue(player) + .format(reinforcement.getHealth() / type.getHealth() * 100); + args.put("perc_health", percFormat); + DecimalFormat reinHealthFormatter = ctiReinforcementHealth.getValue(player); + args.put("health", reinHealthFormatter.format(reinforcement.getHealth())); + args.put("max_health", reinHealthFormatter.format(type.getHealth())); + args.put("type", type.getName()); + args.put("health_color", + ModeListener.getDamageColor(reinforcement.getHealth() / type.getHealth()).toString()); + if (ReinforcementLogic.getDecayDamage(reinforcement) != 1) { + String ctiDecayAmountFormat = ctiDecayMultiplier.getValue(player).format(ReinforcementLogic.getDecayDamage(reinforcement)); + String ctiDecayFormat = ctiDecay.getValue(player).replaceAll("%%decay%%", ctiDecayAmountFormat); + args.put("decay_string", ctiDecayFormat); + } else { + args.put("decay_string",""); + } + CitadelUtility.sendAndLog(player, ChatColor.RESET, ctiEnemy.formatReply(player.getUniqueId(), args)); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/model/HologramManager.java b/src/main/java/vg/civcraft/mc/citadel/model/HologramManager.java new file mode 100644 index 00000000..085d5d96 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/model/HologramManager.java @@ -0,0 +1,180 @@ +package vg.civcraft.mc.citadel.model; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.Vector; + +import com.gmail.filoghost.holographicdisplays.api.Hologram; +import com.gmail.filoghost.holographicdisplays.api.HologramsAPI; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.listener.ModeListener; +public class HologramManager { + + // distance from center to diagonal corner is 0.5 * sqrt(2) and we add 10 % for + // good measure + private static final double HOLOOFFSET = 0.55 * Math.sqrt(2); + + private Map> holograms; + private Set activeHolos; + private CitadelSettingManager settingMan; + + public HologramManager(CitadelSettingManager settingMan) { + this.holograms = new HashMap<>(); + this.activeHolos = new HashSet<>(); + this.settingMan = settingMan; + new BukkitRunnable() { + + @Override + public void run() { + updateHolograms(); + } + + }.runTaskTimer(Citadel.getInstance(), 2L, 2L); + } + + public void showInfoHolo(Reinforcement rein, Player player) { + Map locationSpecificHolos = holograms.get(rein.getLocation()); + if (locationSpecificHolos == null) { + locationSpecificHolos = new TreeMap<>(); + holograms.put(rein.getLocation(), locationSpecificHolos); + } + PlayerHolo holo = locationSpecificHolos.get(player.getUniqueId()); + if (holo == null) { + holo = new PlayerHolo(player, rein); + locationSpecificHolos.put(player.getUniqueId(), holo); + } + activeHolos.add(holo); + holo.show(); + } + + private static Location getHoloLocation(Reinforcement rein, Player player) { + Location baseLoc = rein.getBlockCenter(); + baseLoc = baseLoc.add(0, 0.5, 0); + Vector vector = player.getEyeLocation().toVector(); + vector.subtract(baseLoc.toVector()); + // vector is now the offset from the reinforcement to the player and we now move + // towards the player so the hologram isn't inside the block + vector.normalize(); + // holoOffSet is a good distance to ensure we fully move the hologram out of the + // block + vector.multiply(HOLOOFFSET); + baseLoc.add(vector); + return baseLoc; + } + + private void updateHolograms() { + for (Iterator iter = activeHolos.iterator(); iter.hasNext();) { + PlayerHolo holo = iter.next(); + if (!holo.update()) { + iter.remove(); + } + } + } + + private class PlayerHolo { + + private Player player; + private Hologram hologram; + private Reinforcement reinforcement; + private long timeStamp; + private boolean hasPermission; + private Location cachedPlayerLocation; + private double cachedHealth; + private long cullDelay; + + public PlayerHolo(Player player, Reinforcement reinforcement) { + this.player = player; + this.reinforcement = reinforcement; + this.timeStamp = System.currentTimeMillis(); + this.cullDelay = settingMan.getHologramDuration(player.getUniqueId()); + // we intentionally cache permission to avoid having to look it up often + // showing a bit too much information if the player gets kicked while a holo is + // already visible does not matter + this.hasPermission = reinforcement.hasPermission(player, Citadel.getInstance().getPermissionHandler().getInfo()); + } + + void show() { + refreshTimestamp(); + if (hologram != null) { + return; + } + hologram = HologramsAPI.createHologram(Citadel.getInstance(), getHoloLocation(reinforcement, player)); + cachedPlayerLocation = player.getLocation(); + hologram.getVisibilityManager().setVisibleByDefault(false); + hologram.getVisibilityManager().showTo(player); + updateText(); + } + + boolean update() { + if (System.currentTimeMillis() - timeStamp > cullDelay) { + delete(); + return false; + } + if (reinforcement.isBroken()) { + delete(); + return false; + } + updateLocation(); + updateText(); + return true; + } + + void updateLocation() { + Location current = player.getLocation(); + // Location.equals would also check pitch/yaw + if (current.getBlockX() == cachedPlayerLocation.getBlockX() && current.getBlockY() == cachedPlayerLocation.getBlockY() + && current.getBlockZ() == cachedPlayerLocation.getBlockZ()) { + return; + } + Location updated = getHoloLocation(reinforcement, player); + hologram.teleport(updated); + } + + void refreshTimestamp() { + this.timeStamp = System.currentTimeMillis(); + } + + void updateText() { + if (reinforcement.getHealth() != cachedHealth || hologram.size() == 0) { + if (hologram.size() > 0) { + hologram.removeLine(0); + } + hologram.insertTextLine(0, ModeListener.formatHealth(reinforcement)); + cachedHealth = reinforcement.getHealth(); + } + if (!hasPermission) { + return; + } + if (hologram.size() == 1) { + // not initialized yet + hologram.insertTextLine(1, ChatColor.LIGHT_PURPLE + reinforcement.getGroup().getName()); + hologram.insertTextLine(2, ChatColor.AQUA + reinforcement.getType().getName()); + } + if (hologram.size() == 4) { + hologram.removeLine(3); + } + if (!reinforcement.isMature()) { + hologram.insertTextLine(3, ModeListener.formatProgress(reinforcement.getCreationTime(), + reinforcement.getType().getMaturationTime(), "")); + } + } + + void delete() { + hologram.delete(); + hologram = null; + } + + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/model/Reinforcement.java b/src/main/java/vg/civcraft/mc/citadel/model/Reinforcement.java new file mode 100644 index 00000000..28447dbf --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/model/Reinforcement.java @@ -0,0 +1,210 @@ +package vg.civcraft.mc.citadel.model; + +import java.util.Random; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.locations.chunkmeta.block.table.TableBasedDataObject; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.core.PermissionType; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +public class Reinforcement extends TableBasedDataObject { + + private static Random rng = new Random(); + + private long creationTime; + private ReinforcementType type; + private float health; + private int groupId; + private boolean insecure; + + public Reinforcement(Location loc, ReinforcementType type, Group group) { + this(loc, type, group.getPrimaryId(), System.currentTimeMillis(), type.getHealth(), false, true); + } + + public Reinforcement(Location loc, ReinforcementType type, int groupID, long creationTime, float health, + boolean insecure, boolean isNew) { + super(loc, isNew); + if (type == null) { + throw new IllegalArgumentException("Reinforcement type for reinforcement can not be null"); + } + this.type = type; + this.creationTime = creationTime; + this.health = health; + this.groupId = groupID; + this.insecure = insecure; + } + + /** + * @return Age of this reinforcement in milli seconds + */ + public long getAge() { + return System.currentTimeMillis() - creationTime; + } + + /** + * @return Unix time in ms when the reinforcement was created + */ + public long getCreationTime() { + return creationTime; + } + + /** + * @return Group this reinforcement is under + */ + public Group getGroup() { + return GroupAPI.getGroup(groupId); + } + + /** + * @return Id of the group this reinforcement is under + */ + public int getGroupId() { + return groupId; + } + + /** + * @return Current health + */ + public float getHealth() { + return health; + } + + /** + * Gets the center of the block at the location of this reinforcement. + * getLocation() will return the integer coordinates of the reinforcement while + * this location is offset by 0.5 to the center + * + * @return Center of the block + */ + public Location getBlockCenter() { + Location copy = location.clone(); + copy.add(0.5, 0.5, 0.5); + return copy; + } + + /** + * @return Type of this reinforcement + */ + public ReinforcementType getType() { + return type; + } + + /** + * Checks whether the player with the given UUID has the given permission on the group this reinforcement belongs to + * @param uuid UUID of the player to check permissions for, not null + * @param permission Permission to check, not null + * @return True if the player has the given permission on this reinforcements group, false otherwise + */ + public boolean hasPermission(UUID uuid, PermissionType permission) { + if (permission == null) { + throw new IllegalArgumentException("PermissionType may not be null"); + } + Group g = getGroup(); + if (g == null) { + return false; + } + return GroupAPI.hasPermission(uuid, g, permission); + } + + /** + * Checks whether the given player has the given permission on the group this reinforcement belongs to + * @param player Player to check permissions for, not null + * @param permission Permission to check, not null + * @return True if the player has the given permission on this reinforcements group, false otherwise + */ + public boolean hasPermission(Player player, PermissionType permission) { + return hasPermission(player.getUniqueId(), permission); + } + + /** + * After being broken reinforcements will no longer be accessible via lookup, + * but may still persist in the cache until their deletion is persisted into the + * database + * + * @return True if the reinforcements health is equal to or less than 0 + */ + public boolean isBroken() { + return health <= 0; + } + + /** + * @return Whether the reinforcement is insecure, meaning it ignores Citadel + * restrictions on hoppers etc. + */ + public boolean isInsecure() { + return insecure; + } + + /** + * @return Whether reinforcement is mature, meaning the maturation time + * configured for this reinforcements type has passed since the + * reinforcements creation + */ + public boolean isMature() { + return System.currentTimeMillis() - creationTime > type.getMaturationTime(); + } + + public void setGroup(Group group) { + if (group == null) { + throw new IllegalArgumentException("Group can not be set to null for a reinforcement"); + } + this.groupId = group.getPrimaryId(); + setDirty(); + } + + /** + * Sets the health of a reinforcement. + * + * @param health new health value + */ + public void setHealth(float health) { + this.health = health; + if (health <= 0) { + if (getOwningCache() != null) { + getOwningCache().remove(this); + } + } + else { + setDirty(); + } + } + + public void setType(ReinforcementType type) { + this.type = type; + setDirty(); + } + + /** + * Switches the insecure flag of the reinforcement + */ + public void toggleInsecure() { + insecure = !insecure; + setDirty(); + } + + /** + * Resets the timestamp at which the reinforcement was created to the current one + */ + public void resetCreationTime() { + this.creationTime = System.currentTimeMillis(); + } + + /** + * Does a randomness check based on current reinforcement health and + * reinforcement type to decide whether the reinforcement item should be + * returned + * + * @return Whether to return the reinforcement item or not + */ + public boolean rollForItemReturn() { + double baseChance = type.getReturnChance(); + double relativeHealth = health / type.getHealth(); + baseChance *= relativeHealth; + return rng.nextDouble() <= baseChance; + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/AbstractPlayerState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/AbstractPlayerState.java new file mode 100644 index 00000000..74c5036e --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/AbstractPlayerState.java @@ -0,0 +1,111 @@ +package vg.civcraft.mc.citadel.playerstate; + +import java.util.HashMap; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.events.ReinforcedBlockBreak; +import vg.civcraft.mc.citadel.events.ReinforcementBypassEvent; +import vg.civcraft.mc.citadel.events.ReinforcementDamageEvent; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.playersettings.PlayerSettingAPI; +import vg.civcraft.mc.civmodcore.playersettings.impl.BooleanSetting; +import vg.civcraft.mc.civmodcore.util.DelayedItemDrop; + +public abstract class AbstractPlayerState { + + protected UUID uuid; + + public AbstractPlayerState(Player p) { + if (p == null) { + throw new IllegalArgumentException("Player for player state can not be null"); + } + this.uuid = p.getUniqueId(); + } + + public abstract String getName(); + + public abstract void handleBlockPlace(BlockPlaceEvent e); + + public void handleBreakBlock(BlockBreakEvent e) { + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(e.getBlock()); + if (rein == null) { + // no reinforcement, normal break which we dont care about + return; + } + if (CitadelUtility.isPlant(e.getBlock())) { + if (rein.hasPermission(e.getPlayer(), Citadel.getInstance().getPermissionHandler().getCrops()) + && !e.getBlock().getLocation().equals(rein.getLocation())) { + // allow, because player has crop permission and the only reinforcement + // protecting is in the soil + return; + } + } + boolean hasAccess = rein.hasPermission(e.getPlayer(), Citadel.getInstance().getPermissionHandler().getBypass()); + BooleanSetting setting = (BooleanSetting) PlayerSettingAPI.getSetting("citadelBypass"); + boolean hasByPass = setting.getValue(e.getPlayer()); + if (hasAccess && hasByPass) { + ReinforcementBypassEvent bypassEvent = new ReinforcementBypassEvent(e.getPlayer(), rein); + Bukkit.getPluginManager().callEvent(bypassEvent); + if (bypassEvent.isCancelled()) { + e.setCancelled(true); + return; + } + if (rein.rollForItemReturn()) { + giveReinforcement(e.getBlock().getLocation().clone().add(0.5, 0.5, 0.5), e.getPlayer(), rein.getType()); + } + rein.setHealth(-1); + return; + } + if (hasAccess) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.GREEN, + "You could bypass this reinforcement " + "if you turn bypass mode on with '/ctb'"); + } + e.setCancelled(true); + float damage = ReinforcementLogic.getDamageApplied(rein); + ReinforcementDamageEvent dre = new ReinforcementDamageEvent(e.getPlayer(), rein, damage); + Bukkit.getPluginManager().callEvent(dre); + if (dre.isCancelled()) { + return; + } + damage = dre.getDamageDone(); + ReinforcementLogic.damageReinforcement(rein, damage, e.getPlayer()); + if (rein.getHealth() <= 0) { + // in the case of double chests or similar there might now be another rein + // protecting this block + Reinforcement backupRein = ReinforcementLogic.getReinforcementProtecting(e.getBlock()); + if (backupRein == null) { + e.setCancelled(false); + ReinforcedBlockBreak rbbe = new ReinforcedBlockBreak(e.getPlayer(), rein, e); + Bukkit.getPluginManager().callEvent(rbbe); + } + } + } + + public abstract void handleInteractBlock(PlayerInteractEvent e); + + protected static void giveReinforcement(Location location, Player p, ReinforcementType type) { + HashMap notAdded = p.getInventory().addItem(type.getItem().clone()); + if (!notAdded.isEmpty()) { + DelayedItemDrop.dropAt(location, type.getItem().clone()); + } + } + + public abstract String getOverlayText(); + + @Override + public abstract boolean equals(Object o); + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/AdvancedFortificationState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/AdvancedFortificationState.java new file mode 100644 index 00000000..f7117a61 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/AdvancedFortificationState.java @@ -0,0 +1,101 @@ +package vg.civcraft.mc.citadel.playerstate; + +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.namelayer.core.Group; + +public class AdvancedFortificationState extends AbstractPlayerState { + + private Map setups; + + public AdvancedFortificationState(Player p) { + super(p); + setups = new HashMap<>(); + } + + @Override + public String getName() { + return "Advanced fortification mode"; + } + + @Override + public void handleBlockPlace(BlockPlaceEvent e) { + ItemStack placed = e.getItemInHand(); + Player player = e.getPlayer(); + // check if we have a setup for this block, we need a copy for lookup so we can + // set amount to 1 + ItemStack lookUpCopy = placed.clone(); + lookUpCopy.setAmount(1); + ReinforcingSetup setup = setups.get(lookUpCopy); + if (setup == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "No setup configured for this block type, no reinforcement was applied"); + return; + } + boolean hadError = CitadelUtility.attemptReinforcementCreation(e.getBlock(), setup.type, setup.group, e.getPlayer()); + if (hadError) { + e.setCancelled(true); + Citadel.getInstance().getStateManager().setState(e.getPlayer(), null); + } + } + + public void addSetup(ItemStack forBlock, ReinforcementType type, Group group) { + ItemStack copy = forBlock.clone(); + copy.setAmount(1); + ReinforcingSetup existing = setups.get(copy); + setups.put(copy, new ReinforcingSetup(type, group)); + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + if (existing != null) { + CitadelUtility.sendAndLog(player, ChatColor.GOLD, + "Replaced existing setup with " + ChatColor.AQUA + existing.type.getName() + ChatColor.GOLD + + " on " + ChatColor.LIGHT_PURPLE + existing.group.getName() + ChatColor.GOLD + "for " + + copy.getType() + " with " + ChatColor.AQUA + type.getName() + ChatColor.GOLD + " on " + + ChatColor.LIGHT_PURPLE + group.getName()); + } else { + CitadelUtility.sendAndLog(player, ChatColor.GOLD, copy.getType() + " will be reinforced with " + ChatColor.AQUA + + type.getName() + ChatColor.GOLD + " on " + ChatColor.LIGHT_PURPLE + group.getName()); + } + } + } + + @Override + public void handleInteractBlock(PlayerInteractEvent e) { + + } + + private class ReinforcingSetup { + + ReinforcementType type; + Group group; + + ReinforcingSetup(ReinforcementType type, Group group) { + this.type = type; + this.group = group; + } + + } + + @Override + public boolean equals(Object o) { + //just always make a new state for this one + return false; + } + + @Override + public String getOverlayText() { + return ChatColor.GOLD + "CTAF"; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/FortificationState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/FortificationState.java new file mode 100644 index 00000000..b0c873d8 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/FortificationState.java @@ -0,0 +1,72 @@ +package vg.civcraft.mc.citadel.playerstate; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.namelayer.core.Group; + +public class FortificationState extends AbstractPlayerState { + + private final ReinforcementType type; + private final Group group; + + public FortificationState(Player player, ReinforcementType type, Group group) { + super(player); + this.type = type; + this.group = group; + } + + public Group getGroup() { + return group; + } + + @Override + public String getName() { + return "Fortifying mode with " + ChatColor.AQUA + type.getName() + ChatColor.YELLOW + " on " + + ChatColor.LIGHT_PURPLE + group.getName(); + } + + public ReinforcementType getType() { + return type; + } + + @Override + public void handleBlockPlace(BlockPlaceEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + // Prevent double reinforcement (slabs) + if (ReinforcementLogic.getReinforcementAt(block.getLocation()) != null) { + return; + } + if (CitadelUtility.attemptReinforcementCreation(block, type, group, player)) { // true == fail + Citadel.getInstance().getStateManager().setState(player, null); + event.setCancelled(true); + //return; + } + } + + @Override + public void handleInteractBlock(PlayerInteractEvent event) { } + + @Override + public boolean equals(Object other) { + if (!(other instanceof FortificationState)) { + return false; + } + FortificationState fort = (FortificationState) other; + return fort.type == this.type && fort.group.getName().equals(this.getGroup().getName()); + } + + @Override + public String getOverlayText() { + return String.format("%sCTF %s%s %s%s", ChatColor.GOLD, ChatColor.LIGHT_PURPLE, group.getName(), ChatColor.AQUA, + type.getName()); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/InsecureState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/InsecureState.java new file mode 100644 index 00000000..c71f7a9a --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/InsecureState.java @@ -0,0 +1,59 @@ +package vg.civcraft.mc.citadel.playerstate; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.model.Reinforcement; + +public class InsecureState extends AbstractPlayerState { + + public InsecureState(Player p) { + super(p); + } + + @Override + public String getName() { + return "Insecure mode"; + } + + @Override + public void handleBlockPlace(BlockPlaceEvent e) { + } + + @Override + public void handleInteractBlock(PlayerInteractEvent e) { + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(e.getClickedBlock()); + if (rein == null) { + return; + } + e.setCancelled(true); + if (rein.hasPermission(e.getPlayer(), Citadel.getInstance().getPermissionHandler().getInsecure())) { + rein.toggleInsecure(); + if (rein.isInsecure()) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.YELLOW, + e.getClickedBlock().getType().name() + " is now insecure"); + } else { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.GREEN, + e.getClickedBlock().getType().name() + " is now secure"); + } + } else { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, "You are not allowed to make this reinforcement insecure"); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof InsecureState; + } + + @Override + public String getOverlayText() { + return ChatColor.GREEN + "CTIN"; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/NormalState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/NormalState.java new file mode 100644 index 00000000..54fd4816 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/NormalState.java @@ -0,0 +1,76 @@ +package vg.civcraft.mc.citadel.playerstate; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +public class NormalState extends AbstractPlayerState { + + public NormalState(Player p) { + super(p); + } + + @Override + public String getName() { + return ChatColor.GREEN + "Normal mode"; + } + + @Override + public void handleBlockPlace(BlockPlaceEvent e) { + Player player = e.getPlayer(); + if (!Citadel.getInstance().getSettingManager().isInEasyMode(player.getUniqueId())) { + return; + } + ItemStack offHand = player.getInventory().getItemInOffHand(); + ReinforcementType type = Citadel.getInstance().getReinforcementTypeManager().getByItemStack(offHand); + if (type == null) { + return; + } + Group defaultGroup = GroupAPI.getDefaultGroup(player); + if (defaultGroup == null) { + return; + } + CitadelUtility.attemptReinforcementCreation(e.getBlock(), type, defaultGroup, player); + } + + @Override + public void handleInteractBlock(PlayerInteractEvent e) { + if (e.getAction() != Action.LEFT_CLICK_BLOCK) { + return; + } + Player player = e.getPlayer(); + if (!Citadel.getInstance().getSettingManager().isInEasyMode(player.getUniqueId())) { + return; + } + ItemStack hand = player.getInventory().getItemInMainHand(); + ReinforcementType type = Citadel.getInstance().getReinforcementTypeManager().getByItemStack(hand); + if (type == null) { + return; + } + Group defaultGroup = GroupAPI.getDefaultGroup(player); + if (defaultGroup == null) { + return; + } + CitadelUtility.attemptReinforcementCreation(e.getClickedBlock(), type, defaultGroup, player); + } + + @Override + public boolean equals(Object o) { + return o instanceof NormalState; + } + + @Override + public String getOverlayText() { + return null; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/PatchState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/PatchState.java new file mode 100644 index 00000000..febed38a --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/PatchState.java @@ -0,0 +1,89 @@ +package vg.civcraft.mc.citadel.playerstate; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.command.PatchMode; +import vg.civcraft.mc.citadel.events.ReinforcementRepairEvent; +import vg.civcraft.mc.citadel.listener.ModeListener; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.civmodcore.itemHandling.ItemMap; + +public class PatchState extends AbstractPlayerState { + + public PatchState(Player p) { + super(p); + } + + @Override + public String getName() { + return "Patch mode"; + } + + @Override + public void handleBlockPlace(BlockPlaceEvent e) { + + } + + @Override + public void handleInteractBlock(PlayerInteractEvent e) { + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(e.getClickedBlock()); + Player player = e.getPlayer(); + if (rein == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "This block is not reinforced"); + return; + } + if (!rein.hasPermission(player, Citadel.getInstance().getPermissionHandler().getRepair())) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + "You do not have permission to repair reinforcements on this group"); + return; + } + if (rein.getHealth() >= rein.getType().getHealth()) { + if (rein.hasPermission(player, Citadel.getInstance().getPermissionHandler().getRepair())) { + CitadelUtility.sendAndLog(player, ChatColor.GOLD, + "Reinforcement is already at " + ModeListener.formatHealth(rein) + ChatColor.GOLD + + " health with " + ChatColor.AQUA + rein.getType().getName() + ChatColor.GOLD + " on " + + ChatColor.LIGHT_PURPLE + rein.getGroup().getName()); + } else { + CitadelUtility.sendAndLog(player, ChatColor.GOLD, "Reinforcement is already at " + + ModeListener.formatHealth(rein) + ChatColor.GOLD + " health"); + } + return; + } + ItemMap playerMap = new ItemMap(player.getInventory()); + if (playerMap.getAmount(rein.getType().getItem()) <= 0) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You don't have the item required to repair " + ChatColor.AQUA + + rein.getType().getName() + ChatColor.GOLD + " reinforcements"); + return; + } + ReinforcementRepairEvent repairEvent = new ReinforcementRepairEvent(e.getPlayer(), rein); + Bukkit.getPluginManager().callEvent(repairEvent); + if (repairEvent.isCancelled()) { + return; + } + if (!rein.rollForItemReturn()) { + if (!CitadelUtility.consumeReinforcementItems(player, rein.getType(), false)) { + return; + } + } + rein.setHealth(rein.getType().getHealth()); + rein.resetCreationTime(); + } + + @Override + public boolean equals(Object o) { + return o instanceof PatchMode; + } + + @Override + public String getOverlayText() { + return ChatColor.GREEN + "CTP"; + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/PlayerStateManager.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/PlayerStateManager.java new file mode 100644 index 00000000..2050f1b6 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/PlayerStateManager.java @@ -0,0 +1,60 @@ +package vg.civcraft.mc.citadel.playerstate; + +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.events.ReinforcementModeSwitchEvent; + +public class PlayerStateManager { + + private Map playerStateMap; + + public PlayerStateManager() { + this.playerStateMap = new TreeMap<>(); + } + + public AbstractPlayerState getState(Player player) { + if (player == null) { + throw new IllegalArgumentException("Can not get state for null player"); + } + AbstractPlayerState state = playerStateMap.get(player.getUniqueId()); + if (state == null) { + state = new NormalState(player); + playerStateMap.put(player.getUniqueId(), state); + } + return state; + } + + public void setState(Player player, AbstractPlayerState state) { + if (player == null) { + throw new IllegalArgumentException("Can not set state for null player"); + } + AbstractPlayerState existingState = getState(player); + if (existingState == null) { + existingState = new NormalState(player); + } + // null state is allowed, it just resets the state + if (state == null) { + state = new NormalState(player); + } + if (existingState.equals(state)) { + CitadelUtility.sendAndLog(player, ChatColor.GOLD, "You are still in " + ChatColor.YELLOW + state.getName()); + return; + } + ReinforcementModeSwitchEvent switchEvent = new ReinforcementModeSwitchEvent(player, existingState, state); + Bukkit.getPluginManager().callEvent(switchEvent); + if (switchEvent.isCancelled()) { + return; + } + playerStateMap.put(player.getUniqueId(), state); + CitadelUtility.sendAndLog(player, ChatColor.GOLD, "Switched Citadel mode to " + ChatColor.YELLOW + + state.getName() + ChatColor.GOLD + " from " + ChatColor.YELLOW + existingState.getName()); + } + +} diff --git a/src/main/java/vg/civcraft/mc/citadel/playerstate/ReinforcingState.java b/src/main/java/vg/civcraft/mc/citadel/playerstate/ReinforcingState.java new file mode 100644 index 00000000..a9c0e4e3 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/playerstate/ReinforcingState.java @@ -0,0 +1,164 @@ +package vg.civcraft.mc.citadel.playerstate; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import vg.civcraft.mc.citadel.Citadel; +import vg.civcraft.mc.citadel.CitadelUtility; +import vg.civcraft.mc.citadel.ReinforcementLogic; +import vg.civcraft.mc.citadel.events.ReinforcementChangeTypeEvent; +import vg.civcraft.mc.citadel.events.ReinforcementGroupChangeEvent; +import vg.civcraft.mc.citadel.model.Reinforcement; +import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; +import vg.civcraft.mc.civmodcore.itemHandling.ItemMap; +import vg.civcraft.mc.namelayer.core.Group; +import vg.civcraft.mc.namelayer.mc.GroupAPI; + +public class ReinforcingState extends AbstractPlayerState { + + private Group group; + + public ReinforcingState(Player p, Group group) { + super(p); + this.group = group; + } + + public Group getGroup() { + return group; + } + + @Override + public String getName() { + return "Reinforcing mode on " + ChatColor.LIGHT_PURPLE + group.getName(); + } + + @Override + public void handleBlockPlace(BlockPlaceEvent e) { + } + + @Override + public void handleInteractBlock(PlayerInteractEvent e) { + // always cancel + e.setCancelled(true); + Player player = e.getPlayer(); + // does the player have an item? + if (e.getItem() == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You have nothing in your hand to reinforce with"); + return; + } + ReinforcementType type = Citadel.getInstance().getReinforcementTypeManager().getByItemStack(e.getItem()); + // is it a valid item to reinforce with + if (type == null) { + CitadelUtility.sendAndLog(player, ChatColor.RED, "You can not reinforce with this item"); + return; + } + Block block = ReinforcementLogic.getResponsibleBlock(e.getClickedBlock()); + // can the item reinforce the clicked block + if (!type.canBeReinforced(block.getType())) { + CitadelUtility.sendAndLog(player, ChatColor.RED, + type.getName() + " can not reinforce " + block.getType()); + return; + } + // does the player have permission to reinforce on that group + if (!GroupAPI.hasPermission(e.getPlayer(), group, + Citadel.getInstance().getPermissionHandler().getReinforce())) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, + "You seem to have lost permission to reinforce on " + group.getName()); + Citadel.getInstance().getStateManager().setState(e.getPlayer(), null); + return; + } + Reinforcement rein = ReinforcementLogic.getReinforcementProtecting(block); + // if reinforcement exists, check if player has permission to edit it + if (rein != null) { + if (!rein.hasPermission(e.getPlayer(), Citadel.getInstance().getPermissionHandler().getBypass())) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, + "You do not have permission to bypass reinforcements on " + group.getName()); + return; + } + } + Reinforcement newRein = null; + if (rein == null || rein.getType() != type) { + // check inventory for reinforcement item + ItemMap toConsume = new ItemMap(type.getItem()); + if (!toConsume.isContainedIn(player.getInventory())) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, "No reinforcing item found in your inventory?"); + return; + } + if (rein == null) { + newRein = ReinforcementLogic.callReinforcementCreationEvent(player, block, type, group); + if (newRein == null) { + //event was cancelled, error message is up to whoever cancelled it + return; + } + } + // consume item from inventory + if (!toConsume.removeSafelyFrom(player.getInventory())) { + CitadelUtility.sendAndLog(e.getPlayer(), ChatColor.RED, + "Failed to remove reinforcement item from your inventory"); + return; + } + } + + if (rein == null) { + if (Citadel.getInstance().getConfigManager().logCreation()) { + Citadel.getInstance().getLogger() + .info(player.getName() + " created reinforcement with " + type.getName() + " for " + + block.getType().toString() + " at " + + block.getLocation().toString()); + } + // just create new reinforcement + ReinforcementLogic.createReinforcement(newRein); + } else { + // replace existing one + boolean changedGroup = false; + if (group.getPrimaryId() != rein.getGroup().getPrimaryId()) { + // switch group + ReinforcementGroupChangeEvent rgce = new ReinforcementGroupChangeEvent(player, rein, group); + Bukkit.getPluginManager().callEvent(rgce); + if (!rgce.isCancelled()) { + rein.setGroup(group); + changedGroup = true; + } + // informing the user is up to whoever cancelled it + } + if (type != rein.getType()) { + // switch type + ReinforcementChangeTypeEvent rcte = new ReinforcementChangeTypeEvent(player, rein, type); + Bukkit.getPluginManager().callEvent(rcte); + if (!rcte.isCancelled()) { + if (rein.rollForItemReturn()) { + giveReinforcement(rein.getLocation().clone().add(0.5, 0.5, 0.5), e.getPlayer(), rein.getType()); + } + rein.setType(type); + rein.setHealth(type.getHealth()); + rein.resetCreationTime(); + CitadelUtility.sendAndLog(player, ChatColor.GREEN, + "Updated reinforcement to " + rein.getType().getName() + " on " + group.getName()); + } else if (changedGroup) { + CitadelUtility.sendAndLog(player, ChatColor.GREEN, + "Updated group to " + ChatColor.LIGHT_PURPLE + group.getName()); + } + } else if (changedGroup) { + CitadelUtility.sendAndLog(player, ChatColor.GREEN, + "Updated group to " + ChatColor.LIGHT_PURPLE + group.getName()); + } + } + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ReinforcingState)) { + return false; + } + return ((ReinforcingState) o).group.getName().equals(this.getGroup().getName()); + } + + @Override + public String getOverlayText() { + return String.format("%sCTR %s%s", ChatColor.GOLD, ChatColor.LIGHT_PURPLE, group.getName()); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementEffect.java b/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementEffect.java new file mode 100644 index 00000000..84b660c2 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementEffect.java @@ -0,0 +1,98 @@ +package vg.civcraft.mc.citadel.reinforcementtypes; + +import org.bukkit.Location; +import org.bukkit.Particle; + +import vg.civcraft.mc.citadel.model.Reinforcement; + +public class ReinforcementEffect { + private Particle particle; + private float offsetX; + private float offsetY; + private float offsetZ; + private float speed; + private int particleCount; + + public ReinforcementEffect(Particle particle, float offsetX, float offsetY, float offsetZ, float speed, + int particleCount) { + this.particle = particle; + this.offsetX = offsetX; + this.offsetY = offsetY; + this.offsetZ = offsetZ; + this.speed = speed; + this.particleCount = particleCount; + } + + /** + * + * @return the amount to be randomly offset by in the X axis + */ + public float getOffsetX() { + return offsetX; + } + + /** + * + * @return the amount to be randomly offset by in the Y axis + */ + public float getOffsetY() { + return offsetY; + } + + /** + * + * @return the amount to be randomly offset by in the Z axis + */ + public float getOffsetZ() { + return offsetZ; + } + + /** + * + * @return the type of particle used in this effect + */ + public Particle getParticle() { + return particle; + } + + /** + * + * @return the amount of particle to display. + */ + public int getParticleCount() { + return particleCount; + } + + /** + * + * @return the speed of the particles + */ + public float getSpeed() { + return speed; + } + + /** + * Display an effect defined in the config around a reinforcement. + * + * @param location the location of the reinforcement. + */ + public void playEffect(Location location) { + location.getWorld().spawnParticle(particle, location, particleCount, offsetX, offsetY, offsetZ, speed, null); + } + + /** + * Display an effect defined in the config around a reinforcement. + * + * @param reinforcement Reinforcement to play effect around + */ + public void playEffect(Reinforcement reinforcement) { + playEffect(reinforcement.getBlockCenter()); + } + + @Override + public String toString() { + return String.format( + " type: %s \n offsetX: %f \n offsetY: %f \n offsetZ: %f \n speed: %f \n particleCount: %d", + particle, offsetX, offsetY, offsetZ, speed, particleCount); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementType.java b/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementType.java new file mode 100644 index 00000000..6ac88f17 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementType.java @@ -0,0 +1,205 @@ +package vg.civcraft.mc.citadel.reinforcementtypes; + +import java.util.Collection; +import java.util.Set; +import java.util.TreeSet; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public class ReinforcementType { + + private float health; + private double returnChance; + private ItemStack item; + private long maturationTime; + private int acidPriority; + private long acidTime; + private double scale; + private long gracePeriod; + private ReinforcementEffect creationEffect; + private ReinforcementEffect damageEffect; + private ReinforcementEffect destructionEffect; + private Set allowedReinforceables; + private Set disallowedReinforceables; + private Set globalBlackList; + private short id; + private String name; + private long decayTimer; + private double decayMultiplier; + private double deletedGroupMulitplier; + private int legacyId; + + public ReinforcementType(float health, double returnChance, ItemStack item, long maturationTime, long acidTime, int acidPriority, + double scale, long gracePeriod, ReinforcementEffect creationEffect, ReinforcementEffect damageEffect, + ReinforcementEffect destructionEffect, Collection allowsReinforceables, + Collection disallowedReinforceables, short id, String name, Collection globalBlackList, + long decayTimer, double decayMultiplier, double deletedGroupMulitplier, int legacyId) { + this.health = health; + this.name = name; + this.returnChance = returnChance; + this.item = item; + this.maturationTime = maturationTime; + this.acidTime = acidTime; + this.acidPriority = acidPriority; + this.scale = scale; + this.creationEffect = creationEffect; + this.damageEffect = damageEffect; + this.destructionEffect = destructionEffect; + this.gracePeriod = gracePeriod; + this.deletedGroupMulitplier = deletedGroupMulitplier; + if (allowsReinforceables != null) { + this.allowedReinforceables = new TreeSet<>(allowsReinforceables); + } else { + // can only black list OR white list + if (disallowedReinforceables != null) { + this.disallowedReinforceables = new TreeSet<>(disallowedReinforceables); + } + } + this.globalBlackList = new TreeSet<>(); + if (globalBlackList != null) { + this.globalBlackList.addAll(globalBlackList); + } + this.id = id; + this.decayMultiplier = decayMultiplier; + this.decayTimer = decayTimer; + this.legacyId = legacyId; + } + + public boolean canBeReinforced(Material mat) { + if (globalBlackList.contains(mat)) { + return false; + } + if (allowedReinforceables == null) { + return disallowedReinforceables == null || !disallowedReinforceables.contains(mat); + } + return allowedReinforceables.contains(mat); + } + + /** + * @return Returns the acid maturation time needed until this acid block is + * ready. + */ + public long getAcidTime() { + return acidTime; + } + + /** + * @return the time in milli seconds to "forgive" reinforcements and apply 100% + * return rate. Set to 0 to disable. + */ + public long getGracePeriod() { + return this.gracePeriod; + } + + /** + * @return Maximum health + */ + public float getHealth() { + return health; + } + + /** + * @return The unique id identifying this config + */ + public short getID() { + return id; + } + + /** + * @return Damage multiplier applied if the owning group was deleted + */ + public double getDeletedGroupMultiplier() { + return deletedGroupMulitplier; + } + + /** + * @return Item used to create instance of this item + */ + public ItemStack getItem() { + return item; + } + + /** + * @return Acid priority of this type. Acid blocks can only remove blocks of lower or equal priority + */ + public int getAcidPriority() { + return acidPriority; + } + + /** + * @return Get the scale of amount of damage a block should take when it is not + * fully mature. + */ + public double getMaturationScale() { + return scale; + } + + /** + * @return Returns the Maturation time needed until this block is mature in + * milliseconds + */ + public long getMaturationTime() { + return maturationTime; + } + + /** + * @return Nice name to use for messages + */ + public String getName() { + return name; + } + + /** + * @return Get the effect to spawn around this type of reinforcement when it is + * created + */ + public ReinforcementEffect getCreationEffect() { + return creationEffect; + } + + /** + * @return Get the effect to spawn around this type of reinforcement when it is + * damaged + */ + public ReinforcementEffect getDamageEffect() { + return damageEffect; + } + + /** + * @return Get the effect to spawn around this type of reinforcement when it is + * destroyed + */ + public ReinforcementEffect getDestructionEffect() { + return destructionEffect; + } + + /** + * @return The percent chance that a block will return the reinforcements. + * Scales with damage. 1 means it is 100% and .5 means 50% + */ + public double getReturnChance() { + return returnChance; + } + + /** + * Material id the material used for the reinforcement had pre-flattening (1.12.2 or earlier). Needed once for + * proper migration of reinforcements to higher versions + * @return Old item id of the reinforcement item + */ + public int getLegacyId() { + return legacyId; + } + + public double getDecayDamageMultipler(long since) { + if (decayTimer <= 0 || decayMultiplier == 1) { + return 1; + } + long timePassed = System.currentTimeMillis() - since; + if (timePassed <= decayTimer) { + return 1; + } + double timeExponent = ((double) timePassed / (double) decayTimer); + return Math.pow(decayMultiplier, timeExponent); + } +} diff --git a/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementTypeManager.java b/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementTypeManager.java new file mode 100644 index 00000000..6031a8e7 --- /dev/null +++ b/src/main/java/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementTypeManager.java @@ -0,0 +1,39 @@ +package vg.civcraft.mc.citadel.reinforcementtypes; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import org.bukkit.inventory.ItemStack; + +public class ReinforcementTypeManager { + + private Map typesByItem; + private Map typesById; + + public ReinforcementTypeManager() { + typesByItem = new HashMap<>(); + typesById = new TreeMap<>(); + } + + public Collection getAllTypes() { + return typesById.values(); + } + + public ReinforcementType getById(short id) { + return typesById.get(id); + } + + public ReinforcementType getByItemStack(ItemStack is) { + ItemStack copy = is.clone(); + copy.setAmount(1); + return typesByItem.get(copy); + } + + public void register(ReinforcementType type) { + typesByItem.put(type.getItem(), type); + typesById.put(type.getID(), type); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 00000000..c4909cfe --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,211 @@ +#Log when a player forcefully breaks reinforcements? +logHostileBreaks: true + +#Log when a player bypasses friendly reinforcements? +logFriendlyBreaks: true + +#Log every time damage is done to a reinforcement? Only recommended for debugging +logDamage: true + +#Log creation of reinforcements? +logCreation: true + +#Log message replies sent to users? Very useful +logMessages: true + + +#General debug messages +debug: true + +reinforcements: + stone: + id: 1 + item: + ==: org.bukkit.inventory.ItemStack + v: 1 + type: STONE + effect: + type: ENCHANTING_TABLE + speed: 0.5 + particleCount: 50 + mature_time: 5m + acid_time: 20m + name: Stone + hit_points: 50 + iron: + id: 2 + item: + ==: org.bukkit.inventory.ItemStack + v: 1 + type: IRON_INGOT + effect: + type: ENCHANTING_TABLE + speed: 0.5 + particleCount: 50 + mature_time: 30m + acid_time: 6h + name: Iron + hit_points: 300 + diamond: + id: 3 + item: + ==: org.bukkit.inventory.ItemStack + v: 1 + type: DIAMOND + effect: + type: ENCHANTING_TABLE + speed: 0.5 + particleCount: 50 + mature_time: 4h + acid_time: 48h + name: Diamond + hit_points: 2000 + bedrock: + id: 4 + item: + ==: org.bukkit.inventory.ItemStack + v: 1 + type: BEDROCK + effect: + type: ENCHANTING_TABLE + speed: 0.5 + particleCount: 50 + mature_time: 1s + acid_time: 1s + name: Bedrock + hit_points: 420420420 + +non_reinforceables: + - BEDROCK + - END_PORTAL + - END_PORTAL_FRAME + - OAK_SAPLING + - BIRCH_SAPLING + - SPRUCE_SAPLING + - JUNGLE_SAPLING + - DARK_OAK_SAPLING + - ACACIA_SAPLING + - BAMBOO_SAPLING + - TALL_GRASS + - DEAD_BUSH + - PISTON + - MOVING_PISTON + - PISTON_HEAD + - POPPY + - DANDELION + - BLUE_ORCHID + - ALLIUM + - RED_TULIP + - ORANGE_TULIP + - WHITE_TULIP + - PINK_TULIP + - OXEYE_DAISY + - CORNFLOWER + - LILY_OF_THE_VALLEY + - SUNFLOWER + - SEA_PICKLE + - LILAC + - PEONY + - ROSE_BUSH + - BROWN_MUSHROOM + - RED_MUSHROOM + - CRIMSON_FUNGUS + - WARPED_FUNGUS + - CRIMSON_ROOTS + - WARPED_ROOTS + - NETHER_SPROUTS + - WEEPING_VINES + - TWISTING_VINES + - TWISTING_VINES_PLANT + - WEEPING_VINES_PLANT + - TNT + - WHEAT + - BEETROOTS + - POTATOES + - CARROTS + - FERN + - LARGE_FERN + - GRASS + - SEAGRASS + - TALL_SEAGRASS + - BAMBOO + - SUGAR_CANE + - SWEET_BERRIES + - BROWN_MUSHROOM + - RED_MUSHROOM + - KELP + - SEA_PICKLE + - NETHER_WART + - CHORUS_FRUIT + - FIRE + - SOUL_FIRE + - SNOW + - ICE + - CACTUS + - KELP_PLANT + - NETHER_PORTAL + - CAKE + - PUMPKIN_STEM + - MELON_STEM + - VINE + - BRAIN_CORAL + - BRAIN_CORAL_BLOCK + - BRAIN_CORAL_FAN + - BRAIN_CORAL_WALL_FAN + - BUBBLE_CORAL + - BUBBLE_CORAL_BLOCK + - BUBBLE_CORAL_FAN + - BUBBLE_CORAL_WALL_FAN + - FIRE_CORAL + - FIRE_CORAL_BLOCK + - FIRE_CORAL_FAN + - FIRE_CORAL_WALL_FAN + - HORN_CORAL + - HORN_CORAL_BLOCK + - HORN_CORAL_FAN + - HORN_CORAL_WALL_FAN + - TUBE_CORAL + - TUBE_CORAL_BLOCK + - TUBE_CORAL_FAN + - TUBE_CORAL_WALL_FAN + - DEAD_BRAIN_CORAL + - DEAD_BRAIN_CORAL_BLOCK + - DEAD_BRAIN_CORAL_FAN + - DEAD_BRAIN_CORAL_WALL_FAN + - DEAD_BUBBLE_CORAL + - DEAD_BUBBLE_CORAL_BLOCK + - DEAD_BUBBLE_CORAL_FAN + - DEAD_BUBBLE_CORAL_WALL_FAN + - DEAD_FIRE_CORAL + - DEAD_FIRE_CORAL_BLOCK + - DEAD_FIRE_CORAL_FAN + - DEAD_FIRE_CORAL_WALL_FAN + - DEAD_HORN_CORAL + - DEAD_HORN_CORAL_BLOCK + - DEAD_HORN_CORAL_FAN + - DEAD_HORN_CORAL_WALL_FAN + - DEAD_TUBE_CORAL + - DEAD_TUBE_CORAL_BLOCK + - DEAD_TUBE_CORAL_FAN + - DEAD_TUBE_CORAL_WALL_FAN + - SCAFFOLDING +acidblock_material: + - GOLD_BLOCK + +# Determines whether hanging entities (such as Item Frames) can be protected by their host block +hangers_inherit_reinforcement: false + +# reinforcement_damageMultiplier is m where BlockDamage = 2 ^ (n/m) where n is equal to the number of days the group has been inactive +reinforcement_damageMultiplier: 365 +#database: +# ==: vg.civcraft.mc.civmodcore.dao.ManagedDatasource +# plugin: Citadel +# user: 'mc_namelayer' +# password: 'minecraft' +# host: localhost +# port: 3306 +# database: namelayer +# poolsize: 5 +# connection_timeout: 10000 +# idle_timeout: 600000 +# max_lifetime: 7200000 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 00000000..f9250c3f --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,136 @@ +name: ${project.name} +main: vg.civcraft.mc.citadel.Citadel +version: ${project.version} +authors: +- Rourke750 +- Maxopoly +- ProgrammerDan +- okx-code +- Cranite +- FeatherCrown +- Lazersmoke +- TealNerd +- Scuwr +depend: +- NameLayer +- CivModCore +softdepend: +- HolographicDisplays +description: Citadel allows you to make blocks difficult to break. When a block is reinforced, it must be broken many times before it is destroyed. +commands: + ctr: + aliases: + - ctreinforce + - reinforce + - protect + - cprivate + - lwc + - private + usage: /ctr [group] + description: Enters reinforcing mode. Interacting with blocks in reinforcing mode will reinforce them or modify their reinforcement + min-args: 0 + max-args: 1 + player-only: true + ctacid: + usage: /ctacid + description: Removes the block above it if used on an acid block + min-args: 0 + max-args: 0 + player-only: true + ctf: + aliases: + - ctfortify + - fortify + usage: /ctf [group] + description: Enters fortification mode. All blocks placed in fortification mode will automatically be reinforced. If no group is given, your default group will be used + min-args: 0 + max-args: 1 + player-only: true + ctb: + aliases: + - ctbypass + - bypass + usage: /ctb + description: Toggles bypass state. In bypass state you can break blocks reinforced on groups you have access to in a single break + min-args: 0 + max-args: 0 + player-only: true + cti: + aliases: + - ctinformation + - info + - ctinfo + usage: /cti + description: Enters information mode. Interacting with blocks in information mode will show information on their reinforcement + min-args: 0 + max-args: 0 + player-only: true + ctin: + aliases: + - ctinsecure + - insecure + usage: /ctin + description: Enters insecure mode. Interacting with containers in insecure mode will switch their insecure flag. Insecure containers can interact with hoppers reinforced on a different group. All containers are secure by default + min-args: 0 + max-args: 0 + player-only: true + cto: + aliases: + - ctoff + - false + usage: /cto + description: Leaves all reinforcement modes + min-args: 0 + max-args: 0 + player-only: true + ctur: + permission: citadel.admin + player-only: true + ctar: + permission: citadel.admin + aliases: + - ctareareinforce + player-only: true + cte: + aliases: + - cteasy + - toggleeasymode + player-only: true + ctdl: + aliases: + - reinforcements + - rein + usage: /ctdl + description: Opens a GUI displaying all reinforcement materials + min-args: 0 + max-args: 0 + player-only: true + citadelreload: + aliases: + - reloadcitadel + usage: /citadelreload + description: Reloads Citadel entirely + min-args: 0 + max-args: 0 + permission: citadel.admin + ctp: + aliases: + - repair + - patch + - ctrepair + - ctpatch + usage: /ctp + min-args: 0 + max-args: 0 + player-only: true + description: Enters patch mode, which allows you to repair reinforcements. Note that repairing reinforcements will also reset their maturation cycle + cta: + usage: /cta [group] + description: Enters advanced fortification mode or adds configurations to it. Advanced configuration mode allows you to place on different groups with different reinforcement types at once + min-args: 0 + max-args: 1 + player-only: true +permissions: + citadel.admin: + default: op +api-version: 1.16 diff --git a/src/vg/civcraft/mc/citadel/Citadel.java b/src/vg/civcraft/mc/citadel/Citadel.java deleted file mode 100644 index 978419b5..00000000 --- a/src/vg/civcraft/mc/citadel/Citadel.java +++ /dev/null @@ -1,154 +0,0 @@ -package vg.civcraft.mc.citadel; - -import java.util.LinkedList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.java.JavaPlugin; - -import vg.civcraft.mc.citadel.command.CommandHandler; -import vg.civcraft.mc.citadel.database.CitadelReinforcementData; -import vg.civcraft.mc.citadel.database.Database; -import vg.civcraft.mc.citadel.listener.BlockListener; -import vg.civcraft.mc.citadel.listener.EntityListener; -import vg.civcraft.mc.citadel.listener.GroupsListener; -import vg.civcraft.mc.citadel.listener.InventoryListener; -import vg.civcraft.mc.citadel.listener.ShardListener; -import vg.civcraft.mc.citadel.listener.WorldListener; -import vg.civcraft.mc.citadel.misc.CitadelStatics; -import vg.civcraft.mc.citadel.reinforcementtypes.NaturalReinforcementType; -import vg.civcraft.mc.citadel.reinforcementtypes.NonReinforceableType; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.mercury.MercuryAPI; -import vg.civcraft.mc.namelayer.GroupManager.PlayerType; -import vg.civcraft.mc.namelayer.permission.PermissionType; - -public class Citadel extends JavaPlugin{ - private static Logger logger; - - private static CitadelReinforcementData db; - private static ReinforcementManager rm; - private CommandHandler cHandle; - private static Citadel instance; - - public void onEnable(){ - instance = this; - logger = getLogger(); - if (!Bukkit.getPluginManager().isPluginEnabled("NameLayer")){ - Log("Citadel is shutting down because it could not find NameLayer"); - this.getPluginLoader().disablePlugin(this); // shut down - } - saveDefaultConfig(); - new CitadelConfigManager(getConfig()); - - // Grab the values from config - ReinforcementType.initializeReinforcementTypes(); - NaturalReinforcementType.initializeNaturalReinforcementsTypes(); - NonReinforceableType.initializeNonReinforceableTypes(); - initializeDatabase(); - - rm = new ReinforcementManager(db); - - registerListeners(); - registerCommands(); - registerNameLayerPermissions(); - } - - public void onDisable(){ - // Pushes all reinforcements loaded to be saved to db. - rm.invalidateAllReinforcements(); - CitadelStatics.displayStatisticsToConsole(); - } - /** - * Initializes the database. - */ - public void initializeDatabase(){ - String host = CitadelConfigManager.getHostName(); - String user = CitadelConfigManager.getUserName(); - String password = CitadelConfigManager.getPassword(); - int port = CitadelConfigManager.getPort(); - String dbName = CitadelConfigManager.getDBName(); - Database data = new Database(host, port, dbName, user, password, getLogger()); - db = new CitadelReinforcementData(data); - } - /** - * Registers the listeners for Citadel. - */ - private void registerListeners(){ - getServer().getPluginManager().registerEvents(new BlockListener(), this); - getServer().getPluginManager().registerEvents(new GroupsListener(), this); - getServer().getPluginManager().registerEvents(new EntityListener(), this); - getServer().getPluginManager().registerEvents(new InventoryListener(), this); - getServer().getPluginManager().registerEvents(new WorldListener(), this); - if (Bukkit.getPluginManager().isPluginEnabled("Mercury") && Bukkit.getPluginManager().isPluginEnabled("BetterShards")) { - getServer().getPluginManager().registerEvents(new ShardListener(), this); - MercuryAPI.registerPluginMessageChannel("Citadel"); - } - } - - public void registerNameLayerPermissions() { - LinkedList membersAndAbove = new LinkedList(); - membersAndAbove.add(PlayerType.MEMBERS); - membersAndAbove.add(PlayerType.MODS); - membersAndAbove.add(PlayerType.ADMINS); - membersAndAbove.add(PlayerType.OWNER); - LinkedList modsAndAbove = new LinkedList(); - modsAndAbove.add(PlayerType.MODS); - modsAndAbove.add(PlayerType.ADMINS); - modsAndAbove.add(PlayerType.OWNER); - PermissionType.registerPermission("REINFORCE",(LinkedList) modsAndAbove.clone()); - PermissionType.registerPermission("ACIDBLOCK",(LinkedList) modsAndAbove.clone()); - PermissionType.registerPermission("REINFORCEMENT_INFO",(LinkedList) membersAndAbove.clone()); - PermissionType.registerPermission("BYPASS_REINFORCEMENT", (LinkedList) modsAndAbove.clone()); - PermissionType.registerPermission("DOORS",(LinkedList) membersAndAbove.clone()); - PermissionType.registerPermission("CHESTS",(LinkedList) membersAndAbove.clone()); - PermissionType.registerPermission("CROPS",(LinkedList) membersAndAbove.clone()); - PermissionType.registerPermission("INSECURE_REINFORCEMENT",(LinkedList) membersAndAbove.clone()); - } - - - /** - * Registers the commands for Citadel. - */ - private void registerCommands(){ - cHandle = new CommandHandler(); - cHandle.registerCommands(); - } - /** - * Logs info for Citadel messages. - * @param message - */ - public static void Log(String message){ - logger.log(Level.INFO, "[Citadel] " + message); - } - /** - * @return The ReinforcementManager of Citadel. - */ - public static ReinforcementManager getReinforcementManager(){ - return rm; - } - /** - * @return The instance of Citadel. - */ - public static Citadel getInstance(){ - return instance; - } - /** - * @return The Database Manager for Citadel. - */ - public static CitadelReinforcementData getCitadelDatabase(){ - return db; - } - - public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { - return cHandle.execute(sender, cmd, args); - } - - public List onTabComplete(CommandSender sender, Command cmd, String alias, String[] args){ - return cHandle.complete(sender, cmd, args); - } -} diff --git a/src/vg/civcraft/mc/citadel/CitadelConfigManager.java b/src/vg/civcraft/mc/citadel/CitadelConfigManager.java deleted file mode 100644 index 1855ab92..00000000 --- a/src/vg/civcraft/mc/citadel/CitadelConfigManager.java +++ /dev/null @@ -1,163 +0,0 @@ -package vg.civcraft.mc.citadel; - -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.Material; -import org.bukkit.configuration.file.FileConfiguration; - -public class CitadelConfigManager { - - private static FileConfiguration config; - public CitadelConfigManager(FileConfiguration con){ - config = con; - } - - public static List getReinforcementTypes(){ - List reinforcementTypes = new ArrayList(); - for (String sect: config.getConfigurationSection("reinforcements").getKeys(false)) - reinforcementTypes.add(sect); - return reinforcementTypes; - } - - public static List getNaturalReinforcementTypes(){ - List naturalReinforcementTypes = new ArrayList(); - if (config.getConfigurationSection("natural_reinforcements") == null) - return naturalReinforcementTypes; - for (String sect: config.getConfigurationSection - ("natural_reinforcements").getKeys(false)) - naturalReinforcementTypes.add(sect); - return naturalReinforcementTypes; - } - - public static List getNonReinforceableTypes(){ - List nonReinforcementTypes = new ArrayList(); - if (config.getStringList("non_reinforceables") == null){ - return nonReinforcementTypes; - } - for (String sect: config.getStringList("non_reinforceables")) - nonReinforcementTypes.add(sect); - return nonReinforcementTypes; - } - - public static int getRequireMents(String type){ - return config.getInt("reinforcements." + type + ".requirements"); - } - - public static int getReturns(String type){ - return config.getInt("reinforcements." + type + ".return"); - } - - public static Material getMaterial(String type){ - return Material.getMaterial(config.getString("reinforcements." + type + ".material")); - } - - public static int getPercentReturn(String type){ - return config.getInt("reinforcements." + type + ".percent_chance"); - } - - public static int getHitPoints(String type){ - return config.getInt("reinforcements." + type + ".hit_points"); - } - - public static int getMaturationTime(String type){ - return config.getInt("reinforcements." + type + ".mature_time"); - } - - public static int getAcidTime(String type) { - return config.getInt("reinforcements." + type + ".acid_time", getMaturationTime(type)); - } - - public static int getMaturationScale(String type){ - return config.getInt("reinforcements." + type + ".scale_amount"); - } - - public static List getLoreValues(String type){ - return config.getStringList("reinforcements." + type + ".lore"); - } - - public static Material getNaturalReinforcementMaterial(String type){ - return Material.valueOf(config.getString("natural_reinforcements." + - type + ".material")); - } - - public static int getNaturalReinforcementHitPoints(String type){ - return config.getInt("natural_reinforcements." + type + ".hit_points"); - } - - public static int getPlayerStateReset(){ - return config.getInt("reset_player_state"); - } - - public static boolean isMaturationEnabled(){ - return config.getBoolean("enable_maturation"); - } - - public static int getMaxCacheSize(){ - return config.getInt("max_cache_size"); - } - - public static long getMaxCacheMinutes(){ - return config.getLong("max_cache_load_time"); - } - - public static int getMaxRedstoneDistance(){ - return config.getInt("redstone_distance"); - } - - public static Material getAcidBlock(){ - return Material.valueOf(config.getString("acidblock_material")); - } - - public static boolean shouldDropReinforcedBlock(){ - return config.getBoolean("drop_reinforced_block"); - } - - public static int getTickRepeatingSave(){ - return config.getInt("save_interval_ticks", 500); - } - - public static int getDayMultiplier(){ - return config.getInt("reinforcement_damageMultiplier", 7); - } - - public static String getHostName(){ - return config.getString("mysql.hostname", "localhost"); - } - - public static int getPort(){ - return config.getInt("mysql.port", 3306); - } - - public static String getDBName(){ - return config.getString("mysql.dbname", "bukkit"); - } - - public static String getUserName(){ - return config.getString("mysql.username", "bukkit"); - } - - public static String getPassword(){ - return config.getString("mysql.password", ""); - } - - public static boolean shouldLogInternal() { - return config.getBoolean("internal_logging", false); - } - - public static boolean shouldLogPlayerCommands() { - return config.getBoolean("command_logging", false); - } - - public static boolean shouldLogBreaks() { - return config.getBoolean("break_logging", false); - } - - public static boolean shouldLogReinforcement() { - return config.getBoolean("reinf_logging", false); - } - - public static boolean showHealthAsPercent(){ - return config.getBoolean("show_health_as_percent", false); - } -} diff --git a/src/vg/civcraft/mc/citadel/PlayerState.java b/src/vg/civcraft/mc/citadel/PlayerState.java deleted file mode 100644 index a2b5f5dc..00000000 --- a/src/vg/civcraft/mc/citadel/PlayerState.java +++ /dev/null @@ -1,178 +0,0 @@ -package vg.civcraft.mc.citadel; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.logging.Level; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitScheduler; - -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.group.Group; - -public class PlayerState { - - private static final Map PLAYER_STATES = new HashMap(); - - /** - * Method used to get the PlayerState of the specified player. - * Creates a new instance of a PlayerState if none is found. - * @param The Player you want to get the PlayerState for. - * @return The PlayerState of that player. - */ - public static PlayerState get(Player player) { - if (player == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "PlayerState get called with null player"); - } - UUID id = NameAPI.getUUID(player.getName()); - PlayerState state = PLAYER_STATES.get(id); - if (state == null) { - state = new PlayerState(player); - PLAYER_STATES.put(id, state); - } - return state; - } - - public static PlayerState get(UUID id) { - if (id == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "PlayerState get called with null id"); - } - PlayerState state = PLAYER_STATES.get(id); - if (state == null) { - state = new PlayerState(id); - PLAYER_STATES.put(id, state); - } - return state; - } - - /** - * Removes a PlayerState from the list. - * @param The Player to remove from the list. - */ - public static void remove(Player player) { - PLAYER_STATES.remove(player.getUniqueId()); - } - - private UUID accountId; - private ReinforcementMode mode; - private Group faction; - private boolean bypassMode; - private Integer cancelModePid; - private ItemStack fortificationStack; - - public PlayerState(Player player) { - this(player.getUniqueId()); - } - - public PlayerState(UUID uuid) { - reset(); - this.accountId = uuid; - bypassMode = false; - } - - /** - * Sets the placement mode to NORMAL and resets other properties. - */ - public void reset() { - mode = ReinforcementMode.NORMAL; - fortificationStack = null; - faction = null; - } - /** - * @return Returns the ReinforceMent Mode associated with the given - * Player. - */ - public ReinforcementMode getMode() { - return mode; - } - /** - * Sets the ReinforcementMode of a given Player. - * @param ReinforcementMode. - */ - public void setMode(ReinforcementMode mode) { - this.mode = mode; - } - /** - * Sets the fortificationStack. Make sure this is a ReinforcementType - * or its pretty useless. - * @param ItemStack. - */ - public void setFortificationItemStack(ItemStack fortificationStack) { - if (fortificationStack == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "PlayerState setFortificationItemStack called with null stack"); - } - this.fortificationStack = fortificationStack; - } - /** - * Gets the Group for a given PlayerState. - * @return The group belonging to the PlayerState. - */ - public Group getGroup() { - return faction; - } - /** - * Sets the Group for a PlayerState. - * @param The group. - */ - public void setGroup(Group faction) { - if (faction == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "PlayerState setGroup called with null faction"); - } - this.faction = faction; - } - /** - * Returns if a player is in BypassMode. - * @return True if in Bypass Mode. - */ - public boolean isBypassMode() { - return bypassMode; - } - /** - * Toggles Bypass Mode. - * @return Returns the new value. - */ - public boolean toggleBypassMode() { - bypassMode = !bypassMode; - return bypassMode; - } - - /** - * Prepares a scheduled task to reset the mode after a configured amount - * of time. - * - * If a task is already scheduled it is canceled first. - */ - public void checkResetMode() { - Citadel plugin = Citadel.getInstance(); - BukkitScheduler scheduler = Bukkit.getServer().getScheduler(); - if (cancelModePid != null && scheduler.isQueued(cancelModePid)) - scheduler.cancelTask(cancelModePid); - - cancelModePid = scheduler.scheduleSyncDelayedTask(plugin, new Runnable() { - public void run() { - try { - Player player = Bukkit.getPlayer(accountId); - if (player != null) { - player.sendMessage(ChatColor.YELLOW + mode.name() + " mode off"); - } - reset(); - } catch (Exception e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "PlayerState checkResetMode Failed", e); - } - } - }, 20L * CitadelConfigManager.getPlayerStateReset()); - } - /** - * Returns the ReinforcementType for a PlayerState. - * @return ReinforcementType. - */ - public ReinforcementType getReinforcementType(){ - return ReinforcementType.getReinforcementType(fortificationStack); - } -} \ No newline at end of file diff --git a/src/vg/civcraft/mc/citadel/ReinforcementManager.java b/src/vg/civcraft/mc/citadel/ReinforcementManager.java deleted file mode 100644 index 28584386..00000000 --- a/src/vg/civcraft/mc/citadel/ReinforcementManager.java +++ /dev/null @@ -1,295 +0,0 @@ -package vg.civcraft.mc.citadel; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; - -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; - -import vg.civcraft.mc.citadel.database.CitadelReinforcementData; -import vg.civcraft.mc.citadel.misc.CitadelStatics; -import vg.civcraft.mc.citadel.misc.LoadingCacheNullException; -import vg.civcraft.mc.citadel.reinforcement.NullReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; - -public class ReinforcementManager { - - private CitadelReinforcementData db; - private long dayMultiplier; - - // This shit is cool - private RemovalListener removalListener = new RemovalListener() { - public void onRemoval(RemovalNotification removal) { - Reinforcement rein = removal.getValue(); - if (rein == null || rein instanceof NullReinforcement){ - return; - } - if (rein.isDirty()) { - saveReinforcement(rein); - } - } - }; - - private LoadingCache reinforcements = CacheBuilder - .newBuilder().maximumSize(CitadelConfigManager.getMaxCacheSize()) - .expireAfterAccess(CitadelConfigManager.getMaxCacheMinutes(), TimeUnit.MINUTES) - .removalListener(removalListener) - .build(new CacheLoader() { - public Reinforcement load(Location loc) throws Exception { - if (loc == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager cache load called with null"); - } - - Reinforcement rein = db.getReinforcement(loc); - if (rein == null) { - return new NullReinforcement(loc); - } - CitadelStatics.updateHitStat(CitadelStatics.LOAD); - // decrement cache because it gets increased from getReinforcement() - CitadelStatics.decrementHitStat(CitadelStatics.CACHE); - return rein; - } - }); - - public ReinforcementManager(CitadelReinforcementData db) { - this.db = db; - this.dayMultiplier = (long)CitadelConfigManager.getDayMultiplier(); - - scheduleSave(); - } - - public long getDayMultiplier(){ - return dayMultiplier; - } - - /** - * Saves the reinforcement to the database. If the reinforcement durability - * is less than or equal to zero it will delete it from the database. - * @param The Reinforcement to save - */ - public void saveReinforcement(Reinforcement rein) { - if (rein == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager saveReinforcement called with null"); - return; - } - if (rein.getDurability() <= 0) { - deleteReinforcement(rein); - } - CitadelStatics.updateHitStat(CitadelStatics.UPDATE); - db.saveReinforcement(rein); - rein.setDirty(false); - } - - /** - * Saves the initial reinforcement into the database. - * @param The Reinforcement to save - */ - public void saveInitialReinforcement(Reinforcement rein) { - // Do a check first, there might be an edge case for example half slabs where there is a reinforcement - // but it got this far. Lets just keep the one already there and ignore this new one. - // If this is some other case then the code already in place should have deleted the reinforcement EX: Air. - if (rein == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager saveInitialReinforcement called with null"); - return; - } - if (getReinforcement(rein.getLocation()) == null) { - reinforcements.put(rein.getLocation(), rein); - CitadelStatics.updateHitStat(CitadelStatics.INSERT); - db.insertReinforcement(rein); - } - } - - /** - * Returns the Reinforcement from the specified location. - * - * @param loc - * @return Reinforcement - */ - public Reinforcement getReinforcement(Location loc) { - if (loc == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager getReinforcement called with null"); - return null; - } - - try { - Reinforcement rein = reinforcements.get(loc); - if (rein instanceof NullReinforcement) { - return null; - } - CitadelStatics.updateHitStat(CitadelStatics.CACHE); - return rein; - } catch (Exception e) { - // So we ignore cache errors? - if (!(e.getCause() instanceof LoadingCacheNullException)) { - e.printStackTrace(); - } - } - return null; - } - - /** - * Returns the Reinforcement from the specified block. - * - * @param block - * @return Reinforcement - */ - public Reinforcement getReinforcement(Block block) { - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager getReinforcement block called with null"); - return null; - } - return getReinforcement(block.getLocation()); - } - - /** - * Deletes the reinforcement. Should get called from the saveReinforcement - * method if the durability of the reinforcement is less than or equal to 0. - * - * @param rein - */ - public void deleteReinforcement(Reinforcement rein) { - if (rein == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager deleteReinforcement called with null"); - return; - } - reinforcements.invalidate(rein.getLocation()); - CitadelStatics.updateHitStat(CitadelStatics.DELETE); - db.deleteReinforcement(rein); - } - - /** - * Used to flush all the reinforcements to the db on shutdown. Can be called - * else where if too a manual flush is wanted. - */ - public void invalidateAllReinforcements() { - reinforcements.invalidateAll(); - } - - /** - * Returns if the location is reinforced or not. - * - * @param loc - * - The location of the potential reinforcement. - * @return Returns true if one was found. - */ - public boolean isReinforced(Location loc) { - if (loc == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager isReinforced called with null"); - return false; - } - - return getReinforcement(loc) != null; - } - - /** - * Returns if the block is reinforced or not. - * - * @param block - * - The block of the potential reinforcement. - * @return Returns true if one was found. - */ - public boolean isReinforced(Block block) { - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager isReinforced block called with null"); - return false; - } - - return isReinforced(block.getLocation()); - } - - // Saves periodicly all the reinforcements. - private void scheduleSave(){ - Bukkit.getScheduler().runTaskTimerAsynchronously(Citadel.getInstance(), new Runnable(){ - - @Override - public void run() { - try { - long cached = 0l; - long dirty = 0l; - long s = 0l; - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.Log("Running Scheduled Save"); - s = System.currentTimeMillis(); - } - List reins = new ArrayList(); - synchronized(reinforcements){ - for (Reinforcement r: reinforcements.asMap().values()) { - if (r.isDirty()) { - reins.add(r); - dirty++; - } - cached++; - } - } - for (Reinforcement r: reins) { - saveReinforcement(r); - } - if (CitadelConfigManager.shouldLogInternal()) { - s = System.currentTimeMillis() - s; - Citadel.Log("Scheduled Save complete in " + s + " ms. Cache holds " + - cached + " entries, " + dirty + " entries saved to DB."); - } - } catch (Exception e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager scheduled save encountered a problem", e); - } - } - - }, 100, CitadelConfigManager.getTickRepeatingSave()); - } - - /** - * This gets all reinforcements in a chunk. This should not be called regularly synchronously as this will call the database first. - * After it grabs the reinforcements it checks if they are already in the cache and if they are it skips it and if not it puts it in there. - * Then returns the list of reinforcements in the Chunk. - */ - public List getReinforcementsByChunk(Chunk chunk){ - if (chunk == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager getReinforcementsByChunk called with null"); - return new ArrayList(); - } - - List reins = db.getReinforcements(chunk); - List reins_new = new ArrayList(); - for (Reinforcement rein: reins){ - if (reinforcements.getIfPresent(rein.getLocation()) == null){ - reinforcements.put(rein.getLocation(), rein); - reins_new.add(rein); - } - else { - Reinforcement r = null; - try { - r = reinforcements.get(rein.getLocation()); - } catch (ExecutionException e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager getReinforcementsByChunk called with null", e); - } - reins_new.add(r); - } - } - return reins_new; - } - - public void loadReinforcementChunk(Chunk chunk) { - if (chunk == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementManager loadReinforcementChunk called with null"); - return; - } - List reins = db.getReinforcements(chunk); - for (Reinforcement rein: reins){ - Reinforcement r = reinforcements.getIfPresent(rein.getLocation()); - if (r == null || r instanceof NullReinforcement) { - reinforcements.put(rein.getLocation(), rein); - } - } - } -} diff --git a/src/vg/civcraft/mc/citadel/ReinforcementMode.java b/src/vg/civcraft/mc/citadel/ReinforcementMode.java deleted file mode 100644 index 37d76d96..00000000 --- a/src/vg/civcraft/mc/citadel/ReinforcementMode.java +++ /dev/null @@ -1,10 +0,0 @@ -package vg.civcraft.mc.citadel; - -public enum ReinforcementMode { - - REINFORCEMENT, - REINFORCEMENT_FORTIFICATION, - REINFORCEMENT_INFORMATION, - NORMAL, - INSECURE; -} diff --git a/src/vg/civcraft/mc/citadel/Utility.java b/src/vg/civcraft/mc/citadel/Utility.java deleted file mode 100644 index 0245d05e..00000000 --- a/src/vg/civcraft/mc/citadel/Utility.java +++ /dev/null @@ -1,1024 +0,0 @@ -package vg.civcraft.mc.citadel; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.logging.Level; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.Bed; -import org.bukkit.material.Door; -import org.bukkit.util.Vector; - -import vg.civcraft.mc.citadel.events.ReinforcementCreationEvent; -import vg.civcraft.mc.citadel.listener.BlockListener; -import vg.civcraft.mc.citadel.misc.ReinforcemnetFortificationCancelException; -import vg.civcraft.mc.citadel.reinforcement.MultiBlockReinforcement; -import vg.civcraft.mc.citadel.reinforcement.NaturalReinforcement; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.citadel.reinforcementtypes.NaturalReinforcementType; -import vg.civcraft.mc.citadel.reinforcementtypes.NonReinforceableType; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.NameLayerPlugin; -import vg.civcraft.mc.namelayer.group.Group; -import vg.civcraft.mc.namelayer.permission.PermissionType; -/** - * Just a useful class with general and misplaced methods that can be - * called from anywhere. - * - */ -public class Utility { - - private static ReinforcementManager rm = Citadel.getReinforcementManager(); - private static Random rng = new Random(); - /** - * Creates a PlayerReinforcement or returns null if if player doesn't have - * the required requirements. - * @param The Player who created the reinforcement. - * @param The Group this reinforcement belongs too. - * @param The Block this reinforcement is occurring on. - * @param The ReinforcementType that is being reinforced on the block. - * @param The ItemStack type of the block being placed (if CTF, null if CTR) - * @return The PlayerReinforcement that comes from these parameters or null if certain checks failed. - * @throws ReinforcemnetFortificationCancelException - */ - public static PlayerReinforcement createPlayerReinforcement(Player player, Group g, Block block, - ReinforcementType type, ItemStack reinfMat) { - if (player == null || g == null || block == null || type == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility createPlayerReinforcement called with null: {0},{1},{2},{3}", - new Object[] {player, g, block, type}); - return null; - } - - if (g.isDisciplined()) { - player.sendMessage(ChatColor.RED + "This group is disciplined."); - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Request to create reinforcement for disciplined group " + g.getName()); - } - return null; - } - if (NonReinforceableType.isNonReinforceable(block.getType())){ - player.sendMessage(ChatColor.RED + "That block cannot be reinforced."); - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Request to create reinforcement for unreinforceable block " + block.getType()); - } - return null; - } - - if (!NameAPI.getGroupManager().hasAccess(g.getName(), player.getUniqueId(), PermissionType.getPermission("REINFORCE"))) { - player.sendMessage(ChatColor.RED + "You don't have permission to reinforce on this group"); - return null; - } - - // Find necessary itemstacks - final PlayerInventory inv = player.getInventory(); - final int invSize = inv.getSize(); - final ItemStack itemType = type.getItemStack(); - List slots = new ArrayList(type.getRequiredAmount()); - int requirementscheck = type.getRequiredAmount(); - if (requirementscheck <= 0) { - Citadel.Log("Reinforcement requirements too low for " + itemType.getType().name()); - return null; - } - if (reinfMat != null && itemType.isSimilar(reinfMat)){ // only in CTF. - requirementscheck++; - } - int requirements = requirementscheck; - try { - for (int slot = 0; slot < invSize && requirements > 0; ++slot) { - final ItemStack slotItem = inv.getItem(slot); - if (slotItem == null) { - continue; - } - if (!slotItem.isSimilar(itemType)) { - continue; - } - requirementscheck -= slotItem.getAmount(); - slots.add(slot); - } - } catch (Exception ex) { - // Eat any inventory size mis-match exceptions, like with the Anvil - } - if (requirementscheck > 0) { - // Not enough reinforcement material - return null; - } - // Fire the creation event - PlayerReinforcement rein = new PlayerReinforcement(block.getLocation(), - type.getHitPoints(), getIntFormofMaturation(System.currentTimeMillis(),type.getItemStack()), - getIntFormofAcidMaturation(System.currentTimeMillis(),type.getItemStack()), - g, type.getItemStack()); - ReinforcementCreationEvent event = new ReinforcementCreationEvent(rein, block, player); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - throw new ReinforcemnetFortificationCancelException(); - } - if (CitadelConfigManager.shouldLogReinforcement()) { - StringBuffer slb = new StringBuffer(); - if (player != null) { - slb.append("Player ").append(player.getName()).append(" [").append(player.getUniqueId()) - .append("]"); - } - slb.append("reinforced a ").append(block.getType()).append(" with a ") - .append(rein.getMaterial()).append(" reinforcement at ") - .append(rein.getLocation()); - Citadel.Log(slb.toString()); - } - // Now eat the materials - - // Handle special case with block reinforcements. - if (type.getMaterial().isBlock()){ - if (slots.size()>1){ - if (inv.getItemInHand().isSimilar(itemType) && PlayerState.get(player).getMode() == ReinforcementMode.REINFORCEMENT_FORTIFICATION && slots.get(0) != inv.getHeldItemSlot()){ - requirements--; - } - } - } - for (final int slot : slots) { - if (requirements <= 0) { - break; - } - final ItemStack slotItem = inv.getItem(slot); - final int stackSize = slotItem.getAmount(); - final int deduction = Math.min(stackSize, requirements); - - if (deduction < stackSize) { - slotItem.setAmount(stackSize - deduction); - } else { - inv.clear(slot); - } - requirements -= deduction; - } - if (requirements != 0) { - Citadel.Log(String.format( "Reinforcement material out of sync %d vs %d", - requirements, type.getRequiredAmount())); - } - player.updateInventory(); - rm.saveInitialReinforcement(rein); - return rein; - } - - /** - * Creates a player reinforcement without consuming any materials. This should only be used - * for admin tools - * @param The player who is creating the reinforcement - * @param The Group this reinforcement belongs too. - * @param The Block this reinforcement is occurring on. - * @param The ReinforcementType that is being reinforced on the block. - * @return The PlayerReinforcement that comes from these parameters or null if certain checks failed. - * @throws ReinforcemnetFortificationCancelException - */ - public static PlayerReinforcement createPlayerReinforcementWithoutMaterialConsumption(Player player, - Group g, Block block, ReinforcementType type) { - if (g == null || block == null || type == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility createPlayerReinforcementWithoutMaterialConsumption called with null: {0},{1},{2}", - new Object[] {g, block, type}); - return null; - } else if (player == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility createPlayerReinforcementWithoutMaterialConsumption called with player as null"); - } - - //no error messages towards the player because this might be called a few thousand times - if (g.isDisciplined()) { - return null; - } - if (NonReinforceableType.isNonReinforceable(block.getType())){ - return null; - } - PlayerReinforcement rein = new PlayerReinforcement(block.getLocation(), - type.getHitPoints(), getIntFormofMaturation(System.currentTimeMillis(),type.getItemStack()), - getIntFormofAcidMaturation(System.currentTimeMillis(),type.getItemStack()), - g, type.getItemStack()); - ReinforcementCreationEvent event = new ReinforcementCreationEvent(rein, block, player); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - throw new ReinforcemnetFortificationCancelException(); - } - rm.saveInitialReinforcement(rein); - return rein; - } - - /** - * Checks if creating a plant reinforcement would result in a - * double reinforcement. - * @param The block of the plant. - * @return True if it would create a double reinforcement. - * @return False if it would not. - */ - public static boolean wouldPlantDoubleReinforce(final Block block) { - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility wouldPlantDoubleReinforce called with null"); - return false; - } - - final Material blockMat = block.getType(); - if (isReinforceablePlant(blockMat) - && rm.getReinforcement(block.getLocation()) != null) { - return true; - } - final Block above = block.getRelative(BlockFace.UP); - final Material aboveMat = above.getType(); - if (isReinforceablePlant(aboveMat)) { - final Set soilTypes = getPlantSoilTypes(aboveMat); - if (soilTypes.contains(blockMat) - && Citadel.getReinforcementManager(). - getReinforcement(above.getLocation()) != null) { - return true; - } - } - return false; - } - - private static boolean isReinforceablePlant(Material mat) { - // If this list changes, update wouldPlantDoubleReinforce to account - // for the new soil types. - return Material.MELON_BLOCK.equals(mat) - || Material.PUMPKIN.equals(mat); - } - /** - * Returns a list of Materials that this plant can go on. - * @param Material of the plant. - * @return List of Materials that it can grow on. - */ - public static Set getPlantSoilTypes(Material mat) { - Set soilTypes = new HashSet(); - if (isSoilPlant(mat)) { - soilTypes.add(Material.SOIL); - } - if (isDirtPlant(mat)) { - soilTypes.add(Material.DIRT); - } - if (isGrassPlant(mat)) { - soilTypes.add(Material.GRASS); - } - if (isSandPlant(mat)) { - soilTypes.add(Material.SAND); - } - if (isSoulSandPlant(mat)) { - soilTypes.add(Material.SOUL_SAND); - } - return soilTypes; - } - - private static boolean isSoilPlant(Material mat) { - return Material.WHEAT.equals(mat) - || Material.MELON_STEM.equals(mat) - || Material.PUMPKIN_STEM.equals(mat) - || Material.CARROT.equals(mat) - || Material.POTATO.equals(mat) - || Material.CROPS.equals(mat) - || Material.MELON_BLOCK.equals(mat) - || Material.PUMPKIN.equals(mat); - } - - private static boolean isDirtPlant(Material mat) { - return Material.SUGAR_CANE_BLOCK.equals(mat) - || Material.MELON_BLOCK.equals(mat) - || Material.PUMPKIN.equals(mat); - } - - private static boolean isGrassPlant(Material mat) { - return Material.SUGAR_CANE_BLOCK.equals(mat) - || Material.MELON_BLOCK.equals(mat) - || Material.PUMPKIN.equals(mat); - } - - private static boolean isSandPlant(Material mat) { - return Material.CACTUS.equals(mat) - || Material.SUGAR_CANE_BLOCK.equals(mat); - } - - private static boolean isSoulSandPlant(Material mat) { - return Material.NETHER_WARTS.equals(mat); - } - - public static boolean isPlant(Block plant) { - return isPlant(plant.getType()); - } - - public static boolean isPlant(Material mat) { - return isSoilPlant(mat) - || isDirtPlant(mat) - || isGrassPlant(mat) - || isSandPlant(mat) - || isSoulSandPlant(mat); - } - - private static int maxPlantHeight(Block plant) { - switch(plant.getType()) { - case CACTUS: - return 3; - case SUGAR_CANE_BLOCK: - return 3; - default: - return 1; - } - } - /** - * Checks to see if a reinforcement is damaged if it exists. - * @param The block holding the reinforcement. - * @return Returns false if no reinforcement exists and if it was broken. - */ - public static boolean maybeReinforcementDamaged(Block block) { - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility maybeReinforcementDamaged called with null"); - return false; - } - - Reinforcement reinforcement = rm.getReinforcement(block.getLocation()); - return reinforcement != null && reinforcementDamaged(null, reinforcement); - } - /** - * Damages the reinforcement. - * @param The Reinforcement required. - * @return True if the reinforcement was securable. - */ - public static boolean reinforcementDamaged(Player player, Reinforcement reinforcement) { - if (reinforcement == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility reinforcementDamaged called with null"); - return false; - } - int durability = reinforcement.getDurability(); - int durabilityLoss = 1; - if (reinforcement instanceof PlayerReinforcement && CitadelConfigManager.isMaturationEnabled()) { - final int maturationTime = timeUntilMature(reinforcement); - PlayerReinforcement rein = (PlayerReinforcement) reinforcement; - ReinforcementType type = ReinforcementType.getReinforcementType(rein.getStackRepresentation()); - - durabilityLoss = rein.getDamageMultiplier(); - - if (maturationTime > 0 && type.getMaturationScale() != 0) { - // the default amount of minutes it takes to mature - int normal = type.getMaturationTime(); - if (maturationTime == normal) { - durabilityLoss = durability; - } else { - double percentTo = (double) maturationTime / (double) normal; // the percent of time left of maturation - durabilityLoss = (int) (((double) durabilityLoss / (1.0d - percentTo)) * (double) type.getMaturationScale()); - } // this new code scales smoothly between MaturationScale and a very large number, being closer to - // MaturationScale the closer to "done" a maturation cycle - } - - if (durability < durabilityLoss) { - durabilityLoss = durability; - } - } - int olddurability = durability; - durability -= durabilityLoss; - reinforcement.setDurability(durability); - boolean cancelled = durability > 0; - if (durability <= 0) { - cancelled = reinforcementBroken(null, reinforcement); - } else { - /* TODO: Move to ReinforcementEvent listener*/ - if (CitadelConfigManager.shouldLogBreaks()) { - StringBuffer slb = new StringBuffer(); - if (player != null) { - slb.append("Player ").append(player.getName()).append(" [").append(player.getUniqueId()) - .append("]"); - } else { - slb.append("Something "); - } - slb.append("damaged a ").append(reinforcement.getMaterial()); - int strength = 0; - if (reinforcement instanceof PlayerReinforcement) { - slb.append("reinforcement to "); - ReinforcementType type = ReinforcementType.getReinforcementType( - ((PlayerReinforcement) reinforcement).getStackRepresentation()); - strength = type.getHitPoints(); - } else if (reinforcement instanceof NaturalReinforcement) { - slb.append("natural reinforcement to "); - NaturalReinforcementType type = NaturalReinforcementType.getNaturalReinforcementType( - reinforcement.getType()); - strength = type.getDurability(); - } else { - slb.append("null reinforcement to "); - } - double nratio = strength > 0 ? (double) durability / (double) strength: 0; - double oratio = strength > 0 ? (double) olddurability / (double) strength: 1; - if ( nratio <= 0.25 && oratio > 0.25) { - slb.append("poor ("); - } else if ( nratio <= 0.5 && oratio > 0.5) { - slb.append("decent ("); - } else if ( nratio <= 0.75 && oratio > 0.75) { - slb.append("well ("); - } else if ( nratio < 1.0 && oratio == 1.0) { - slb.append("excellent ("); - } - slb.append(durability).append(") at ").append(reinforcement.getLocation()); - } - if (reinforcement instanceof PlayerReinforcement) { - // leave message - } - rm.saveReinforcement(reinforcement); - } - return cancelled; - } - /** - * Used to get the amount of time left until a reinforcement is mature. - * @param Reinforcement. - * @return Returns 0 if it is mature or the time in minutes until it is mature. - */ - public static int timeUntilMature(Reinforcement reinforcement) { - if (reinforcement == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility timeUntilMature called with null"); - return 0; - } - // Doesn't explicitly save the updated Maturation time into the cache. - // That's the responsibility of the caller. - if (reinforcement instanceof PlayerReinforcement){ - int maturationTime = reinforcement.getMaturationTime(); - if (maturationTime > 0) { - final int curMinute = (int)(System.currentTimeMillis() / 60000L); - if (curMinute >= maturationTime) { - maturationTime = 0; - reinforcement.setMaturationTime(0); - } else { - maturationTime = maturationTime - curMinute; - } - } - return (int) maturationTime; // should be small enough by now - } - return 0; - } - /** - * Used to get the amount of time left until a reinforcement's acid component is mature. - * @param Reinforcement. - * @return Returns 0 if it is mature or the time in minutes until it is mature. - */ - public static int timeUntilAcidMature(Reinforcement reinforcement) { - if (reinforcement == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility timeUntilAcidMature called with null"); - return 0; - } // Doesn't explicitly save the updated Acid Maturation time into the cache. - // That's the responsibility of the caller. - if (reinforcement instanceof PlayerReinforcement){ - int maturationTime = reinforcement.getAcidTime(); - if (maturationTime > 0) { - final int curMinute = (int)(System.currentTimeMillis() / 60000L); - if (curMinute >= maturationTime) { - maturationTime = 0; - reinforcement.setAcidTime(0); - } else { - maturationTime = maturationTime - curMinute; - } - } - return (int) maturationTime; // should be small enough by now - } - return 0; - } - - /** - * - * /ctb mode type break - * - * @param The Player who broke the reinforcement - * @param The Reinforcement broken. - * @return Returns true if it is securable. - * @return Returns false if it is no securable. - */ - public static boolean reinforcementBroken(Player player, Reinforcement reinforcement) { - if (reinforcement == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility reinforcementBroken called with null reinforcement"); - return false; - } - StringBuffer slb = null; - if (CitadelConfigManager.shouldLogBreaks()) { - slb = new StringBuffer(); - if (player != null) { - slb.append("Player ").append(player.getName()).append(" [").append(player.getUniqueId()) - .append("]"); - } else { - slb.append("Something "); - } - slb.append("broke a ").append(reinforcement.getMaterial()).append(" reinforcement at ") - .append(reinforcement.getLocation()); - } - Citadel.getReinforcementManager().deleteReinforcement(reinforcement); - if (reinforcement instanceof PlayerReinforcement) { - PlayerReinforcement pr = (PlayerReinforcement)reinforcement; - ReinforcementType material = ReinforcementType.getReinforcementType(pr.getStackRepresentation()); - if (rng.nextDouble() <= pr.getHealth() * material.getPercentReturn()) { - Location location = pr.getLocation(); - if (player != null){ - Inventory inv = player.getInventory(); - if (CitadelConfigManager.shouldDropReinforcedBlock()){ - // If we should drop a block instead - ItemStack stack = createDroppedReinforcementBlock - (reinforcement.getLocation().getBlock(), (PlayerReinforcement) reinforcement); - for(ItemStack leftover : inv.addItem( - stack).values()) { - dropItemAtLocation(location, leftover); - } - } - else { - for(ItemStack leftover : inv.addItem( - material.getItemStack()) - .values()) { - dropItemAtLocation(location, leftover); - } - } - } - else { - dropItemAtLocation(location, new ItemStack(material.getMaterial() - , material.getReturnValue())); - } - if (CitadelConfigManager.shouldLogBreaks()) { - slb.append(" - reinf mat refunded"); - Citadel.Log(slb.toString()); - } - } else if (CitadelConfigManager.shouldLogBreaks()) { - slb.append(" - reinf mat lost"); - Citadel.Log(slb.toString()); - } - return (pr.isDoor() || pr.isContainer()); - } - if (CitadelConfigManager.shouldLogBreaks()) { - Citadel.Log(slb.toString()); - } - return false; // implicit isSecureable() == false - } - - - /** - * A better version of dropNaturally that mimics normal drop behavior. - * - * The built-in version of Bukkit's dropItem() method places the item at the block - * vertex which can make the item jump around. - * This method places the item in the middle of the block location with a slight - * vertical velocity to mimic how normal broken blocks appear. - * @param l The location to drop the item - * @param is The item to drop - * - * @author GordonFreemanQ - */ - public static void dropItemAtLocation(final Location l, final ItemStack is) { - // Schedule the item to drop 1 tick later - Bukkit.getScheduler().scheduleSyncDelayedTask(Citadel.getInstance(), new Runnable() { - @Override - public void run() { - try { - l.getWorld().dropItem(l.add(0.5, 0.5, 0.5), is).setVelocity(new Vector(0, 0.05, 0)); - } catch (Exception e) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility dropItemAtLocation called but errored: ", e); - } - } - }, 1); - } - - - /** - * Overload for dropItemAtLocation(Location l, ItemStack is) that accepts a block parameter. - * @param b The block to drop it at - * @param is The item to drop - * - * @author GordonFreemanQ - */ - public static void dropItemAtLocation(Block b, ItemStack is) { - if (b == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility dropItemAtLocation block called with null"); - return; - } - dropItemAtLocation(b.getLocation(), is); - } - - /** - * Checks if a Redstone player is trying to power a block. - * @param The Reinforcement in question. - * @param The distance the player is from the block. - * @return Returns true if the player is on the group and has permission. - * @return Returns false if the player is not on the group or doesn't have permission. - */ - public static boolean isAuthorizedPlayerNear(PlayerReinforcement reinforcement, double distance) { - if (reinforcement == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility isAuthorizedPlayerNear called with null"); - return false; - } - Location reinLocation = reinforcement.getLocation(); - double min_x = reinLocation.getX() - distance; - double min_z = reinLocation.getZ() - distance; - double max_x = reinLocation.getX() + distance; - double max_z = reinLocation.getZ() + distance; - List onlinePlayers = new ArrayList(); - for (Player p: Bukkit.getOnlinePlayers()) { - onlinePlayers.add(p); - } - boolean result = false; - try { - for (Player player : onlinePlayers) { - if (player.isDead()) { - continue; - } - Location playerLocation = player.getLocation(); - double player_x = playerLocation.getX(); - double player_z = playerLocation.getZ(); - // Simple bounding box check to quickly rule out Players - // before doing the more expensive playerLocation.distance - if (player_x < min_x || player_x > max_x || - player_z < min_z || player_z > max_z) { - continue; - } - if (!reinforcement.canAccessDoors(player) - && !player.hasPermission("citadel.admin.accesssecurable")) { - continue; - } - double distanceSquared = playerLocation.distance(reinLocation); - if (distanceSquared <= distance) { - result = true; - break; - } - } - } catch (ConcurrentModificationException e) { - Citadel.Log("ConcurrentModificationException at redstonePower() in BlockListener"); - } - return result; - } - /** - * Creates a Natural Reinforcement. - * @param The block that will have a natural reinforcement - * @param The Player who damaged the block. - * @return Returns a natural Reinforcement for the block or null if it isn't meant to have one. - */ - public static NaturalReinforcement createNaturalReinforcement(Block block, Player player) { - if (block == null || player == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility createNaturalReinforcement called with null"); - return null; - } - Material material = block.getType(); - NaturalReinforcementType nType = NaturalReinforcementType. - getNaturalReinforcementType(material); - if (nType == null) { - return null; - } - int breakCount = nType.getDurability(); - NaturalReinforcement nr = new NaturalReinforcement(block, breakCount); - ReinforcementCreationEvent event = new ReinforcementCreationEvent(nr, block, player); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, - "createNaturalReinforcement for " + block.getType() + " cancelled"); - } - - return null; - } - Citadel.getReinforcementManager().saveInitialReinforcement(nr); - return nr; - } - - /** - * This method is used to convert Block Reinforcements to itemstacks - * @param The block that is being converted into a BlockReinforcement - * @param The reinforcement on it - * @return Itemstack form of the reinforcement on a block - */ - public static ItemStack createDroppedReinforcementBlock(Block block, PlayerReinforcement rein){ - if (block == null || rein == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility createDroppedReinforcementBlock called with null"); - return null; - } - ItemStack reinBlock = new ItemStack(block.getType(), 1); - ItemMeta lore = reinBlock.getItemMeta(); - List info = new ArrayList(); - String reinMat = rein.getMaterial().name(); - String amount = Integer.toString(rein.getStackRepresentation().getAmount()); - String dur = Integer.toString(ReinforcementType.getReinforcementType(rein.getStackRepresentation()).getHitPoints()); - String group = rein.getGroup().getName(); - info.add(reinMat); - info.add(amount); - info.add(dur); - info.add(group); - if (rein.getStackRepresentation().hasItemMeta()) { - info.addAll(rein.getStackRepresentation().getItemMeta().getLore()); - lore.setLore(info); - } - reinBlock.setItemMeta(lore); - return reinBlock; - } - /** - * Returns the Reinforcement of a block if it was previously a reinforcement. - * Importantly though if a group that this block was associated with - * gets deleted this block when placed will not belong to anyone. - * @param The player placing the block - * @param The stack the player is placing from - * @param The location where the block is being placed - * @return The PlayerReiforcement associated with this block - */ - public static PlayerReinforcement isDroppedReinforcementBlock(Player p, ItemStack stack, Location loc){ - if (stack == null || loc == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility isDroppedReinforcementBlock called with null"); - return null; - } - ItemMeta meta = stack.getItemMeta(); - List lore = meta.getLore(); - try{ - if (!meta.hasLore()) { - return null; - } - Iterator value = lore.iterator(); - if (!value.hasNext()) { - return null; - } - Material mat = Material.valueOf(value.next()); - if (!value.hasNext()) { - return null; - } - int amount = Integer.parseInt(value.next()); - if (!value.hasNext()) { - return null; - } - int dur = Integer.parseInt(value.next()); - if (!value.hasNext()) { - return null; - } - String group = value.next(); - List itemStackInfo = new ArrayList(); - while(value.hasNext()) { - itemStackInfo.add(value.next()); - } - ItemStack newStack = new ItemStack(mat, amount); - meta.setLore(itemStackInfo); - newStack.setItemMeta(meta); - ReinforcementType reinType = ReinforcementType.getReinforcementType(newStack); - if (reinType == null) { - return null; - } - Group g = GroupManager.getSpecialCircumstanceGroup(group); - PlayerReinforcement rein = new PlayerReinforcement(loc, dur, - getIntFormofMaturation(System.currentTimeMillis(),reinType.getItemStack()), - getIntFormofAcidMaturation(System.currentTimeMillis(),reinType.getItemStack()), - g, reinType.getItemStack()); - ReinforcementCreationEvent event = - new ReinforcementCreationEvent(rein, loc.getBlock(), p); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, - "Dropped reinforcement creation event for " + rein.getType() + " cancelled"); - } - return null; - } - return rein; - } catch (IllegalArgumentException iae){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility isDroppedReinforcementBlock failed", iae); - } catch(Exception ex){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility isDroppedReinforcementBlock failed", ex); - } - return null; - } - /** - * If a reinforcement is exploded checks if it has a reinforcement on it - * or not. - * @param The block that exploded. - * @return True if there is a reinforcement. - * @return False if there is not a reinforcement. - */ - public static boolean explodeReinforcement(Block block) { - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility explodeReinforcement called with null"); - return false; - } - Reinforcement reinforcement = rm.getReinforcement(block); - if (reinforcement == null) { - reinforcement = createNaturalReinforcement(block, null); - } - if (reinforcement == null) { - return false; - } - return reinforcementDamaged(null, reinforcement); - } - - /** - * Creates a MultiBlockReinforcement and saves it to the db. This method is to be used only be other plugins. Citadel - * will not use this anywhere. - * @param locs The locations that make up the structure. - * @param g The group this will belong too. - * @param dur The durability this structure will have. - * @param mature The amount of time until it is mature (in minutes). - * @param acid The amount of time until it is mature (if acid -- in minutes). - * @return - */ - public static MultiBlockReinforcement createMultiBlockReinforcement(List locs, Group g, int dur, int mature, int acid){ - if (locs == null || g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility createMultiBlockReinforcement called with null"); - return null; - } - MultiBlockReinforcement rein = new MultiBlockReinforcement(locs, g, dur, mature, acid, -1); - ReinforcementCreationEvent event = new ReinforcementCreationEvent(rein, rein.getLocation().getBlock(), null); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, - "multiblock reinforcement creation event for " + rein.getType() + " cancelled"); - } - return null; - } - rm.saveInitialReinforcement(rein); - return rein; - } - - public static Block getAttachedChest(Block block) { - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility getAttachedChest called with null"); - return null; - } - Material mat = block.getType(); - if (Material.CHEST.equals(mat) || Material.TRAPPED_CHEST.equals(mat)) { - for (BlockFace face : cardinals) { - Block b = block.getRelative(face); - if (b.getType() == mat) { - return b; - } - } - } - return null; - } - - private static BlockFace[] cardinals = new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}; - - public static List doorTypes = new ArrayList(Arrays.asList( - Material.WOODEN_DOOR, Material.IRON_DOOR_BLOCK, - Material.ACACIA_DOOR, Material.BIRCH_DOOR, - Material.DARK_OAK_DOOR, Material.JUNGLE_DOOR, - Material.SPRUCE_DOOR, Material.WOOD_DOOR)); - /** - * Returns the block the Citadel is looking at, example: for beds, doors we want the bottom half. - * @param block - * @return Returns the block we want. - */ - public static Block getRealBlock(Block block){ - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility getRealBlock called with null"); - return null; - } - Block b = block; - switch (block.getType()){ - case CHEST: - case TRAPPED_CHEST: - if (!rm.isReinforced(block)) { - b = getAttachedChest(block); - } - if (b == null) { - b = block; - } - break; - case WOODEN_DOOR: - case IRON_DOOR_BLOCK: - case ACACIA_DOOR: - case BIRCH_DOOR: - case DARK_OAK_DOOR: - case JUNGLE_DOOR: - case SPRUCE_DOOR: - case WOOD_DOOR: - if (!doorTypes.contains(block.getRelative(BlockFace.UP).getType())) { - b = block.getRelative(BlockFace.DOWN); - } - break; - case BED_BLOCK: - if (((Bed) block.getState().getData()).isHeadOfBed()) { - b = block.getRelative(((Bed) block.getState().getData()).getFacing().getOppositeFace()); - } - break; - default: - b = block; - } - return b; - } - - private static int getIntFormofMaturation(long creation, ItemStack stack){ - if (stack == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility getIntFormofMaturation called with null"); - return 0; - } - int maturation = (int)(creation / 60000) + - ReinforcementType. - getReinforcementType(stack) - .getMaturationTime(); - return maturation; - } - - private static int getIntFormofAcidMaturation(long creation, ItemStack stack) { - if (stack == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility getIntFormofAcidMaturation called with null"); - return 0; - } - int maturation = (int)(creation / 60000) + - ReinforcementType. - getReinforcementType(stack) - .getAcidTime(); - return maturation; - } - - public static Block findPlantSoil(Block block){ - if (block == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Utility findPlantSoil called with null"); - return null; - } - final Set soilTypes = getPlantSoilTypes(block.getType()); - if(soilTypes.size() <= 0){ - return null; - } - //find the plants soil below it - Block down = block; - int max_depth = maxPlantHeight(block); - for(int i =0; i < max_depth; ++i){ - down = down.getRelative(BlockFace.DOWN); - if(soilTypes.contains(down.getType())){ - return down; - } - } - return null; - } - - public static boolean canPlace(Block block, Player player) { - Material block_mat = block.getType(); - - if (block_mat == Material.HOPPER || block_mat == Material.DROPPER){ - for (BlockFace direction : BlockListener.all_sides) { - Block adjacent = block.getRelative(direction); - if (!(adjacent.getState() instanceof InventoryHolder)) { - continue; - } - Reinforcement rein = rm.getReinforcement(adjacent); - if (null != rein && rein instanceof PlayerReinforcement) { - PlayerReinforcement pr = (PlayerReinforcement)rein; - if (pr.isInsecure() && !pr.canAccessChests(player)) { - return false; - } - } - } - } - if (block_mat == Material.CHEST || block_mat == Material.TRAPPED_CHEST){ - for (BlockFace direction : BlockListener.planar_sides) { - Block adjacent = block.getRelative(direction); - if (!(adjacent.getState() instanceof InventoryHolder)) { - continue; - } - Reinforcement rein = rm.getReinforcement(adjacent); - if (null != rein && rein instanceof PlayerReinforcement) { - PlayerReinforcement pr = (PlayerReinforcement)rein; - if (!pr.canAccessChests(player)) { - return false; - } - } - } - } - //stops players from modifying the reinforcement on a half slab by placing another block on top - Reinforcement reinforcement_on_block = Citadel.getReinforcementManager().getReinforcement(block); - if (reinforcement_on_block instanceof PlayerReinforcement) { - PlayerReinforcement reinforcement = (PlayerReinforcement) reinforcement_on_block; - if (!reinforcement.canBypass(player)) { - return false; - } - } else if (reinforcement_on_block != null) { - return false; //not really sure when this could happen but just in case - } - - return true; - } -} diff --git a/src/vg/civcraft/mc/citadel/command/CommandHandler.java b/src/vg/civcraft/mc/citadel/command/CommandHandler.java deleted file mode 100644 index 3cc44f84..00000000 --- a/src/vg/civcraft/mc/citadel/command/CommandHandler.java +++ /dev/null @@ -1,97 +0,0 @@ -package vg.civcraft.mc.citadel.command; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.citadel.command.commands.Acid; -import vg.civcraft.mc.citadel.command.commands.AreaReinforce; -import vg.civcraft.mc.citadel.command.commands.Bypass; -import vg.civcraft.mc.citadel.command.commands.Fortification; -import vg.civcraft.mc.citadel.command.commands.Information; -import vg.civcraft.mc.citadel.command.commands.Insecure; -import vg.civcraft.mc.citadel.command.commands.Materials; -import vg.civcraft.mc.citadel.command.commands.Off; -import vg.civcraft.mc.citadel.command.commands.Reinforce; -import vg.civcraft.mc.citadel.command.commands.SetLogging; -import vg.civcraft.mc.citadel.command.commands.Stats; -import vg.civcraft.mc.citadel.command.commands.UpdateReinforcements; -import vg.civcraft.mc.civmodcore.command.Command; - -public class CommandHandler { - public Map commands = new HashMap(); - /** - * Registers the commands for the CommandHandler. - */ - public void registerCommands(){ - addCommands(new Acid("Acid")); - addCommands(new Bypass("Bypass")); - addCommands(new Fortification("Fortification")); - addCommands(new Information("Information")); - addCommands(new Insecure("Insecure")); - addCommands(new Reinforce("Reinforce")); - addCommands(new Materials("Materials")); - addCommands(new Off("Off")); - addCommands(new Stats("Stats")); - addCommands(new UpdateReinforcements("UpdateReinforcements")); - addCommands(new AreaReinforce("AreaReinforce")); - addCommands(new SetLogging("SetLogging")); - } - - private void addCommands(Command command){ - commands.put(command.getIdentifier().toLowerCase(), command); - } - /** - * Is called when a command is executed. Should not be touched by any outside - * plugin. - * @param sender - * @param cmd - * @param args - * @return - */ - public boolean execute(CommandSender sender, org.bukkit.command.Command cmd, String[] args){ - if (commands.containsKey(cmd.getName().toLowerCase())){ - Command command = commands.get(cmd.getName().toLowerCase()); - if (args.length < command.getMinArguments() || args.length > command.getMaxArguments()){ - helpPlayer(command, sender); - return true; - } - - command.execute(sender, args); - } - return true; - } - - /** - * Is called when a tab is pressed. Should not be touched by any outside - * plugin. - * @param sender - * @param cmd - * @param args - * @return - */ - - public List complete(CommandSender sender, org.bukkit.command.Command cmd, String[] args){ - if (commands.containsKey(cmd.getName().toLowerCase())){ - Command command = commands.get(cmd.getName().toLowerCase()); - return command.tabComplete(sender, args); - } - return null; - } - /** - * Sends a player help message. - * @param The Command that was executed. - * @param The CommandSender who executed the command. - */ - public void helpPlayer(Command command, CommandSender sender){ - sender.sendMessage(new StringBuilder().append(ChatColor.RED + "Command: " ).append(command.getName()).toString()); - sender.sendMessage(new StringBuilder().append(ChatColor.RED + "Description: " ).append(command.getDescription()).toString()); - sender.sendMessage(new StringBuilder().append(ChatColor.RED + "Usage: ").append(command.getUsage()).toString()); - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Acid.java b/src/vg/civcraft/mc/citadel/command/commands/Acid.java deleted file mode 100644 index 412e998f..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Acid.java +++ /dev/null @@ -1,133 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.*; -import java.util.logging.Level; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.util.BlockIterator; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.Utility; -import vg.civcraft.mc.citadel.events.AcidBlockEvent; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.NameAPI; - -public class Acid extends PlayerCommandMiddle { - private ReinforcementManager rm = Citadel.getReinforcementManager(); - - public Acid(String name) { - super(name); - setIdentifier("ctacid"); - setDescription("Removes the block above it if using an acid block."); - setUsage("/ctacid"); - setArguments(0, 0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("You must be a player to perform this command."); - return true; - } - Player p = (Player) sender; - Iterator itr = new BlockIterator(p, 40); // Within 2.5 chunks - Material acidBlock = CitadelConfigManager.getAcidBlock(); - while (itr.hasNext()) { - Block block = itr.next(); - if (block.getType() != acidBlock) { - continue; - } - Reinforcement rein = rm.getReinforcement(block); - if (rein == null) { - sendAndLog(p, ChatColor.RED, "That block is not reinforced."); - return true; - } - if (!(rein instanceof PlayerReinforcement)) { // Just in case. - // Most chance it is a PlayerReinforcement but otherwise. - sendAndLog(p, ChatColor.RED, - "An acid block cannot be a natural reinforcement."); - return true; - } - PlayerReinforcement pRein = (PlayerReinforcement) rein; - UUID uuid = NameAPI.getUUID(p.getName()); - if (pRein.getGroup() == null) { - sendAndLog(p, ChatColor.RED, "No-one is on that group."); - return true; - } - if (!pRein.getGroup().isMember(uuid)) { - sendAndLog(p, ChatColor.RED, "You do not belong on that group."); - return true; - } - if (!pRein.canAcid(p)) { - sendAndLog(p, ChatColor.RED, "You do not have sufficient permission to use acid blocks on this group."); - return true; - } - int time = Utility.timeUntilAcidMature(pRein); - if (time != 0) { - sendAndLog(p, ChatColor.RED, "That acid block is not mature yet."); - return true; - } - Block topFace = block.getRelative(BlockFace.UP); - if (Material.AIR.equals(topFace.getType())) { - sendAndLog(p, ChatColor.RED, "There is no block above to acid block."); - return true; - } - Reinforcement topRein = rm.getReinforcement(topFace); - if (topRein == null) { - sendAndLog(p, ChatColor.RED, "That block doesn't have a reinforcement."); - return true; - } - if (!(topRein instanceof PlayerReinforcement)) { - continue; - } - PlayerReinforcement pTopRein = (PlayerReinforcement) topRein; - ReinforcementType acidBlockType = ReinforcementType - .getReinforcementType(pRein.getStackRepresentation()); - ReinforcementType topReinType = ReinforcementType - .getReinforcementType(pTopRein.getStackRepresentation()); - if (acidBlockType.getAcidTime() < topReinType.getAcidTime()) { - sendAndLog(p, ChatColor.RED, "This acid block is too weak for that reinforcement."); - return true; - } - AcidBlockEvent event = new AcidBlockEvent(p, pRein, pTopRein); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, - "Acid block event cancelled for acid at " + pRein.getLocation() ); - } - return true; - } - - if (CitadelConfigManager.shouldLogBreaks()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Acid at {0} broke {1} at {2}", - new Object[] {block.getLocation(), topFace.getType(), topFace.getLocation()}); - } - - topFace.setType(Material.AIR); - - block.breakNaturally(); - - // Consider if should simply be an AcidBlockEvent listener. This will do for now. - Utility.reinforcementBroken(p, pRein); - rm.deleteReinforcement(pTopRein); - - } - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/AreaReinforce.java b/src/vg/civcraft/mc/citadel/command/commands/AreaReinforce.java deleted file mode 100644 index 2ae540cf..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/AreaReinforce.java +++ /dev/null @@ -1,112 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.lang.Integer; -import java.lang.Math; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.Utility; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.group.Group; - -public class AreaReinforce extends PlayerCommandMiddle { - private ReinforcementManager rm = Citadel.getReinforcementManager(); - private GroupManager gm = NameAPI.getGroupManager(); - - public AreaReinforce(String name) { - super(name); - setIdentifier("ctar"); - setDescription("Allows you to reinforce entire areas"); - setUsage("/ctar "); - setArguments(6, 7); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("Must be a player to perform this command."); - return true; - } - Player p = (Player) sender; - UUID uuid = NameAPI.getUUID(p.getName()); - if (!p.isOp() && !p.hasPermission("citadel.admin")) { - // This should never actually happen thanks to the plugin.yml, but - // we just want to be sure - sendAndLog(p, ChatColor.RED, "Nice try"); - return true; - } - ReinforcementType rt = ReinforcementType.getReinforcementType(p - .getItemInHand()); - if (rt == null) { - sendAndLog(p, ChatColor.RED, "The item you are holding is not a possible reinforcement"); - return true; - } - String groupName = null; - if (args.length == 6) { - groupName = gm.getDefaultGroup(uuid); - if (groupName == null) { - sendAndLog(p, ChatColor.RED, "You need to set a default group \n Use /nlsdg to do so"); - return true; - } - } else { - groupName = args[0]; - } - Group g = gm.getGroup(groupName); - if (g == null) { - sendAndLog(p, ChatColor.RED, "That group does not exist."); - return true; - } - // no additional group permission check here because the player is - // admin/op anyway - int xMin, yMin, zMin, xMax, yMax, zMax; - int offset = args.length == 7 ? 1 : 0; - try { - int x1 = Integer.parseInt(args[offset]); - int y1 = Integer.parseInt(args[offset + 1]); - int z1 = Integer.parseInt(args[offset + 2]); - int x2 = Integer.parseInt(args[offset + 3]); - int y2 = Integer.parseInt(args[offset + 4]); - int z2 = Integer.parseInt(args[offset + 5]); - xMin = Math.min(x1, x2); - yMin = Math.min(y1, y2); - zMin = Math.min(z1, z2); - xMax = Math.max(x1, x2); - yMax = Math.max(y1, y2); - zMax = Math.max(z1, z2); - } catch (NumberFormatException e) { - sendAndLog(p, ChatColor.RED, "One of the arguments you provided was not a number"); - return false; - } - for (int x = xMin; x <= xMax; x++) { - for (int y = yMin; y <= yMax; y++) { - for (int z = zMin; z <= zMax; z++) { - Block current = Utility.getRealBlock(p.getWorld() - .getBlockAt(x, y, z)); - if (!(current.getType() == Material.AIR) && !rm.isReinforced(current) - && !Utility.wouldPlantDoubleReinforce(current)) { - Utility.createPlayerReinforcementWithoutMaterialConsumption(p, g, current, rt); - } - } - } - } - - sendAndLog(p, ChatColor.GREEN, "Successfully created reinforcements"); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Bypass.java b/src/vg/civcraft/mc/citadel/command/commands/Bypass.java deleted file mode 100644 index 77829fc5..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Bypass.java +++ /dev/null @@ -1,46 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementManager; - -import java.util.ArrayList; -import java.util.List; - -public class Bypass extends PlayerCommandMiddle{ - private ReinforcementManager rm = Citadel.getReinforcementManager(); - - public Bypass(String name) { - super(name); - setIdentifier("ctb"); - setDescription("Used to bypass block reinforcements."); - setUsage("/ctb"); - setArguments(0,0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to perform that command."); - return true; - } - Player p = (Player) sender; - PlayerState state = PlayerState.get(p); - if (state.toggleBypassMode()){ - sendAndLog(p, ChatColor.GREEN, "Bypass mode has been enabled."); - } - else { - sendAndLog(p, ChatColor.GREEN, "Bypass mode has been disabled."); - } - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Fortification.java b/src/vg/civcraft/mc/citadel/command/commands/Fortification.java deleted file mode 100644 index 60127d1d..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Fortification.java +++ /dev/null @@ -1,109 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.ReinforcementMode; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.GroupManager.PlayerType; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.command.TabCompleters.GroupTabCompleter; -import vg.civcraft.mc.namelayer.group.Group; -import vg.civcraft.mc.namelayer.permission.PermissionType; - -public class Fortification extends PlayerCommandMiddle{ - private ReinforcementManager rm = Citadel.getReinforcementManager(); - private GroupManager gm = NameAPI.getGroupManager(); - - public Fortification(String name) { - super(name); - setIdentifier("ctf"); - setDescription("Allows you to place already reinforced blocks."); - setUsage("/ctf "); - setArguments(0,1); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to perform this command."); - return true; - } - Player p = (Player) sender; - UUID uuid = NameAPI.getUUID(p.getName()); - String groupName = null; - if(args.length == 0){ - groupName = gm.getDefaultGroup(uuid); - if(groupName == null){ - sendAndLog(p, ChatColor.RED, "You need to set a default group \n Use /nlsdg to do so"); - return true; - } - } - else{ - groupName = args[0]; - } - Group g = gm.getGroup(groupName); - if (g == null){ - sendAndLog(p, ChatColor.RED, "That group does not exist."); - return true; - } - - PlayerType type = g.getPlayerType(uuid); - if (!p.hasPermission("citadel.admin") && !p.isOp() && type == null){ - sendAndLog(p, ChatColor.RED, "You are not on this group."); - return true; - } - if (!p.hasPermission("citadel.admin") && !p.isOp() && !gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("REINFORCE"))){ - sendAndLog(p, ChatColor.RED, "You do not have permission to " - + "place a reinforcement on this group."); - return true; - } - ItemStack stack = p.getItemInHand(); - PlayerState state = PlayerState.get(p); - ReinforcementType reinType = ReinforcementType.getReinforcementType(stack); - if (state.getMode() == ReinforcementMode.REINFORCEMENT_FORTIFICATION){ - sendAndLog(p, ChatColor.GREEN, state.getMode().name() + " has been disabled"); - state.reset(); - } - else{ - if (stack.getType() == Material.AIR){ - sendAndLog(p, ChatColor.RED, "You need to be holding an ItemStack."); - return true; - } - else if (reinType == null){ - sendAndLog(p, ChatColor.RED, "That is not a ReinforcementType."); - return true; - } - sendAndLog(p, ChatColor.GREEN, "Your mode has been set to " + - ReinforcementMode.REINFORCEMENT_FORTIFICATION.name() + "."); - state.setMode(ReinforcementMode.REINFORCEMENT_FORTIFICATION); - state.setFortificationItemStack(reinType.getItemStack()); - state.setGroup(g); - } - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) - return null; - - if (args.length == 0) - return GroupTabCompleter.complete(null, PermissionType.getPermission("REINFORCE"), (Player)sender); - else if (args.length == 1) - return GroupTabCompleter.complete(args[0], PermissionType.getPermission("REINFORCE"), (Player)sender); - else{ - return new ArrayList(); - } - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Information.java b/src/vg/civcraft/mc/citadel/command/commands/Information.java deleted file mode 100644 index 71dfb689..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Information.java +++ /dev/null @@ -1,47 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementMode; - -import java.util.ArrayList; -import java.util.List; - -public class Information extends PlayerCommandMiddle{ - - public Information(String name) { - super(name); - setIdentifier("cti"); - setDescription("Get information about a clicked block."); - setUsage("/cti"); - setArguments(0,0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to perform that command."); - return true; - } - Player p = (Player) sender; - PlayerState state = PlayerState.get(p); - if (state.getMode() == ReinforcementMode.REINFORCEMENT_INFORMATION){ - sendAndLog(p, ChatColor.GREEN, state.getMode().name() + " has been disabled"); - state.reset(); - } - else{ - sendAndLog(p, ChatColor.GREEN, "Reinforcement mode changed to " - + ReinforcementMode.REINFORCEMENT_INFORMATION.name() + "."); - state.setMode(ReinforcementMode.REINFORCEMENT_INFORMATION); - } - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Insecure.java b/src/vg/civcraft/mc/citadel/command/commands/Insecure.java deleted file mode 100644 index 03c3a207..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Insecure.java +++ /dev/null @@ -1,48 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementMode; - -import java.util.ArrayList; -import java.util.List; - -public class Insecure extends PlayerCommandMiddle{ - - public Insecure(String name) { - super(name); - setIdentifier("ctin"); - setDescription("Set a block to an insecure reinforcement."); - setUsage("/ctin"); - setArguments(0,0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to perform that command."); - return true; - } - Player p = (Player) sender; - PlayerState state = PlayerState.get(p); - if (state.getMode() == ReinforcementMode.INSECURE){ - sendAndLog(p, ChatColor.GREEN, state.getMode().name() + " has been disabled"); - state.reset(); - } - else{ - sendAndLog(p, ChatColor.GREEN, "Reinforcement mode changed to " - + ReinforcementMode.INSECURE.name() + "."); - state.setMode(ReinforcementMode.INSECURE); - } - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } - -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Materials.java b/src/vg/civcraft/mc/citadel/command/commands/Materials.java deleted file mode 100644 index 756c430a..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Materials.java +++ /dev/null @@ -1,54 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; - -public class Materials extends PlayerCommandMiddle{ - - public Materials(String name) { - super(name); - setIdentifier("ctm"); - setDescription("Shows a list of all the ReinforcementTypes."); - setUsage("/ctm"); - setArguments(0,0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to run this command."); - return true; - } - Player p = (Player) sender; - List types = ReinforcementType.getReinforcementTypes(); - String t = "The ItemStacks are as follows: \n"; - for (ReinforcementType type: types){ - t += type.getMaterial().name() + ":\n "; - t += "Amount: " + type.getRequiredAmount() + ".\n "; - t += "Strength: " + type.getHitPoints() + ".\n "; - t += "Material: " + type.getMaterial() + ".\n "; - t += "Maturation: " + type.getMaturationTime() + ".\n "; - t += "Acid Maturation: " + type.getAcidTime() + ".\n "; - if (type.getItemStack().getItemMeta().hasLore()){ - t += "Lore: "; - for (String x: type.getItemStack().getItemMeta().getLore()) - t += x + "\n "; - } - t += "-------\n"; - } - p.sendMessage(ChatColor.GREEN + t); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } - -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Off.java b/src/vg/civcraft/mc/citadel/command/commands/Off.java deleted file mode 100644 index f31eb4ac..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Off.java +++ /dev/null @@ -1,43 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.PlayerState; - -import java.util.ArrayList; -import java.util.List; - -public class Off extends PlayerCommandMiddle{ - - public Off(String name) { - super(name); - setIdentifier("cto"); - setDescription("Turns all Reinforcement Modes off."); - setUsage("/cto"); - setArguments(0,0); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to run this command."); - return true; - } - Player p = (Player) sender; - PlayerState state = PlayerState.get(p); - state.reset(); - if (state.isBypassMode()) { - state.toggleBypassMode(); - } - sendAndLog(p, ChatColor.GREEN, "Reinforcement mode has been set to Normal."); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - return new ArrayList(); - } - -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/PlayerCommandMiddle.java b/src/vg/civcraft/mc/citadel/command/commands/PlayerCommandMiddle.java deleted file mode 100644 index e2ec7953..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/PlayerCommandMiddle.java +++ /dev/null @@ -1,25 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.logging.Level; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.civmodcore.command.PlayerCommand; - -public abstract class PlayerCommandMiddle extends PlayerCommand { - - public PlayerCommandMiddle(String name) { - super(name); - } - - protected void sendAndLog(CommandSender receiver, ChatColor color, String message) { - receiver.sendMessage(color + message); - if (CitadelConfigManager.shouldLogPlayerCommands()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Sent {0} reply {1}", new Object[]{receiver.getName(), message}); - } - } -} \ No newline at end of file diff --git a/src/vg/civcraft/mc/citadel/command/commands/Reinforce.java b/src/vg/civcraft/mc/citadel/command/commands/Reinforce.java deleted file mode 100644 index 92e04c8e..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Reinforce.java +++ /dev/null @@ -1,91 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementMode; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.GroupManager.PlayerType; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.command.TabCompleters.GroupTabCompleter; -import vg.civcraft.mc.namelayer.group.Group; -import vg.civcraft.mc.namelayer.permission.PermissionType; - -public class Reinforce extends PlayerCommandMiddle { - - private GroupManager gm = NameAPI.getGroupManager(); - - public Reinforce(String name) { - super(name); - setIdentifier("ctr"); - setDescription("Reinforce blocks under a group."); - setUsage("/ctr "); - setArguments(0,1); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("Must be a player to use that command."); - return true; - } - String groupName = null; - Player p = (Player) sender; - UUID uuid = NameAPI.getUUID(p.getName()); - if(args.length == 0){ - groupName = gm.getDefaultGroup(uuid); - if(groupName == null){ - sendAndLog(p, ChatColor.RED, "You need to set a default group \n Use /nlsdg to do so"); - return true; - } - } - else{ - groupName = args[0]; - } - Group g = gm.getGroup(groupName); - if (g == null){ - sendAndLog(p, ChatColor.RED, "That group does not exist."); - return true; - } - PlayerType type = g.getPlayerType(uuid); - if (!p.hasPermission("citadel.admin") && !p.isOp() && type == null){ - sendAndLog(p, ChatColor.RED, "You are not on this group."); - return true; - } - if (!p.hasPermission("citadel.admin") && !p.isOp() && !gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("REINFORCE"))){ - sendAndLog(p, ChatColor.RED, "You do not have permission to " - + "place a reinforcement on this group."); - return true; - } - PlayerState state = PlayerState.get(p); - if (state.getMode() == ReinforcementMode.REINFORCEMENT){ - sendAndLog(p, ChatColor.GREEN, state.getMode().name() + " has been disabled"); - state.reset(); - } - else{ - sendAndLog(p, ChatColor.GREEN, "Your mode has been set to " + - ReinforcementMode.REINFORCEMENT.name() + "."); - state.setMode(ReinforcementMode.REINFORCEMENT); - state.setGroup(g); - } - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) - return null; - - if (args.length == 0) - return GroupTabCompleter.complete(null, PermissionType.getPermission("REINFORCE"), (Player)sender); - else if (args.length == 1) - return GroupTabCompleter.complete(args[0], PermissionType.getPermission("REINFORCE"), (Player)sender); - else { - return new ArrayList(); - } - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/SetLogging.java b/src/vg/civcraft/mc/citadel/command/commands/SetLogging.java deleted file mode 100644 index 9d4b4363..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/SetLogging.java +++ /dev/null @@ -1,117 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; - -public class SetLogging extends PlayerCommandMiddle { - - public SetLogging(String name) { - super(name); - setIdentifier("ctsl"); - setDescription("Allows admins to toggle special logging types live or show current status"); - setUsage("/ctsl [internal|playercommands|breaks|reinforcements [on|off]]"); - setArguments(0, 2); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (args.length > 0 && !cmds.contains(args[0])) { - return false; - } - - if (args.length >= 1 && !flgs.contains(args[1])) { - return false; - } - - if (!(sender instanceof ConsoleCommandSender) && !sender.isOp() && !sender.hasPermission("citadel.admin")) { - // This should never actually happen thanks to the plugin.yml, but - // we just want to be sure - sendAndLog(sender, ChatColor.RED, "Nice try"); - return true; - } - - // validated, so lets just do it. - if (args.length == 0) { - StringBuilder sb = new StringBuilder("Current deep logging set to: \n"); - sb.append(" Internal: ").append(CitadelConfigManager.shouldLogInternal()).append("\n"); - sb.append(" Player Command Responses: ").append(CitadelConfigManager.shouldLogPlayerCommands()).append("\n"); - sb.append(" Breaks: ").append(CitadelConfigManager.shouldLogBreaks()).append("\n"); - sb.append(" Reinforcements: ").append(CitadelConfigManager.shouldLogReinforcement()).append("\n"); - - sendAndLog(sender, ChatColor.GREEN, sb.toString()); - } - - String flag = null; - boolean newval = false; - if (args.length >= 1) { - if ("internal".equalsIgnoreCase(args[0])) { - flag = "internal_logging"; - newval = CitadelConfigManager.shouldLogInternal(); - } else if ("playercommands".equalsIgnoreCase(args[0])) { - flag = "command_logging"; - newval = CitadelConfigManager.shouldLogPlayerCommands(); - } else if ("breaks".equalsIgnoreCase(args[0])) { - flag = "break_logging"; - newval = CitadelConfigManager.shouldLogBreaks(); - } else if ("reinforcements".equalsIgnoreCase(args[0])) { - flag = "reinf_logging"; - newval = CitadelConfigManager.shouldLogReinforcement(); - } - } - - if (args.length < 2) { - newval = !newval; // invert current. - } else { - // If can't figure it out, leave current. - newval = "on".equalsIgnoreCase(args[1])? true : "off".equalsIgnoreCase(args[1]) ? false : newval; - } - - if (flag != null) { - Citadel.getInstance().getConfig().set(flag, newval); - sendAndLog(sender, ChatColor.GREEN, "Flag " + newval + " is " + (newval ? "on" : "off")); - return true; - } else { - sendAndLog(sender, ChatColor.RED, "Unknown setting!"); - return false; - } - } - - private static List cmds = Arrays.asList("internal","playercommands", "breaks", "reinforcements"); - private static List flgs = Arrays.asList("on", "off"); - @Override - public List tabComplete(CommandSender arg0, String[] arg1) { - if (arg1.length == 0) { - return cmds; - } else if (arg1.length == 1) { - ArrayList lst = new ArrayList(); - for (String cmd : cmds) { - if (cmd.toLowerCase().equals(arg1[0])) { - return flgs; - } else if (cmd.contains(arg1[0].toLowerCase())) { - lst.add(cmd); - } - } - return lst; - } else if (arg1.length == 2) { - ArrayList lst = new ArrayList(); - for (String flg : flgs) { - if (flg.toLowerCase().equals(arg1[1])) { - return flgs; - } else if (flg.contains(arg1[1].toLowerCase())) { - lst.add(flg); - } - } - return lst; - } - return null; - } - -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/Stats.java b/src/vg/civcraft/mc/citadel/command/commands/Stats.java deleted file mode 100644 index f4b90ccc..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/Stats.java +++ /dev/null @@ -1,128 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.command.TabCompleters.GroupTabCompleter; -import vg.civcraft.mc.namelayer.group.Group; - -public class Stats extends PlayerCommandMiddle{ - - private List run = new ArrayList(); - private GroupManager gm = NameAPI.getGroupManager(); - - public Stats(String name) { - super(name); - setIdentifier("cts"); - setDescription("Lists the stats about a certain group."); - setUsage("/cts "); - setArguments(0,1); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("meh"); - return true; - } - Player p = (Player) sender; - if (!(p.isOp() || p.hasPermission("citadel.admin"))){ - sendAndLog(p, ChatColor.RED, "You do not have permission for this command."); - return true; - } - if (args.length == 0){ - Bukkit.getScheduler().runTaskAsynchronously(Citadel.getInstance(), new StatsMessageAllGroups(p)); - return true; - } - Group g = gm.getGroup(args[0]); - - if (g == null){ - sendAndLog(p, ChatColor.RED, "This group does not exist."); - return true; - } - UUID uuid = NameAPI.getUUID(p.getName()); - if (!g.isMember(uuid) && !(p.isOp() || p.hasPermission("citadel.admin"))){ - sendAndLog(p, ChatColor.RED, "You are not on this group."); - return true; - } - synchronized(run){ - if (run.contains(g)){ - sendAndLog(p, ChatColor.RED, "That group is already being searched for."); - return true; - } - run.add(g); - } - Bukkit.getScheduler().runTaskAsynchronously(Citadel.getInstance(), new StatsMessage(p, g)); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) - return new ArrayList(); - - if (args.length == 0) { - return GroupTabCompleter.complete(null, null, (Player)sender); - } else if (args.length == 1) { - return GroupTabCompleter.complete(args[0], null, (Player)sender); - } else { - return new ArrayList(); - } - - } - - public class StatsMessage implements Runnable{ - - private final Player p; - private final Group g; - - public StatsMessage(Player p, Group g){ - this.p = p; - this.g = g; - } - - @Override - public void run() { - if (g == null || p == null) { - return; - } - String message = "The amount of reinforcements on this group are: "; - int count = Citadel.getCitadelDatabase().getReinCountForGroup(g.getName()); - message += Integer.toString(count); - synchronized(run){ - run.remove(g); - } - if (p != null && !p.isOnline()) {// meh be safe - return; - } - sendAndLog(p, ChatColor.GREEN, message); - } - - } - - public class StatsMessageAllGroups implements Runnable{ - - private final Player p; - public StatsMessageAllGroups(Player p){ - this.p = p; - } - - @Override - public void run() { - String message = "The amount of reinforcements on the server are: "; - int count = Citadel.getCitadelDatabase().getReinCountForAllGroups(); - message += count; - if (p != null && !p.isOnline()) // meh be safe - return; - sendAndLog(p, ChatColor.GREEN, message); - } - } -} diff --git a/src/vg/civcraft/mc/citadel/command/commands/UpdateReinforcements.java b/src/vg/civcraft/mc/citadel/command/commands/UpdateReinforcements.java deleted file mode 100644 index 4063e604..00000000 --- a/src/vg/civcraft/mc/citadel/command/commands/UpdateReinforcements.java +++ /dev/null @@ -1,159 +0,0 @@ -package vg.civcraft.mc.citadel.command.commands; - -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.reinforcement.MultiBlockReinforcement; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.group.Group; - -public class UpdateReinforcements extends PlayerCommandMiddle{ - - private GroupManager gm = NameAPI.getGroupManager(); - - public UpdateReinforcements(String name) { - super(name); - setIdentifier("ctur"); - setDescription("Updates all reinforcements in a chunk and group to a certain group."); - setUsage("/ctur "); - setArguments(0,2); - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player)){ - sender.sendMessage("How would this even work."); - return true; - } - Player p = (Player) sender; - if (!p.hasPermission("citadel.admin") || !p.isOp()){ - sendAndLog(p, ChatColor.RED, "Nice try"); - return true; - } - - if (args.length == 0){ - sendAndLog(p, ChatColor.GREEN, "Searching for groups in current chunk."); - Bukkit.getScheduler().runTaskAsynchronously(Citadel.getInstance(), new FindGroups(p, p.getLocation())); - return true; - } - else if (args.length == 1){ - sendAndLog(p, ChatColor.RED, "Please enter two groups."); - return true; - } - - Group old = gm.getGroup(args[0]); - Group n = gm.getGroup(args[1]); - - if (old == null || n == null){ - sendAndLog(p, ChatColor.RED, "One of the groups does not exist."); - return true; - } - - sendAndLog(p, ChatColor.GREEN, "Beginning to change groups."); - Bukkit.getScheduler().runTaskAsynchronously(Citadel.getInstance(), new UpdateGroups(p, p.getLocation().getChunk(), old, n)); - return true; - } - - @Override - public List tabComplete(CommandSender sender, String[] args) { - // TODO Auto-generated method stub - return null; - } - - class UpdateGroups implements Runnable{ - - private final Group old, n; - private final Player p; - private final Chunk c; - public UpdateGroups(Player p, Chunk c, Group old, Group n){ - this.old = old; - this.n = n; - this.p = p; - this.c = c; - } - - @Override - public void run() { - ReinforcementManager rm = Citadel.getReinforcementManager(); - List reins = rm.getReinforcementsByChunk(c); - for (Reinforcement r: reins){ - if (r instanceof PlayerReinforcement){ - PlayerReinforcement rein = (PlayerReinforcement) r; - if (rein.getGroup().getName().equals(old.getName())) { - rein.setGroup(n); - } - } - else if (r instanceof MultiBlockReinforcement){ - MultiBlockReinforcement rein = (MultiBlockReinforcement) r; - if (rein.getGroup().getName().equals(old.getName())) { - rein.setGroup(n); - } - } - } - if (!p.isOnline()) - return; - - sendAndLog(p, ChatColor.GREEN, "The groups have been updated."); - } - - } - - class FindGroups implements Runnable{ - - private final Player p; - private final Location loc; - - public FindGroups(Player p, Location loc){ - this.p = p; - this.loc = loc; - } - - @Override - public void run() { - ReinforcementManager rm = Citadel.getReinforcementManager(); - List reins = rm.getReinforcementsByChunk(loc.getChunk()); - List groups = new ArrayList(); - for (Reinforcement r: reins){ - if (r instanceof PlayerReinforcement){ - PlayerReinforcement rein = (PlayerReinforcement) r; - String name = rein.getGroup().getName(); - if (groups.contains(name)) { - continue; - } - groups.add(name); - } - else if (r instanceof MultiBlockReinforcement){ - MultiBlockReinforcement rein = (MultiBlockReinforcement) r; - String name = rein.getGroup().getName(); - if (groups.contains(name)) { - continue; - } - groups.add(name); - } - } - if (!p.isOnline()) { - return; - } - StringBuilder names = new StringBuilder(); - for (String g: groups) { - names.append(g).append(" "); - } - - sendAndLog(p, ChatColor.GREEN, "The groups in this chunk are: " + names); - } - - } - -} diff --git a/src/vg/civcraft/mc/citadel/database/CitadelReinforcementData.java b/src/vg/civcraft/mc/citadel/database/CitadelReinforcementData.java deleted file mode 100644 index df783364..00000000 --- a/src/vg/civcraft/mc/citadel/database/CitadelReinforcementData.java +++ /dev/null @@ -1,842 +0,0 @@ -package vg.civcraft.mc.citadel.database; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.logging.Level; - -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.citadel.reinforcement.MultiBlockReinforcement; -import vg.civcraft.mc.citadel.reinforcement.NaturalReinforcement; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.group.Group; - -public class CitadelReinforcementData { - - private Database db; - private Citadel plugin = Citadel.getInstance(); - public CitadelReinforcementData(Database db){ - this.db = db; - if (db.connect()){ - initalizePreparedStatements(); - createTables(); - intitializeProcedures(); - } - } - - private void intitializeProcedures(){ - db.execute("drop procedure if exists insertReinID;"); - db.execute("create definer=current_user procedure insertReinID(" + - "in x int," - + "in y int," - + "in z int," - + "in chunk_id varchar(255)," - + "in world varchar(255)" + - ") sql security invoker begin " - + "insert into reinforcement_id(x, y, z, chunk_id, world) values (x, y, z, chunk_id, world);" - + "select LAST_INSERT_ID() as id;" - + "end;"); - db.execute("drop procedure if exists insertCustomReinID;"); - db.execute("create definer=current_user procedure insertCustomReinID(" - + "in rein_id int," + - "in x int," - + "in y int," - + "in z int," - + "in chunk_id varchar(255)," - + "in world varchar(255)" + - ") sql security invoker begin " - + "insert into reinforcement_id(rein_id, x, y, z, chunk_id, world) values (rein_id, x, y, z, chunk_id, world);" - + "select LAST_INSERT_ID() as id;" - + "end;"); - } - /** - * Creates the required mysql tables and updates the db if needed. - */ - private void createTables(){ - int ver = checkVersion(plugin.getName()); - long begin_time = System.currentTimeMillis(); - db.execute("create table if not exists db_version (db_version int not null," + - "update_time varchar(24)," - + "plugin_name varchar(40));"); - if (ver == 0){ - db.execute(String.format("update db_version set plugin_name = '%s' " + - "where plugin_name is null", plugin.getName())); - ver = checkVersion(plugin.getName()); - if (ver == 0){ - Citadel.Log("Creating tables from scratch, this is a new " + - "instance of citadel."); - } - else{ - Citadel.Log("Detected previous version of Citadel, " + - "updating to new db.\n" + - "You should have backed up your data, " + - "if you havent already you have ten seconds to" + - " shut down the server and perform a backup."); - try { - Thread.sleep(10000); - } catch (InterruptedException e1) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Update sleep interrupted", e1); - } - long first_time = System.currentTimeMillis(); - db.execute("alter table reinforcement drop security_level, drop version, add group_id int not null;"); - db.execute("insert into faction_id (group_name) values (null);"); // For natural reinforcements - db.execute("delete from reinforcement where `name` is null;"); - db.execute("update ignore reinforcement r inner join faction_id f on f.group_name = r.`name` " - + "set r.group_id = f.group_id;"); - db.execute("alter table reinforcement drop `name`, add rein_type_id int not null default 1, " - + "add lore varchar(255);"); - db.execute("drop table citadel_account_id_map;"); - Citadel.Log("The update to new format took " + (System.currentTimeMillis() - first_time) / 1000 + " seconds."); - } - } - if (ver == 5 || ver == 0){ - long first_time = System.currentTimeMillis(); - Citadel.Log("Updating to Citadel Version 6."); - db.execute("create table if not exists reinforcement(" + - "x int not null," + - "y int not null," + - "z int not null," + - "world varchar(10) not null," + - "material_id int not null," + - "durability varchar(10) not null," + - "chunk_id varchar(255) not null," + - "insecure tinyint(1) not null," + - "group_id int not null," + - "maturation_time int not null," + - "rein_type_id int not null," + - "lore varchar(255)," - + "primary key (x,y,z,world));"); - db.execute("create table if not exists reinforcement_type(" - + "rein_type_id int not null auto_increment," - + "rein_type varchar(30) not null," - + "primary key rein_type_key (rein_type_id));"); - String[] types = {"PlayerReinforcement", "NaturalReinforcement", "MultiBlockReinforcement"}; - for (String x: types) { - db.execute(String.format("insert into reinforcement_type(rein_type)" - + "values('%s');", x)); - } - updateVersion(5, plugin.getName()); - ver = checkVersion(plugin.getName()); - Citadel.Log("The update to Version 6 took " + (System.currentTimeMillis() - first_time) / 1000 + " seconds."); - } - if (ver == 6){ - long first_time = System.currentTimeMillis(); - Citadel.Log("Updating to version 7. No fun message for you :("); - db.execute("create table if not exists reinforcement_id(" - + "rein_id int not null auto_increment," - + "x int not null," - + "y int not null," - + "z int not null," - + "chunk_id varchar(255)," - + "world varchar (255) not null," - + "primary key rein_id_key (rein_id)," - + "unique key x_y_z_world(x,y,z,world));-- Your mother is a whore and sleeps with banjos"); - // I like turtles mother fucker. Never program because then you get turtles. - db.execute("insert into reinforcement_id (x, y, z, chunk_id, world) select x, y, z, chunk_id, world from reinforcement;"); // populate that bitch. - db.execute("alter table reinforcement add rein_id int not null, drop chunk_id;"); - db.execute("update reinforcement r inner join reinforcement_id ri on " - + "ri.x = r.x and ri.y = r.y and ri.z = r.z and ri.world = r.world " - + "set r.rein_id = ri.rein_id"); - db.execute("alter table reinforcement DROP PRIMARY KEY, " - + "add primary key rein_id_key(rein_id), " - + "drop x," - + "drop y," - + "drop z," - + "drop world;"); - db.execute("alter table reinforcement_id add index `chunk_id_index` (chunk_id);"); - updateVersion(ver, plugin.getName()); - ver = checkVersion(plugin.getName()); - Citadel.Log("The update to Version 7 took " + (System.currentTimeMillis() / first_time) / 1000 + " seconds."); - } - if (ver == 7){ - long first_time = System.currentTimeMillis(); - db.execute("alter table reinforcement_id drop primary key," - + " add primary key (rein_id, x, y, z, world);"); - updateVersion(ver, plugin.getName()); - ver = checkVersion(plugin.getName()); - Citadel.Log("The update to Version 8 took " + (System.currentTimeMillis() / first_time) / 1000 + " seconds."); - } - if (ver == 8) { - long first_time = System.currentTimeMillis(); - Citadel.Log("Updating to version 9: The acid test. Note: This will take a while."); - db.execute("alter table reinforcement add acid_time int not null;"); - db.execute("update reinforcement set acid_time = maturation_time;"); // Might take a minute. - updateVersion(ver, plugin.getName()); - ver = checkVersion(plugin.getName()); - Citadel.Log("The update to Version 9 took " + (System.currentTimeMillis() / first_time) / 1000 + " seconds."); - } - Citadel.Log("The total time it took Citadel to update was " + - (System.currentTimeMillis() - begin_time) / 1000 + " seconds."); - } - /** - * Reconnects and reinitializes the mysql connection and preparedstatements. - */ - private void reconnectAndReinitialize(){ - if (db.isConnected()) { - return; - } - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.Log("Database went away, reconnecting."); - } - db.connect(); - initalizePreparedStatements(); - } - - private String version, updateVersion; - private String getRein, getReins, addRein, removeRein, updateRein; - //private PreparedStatement deleteGroup, insertDeleteGroup, removeDeleteGroup, getDeleteGroup; - private String insertReinID, insertCustomReinID, getCordsbyReinID, selectReinCountForGroup, selectReinCount; - /** - * Initializes the PreparedStatements. Gets called on db connect or - * reconnect. - */ - private void initalizePreparedStatements(){ - getRein = "select r.material_id, r.durability, " + - "r.insecure, r.maturation_time, r.acid_time, rt.rein_type, " - + "r.lore, r.group_id, r.rein_id from reinforcement r " - + "inner join reinforcement_id ri on r.rein_id = ri.rein_id " - + "inner join reinforcement_type rt on rt.rein_type_id = r.rein_type_id " - + "where ri.x = ? and ri.y = ? and ri.z = ? and ri.chunk_id = ? and ri.world = ?"; - getReins = "select ri.x, ri.y, ri.z, ri.world, r.material_id, r.durability, " + - "r.insecure, r.maturation_time, rt.rein_type, " - + "r.lore, r.group_id, r.rein_id, r.acid_time from reinforcement r " - + "inner join reinforcement_id ri on r.rein_id = ri.rein_id " - + "inner join reinforcement_type rt on rt.rein_type_id = r.rein_type_id " - + "where ri.chunk_id = ?"; - addRein = "insert into reinforcement (" - + "material_id, durability, " - + "insecure, group_id, maturation_time, rein_type_id," - + "lore, rein_id, acid_time) select ?, ?, ?, ?, ?, rt.rein_type_id, ?, ?, ? " - + "from reinforcement_type rt where rt.rein_type = ?"; - removeRein = "delete r.*, ri.* from reinforcement r " - + "left join reinforcement_id ri on r.rein_id = ri.rein_id " - + "where ri.x = ? and ri.y = ? and ri.z = ? and ri.world = ?"; - updateRein = "update reinforcement r " - + "inner join reinforcement_id ri on ri.rein_id = r.rein_id " - + "set r.durability = ?, r.insecure = ?, r.group_id = ?, " - + "maturation_time = ?, acid_time = ? " - + "where ri.x = ? and ri.y = ? and ri.z = ? and ri.world =?"; - insertReinID = "call insertReinID(?,?,?,?,?)"; - insertCustomReinID = "call insertCustomReinID(?,?,?,?,?,?)"; - getCordsbyReinID = "select x, y, z, world from reinforcement_id where rein_id = ?"; - selectReinCountForGroup = "select count(*) as count from reinforcement r " - + "inner join faction_id f on f.group_id = r.group_id " - + "where f.group_name = ?"; - selectReinCount = "select count(*) as count from reinforcement r"; - - version = "select max(db_version) as db_version from db_version where plugin_name=?"; - updateVersion = "insert into db_version (db_version, update_time, plugin_name) values (?,?,?)"; - } - - /** - * Checks the version of a specific plugin's db. - * @param name- The name of the plugin. - * @return Returns the version of the plugin or 0 if none was found. - */ - public int checkVersion(String name){ - reconnectAndReinitialize(); - PreparedStatement version = db.prepareStatement(this.version); - try { - version.setString(1, name); - ResultSet set = version.executeQuery(); - if (!set.next()) - return 0; - return set.getInt("db_version"); - } catch (SQLException e) { - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.WARNING, "Version control table missing for Citadel!", e); - } - return 0; - } - } - - /** - * Updates the version number for a plugin. You must specify what - * the current version number is. - * @param version- The current version of the plugin. - * @param pluginname- The plugin name. - * @return Returns the new version of the db. - */ - public synchronized int updateVersion(int version, String pluginname){ - reconnectAndReinitialize(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - PreparedStatement updateVersion = db.prepareStatement(this.updateVersion); - try { - updateVersion.setInt(1, version+ 1); - updateVersion.setString(2, sdf.format(new Date())); - updateVersion.setString(3, pluginname); - updateVersion.execute(); - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "Version control table error; unable to update DB version for Citadel!", e); - } - return ++version; - } - - /** - * Is used to grab the reinforcement from the mysql db. - * If there isn't a reinforcement at the location it - * returns null. - * @param The Location of the wanted Reinforcement. - * @return Returns the Reinforcement of the location. - * @return Returns null if there is no reinforcement. - */ - public Reinforcement getReinforcement(Location loc){ - if (loc == null){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData getReinforcement called with null"); - return null; - } - reconnectAndReinitialize(); - PreparedStatement getRein = db.prepareStatement(this.getRein); - try { - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - getRein.setInt(1, x); - getRein.setInt(2, y); - getRein.setInt(3, z); - String formatChunk = formatChunk(loc); - getRein.setString(4, formatChunk); - getRein.setString(5, loc.getWorld().getName()); - ResultSet set = getRein.executeQuery(); - if (!set.next()) { - set.close(); - return null; - } - @SuppressWarnings("deprecation") - Material mat = Material.getMaterial(set.getInt(1)); - int durability = set.getInt(2); - boolean inSecure = set.getBoolean(3); - int mature = set.getInt(4); - int acid = set.getInt(5); - String rein_type = set.getString(6); - String lore = set.getString(7); - int group_id = set.getInt(8); - // Check for what type of reinforcement and return the one needed. - if ("PlayerReinforcement".equals(rein_type)) { - set.close(); - ItemStack stack = new ItemStack(mat); - if (lore != null) { - ItemMeta meta = stack.getItemMeta(); - List array = Arrays.asList(lore.split("\n")); - meta.setLore(array); - stack.setItemMeta(meta); - } - Group g = GroupManager.getGroup(group_id); - if (g == null) { - if (CitadelConfigManager.shouldLogReinforcement()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Player Reinforcement at {0} lacks a valid group (group {1} failed lookup)", - new Object[] {loc, group_id}); - } - return null; // group not found! - } - PlayerReinforcement rein = new PlayerReinforcement(loc, durability, - mature, acid, g,stack); - rein.setInsecure(inSecure); - return rein; - } else if ("NaturalReinforcement".equals(rein_type)){ - set.close(); - NaturalReinforcement rein = new NaturalReinforcement(loc.getBlock(), durability); - return rein; - } else if ("MultiBlockReinforcement".equals(rein_type)) { - int id = set.getInt(9); - set.close(); - MultiBlockReinforcement rein = MultiBlockReinforcement.getMultiRein(id); - if (rein != null) { - return rein; - } - PreparedStatement getCordsbyReinID = db.prepareStatement(this.getCordsbyReinID); - getCordsbyReinID.setInt(1, id); - set = getCordsbyReinID.executeQuery(); - List locs = new ArrayList(); - while (set.next()){ - int xx = set.getInt(1), yy = set.getInt(2), zz = set.getInt(3); - String world = set.getString(4); - locs.add(new Location(Bukkit.getWorld(world), xx, yy, zz)); - } - set.close(); - - Group g = GroupManager.getGroup(group_id); - if (g == null) { - if (CitadelConfigManager.shouldLogReinforcement()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Multiblock Reinforcement touching {0} lacks a valid group (group {1} failed lookup)", - new Object[] {loc, group_id}); - } - return null; // group not found! - } - rein = new MultiBlockReinforcement(locs, g, durability, mature, acid, id); - return rein; - } - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Failed while retrieving reinforcement from database", e); - } - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData getReinforcement failed for {0}", loc); - } - return null; - } - - /** - * Returns a list of reinforcements in a given chunk. - * @param The chunk you want the reinforcements about. - * @return A list of reinforcements in a chunk - */ - public List getReinforcements(Chunk chunk){ - if (chunk == null){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData getReinforcements called with null"); - return null; - } - reconnectAndReinitialize(); - PreparedStatement getReins = db.prepareStatement(this.getReins); - String formatChunk = formatChunk(chunk); - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData getReinforcements chunk called for {0}", formatChunk); - } - List reins = new ArrayList(); - try { - getReins.setString(1, formatChunk); - ResultSet set = getReins.executeQuery(); - while (set.next()) { - int x = set.getInt(1), y = set.getInt(2), z = set.getInt(3); - String world = set.getString(4); - @SuppressWarnings("deprecation") - Material mat = Material.getMaterial(set.getInt(5)); - int durability = set.getInt(6); - boolean inSecure = set.getBoolean(7); - int mature = set.getInt(8); - String rein_type = set.getString(9); - String lore = set.getString(10); - int group_id = set.getInt(11); - int acid = set.getInt(13); - - Location loc = new Location(Bukkit.getWorld(world), x, y, z); - - if ("PlayerReinforcement".equals(rein_type)){ - Group g = GroupManager.getGroup(group_id); - if (g == null) { - if (CitadelConfigManager.shouldLogReinforcement()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "During Chunk {0} load, Player Reinforcement at {1} lacks a valid group (group {2} failed lookup)", - new Object[] {formatChunk, loc, group_id}); - } - continue; // group not found! - } - ItemStack stack = new ItemStack(mat); - if (lore != null){ - ItemMeta meta = stack.getItemMeta(); - List array = Arrays.asList(lore.split("\n")); - meta.setLore(array); - stack.setItemMeta(meta); - } - PlayerReinforcement rein = new PlayerReinforcement(loc, durability, - mature, acid, g, stack); - rein.setInsecure(inSecure); - reins.add(rein); - } - else if("NaturalReinforcement".equals(rein_type)){ - NaturalReinforcement rein = new NaturalReinforcement(loc.getBlock(), durability); - reins.add(rein); - } - else if ("MultiBlockReinforcement".equals(rein_type)){ - int id = set.getInt(12); - MultiBlockReinforcement rein = MultiBlockReinforcement.getMultiRein(id); - if (rein != null) { - reins.add(rein); - continue; - } - - Group g = GroupManager.getGroup(group_id); - if (g == null) { - if (CitadelConfigManager.shouldLogReinforcement()) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "During Chunk {0} load, Multiblock Reinforcement at {1} lacks a valid group (group {2} failed lookup)", - new Object[] {formatChunk, loc, group_id}); - } - continue; // group not found! - } - PreparedStatement getCordsbyReinID = db.prepareStatement(this.getCordsbyReinID); - getCordsbyReinID.setInt(1, id); - ResultSet multi = getCordsbyReinID.executeQuery(); - List locs = new ArrayList(); - while (multi.next()){ - int xx = multi.getInt(1), yy = multi.getInt(2), zz = multi.getInt(3); - String w = multi.getString(4); - locs.add(new Location(Bukkit.getWorld(w), xx, yy, zz)); - } - multi.close(); - - rein = new MultiBlockReinforcement(locs, g, durability, mature, acid, id); - reins.add(rein); - } - } - set.close(); - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Failed while retrieving chunk " + - formatChunk + " reinforcement from database", e); - } - return reins; - } - - /** - * Inserts a reinforcement into the Database. Should only be called from SaveManager. - * @param The Reinforcement to save. - */ - public void insertReinforcement(Reinforcement rein){ - insertReinforcement(rein, false); - } - - @SuppressWarnings("deprecation") - public void insertReinforcement(Reinforcement rein, boolean retry){ - if (rein == null){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData insertReinforcement called with null"); - return; - } - reconnectAndReinitialize(); - - if (rein instanceof PlayerReinforcement){ - Location loc = rein.getLocation(); - int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); - String world = loc.getWorld().getName(); - Material mat = rein.getMaterial(); - int dur = rein.getDurability(); - int maturationTime = rein.getMaturationTime(); - int acidTime = rein.getAcidTime(); - boolean insecure = false; - String reinType = "PlayerReinforcement"; - - PlayerReinforcement pRein = (PlayerReinforcement) rein; - insecure = pRein.isInsecure(); - ItemMeta meta = pRein.getStackRepresentation().getItemMeta(); - String lore = ""; - if (meta.hasLore()) { - for (String xx: meta.getLore()) { - lore += xx + "\n"; - } - } else { - lore = null; - } - - Group g = pRein.getGroup(); - if (g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Player Reinforcement insert at {0} lacks a valid group (lookup failed)", loc); - } - - try { - PreparedStatement insertReinID = db.prepareStatement(this.insertReinID); - insertReinID.setInt(1, x); - insertReinID.setInt(2, y); - insertReinID.setInt(3, z); - String formatChunk = formatChunk(loc); - insertReinID.setString(4, formatChunk); - insertReinID.setString(5, world); - ResultSet set = insertReinID.executeQuery(); - if (!set.next()) { - throw new SQLException("Failed ID insertion"); - } - int id = set.getInt("id"); - - PreparedStatement addRein = db.prepareStatement(this.addRein); - addRein.setInt(1, mat.getId()); - addRein.setInt(2, dur); - addRein.setBoolean(3, insecure); - addRein.setInt(4, pRein.getGroupId()); - addRein.setInt(5, maturationTime); - addRein.setString(6, lore); - addRein.setInt(7, id); - addRein.setInt(8, acidTime); - addRein.setString(9, reinType); - addRein.execute(); - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Citadel has detected a reinforcement that should not be there. Deleting it and trying again. " - + "Including the stack incase it is useful.", e); - // Let's delete the reinforcement; if a user is able to place one then the db is - // out of synch / messed up some how. - deleteReinforcement(rein); - // Now lets try again. - if (!retry) { - insertReinforcement(rein, true); - } - } - } else if (rein instanceof NaturalReinforcement) { - /* - * TODO: Why removed? We had thoughts of using this.. - * - * We don't need to worry about saving this right now. - * - Location loc = rein.getLocation(); - int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); - String world = loc.getWorld().getName(); - Material mat = rein.getMaterial(); - int dur = rein.getDurability(); - String chunk_id = loc.getChunk().toString(); - int maturationTime = rein.getMaturationTime(); - int acidTime = rein.getAcidTime(); - boolean insecure = false; - String group = NameLayerPlugin.getSpecialAdminGroup(); - String reinType = "NaturalReinforcement"; - String lore = ""; - lore = null; - try { - PreparedStatement insertReinID = db.prepareStatement(this.insertReinID); - insertReinID.setInt(1, x); - insertReinID.setInt(2, y); - insertReinID.setInt(3, z); - String formatChunk = formatChunk(loc); - insertReinID.setString(4, formatChunk); - insertReinID.setString(5, world); - insertReinID.execute(); - - int id = getLastReinId(); - - PreparedStatement addRein = db.prepareStatement(this.addRein); - addRein.setInt(1, mat.getId()); - addRein.setInt(2, dur); - addRein.setBoolean(3, insecure); - addRein.setInt(4, maturationTime); - addRein.setString(5, lore); - addRein.setInt(6, id); - addRein.setInt(7, acidTime); - addRein.setString(8, reinType); - addRein.setString(9, group); - addRein.execute(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - */ - } else if (rein instanceof MultiBlockReinforcement){ - MultiBlockReinforcement mbRein = (MultiBlockReinforcement) rein; - - Group g = mbRein.getGroup(); // let's confirm it's good. - if (g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Multiblock Reinforcement insert request lacks a valid group (lookup failed)"); - } - - int id = -1; // We add one because we haven't added it yet. - try { - PreparedStatement insertCustomReinID = db.prepareStatement(this.insertCustomReinID); - // add all the locations into the db. - int count = 0; - try { - for (Location lo: mbRein.getLocations()){ - if (count == 0) { - PreparedStatement insertReinID = db.prepareStatement(this.insertReinID); - insertReinID.setInt(1, lo.getBlockX()); - insertReinID.setInt(2, lo.getBlockY()); - insertReinID.setInt(3, lo.getBlockZ()); - String formatChunk = formatChunk(lo); - insertReinID.setString(4, formatChunk); - insertReinID.setString(5, lo.getWorld().getName()); - ResultSet set = insertReinID.executeQuery(); - if (!set.next()) { - throw new SQLException("Failed ID insertion"); - } - - id = set.getInt("id"); - mbRein.setReinId(id); - continue; - } - insertCustomReinID.setInt(1, id); - insertCustomReinID.setInt(2, lo.getBlockX()); - insertCustomReinID.setInt(3, lo.getBlockY()); - insertCustomReinID.setInt(4, lo.getBlockZ()); - String formatChunk = formatChunk(lo); - insertCustomReinID.setString(5, formatChunk); - insertCustomReinID.setString(6, lo.getWorld().getName()); - insertCustomReinID.addBatch(); - } - insertCustomReinID.executeBatch(); - } catch (SQLException se) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Citadel has failed to insert locations in a" + - " multiblock reinforcement insertion. ", se); - insertCustomReinID.clearBatch(); - // TODO: Consider forcing the reinf ID removal. - throw se; // propagate the exception. - } - - PreparedStatement addRein = db.prepareStatement(this.addRein); - addRein.setInt(1, -1); - addRein.setInt(2, mbRein.getDurability()); - addRein.setBoolean(3, false); - addRein.setInt(4, mbRein.getGroupId()); - addRein.setInt(5, mbRein.getMaturationTime()); - addRein.setString(6, null); - addRein.setInt(7, id); - addRein.setInt(8, mbRein.getAcidTime()); - addRein.setString(9, "MultiBlockReinforcement"); - addRein.execute(); - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Citadel has failed to insert a" + - " multiblock reinforcement. ", e); - deleteReinforcement(rein); - // Now lets try again. - if (!retry) { - insertReinforcement(rein); - } - } - } - - } - /** - * Deletes a Reinforcement from the database. Should only be called - * within SaveManager - * @param The Reinforcement to delete. - */ - public void deleteReinforcement(Reinforcement rein){ - if (rein == null){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData deleteReinforcement called with null"); - return; - } - reconnectAndReinitialize(); - - Location loc = rein.getLocation(); - int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); - String world = loc.getWorld().getName(); - try { - PreparedStatement removeRein = db.prepareStatement(this.removeRein); - removeRein.setInt(1, x); - removeRein.setInt(2, y); - removeRein.setInt(3, z); - removeRein.setString(4, world); - removeRein.execute(); - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "Citadel has failed to delete a" + - " reinforcement at "+ loc, e); - } - } - - /** - * Saves the Reinforcement to the Database. Should only be called - * from SaveManager. - * @param The Reinforcement to save. - */ - public void saveReinforcement(Reinforcement rein){ - if (rein == null){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData saveReinforcement called with null"); - return; - } - reconnectAndReinitialize(); - - int dur = rein.getDurability(); - boolean insecure = false; - int groupId = -1; - int mature = rein.getMaturationTime(); - int acid = rein.getAcidTime(); - Location loc = rein.getLocation(); - int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); - String world = loc.getWorld().getName(); - if (rein instanceof PlayerReinforcement){ - PlayerReinforcement pRein = (PlayerReinforcement) rein; - insecure = pRein.isInsecure(); - Group g = pRein.getGroup(); - if (g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Player saveReinforcement at {0} lacks a valid group (lookup failed)", loc); - } else { - groupId = g.getGroupId(); - } - } - if (rein instanceof MultiBlockReinforcement){ - MultiBlockReinforcement mbRein = (MultiBlockReinforcement) rein; - insecure = false; - Group g = mbRein.getGroup(); - if (g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, - "Player saveinsert at {0} lacks a valid group (lookup failed)", loc); - } else { - groupId = g.getGroupId(); - } - } - try { - PreparedStatement updateRein = db.prepareStatement(this.updateRein); - updateRein.setInt(1, dur); - updateRein.setBoolean(2, insecure); - updateRein.setInt(3, groupId); - updateRein.setInt(4, mature); - updateRein.setInt(5, acid); - updateRein.setInt(6, x); - updateRein.setInt(7, y); - updateRein.setInt(8, z); - updateRein.setString(9, world); - updateRein.execute(); - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.WARNING, String.format("The Null Group Exception that is being followed has to deal with the group id: %s," - + " at location: %d, %d, %d, at world: %s", groupId, x, y, z, world), e); - } - } - - private String formatChunk(Location loc){ - Chunk c = loc.getChunk(); - return formatChunk(c); - } - - private String formatChunk(Chunk c){ - StringBuilder chunk = new StringBuilder(c.getWorld().getName()); - chunk.append(":").append(c.getX()).append(":").append(c.getZ()); - return chunk.toString(); - } - - public int getReinCountForGroup(String group){ - if (group == null){ - Citadel.getInstance().getLogger().log(Level.WARNING, - "CitadelReinforcementData getReinCountForGroup called with null"); - return 0; - } - try { - PreparedStatement selectReinCountForGroup = db.prepareStatement(this.selectReinCountForGroup); - selectReinCountForGroup.setString(1, group); - ResultSet set = selectReinCountForGroup.executeQuery(); - if (!set.next()) { - throw new SQLException("Failed Count"); - } - int r = set.getInt(1); - set.close(); - return r; - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "getReinCountForGroup has failed for " + - group, e); - } - return 0; - } - - public int getReinCountForAllGroups(){ - try { - PreparedStatement selectReinCount = db.prepareStatement(this.selectReinCount); - ResultSet set = selectReinCount.executeQuery(); - if (!set.next()) { - throw new SQLException("Failed Count"); - } - int r = set.getInt(1); - set.close(); - return r; - } catch (SQLException e) { - Citadel.getInstance().getLogger().log(Level.SEVERE, "getReinCountForAllGroups has failed", e); - } - return 0; - } -} diff --git a/src/vg/civcraft/mc/citadel/database/Database.java b/src/vg/civcraft/mc/citadel/database/Database.java deleted file mode 100644 index 369c9d36..00000000 --- a/src/vg/civcraft/mc/citadel/database/Database.java +++ /dev/null @@ -1,122 +0,0 @@ - package vg.civcraft.mc.citadel.database; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.avaje.ebeaninternal.server.lib.sql.DataSourceException; -public class Database { - private String host; - private int port; - private String db; - private String user; - private String password; - private Logger logger; - private Connection connection; - - public Database(String host, int port, String db, String user, String password, Logger logger) { - this.host = host; - this.port = port; - this.db = db; - this.user = user; - this.password = password; - this.logger = logger; - } - - public String getDb() { - return db; - } - - public String getHost() { - return host; - } - - public String getPassword() { - return password; - } - - public String getUser() { - return user; - } - - /** - * Connects to the database. - * - * @since 0.1 - */ - public boolean connect() { - String jdbc = "jdbc:mysql://" + host + ":" + port + "/" + db + "?user=" + user + "&password=" + password; - try { - Class.forName("com.mysql.jdbc.Driver").newInstance(); - } catch (Exception ex) { - throw new DataSourceException("Failed to initialize JDBC driver."); - } - try { - connection = DriverManager.getConnection(jdbc); - this.logger.log(Level.INFO, "Connected to database!"); - return true; - } catch (SQLException ex) { //Error handling below: - this.logger.log(Level.SEVERE, "Could not connnect to the database!", ex); - return false; - } - } - - /** - * Closes the database connection. - * - * @since 0.1 - */ - public void close() { - try { - connection.close(); - } catch (SQLException ex) { - this.logger.log(Level.SEVERE, "An error occured while closing the connection.", ex); - } - } - - /** - * Are we connected to the database? - * - * @return Connected - * @throws SQLException - */ - public boolean isConnected() { - try { - return connection.isValid(5); - } catch (SQLException ex) { - this.logger.log(Level.SEVERE, "isConnected error!", ex); - } - return false; - } - - /** - * Prepare the SQL statements - * - * @return PreparedStatement - * @throws SQLException - */ - public PreparedStatement prepareStatement(String sqlStatement) { - try { - return connection.prepareStatement(sqlStatement); - } catch (SQLException ex) { - this.logger.log(Level.SEVERE, "Failed to prepare statement! " + sqlStatement, ex); - } - return null; - } - - public void execute(String sql) { - try { - if (isConnected()) { - connection.prepareStatement(sql).executeUpdate(); - } else { - connect(); - execute(sql); - } - } catch (SQLException ex) { - this.logger.log(Level.SEVERE, "Could not execute SQL statement!", ex); - } - } -} diff --git a/src/vg/civcraft/mc/citadel/events/AcidBlockEvent.java b/src/vg/civcraft/mc/citadel/events/AcidBlockEvent.java deleted file mode 100644 index 39dd220f..00000000 --- a/src/vg/civcraft/mc/citadel/events/AcidBlockEvent.java +++ /dev/null @@ -1,56 +0,0 @@ -package vg.civcraft.mc.citadel.events; - -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; - -public class AcidBlockEvent extends Event implements Cancellable{ - private static final HandlerList handlers = new HandlerList(); - - private Player p; - private PlayerReinforcement acidBlock; - private PlayerReinforcement destroyedBlock; - public AcidBlockEvent(Player p, PlayerReinforcement acidBlock, - PlayerReinforcement destroyedBlock){ - this.p = p; - this.acidBlock = acidBlock; - this.destroyedBlock = destroyedBlock; - } - /** - * Gets the PlayerReinforcement on the acid block. - * @return Returns the PlayerReinforcement. - */ - public PlayerReinforcement getAcidBlockReinforcement(){ - return acidBlock; - } - /** - * Gets the PlayerReinforcement on the block above the Acid Block. - * @return Returns the PlayerReinforcement for the block above the Acid Block. - */ - public PlayerReinforcement getDestoryedBlockReinforcement(){ - return destroyedBlock; - } - - private boolean isCancelled = false; - @Override - public boolean isCancelled() { - return isCancelled; - } - - @Override - public void setCancelled(boolean value) { - isCancelled = value; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} \ No newline at end of file diff --git a/src/vg/civcraft/mc/citadel/events/ReinforcementCreationEvent.java b/src/vg/civcraft/mc/citadel/events/ReinforcementCreationEvent.java deleted file mode 100644 index dac56907..00000000 --- a/src/vg/civcraft/mc/citadel/events/ReinforcementCreationEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -package vg.civcraft.mc.citadel.events; - -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; - -public class ReinforcementCreationEvent extends Event implements Cancellable{ - private static final HandlerList handlers = new HandlerList(); - - private Reinforcement rein; - private Block bl; - private Player player; - - private boolean isCancelled = false; - - public ReinforcementCreationEvent(Reinforcement rein, Block block, Player p){ - this.rein = rein; - bl = block; - player = p; - } - /** - * Gets the Reinforcement that was just created. - * @return Returns the Reinforcement. - */ - public Reinforcement getReinforcement(){ - return rein; - } - /** - * Gets the Block that the Reinforcement was created on. - * @return Returns the Block associated with the reinforcement. - */ - public Block getBlock(){ - return bl; - } - /** - * @return Returns the Player that created the Reinforcement. - */ - public Player getPlayer(){ - return player; - } - - @Override - public boolean isCancelled() { - return isCancelled; - } - - @Override - public void setCancelled(boolean value) { - isCancelled = value; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/vg/civcraft/mc/citadel/events/ReinforcementDamageEvent.java b/src/vg/civcraft/mc/citadel/events/ReinforcementDamageEvent.java deleted file mode 100644 index f1022f18..00000000 --- a/src/vg/civcraft/mc/citadel/events/ReinforcementDamageEvent.java +++ /dev/null @@ -1,60 +0,0 @@ -package vg.civcraft.mc.citadel.events; - -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; - -public class ReinforcementDamageEvent extends Event implements Cancellable{ - private static final HandlerList handlers = new HandlerList(); - - private boolean isCancelled = false; - private Reinforcement rein; - private Player player; - private Block block; - public ReinforcementDamageEvent(Reinforcement rein, Player player, Block block){ - this.rein = rein; - this.player = player; - this.block = block; - } - /** - * @return Returns the Reinforcement. - */ - public Reinforcement getReinforcement(){ - return rein; - } - /** - * @return Returns the block. - */ - public Block getBlock(){ - return block; - } - /** - * @return Returns the Player who damaged the Reinforcement. - */ - public Player getPlayer(){ - return player; - } - - @Override - public boolean isCancelled() { - return isCancelled; - } - - @Override - public void setCancelled(boolean value) { - isCancelled = value; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/vg/civcraft/mc/citadel/listener/BlockListener.java b/src/vg/civcraft/mc/citadel/listener/BlockListener.java deleted file mode 100644 index 973f5af3..00000000 --- a/src/vg/civcraft/mc/citadel/listener/BlockListener.java +++ /dev/null @@ -1,593 +0,0 @@ -package vg.civcraft.mc.citadel.listener; - -import static vg.civcraft.mc.citadel.Utility.canPlace; -import static vg.civcraft.mc.citadel.Utility.createNaturalReinforcement; -import static vg.civcraft.mc.citadel.Utility.createPlayerReinforcement; -import static vg.civcraft.mc.citadel.Utility.isAuthorizedPlayerNear; -import static vg.civcraft.mc.citadel.Utility.isDroppedReinforcementBlock; -import static vg.civcraft.mc.citadel.Utility.isPlant; -import static vg.civcraft.mc.citadel.Utility.maybeReinforcementDamaged; -import static vg.civcraft.mc.citadel.Utility.reinforcementBroken; -import static vg.civcraft.mc.citadel.Utility.reinforcementDamaged; -import static vg.civcraft.mc.citadel.Utility.timeUntilMature; -import static vg.civcraft.mc.citadel.Utility.timeUntilAcidMature; -import static vg.civcraft.mc.citadel.Utility.wouldPlantDoubleReinforce; - -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Hanging; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockBurnEvent; -import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.block.BlockPhysicsEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.BlockRedstoneEvent; -import org.bukkit.event.player.PlayerBucketEmptyEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.material.MaterialData; -import org.bukkit.material.Openable; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.ReinforcementMode; -import vg.civcraft.mc.citadel.Utility; -import vg.civcraft.mc.citadel.events.ReinforcementCreationEvent; -import vg.civcraft.mc.citadel.events.ReinforcementDamageEvent; -import vg.civcraft.mc.citadel.misc.ReinforcemnetFortificationCancelException; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.group.Group; - -public class BlockListener implements Listener{ - - public static final List all_sides = Arrays.asList( - BlockFace.UP, BlockFace.DOWN, BlockFace.NORTH, - BlockFace.SOUTH, BlockFace.WEST, BlockFace.EAST); - - public static final List planar_sides = Arrays.asList( - BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST, BlockFace.EAST); - - private ReinforcementManager rm = Citadel.getReinforcementManager(); - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onFortificationMode(BlockPlaceEvent event){ - Player p = event.getPlayer(); - Block b = event.getBlock(); - Location loc = b.getLocation(); - Inventory inv = p.getInventory(); - Reinforcement rein = rm.getReinforcement(b.getLocation()); - if (Material.AIR.equals(event.getBlockReplacedState().getType())) { - if (rein != null && rein instanceof PlayerReinforcement){ - //Would be nice to find a more performant way to detect the entity w/o checking every entity. - for (Entity e : loc.getChunk().getEntities()){ - if (e instanceof Hanging){ - Location eloc = e.getLocation().getBlock().getLocation(); - if (eloc.getBlockX() == loc.getBlockX() && eloc.getBlockY() == loc.getBlockY() - && eloc.getBlockZ() == loc.getBlockZ()){ - event.setCancelled(true); - return; - } - } - } - - rm.deleteReinforcement(rein); - } - ItemStack stack = event.getItemInHand(); - rein = isDroppedReinforcementBlock(p, stack, loc); - if (rein != null){ - rm.saveInitialReinforcement(rein); - return; - } - } - PlayerState state = PlayerState.get(p); - if (state.getMode() != ReinforcementMode.REINFORCEMENT_FORTIFICATION) { - return; - } - if (!canPlace(b, p)){ - sendAndLog(p, ChatColor.RED, "Cancelled block place, mismatched reinforcement."); - event.setCancelled(true); - return; - } - ReinforcementType type = state.getReinforcementType(); - // Don't allow double reinforcing reinforceable plants - if (wouldPlantDoubleReinforce(b)) { - sendAndLog(p, ChatColor.RED, "Cancelled block place, crop would already be reinforced."); - event.setCancelled(true); - return; - } - int required = type.getRequiredAmount(); - if (type.getItemStack().isSimilar(event.getItemInHand())){ - required++; - } - if (inv.containsAtLeast(type.getItemStack(), required)) { - try { - if (createPlayerReinforcement(p, state.getGroup(), b, type, event.getItemInHand()) == null) { - sendAndLog(p, ChatColor.RED, String.format("%s is not a reinforcible material ", b.getType().name())); - } else { - state.checkResetMode(); - } - } catch(ReinforcemnetFortificationCancelException ex){ - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementFortificationCancelException occured in BlockListener, BlockPlaceEvent ", ex); - } - } else { - sendAndLog(p, ChatColor.YELLOW, String.format("%s depleted, left fortification mode ", - state.getReinforcementType().getMaterial().name())); - state.reset(); - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBreakEvent(BlockBreakEvent event){ - Block block = event.getBlock(); - Player player = event.getPlayer(); - Block reinforcingBlock = null; - Reinforcement rein = rm.getReinforcement(Utility.getRealBlock(block)); - - //if block is a plant check reinforcement on soil block - if(isPlant(block)){ - reinforcingBlock = Utility.findPlantSoil(block); - Reinforcement plant = null; - if (reinforcingBlock != null) - plant = rm.getReinforcement(reinforcingBlock); - if (plant != null) - rein = plant; - } - - if (rein == null){ - rein = createNaturalReinforcement(event.getBlock(), player); - if (rein != null){ - ReinforcementDamageEvent e = new ReinforcementDamageEvent(rein, player, block); - Bukkit.getPluginManager().callEvent(e); - if (e.isCancelled()){ - event.setCancelled(true); - return; - } - if(reinforcementDamaged(player, rein)) { - event.setCancelled(true); - } - } - return; - } - - boolean is_cancelled = true; - if (rein instanceof PlayerReinforcement) { - PlayerReinforcement pr = (PlayerReinforcement) rein; - PlayerState state = PlayerState.get(player); - boolean admin_bypass = player.hasPermission("citadel.admin.bypassmode"); - if (reinforcingBlock != null && isPlant(block) && (pr.canAccessCrops(player) || admin_bypass)) { - //player has CROPS access to the soil block, allow them to break without affecting reinforcement - is_cancelled = false; - } else if (state.isBypassMode() && (pr.canBypass(player) || admin_bypass) && !pr.getGroup().isDisciplined()) { - if (admin_bypass) { - /* - Citadel.verbose( - VerboseMsg.AdminReinBypass, - player.getDisplayName(), pr.getBlock().getLocation().toString()); - */ - } else { - /* - Citadel.verbose( - VerboseMsg.ReinBypass, - player.getDisplayName(), pr.getBlock().getLocation().toString()); - */ - } - is_cancelled = reinforcementBroken(player, rein); - } else { - - ReinforcementDamageEvent dre = new ReinforcementDamageEvent(rein, player, block); - - Bukkit.getPluginManager().callEvent(dre); - - if(dre.isCancelled()) { - is_cancelled = true; - } - else { - is_cancelled = reinforcementDamaged(player, rein); - } - } - if (!is_cancelled) { - // The player reinforcement broke. Now check for natural - is_cancelled = createNaturalReinforcement(block, player) != null; - } - } else { - ReinforcementDamageEvent dre = new ReinforcementDamageEvent(rein, player, block); - - Bukkit.getPluginManager().callEvent(dre); - - if(dre.isCancelled()) { - is_cancelled = reinforcementDamaged(player, rein); - return; - } - else { - is_cancelled = reinforcementDamaged(player, rein); - } - } - - if (is_cancelled) { - event.setCancelled(true); - block.getDrops().clear(); - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) - public void pistonExtend(BlockPistonExtendEvent bpee) { - for (Block block : bpee.getBlocks()) - { - Reinforcement reinforcement = rm.getReinforcement(block.getLocation()); - if (reinforcement != null){ - bpee.setCancelled(true); - break; - } - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) - public void pistonRetract(BlockPistonRetractEvent bpre) { - for (Block block : bpre.getBlocks()) - { - Reinforcement reinforcement = rm.getReinforcement(block.getLocation()); - if (reinforcement != null){ - bpre.setCancelled(true); - break; - } - } - } - - private static final Material matfire = Material.FIRE; - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) - public void blockBurn(BlockBurnEvent bbe) { - boolean wasprotected = maybeReinforcementDamaged(bbe.getBlock()); - if (wasprotected) { - bbe.setCancelled(wasprotected); - Block block = bbe.getBlock(); - // Basic essential fire protection - if (block.getRelative(0,1,0).getType() == matfire) {block.getRelative(0,1,0).setTypeId(0);} // Essential - // Extended fire protection (recommend) - if (block.getRelative(1,0,0).getType() == matfire) {block.getRelative(1,0,0).setTypeId(0);} - if (block.getRelative(-1,0,0).getType() == matfire) {block.getRelative(-1,0,0).setTypeId(0);} - if (block.getRelative(0,-1,0).getType() == matfire) {block.getRelative(0,-1,0).setTypeId(0);} - if (block.getRelative(0,0,1).getType() == matfire) {block.getRelative(0,0,1).setTypeId(0);} - if (block.getRelative(0,0,-1).getType() == matfire) {block.getRelative(0,0,-1).setTypeId(0);} - // Aggressive fire protection (would seriously reduce effectiveness of flint down to near the "you'd have to use it 25 times" mentality) - /* - if (block.getRelative(1,1,0).getType() == matfire) {block.getRelative(1,1,0).setTypeId(0);} - if (block.getRelative(1,-1,0).getType() == matfire) {block.getRelative(1,-1,0).setTypeId(0);} - if (block.getRelative(-1,1,0).getType() == matfire) {block.getRelative(-1,1,0).setTypeId(0);} - if (block.getRelative(-1,-1,0).getType() == matfire) {block.getRelative(-1,-1,0).setTypeId(0);} - if (block.getRelative(0,1,1).getType() == matfire) {block.getRelative(0,1,1).setTypeId(0);} - if (block.getRelative(0,-1,1).getType() == matfire) {block.getRelative(0,-1,1).setTypeId(0);} - if (block.getRelative(0,1,-1).getType() == matfire) {block.getRelative(0,1,-1).setTypeId(0);} - if (block.getRelative(0,-1,-1).getType() == matfire) {block.getRelative(0,-1,-1).setTypeId(0);} - */ - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) - public void onBlockFromToEvent(BlockFromToEvent event) { - Block reinforcementBlock = event.getToBlock(); - if(isPlant(reinforcementBlock)){ - //block to is as plant check block under it for reinforcement - reinforcementBlock = Utility.findPlantSoil(reinforcementBlock); - } - Reinforcement rein = rm.getReinforcement(reinforcementBlock); - if (rein != null) { - event.setCancelled(true); - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void redstonePower(BlockRedstoneEvent bre) { - // This currently only protects against reinforced openable objects, - // like doors, from being opened by unauthorizied players. - try { - // NewCurrent <= 0 means the redstone wire is turning off, so the - // container is closing. Closing is good so just return. This also - // shaves off some time when dealing with sand generators. - // OldCurrent > 0 means that the wire was already on, thus the - // container was already open by an authorized player. Now it's - // either staying open or closing. Just return. - if (bre.getNewCurrent() <= 0 || bre.getOldCurrent() > 0) { - return; - } - Block block = bre.getBlock(); - MaterialData blockData = block.getState().getData(); - if (!(blockData instanceof Openable)) { - return; - } - Openable openable = (Openable)blockData; - if (openable.isOpen()) { - return; - } - Reinforcement generic_reinforcement = - Citadel.getReinforcementManager().getReinforcement(block); - if (generic_reinforcement == null || - !(generic_reinforcement instanceof PlayerReinforcement)) { - return; - } - PlayerReinforcement reinforcement = - (PlayerReinforcement)generic_reinforcement; - double redstoneDistance = CitadelConfigManager.getMaxRedstoneDistance(); - if (!isAuthorizedPlayerNear(reinforcement, redstoneDistance)) { - // Citadel.Log( - // reinforcement.getLocation().toString()); - bre.setNewCurrent(bre.getOldCurrent()); - } - } catch(Exception e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "Exception occured in BlockListener, BlockRedstoneEvent ", e); - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void interact(PlayerInteractEvent pie) { - try { - if (!pie.hasBlock()) return; - - Player player = pie.getPlayer(); - Block block = Utility.getRealBlock(pie.getClickedBlock()); - Reinforcement generic_reinforcement = rm.getReinforcement(block); - PlayerReinforcement reinforcement = null; - if (generic_reinforcement instanceof PlayerReinforcement) { - reinforcement = (PlayerReinforcement)generic_reinforcement; - } - - Action action = pie.getAction(); - boolean access_reinforcement = - action == Action.RIGHT_CLICK_BLOCK - && reinforcement != null - && reinforcement.isSecurable(); - boolean normal_access_denied = - reinforcement != null - && ((reinforcement.isDoor() && !reinforcement.canAccessDoors(player)) || - (reinforcement.isContainer() &&!reinforcement.canAccessChests(player))); - boolean admin_can_access = player.hasPermission("citadel.admin"); - if (access_reinforcement && normal_access_denied && !admin_can_access) { - /*Citadel.verbose( - VerboseMsg.ReinLocked, - player.getDisplayName(), block.getLocation().toString()); - */ - pie.getPlayer().sendMessage(ChatColor.RED + String.format("%s is locked", block.getType().name())); - pie.setCancelled(true); - } - // Not really sure what this is for. Should come up in testing. - /*else if (action == Action.PHYSICAL) { - AccessDelegate aboveDelegate = AccessDelegate.getDelegate(block.getRelative(BlockFace.UP)); - if (aboveDelegate instanceof CropAccessDelegate - && aboveDelegate.isReinforced()) { - Citadel.verbose( - VerboseMsg.CropTrample, - block.getLocation().toString()); - pie.setCancelled(true); - } - } - */ - if (pie.isCancelled()) return; - - PlayerState state = PlayerState.get(player); - ReinforcementMode placementMode = state.getMode(); - switch (placementMode) { - case NORMAL: - if (access_reinforcement && normal_access_denied && admin_can_access) { - /* - Citadel.verbose( - VerboseMsg.AdminReinLocked, - player.getDisplayName(), block.getLocation().toString()); - */ - } - return; - case REINFORCEMENT_FORTIFICATION: - return; - case REINFORCEMENT_INFORMATION: - // did player click on a reinforced block? - if (reinforcement != null) { - String reinforcementStatus = reinforcement.getStatus(); - String ageStatus = reinforcement.getAgeStatus(); - Group group = reinforcement.getGroup(); - StringBuilder sb; - if (player.hasPermission("citadel.admin.ctinfodetails")) { - sendAndLog(player, ChatColor.GREEN, String.format( - "Loc[%s]", reinforcement.getLocation().toString())); - String groupName = "!NULL!"; - if (group != null) { - groupName = String.format("[%s]", group.getName()); - } - sb = new StringBuilder(); - sb.append(String.format(" Group%s Durability[%d/%d]", - groupName, - reinforcement.getDurability(), - ReinforcementType.getReinforcementType - (reinforcement.getStackRepresentation()).getHitPoints())); - int maturationTime = timeUntilMature(reinforcement); - if (maturationTime != 0) { - sb.append(" Immature["); - sb.append(maturationTime); - sb.append("]"); - } - int acidTime = timeUntilAcidMature(reinforcement); - if (CitadelConfigManager.getAcidBlock() == block.getType()) { - sb.append(" Acid "); - if (acidTime != 0) { - sb.append("Immature["); - sb.append(acidTime); - sb.append("]"); - } else { - sb.append("Mature"); - } - } - if (reinforcement.isInsecure()) { - sb.append(" (Insecure)"); - } - if (group.isDisciplined()) { - sb.append(" (Disciplined)"); - } - sb.append("\nGroup id: " + reinforcement.getGroupId()); - - sendAndLog(player, ChatColor.GREEN, sb.toString()); - } else if(reinforcement.canViewInformation(player)){ - sb = new StringBuilder(); - boolean immature = timeUntilMature(reinforcement) != 0 - && CitadelConfigManager.isMaturationEnabled(); - boolean acid = timeUntilAcidMature(reinforcement) != 0 - && CitadelConfigManager.getAcidBlock() == block.getType(); - String groupName = "!NULL!"; - if (group != null) { - groupName = group.getName(); - } - sb.append(String.format("%s, %s, group: %s", - reinforcementStatus, ageStatus, groupName)); - if(immature){ - sb.append(" (Hardening)"); - } - if(acid){ - sb.append(" (Acid Maturing)"); - } - if (reinforcement.isInsecure()) { - sb.append(" (Insecure)"); - } - sendAndLog(player, ChatColor.GREEN, sb.toString()); - } else { - sendAndLog(player, ChatColor.RED, reinforcementStatus + ", " + ageStatus); - } - if (player.getGameMode() == GameMode.CREATIVE) { - pie.setCancelled(true); - } - } - break; - - case INSECURE: - // did player click on a reinforced block? - pie.setCancelled(true); - if (reinforcement != null) { - if (reinforcement.canMakeInsecure(player)) { - reinforcement.toggleInsecure(); - // Save the change - Citadel.getReinforcementManager().saveReinforcement(reinforcement); - if (reinforcement.isInsecure()) { - sendAndLog(player, ChatColor.YELLOW, "Reinforcement now insecure"); - } else { - sendAndLog(player, ChatColor.GREEN, "Reinforcement secured"); - } - } else { - sendAndLog(player, ChatColor.RED, "Access denied"); - } - } - break; - - case REINFORCEMENT: - // player is in reinforcement mode - if (reinforcement == null) { - // set the reinforcemet material to what the player is holding - ItemStack stack = player.getItemInHand(); - ReinforcementType type = ReinforcementType.getReinforcementType(stack); - if (type == null){ - sendAndLog(player, ChatColor.RED, stack.getType().name() + " is not a reinforcable material."); - sendAndLog(player, ChatColor.RED, "Left Reinforcement mode."); - state.reset(); - return; - } - state.setFortificationItemStack(type.getItemStack()); - // Break any natural reinforcement before placing the player reinforcement - if (generic_reinforcement != null) { - reinforcementBroken(null, generic_reinforcement); - } - // Don't allow double reinforcing reinforceable plants - if (wouldPlantDoubleReinforce(block)) { - sendAndLog(player, ChatColor.RED, "Cancelled reinforcement, crop would already be reinforced."); - } else { - try { - createPlayerReinforcement(player, state.getGroup(), - block, state.getReinforcementType(), null); - } catch(ReinforcemnetFortificationCancelException e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementFortificationCancelException occured in BlockListener, PlayerInteractEvent ",e); - } - } - } else if (reinforcement.canBypass(player) || (player.isOp() || player.hasPermission("citadel.admin"))) { - String message = ""; - Group group = state.getGroup(); - Group old_group = reinforcement.getGroup(); - if(!old_group.getName().equals(group.getName())) { - reinforcement.setGroup(group); - ReinforcementCreationEvent event = new ReinforcementCreationEvent(reinforcement, block, player); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) { - rm.saveReinforcement(reinforcement); - message = "Group has been changed to: " + group.getName() + "."; - sendAndLog(player, ChatColor.GREEN, message); - } - else - reinforcement.setGroup(old_group); - } - } else { - sendAndLog(player, ChatColor.RED, "You are not permitted to modify this reinforcement"); - } - pie.setCancelled(true); - state.checkResetMode(); - default: - break; - } - - } catch(Exception e) { - Citadel.getInstance().getLogger().log(Level.WARNING, "General Exception during player interaction", e); - } - } - -// TODO: Come back and figure out why this is causing all the data to be re-written inplace with no change -/* @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void chunkLoadEvent(ChunkLoadEvent event) { - Chunk chunk = event.getChunk(); - rm.loadReinforcementChunk(chunk); - }*/ - - @EventHandler(priority = EventPriority.HIGHEST) - public void blockPhysEvent(BlockPhysicsEvent event){ - Block block = event.getBlock(); - if (block.getType().hasGravity()){ - Reinforcement rein = rm.getReinforcement(Utility.getRealBlock(block)); - if (rein != null){ - event.setCancelled(true); - } - } - - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void liquidDumpEvent(PlayerBucketEmptyEvent event){ - Block block = event.getBlockClicked().getRelative(event.getBlockFace()); - if (block.getType().equals(Material.AIR) || block.getType().isSolid()) - return; - - Reinforcement rein = rm.getReinforcement(Utility.getRealBlock(block)); - if (rein != null){ - event.setCancelled(true); - } - } - - protected void sendAndLog(Player receiver, ChatColor color, String message) { - receiver.sendMessage(color + message); - if (CitadelConfigManager.shouldLogPlayerCommands()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Sent {0} reply {1}", new Object[]{receiver.getName(), message}); - } - } -} diff --git a/src/vg/civcraft/mc/citadel/listener/EntityListener.java b/src/vg/civcraft/mc/citadel/listener/EntityListener.java deleted file mode 100644 index 3859c656..00000000 --- a/src/vg/civcraft/mc/citadel/listener/EntityListener.java +++ /dev/null @@ -1,378 +0,0 @@ -package vg.civcraft.mc.citadel.listener; - -import static vg.civcraft.mc.citadel.Utility.canPlace; -import static vg.civcraft.mc.citadel.Utility.createNaturalReinforcement; -import static vg.civcraft.mc.citadel.Utility.createPlayerReinforcement; -import static vg.civcraft.mc.citadel.Utility.explodeReinforcement; -import static vg.civcraft.mc.citadel.Utility.maybeReinforcementDamaged; -import static vg.civcraft.mc.citadel.Utility.reinforcementBroken; -import static vg.civcraft.mc.citadel.Utility.reinforcementDamaged; -import static vg.civcraft.mc.citadel.Utility.timeUntilAcidMature; -import static vg.civcraft.mc.citadel.Utility.timeUntilMature; -import static vg.civcraft.mc.citadel.Utility.wouldPlantDoubleReinforce; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; -import java.util.logging.Level; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityBreakDoorEvent; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.hanging.HangingBreakByEntityEvent; -import org.bukkit.event.hanging.HangingBreakEvent; -import org.bukkit.event.hanging.HangingPlaceEvent; -import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.Inventory; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.ReinforcementMode; -import vg.civcraft.mc.citadel.Utility; -import vg.civcraft.mc.citadel.events.ReinforcementDamageEvent; -import vg.civcraft.mc.citadel.misc.ReinforcemnetFortificationCancelException; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.GroupManager.PlayerType; -import vg.civcraft.mc.namelayer.NameLayerPlugin; -import vg.civcraft.mc.namelayer.database.GroupManagerDao; -import vg.civcraft.mc.namelayer.events.PromotePlayerEvent; -import vg.civcraft.mc.namelayer.group.Group; -import vg.civcraft.mc.namelayer.permission.GroupPermission; -import vg.civcraft.mc.namelayer.permission.PermissionType; - - -public class EntityListener implements Listener{ - protected GroupManager gm = NameAPI.getGroupManager(); - private ReinforcementManager rm = Citadel.getReinforcementManager(); - - @EventHandler(ignoreCancelled = true) - public void explode(EntityExplodeEvent eee) { - Iterator iterator = eee.blockList().iterator(); - List blocks = new ArrayList(); - while (iterator.hasNext()) { - Block b = iterator.next(); - Block block = Utility.getRealBlock(b); - //if it's a plant we want to check the reinforcement of the soil block - if(Utility.isPlant(block)) { - Block soilBlock = block.getRelative(BlockFace.DOWN); - if(Citadel.getReinforcementManager().isReinforced(soilBlock)) { - block.getDrops().clear(); - iterator.remove(); - } - } - // getRealBlock should return the block we care about so if its already in the list we know it is a double block and was already handled. - if (blocks.contains(block)){ - block.getDrops().clear(); - iterator.remove(); - continue; - } - blocks.add(block); - try { - if (explodeReinforcement(block)) { - block.getDrops().clear(); - iterator.remove(); - } - } catch (NoClassDefFoundError e){ - Citadel.getInstance().getLogger().log(Level.WARNING, "Class Definition not found in explode", e); - } - } - } - - @EventHandler(ignoreCancelled = true) - public void breakDoor(EntityBreakDoorEvent ebde) { - ebde.setCancelled(maybeReinforcementDamaged(ebde.getBlock())); - } - - @EventHandler(ignoreCancelled = true) - public void changeBlock(EntityChangeBlockEvent ecbe) { - ecbe.setCancelled(maybeReinforcementDamaged(ecbe.getBlock())); - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void spawn(CreatureSpawnEvent cse) { - ReinforcementManager reinforcementManager = Citadel.getReinforcementManager(); - EntityType type = cse.getEntityType(); - if (type != EntityType.IRON_GOLEM && type != EntityType.SNOWMAN && type != EntityType.WITHER && type != EntityType.SILVERFISH) return; - - for (Block block : getGolemBlocks(type, cse.getLocation().getBlock())) { - Reinforcement reinforcement = reinforcementManager.getReinforcement(block); - if (reinforcement != null) { - cse.setCancelled(true); - } - } - } - - private List getGolemBlocks(EntityType type, Block base) { - ArrayList blocks = new ArrayList(); - blocks.add(base); - base = base.getRelative(BlockFace.UP); - blocks.add(base); - if (type == EntityType.IRON_GOLEM) { - for (BlockFace face : new BlockFace[]{ BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST }) { - Block arm = base.getRelative(face); - if (arm.getType() == Material.IRON_BLOCK) - blocks.add(arm); - } - } - base = base.getRelative(BlockFace.UP); - blocks.add(base); - - return blocks; - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void playerQuitEvent(PlayerQuitEvent event){ - Player p = event.getPlayer(); - PlayerState state = PlayerState.get(p); - state.reset(); - } - - - @EventHandler(priority = EventPriority.HIGHEST) - public void hangingPlaceEvent(HangingPlaceEvent event){ - Player p = event.getPlayer(); - Block b = event.getBlock().getRelative(event.getBlockFace()); - Inventory inv = p.getInventory(); - PlayerState state = PlayerState.get(p); - if (ReinforcementMode.REINFORCEMENT_FORTIFICATION != state.getMode()) { - return; - } - if (!canPlace(b, p)){ - sendAndLog(p, ChatColor.RED, "Cancelled block place, mismatched reinforcement."); - event.setCancelled(true); - return; - } - ReinforcementType type = state.getReinforcementType(); - // Don't allow double reinforcing reinforceable plants - if (wouldPlantDoubleReinforce(b)) { - sendAndLog(p, ChatColor.RED, "Cancelled block place, crop would already be reinforced."); - event.setCancelled(true); - return; - } - int required = type.getRequiredAmount(); - if (type.getItemStack().isSimilar(p.getItemInHand())){ - required++; - } - if (inv.containsAtLeast(type.getItemStack(), required)) { - try { - if (createPlayerReinforcement(p, state.getGroup(), b, type, p.getItemInHand()) == null) { - sendAndLog(p, ChatColor.RED, String.format("%s is not a reinforcible material ", b.getType().name())); - } else { - state.checkResetMode(); - } - } catch(ReinforcemnetFortificationCancelException ex){ - Citadel.getInstance().getLogger().log(Level.WARNING, "ReinforcementFortificationCancelException occured in BlockListener, BlockPlaceEvent ", ex); - } - } else { - sendAndLog(p, ChatColor.YELLOW, String.format("%s depleted, left fortification mode ", - state.getReinforcementType().getMaterial().name())); - state.reset(); - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void hangingEntityBreakEvent(HangingBreakByEntityEvent event){ - Reinforcement rein = rm.getReinforcement(event.getEntity().getLocation()); if (rein == null){return;} - if (RemoveCause.PHYSICS.equals(event.getCause())){ - //Checks if block entity was attached to was broken - if (event.getEntity().getLocation().getBlock().getRelative( - event.getEntity().getAttachedFace()).getType().equals(Material.AIR)){ - //Comment out these next two lines to keep floating hanging entities if they are reinforced - rm.deleteReinforcement(rein); - return; - } else { - event.setCancelled(true); - return; - } - } - Entity remover = event.getRemover(); if (!(remover instanceof Player)){event.setCancelled(true);return;} - Player player = (Player)remover; - Block block = event.getEntity().getLocation().getBlock(); - boolean is_cancelled = true; - if (rein instanceof PlayerReinforcement) { - PlayerReinforcement pr = (PlayerReinforcement) rein; - PlayerState state = PlayerState.get(player); - ReinforcementMode mode = state.getMode(); - if (ReinforcementMode.REINFORCEMENT_INFORMATION.equals(mode)){ - Group group = pr.getGroup(); - StringBuilder sb; - if (player.hasPermission("citadel.admin.ctinfodetails")) { - sendAndLog(player, ChatColor.GREEN, String.format( - "Loc[%s]", pr.getLocation().toString())); - String groupName = "!NULL!"; - if (group != null) { - groupName = String.format("[%s]"); - } - sb = new StringBuilder(); - sb.append(String.format(" Group%s Durability[%d/%d]", - groupName, - pr.getDurability(), - ReinforcementType.getReinforcementType - (pr.getStackRepresentation()).getHitPoints())); - int maturationTime = timeUntilMature(pr); - if (maturationTime != 0) { - sb.append(" Immature["); - sb.append(maturationTime); - sb.append("]"); - } - int acidTime = timeUntilAcidMature(pr); - if (CitadelConfigManager.getAcidBlock() == block.getType()) { - sb.append(" Acid "); - if (acidTime != 0) { - sb.append("Immature["); - sb.append(acidTime); - sb.append("]"); - } else { - sb.append("Mature"); - } - } - if (pr.isInsecure()) { - sb.append(" (Insecure)"); - } - if (group.isDisciplined()) { - sb.append(" (Disciplined)"); - } - sb.append("\nGroup id: " + pr.getGroupId()); - - sendAndLog(player, ChatColor.GREEN, sb.toString()); - event.setCancelled(is_cancelled); - return; - } - } - boolean admin_bypass = player.hasPermission("citadel.admin.bypassmode"); - if (state.isBypassMode() && (pr.canBypass(player) || admin_bypass) && !pr.getGroup().isDisciplined()) { - reinforcementBroken(player, rein); - is_cancelled = false; - } else { - - ReinforcementDamageEvent dre = new ReinforcementDamageEvent(rein, player, event.getEntity().getLocation().getBlock()); - - Bukkit.getPluginManager().callEvent(dre); - - if(dre.isCancelled()) { - is_cancelled = true; - } - else { - is_cancelled = reinforcementDamaged(player, rein); - } - } - if (!is_cancelled) { - // The player reinforcement broke. Now check for natural - is_cancelled = createNaturalReinforcement(block, player) != null; - } - } else { - ReinforcementDamageEvent dre = new ReinforcementDamageEvent(rein, player, block); - - Bukkit.getPluginManager().callEvent(dre); - - if(dre.isCancelled()) { - is_cancelled = reinforcementDamaged(player, rein); - return; - } - else { - is_cancelled = reinforcementDamaged(player, rein); - } - } - - if (is_cancelled) { - event.setCancelled(true); - block.getDrops().clear(); - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void hangingBreakEvent(HangingBreakEvent event){ - Reinforcement rein = rm.getReinforcement(event.getEntity().getLocation()); if (rein == null){return;} - if (RemoveCause.PHYSICS.equals(event.getCause())){ - //Checks if block entity was attached to was broken - if (event.getEntity().getLocation().getBlock().getRelative( - event.getEntity().getAttachedFace()).getType().equals(Material.AIR)){ - //Comment out these next two lines to keep floating hanging entities if they are reinforced - rm.deleteReinforcement(rein); - return; - } - } - event.setCancelled(true); - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void playerEntityInteractEvent(PlayerInteractEntityEvent event){ - Entity entity = event.getRightClicked(); - if (entity instanceof ItemFrame){ - Reinforcement rein = rm.getReinforcement(entity.getLocation()); - if (rein == null || !(rein instanceof PlayerReinforcement)) - return; - PlayerReinforcement pr = (PlayerReinforcement)rein; - Group group = pr.getGroup(); if (group == null){return;} - - if (group.isMember(event.getPlayer().getUniqueId()) == false){ - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void entityDamageEvent(EntityDamageByEntityEvent event){ - Entity entity = event.getEntity(); - if (entity instanceof ItemFrame){ - Reinforcement rein = rm.getReinforcement(entity.getLocation()); - if (rein == null || !(rein instanceof PlayerReinforcement)) - return; - Entity damager = event.getDamager(); if (!(damager instanceof Player)){event.setCancelled(true);return;} - Player player = (Player)damager; - PlayerReinforcement pr = (PlayerReinforcement)rein; - Group group = pr.getGroup(); if (group == null){return;} - - if (group.isMember(player.getUniqueId()) == false){ - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority=EventPriority.LOWEST) - public void playerJoinEvent(PlayerJoinEvent event){ - Player p = event.getPlayer(); - UUID uuid = p.getUniqueId(); - GroupManagerDao db = NameLayerPlugin.getGroupManagerDao(); - for (String groupName : db.getGroupNames(uuid)){ - if(NameAPI.getGroupManager().hasAccess(groupName, p.getUniqueId(), PermissionType.getPermission("REINFORCE"))) { - db.updateTimestamp(groupName); - } - } - } - - protected void sendAndLog(Player receiver, ChatColor color, String message) { - receiver.sendMessage(color + message); - if (CitadelConfigManager.shouldLogPlayerCommands()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Sent {0} reply {1}", new Object[]{receiver.getName(), message}); - } - } -} diff --git a/src/vg/civcraft/mc/citadel/listener/GroupsListener.java b/src/vg/civcraft/mc/citadel/listener/GroupsListener.java deleted file mode 100644 index 6b53220d..00000000 --- a/src/vg/civcraft/mc/citadel/listener/GroupsListener.java +++ /dev/null @@ -1,22 +0,0 @@ -package vg.civcraft.mc.citadel.listener; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.namelayer.events.GroupDeleteEvent; -import vg.civcraft.mc.namelayer.events.GroupMergeEvent; - -public class GroupsListener implements Listener { - private ReinforcementManager rm = Citadel.getReinforcementManager(); - - @EventHandler(priority = EventPriority.HIGHEST) - public void deleteGroupEvent(GroupDeleteEvent event){ - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void mergeGroupEvent(GroupMergeEvent event){ - } -} diff --git a/src/vg/civcraft/mc/citadel/listener/InventoryListener.java b/src/vg/civcraft/mc/citadel/listener/InventoryListener.java deleted file mode 100644 index 5d509e1c..00000000 --- a/src/vg/civcraft/mc/citadel/listener/InventoryListener.java +++ /dev/null @@ -1,127 +0,0 @@ -package vg.civcraft.mc.citadel.listener; - -import java.util.Set; -import java.util.TreeSet; - -import org.bukkit.Location; -import org.bukkit.block.BlockState; -import org.bukkit.block.DoubleChest; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryMoveItemEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.ReinforcementManager; -import vg.civcraft.mc.citadel.Utility; -import vg.civcraft.mc.citadel.reinforcement.PlayerReinforcement; -import vg.civcraft.mc.citadel.reinforcement.Reinforcement; -import vg.civcraft.mc.namelayer.group.Group; - -public class InventoryListener implements Listener { - private ReinforcementManager rm = Citadel.getReinforcementManager(); - private Set priorMessages_ = new TreeSet(); - - public PlayerReinforcement getReinforcement(Inventory inv) { - // Returns reinforcement of the inventory's holder or null if none - // exists - final InventoryHolder holder = inv.getHolder(); - Location loc; - if (holder instanceof DoubleChest) { - loc = Utility.getRealBlock(((DoubleChest) holder).getLocation().getBlock()).getLocation(); - } else if (holder instanceof BlockState) { - loc = Utility.getRealBlock(((BlockState) holder).getLocation().getBlock()).getLocation(); - } else { - // Entity or Vehicle inventories - return null; - } - Reinforcement rein = rm.getReinforcement(loc); - if (rein instanceof PlayerReinforcement) { - PlayerReinforcement pr = (PlayerReinforcement) rein; - return pr; - } - return null; - } - - @EventHandler(ignoreCancelled = true) - public void onInventoryMoveItemEvent(InventoryMoveItemEvent event) { - // Prevent hopper minecarts from extracting from reinforced containers - // or - // filling up reinforced containers. - // Prevent misowned hoppers from stealing from reinforced containers. - // - // Allowed transfers: - // Assertions: - // Public reinforcement == Non-reinforced - // Y is a member of Group X - // Insecure sources act like public reinforcements - // Public -> Public - // Public -> Group X - // Public -> Personal Y - // Group X -> Group X - // Group X -> Personal Y - // Personal Y -> Personal Y - - // Fail safe - event.setCancelled(true); - // Source - final Inventory src = event.getSource(); - final PlayerReinforcement srcRein = getReinforcement(src); - // Destination - final Inventory dest = event.getDestination(); - final PlayerReinforcement destRein = getReinforcement(dest); - if (srcRein == null) { - if (destRein != null) { - final Group destOwner = destRein.getGroup(); - if (destOwner != null && destOwner.isDisciplined()) { - // Dest is disabled, deny - return; - } - } - // Public can transfer into any, allow - // (Public -> Public, Public -> Group X, Public -> Personal Y) - event.setCancelled(false); - return; - } - if (srcRein.isInsecure()) { - // Insecure source reinforcement allows transfer as if it's - // a public reinforcement, allow - event.setCancelled(false); - return; - } - // Assertion: srcRein != null - if (destRein == null) { - // Non-public cannot transfer into a public, deny - return; - } - // Assertion: srcRein != null && destRein != null - final Group srcOwner = srcRein.getGroup(); - final Group destOwner = destRein.getGroup(); - // Check for null group failure - if (srcOwner == null || destOwner == null) { - /* - * if (Citadel.verboseEnabled(VerboseMsg.NullGroup)) { String msg; - * if (srcOwner == null) { msg = Citadel.verboseFmt( - * VerboseMsg.NullGroup, "srcOwner", srcRein.getOwnerName()); } else - * { // destOwner == null msg = Citadel.verboseFmt( - * VerboseMsg.NullGroup, "dstOwner", destRein.getOwnerName()); } if - * (!priorMessages_.contains(msg)) { Citadel.info(msg); - * priorMessages_.add(msg); } } - */ - // Unable to determine reinforcement owner match, deny - return; - } - if (srcOwner.isDisciplined() || destOwner.isDisciplined()) { - // Disabled group involved, deny - return; - } - if (srcOwner == destOwner) { - // Reinforcement owners match, allow - // (Group X -> Group X, Personal Y -> Personal Y) - event.setCancelled(false); - return; - } - // Reinforcement owners don't match, deny - } -} \ No newline at end of file diff --git a/src/vg/civcraft/mc/citadel/listener/ShardListener.java b/src/vg/civcraft/mc/citadel/listener/ShardListener.java deleted file mode 100644 index 5fe33229..00000000 --- a/src/vg/civcraft/mc/citadel/listener/ShardListener.java +++ /dev/null @@ -1,92 +0,0 @@ -package vg.civcraft.mc.citadel.listener; - -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; - -import org.bukkit.Material; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import vg.civcraft.mc.bettershards.events.PlayerChangeServerEvent; -import vg.civcraft.mc.bettershards.events.PlayerChangeServerReason; -import vg.civcraft.mc.citadel.PlayerState; -import vg.civcraft.mc.citadel.ReinforcementMode; -import vg.civcraft.mc.mercury.MercuryAPI; -import vg.civcraft.mc.mercury.events.AsyncPluginBroadcastMessageEvent; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.group.Group; - -public class ShardListener implements Listener { - - @EventHandler(ignoreCancelled = true) - public void serverChange(PlayerChangeServerEvent e) { - StringBuilder sb; - if (e.getReason() == PlayerChangeServerReason.PORTAL) { - sb = new StringBuilder(); - sb.append("modetransfer"); - sb.append("|"); - sb.append(e.getPlayerUUID()); - sb.append("|"); - PlayerState ps = PlayerState.get(e.getPlayerUUID()); - sb.append(ps.getMode().toString()); - if (ps.getMode() == ReinforcementMode.REINFORCEMENT - || ps.getMode() == ReinforcementMode.REINFORCEMENT_FORTIFICATION) { - sb.append("|"); - sb.append(ps.getGroup().getName()); - if (ps.getMode() == ReinforcementMode.REINFORCEMENT_FORTIFICATION) { - sb.append("|"); - ItemStack is = ps.getReinforcementType().getItemStack(); - sb.append(is.getType()); - sb.append("|"); - sb.append(is.getDurability()); - if (is.getItemMeta().getLore() != null) { - for (String s : is.getItemMeta().getLore()) { - sb.append("|"); - sb.append(s); - } - } - } - } - } - else { - return; - } - MercuryAPI.sendMessage(e.getServerTravelingTo(), sb.toString(), - "Citadel"); - } - - @EventHandler - public void messageReceive(AsyncPluginBroadcastMessageEvent e) { - if (!e.getChannel().equals("Citadel")) { - return; - } - String[] data = e.getMessage().split("\\|"); - if (data[0].equals("modetransfer")) { - UUID uuid = UUID.fromString(data[1]); - PlayerState ps = PlayerState.get(uuid); - ReinforcementMode mode = ReinforcementMode.valueOf(data[2]); - ps.setMode(mode); - if (mode == ReinforcementMode.REINFORCEMENT - || mode == ReinforcementMode.REINFORCEMENT_FORTIFICATION) { - Group g = NameAPI.getGroupManager().getGroup(data[3]); - ps.setGroup(g); - if (mode == ReinforcementMode.REINFORCEMENT_FORTIFICATION) { - Material m = Material.valueOf(data[4]); - short dura = Short.parseShort(data[5]); - List lore = new LinkedList(); - for(int i = 6; i < data.length; i++) { - lore.add(data[i]); - } - ItemStack is = new ItemStack(m, 1, dura); - ItemMeta im = is.getItemMeta(); - im.setLore(lore); - is.setItemMeta(im); - ps.setFortificationItemStack(is); - } - } - } - } -} diff --git a/src/vg/civcraft/mc/citadel/listener/WorldListener.java b/src/vg/civcraft/mc/citadel/listener/WorldListener.java deleted file mode 100644 index 7fe9c5d6..00000000 --- a/src/vg/civcraft/mc/citadel/listener/WorldListener.java +++ /dev/null @@ -1,26 +0,0 @@ -package vg.civcraft.mc.citadel.listener; - -import org.bukkit.block.BlockState; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.world.StructureGrowEvent; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.ReinforcementManager; - -public class WorldListener implements Listener{ - @EventHandler(ignoreCancelled = true) - public void onStructureGrow(StructureGrowEvent event) { - ReinforcementManager rm = Citadel.getReinforcementManager(); - for (BlockState block_state : event.getBlocks()) { - if (rm.getReinforcement(block_state.getLocation()) != null) { - event.setCancelled(true); - /*Citadel.verbose( - VerboseMsg.ReinOvergrowth, - block_state.getLocation().toString()); - */ - return; - } - } - } -} diff --git a/src/vg/civcraft/mc/citadel/misc/CitadelStatics.java b/src/vg/civcraft/mc/citadel/misc/CitadelStatics.java deleted file mode 100644 index c73ce481..00000000 --- a/src/vg/civcraft/mc/citadel/misc/CitadelStatics.java +++ /dev/null @@ -1,73 +0,0 @@ -package vg.civcraft.mc.citadel.misc; - -import vg.civcraft.mc.citadel.Citadel; - -public enum CitadelStatics { - - UPDATE, - DELETE, - INSERT, - CACHE, - LOAD; - - private static int reins_loaded_from_db = 0; - private static int reins_called_from_cache = 0; - private static int reins_updated_to_db = 0; - private static int reins_deleted_from_db = 0; - private static int reins_insert_to_db = 0; - - /** - * Increments the counter of the db call type. - * @param en - */ - public static void updateHitStat(CitadelStatics en){ - switch(en){ - case UPDATE: - reins_updated_to_db++; - break; - case DELETE: - reins_deleted_from_db++; - break; - case INSERT: - reins_insert_to_db++; - break; - case CACHE: - reins_called_from_cache++; - break; - case LOAD: - reins_loaded_from_db++; - break; - } - } - - public static void decrementHitStat(CitadelStatics en){ - switch(en){ - case UPDATE: - reins_updated_to_db--; - break; - case DELETE: - reins_deleted_from_db--; - break; - case INSERT: - reins_insert_to_db--; - break; - case CACHE: - reins_called_from_cache--; - break; - case LOAD: - reins_loaded_from_db--; - break; - } - } - - public static void displayStatisticsToConsole(){ - StringBuilder stats = new StringBuilder("Citadel Reinforcement Stats:\n"); - stats.append(" Reinforcements loaded from db ").append(reins_loaded_from_db).append(".\n"); - stats.append(" Reinforcements loaded from cache ").append(reins_called_from_cache).append(".\n"); - stats.append(" Total Reinforcement calls ").append(reins_called_from_cache + reins_loaded_from_db).append(".\n"); - stats.append(" Amount of Reinforcement saves ").append(reins_updated_to_db).append(".\n"); - stats.append(" Reinforcements deleted from the db ").append(reins_deleted_from_db).append(".\n"); - stats.append(" Reinforcements created and saved to db ").append(reins_insert_to_db).append(".\n"); - Citadel.Log(stats.toString()); - } -} diff --git a/src/vg/civcraft/mc/citadel/misc/LoadingCacheNullException.java b/src/vg/civcraft/mc/citadel/misc/LoadingCacheNullException.java deleted file mode 100644 index 8a5dd672..00000000 --- a/src/vg/civcraft/mc/citadel/misc/LoadingCacheNullException.java +++ /dev/null @@ -1,12 +0,0 @@ -package vg.civcraft.mc.citadel.misc; - -public class LoadingCacheNullException extends RuntimeException{ - - public LoadingCacheNullException(String message){ - super(message); - } - - public LoadingCacheNullException(){ - super(); - } -} diff --git a/src/vg/civcraft/mc/citadel/misc/ReinforcemnetFortificationCancelException.java b/src/vg/civcraft/mc/citadel/misc/ReinforcemnetFortificationCancelException.java deleted file mode 100644 index 4bd03710..00000000 --- a/src/vg/civcraft/mc/citadel/misc/ReinforcemnetFortificationCancelException.java +++ /dev/null @@ -1,8 +0,0 @@ -package vg.civcraft.mc.citadel.misc; - -public class ReinforcemnetFortificationCancelException extends RuntimeException{ - - public ReinforcemnetFortificationCancelException(){ - - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcement/MultiBlockReinforcement.java b/src/vg/civcraft/mc/citadel/reinforcement/MultiBlockReinforcement.java deleted file mode 100644 index 3bfc641a..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcement/MultiBlockReinforcement.java +++ /dev/null @@ -1,86 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcement; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -import org.bukkit.Location; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.group.Group; - -public class MultiBlockReinforcement extends Reinforcement{ - - List locs; - private Group g; - private static Map reins = - new HashMap(); - - public MultiBlockReinforcement(List locs, Group g, int dur, - int creation, int acid, int multiBlockId) { - super(null, null, dur, creation, acid); - this.g = g; - this.locs = locs; - } - - @Override - /** - * @return Returns the first location in the list of locations. - */ - public Location getLocation(){ - return locs.get(0); - } - - public List getLocations(){ - return locs; - } - - public void setGroup(Group g){ - this.g = g; - isDirty = true; - } - - public Group getGroup(){ - checkValid(); - return g; - } - - private void checkValid(){ - if (g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "CheckValid was called but the underlying group is gone for " + this.getLocation() + "!"); - return; - } - if (!g.isValid()){ // incase it was recently merged/ deleted. - g = NameAPI.getGroupManager().getGroup(g.getGroupId()); - if (g == null) { - Citadel.getInstance().getLogger().log(Level.INFO, "Group " + g.getGroupId() + " was deleted or merged but not marked invalid!"); - } - isDirty = true; - } - } - /** - * This method is used to get the MultiblockReinforcement from a - * particular id. The id is the one from the db. - * @param id- The unique identifier for the MultiBlock. - * @return Returns the MultiBlockReinforcement. - */ - public static MultiBlockReinforcement getMultiRein(int id){ - return reins.get(id); - } - - /** - * Note this is different to the group id of a Group. - * If a reinforcement is made with Group 1 and then is merged into Group 0 then this will return the group_id - * of Group 1. - * @return Returns the value of the group_id from the group it was created with. - */ - public int getGroupId(){ - return g.getGroupId(); - } - - public void setReinId(int id) { - reins.put(id, this); - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcement/NaturalReinforcement.java b/src/vg/civcraft/mc/citadel/reinforcement/NaturalReinforcement.java deleted file mode 100644 index e20aa819..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcement/NaturalReinforcement.java +++ /dev/null @@ -1,12 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcement; - -import org.bukkit.block.Block; - -public class NaturalReinforcement extends Reinforcement{ - - public NaturalReinforcement(Block block, int dur){ - super(block.getLocation(), block.getType(), dur, 0, 0); - // The group is null be natural reinforcements don't belong to a group. - } - -} diff --git a/src/vg/civcraft/mc/citadel/reinforcement/NullReinforcement.java b/src/vg/civcraft/mc/citadel/reinforcement/NullReinforcement.java deleted file mode 100644 index 94a29b16..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcement/NullReinforcement.java +++ /dev/null @@ -1,13 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcement; - -import org.bukkit.Location; - -/** - * Just a place holder for null reinforcements for the cache. No one Should be using this. - */ -public class NullReinforcement extends Reinforcement{ - - public NullReinforcement(Location loc) { - super(loc, null, 0, 0, 0); - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcement/PlayerReinforcement.java b/src/vg/civcraft/mc/citadel/reinforcement/PlayerReinforcement.java deleted file mode 100644 index d938ab75..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcement/PlayerReinforcement.java +++ /dev/null @@ -1,264 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcement; - -import java.sql.Timestamp; -import java.util.logging.Level; - -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.material.Openable; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; -import vg.civcraft.mc.citadel.Utility; -import vg.civcraft.mc.citadel.reinforcementtypes.ReinforcementType; -import vg.civcraft.mc.namelayer.GroupManager; -import vg.civcraft.mc.namelayer.NameAPI; -import vg.civcraft.mc.namelayer.group.Group; -import vg.civcraft.mc.namelayer.permission.PermissionType; - -public class PlayerReinforcement extends Reinforcement{ - private transient int gid; - private Group g; - private static GroupManager gm; - private boolean isInsecure = false; - private ItemStack stack; - - public PlayerReinforcement(Location loc, int health, - int creation, int acid, Group g, ItemStack stack) { - super(loc, stack.getType(), health, creation, acid); - this.g = g; - this.stack = stack; - if (gm == null) { - gm = NameAPI.getGroupManager(); - } - this.gid = g.getGroupId(); - } - - public boolean canBypass(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("BYPASS_REINFORCEMENT")); - } - - public boolean canAccessCrops(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("CROPS")); - } - - public boolean canAccessChests(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("CHESTS")); - } - - public boolean canAccessDoors(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("DOORS")); - } - - public boolean canViewInformation(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("REINFORCEMENT_INFO")); - } - - public boolean canMakeInsecure(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("INSECURE_REINFORCEMENT")); - } - - public boolean canAcid(Player p) { - checkValid(); - if (g == null) { - return false; - } - return gm.hasAccess(g.getName(), p.getUniqueId(), PermissionType.getPermission("ACIDBLOCK")); - } - - public boolean isSecurable() { - return (isContainer() || isDoor()); - } - - public int getDamageMultiplier(){ - if (g == null){ - return 1; - } - Timestamp ts = NameAPI.getGroupManager().getTimestamp(g.getName()); - - long shiftMultiplier = ((System.currentTimeMillis() - ts.getTime()) / (long)86400000) / (long)Citadel.getReinforcementManager().getDayMultiplier(); - if (shiftMultiplier > 0) { - return 1 << shiftMultiplier; - } - return 1; - } - - /** - * @return return false if it is secure, return true if it is insecure. - */ - public boolean isInsecure(){ - return isInsecure; - } - /** - * Toggles whether or not the block is insecure. - */ - public void toggleInsecure() { - this.setInsecure(!this.isInsecure()); - } - /** - * Set the status of either insecure or secure. - * Mostly used with hoppers to allow or disallow the transfer of items - * from one hopper to another if they are on separate groups. - * @param bool - */ - public void setInsecure(boolean bool){ - isInsecure = bool; - isDirty = true; - } - /** - * @return Returns the percent of the reinforcement. - */ - public double getHealth() { - return (double)getDurability() / ((double)ReinforcementType. - getReinforcementType(stack).getHitPoints()); - } - /** - * @return Returns in textual form the health of the reinforcement. - */ - public String getHealthText() { - double health = getHealth(); - if (CitadelConfigManager.showHealthAsPercent()) { - return health * 100 + "%"; - } else { - if (health > 0.75) { - return "excellently"; - } else if (health > 0.50) { - return "well"; - } else if (health > 0.25) { - return "decently"; - } else { - return "poorly"; - } - } - } - /** - * Returns true if the block has an inventory that can be opened. - * @return boolean - */ - public boolean rable() { - Block block = getLocation().getBlock(); - return block.getState() instanceof InventoryHolder - || block.getState().getData() instanceof Openable || Utility.doorTypes.contains(block.getType()); - } - - /** - * @return True if the reinforced block is a door/trapdoor etc. or part of one - */ - public boolean isDoor() { - Block block = getLocation().getBlock(); - return Utility.doorTypes.contains(block.getType()) || block.getState().getData() instanceof Openable; - } - - public boolean isContainer() { - return getLocation().getBlock().getState() instanceof InventoryHolder; - } - - - /** - * Returns the group this PlayerReinforcement is associated with. - * @return group - */ - public Group getGroup(){ - checkValid(); - return g; - } - /** - * Sets the Group for this reinforcement - * @param Group - */ - public void setGroup(Group g){ - this.g = g; - this.gid = g.getGroupId(); - isDirty = true; - } - /** - * @return ItemStack associated with this reinforcement - */ - public ItemStack getStackRepresentation(){ - return stack; - } - /** - * @return A string representation of a reinforcement's health, material, ect. - */ - public String getStatus() { - String verb; - if (isSecurable()) { - verb = "Locked"; - } else { - verb = "Reinforced"; - } - return String.format("%s %s with %s", verb, getHealthText(), getMaterial().name()); - } - - private void checkValid(){ - if (g == null) { - Citadel.getInstance().getLogger().log(Level.WARNING, "CheckValid was called but the underlying group " + gid + " is gone for " + this.getLocation() + "!"); - return; - } - if (!g.isValid()){ // incase it was recently merged/ deleted. - g = NameAPI.getGroupManager().getGroup(g.getGroupId()); - if (g == null) { - Citadel.getInstance().getLogger().log(Level.INFO, "Group " + g.getGroupId() + " was deleted or merged but not marked invalid!"); - } - isDirty = true; - } - } - /** - * Note this is different to the group id of a Group. - * If a reinforcement is made with Group 1 and then is merged into Group 0 then this will return the group_id - * of Group 1. - * @return Returns the value of the group_id from the group it was created with. - */ - public int getGroupId(){ - if (g == null) return gid; - return g.getGroupId(); - } - - public String getAgeStatus() { - int d = this.getDamageMultiplier(); - if(d < 2){ - return "not decayed"; - } - else if(d < 16){ - return "partially decayed"; - } - else if(d < 256){ - return "highly decayed"; - } - else if(d < 2048){ - return "heavily decayed"; - } - else if(d > 2047){ - return "completely decayed"; - } - else - return ""; - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcement/Reinforcement.java b/src/vg/civcraft/mc/citadel/reinforcement/Reinforcement.java deleted file mode 100644 index 17ac1500..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcement/Reinforcement.java +++ /dev/null @@ -1,94 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcement; - -import org.bukkit.Location; -import org.bukkit.Material; - -public class Reinforcement { - - private int creation; - private int acid; - private Location loc; - private Material mat; - private int dur; - protected boolean isDirty; - - public Reinforcement(Location loc, Material mat, int dur, int creation, int acid){ - this.loc = loc; - this.mat = mat; - this.dur = dur; - this.creation = creation; - this.acid = acid; - isDirty = false; - } - /** - * Sets the durability of a reinforcement. - * @param The int of the durability. - */ - public void setDurability(int dur){ - this.dur = dur; - isDirty = true; - } - /** - * @return Returns what the current durability is. - */ - public int getDurability(){ - return dur; - } - /** - * @return Returns the material of the ReinforcementMaterial. - */ - public Material getMaterial(){ - return mat; - } - /** - * @return Return the location of the Reinforcement. - */ - public Location getLocation(){ - return loc; - } - /** - * @return Returns the time that this reinforcement was created or 0 if it is mature. - */ - public int getMaturationTime(){ - return creation; - } - /** - * Sets the maturation time of this reinforcement. - * @param The time in minutes it was created. - */ - public void setMaturationTime(int time){ - creation = time; - isDirty = true; - } - /** - * @return Returns the time that this acid process began or 0 if not acid/done. - */ - public int getAcidTime(){ - return acid; - } - /** - * Sets the acid process time of this reinforcement (0 to indicate done/not acid). - * @param The time in minutes acid process began. - */ - public void setAcidTime(int acid) { - this.acid = acid; - isDirty = true; - } - /** - * @return Returns if this reinforcement needs to be saved. - */ - public boolean isDirty(){ - return isDirty; - } - /** - * Sets if this reinforcement needs to be saved or not. - * @param dirty - */ - public void setDirty(boolean dirty){ - isDirty = dirty; - } - - public Material getType() { - return this.mat; - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcementtypes/NaturalReinforcementType.java b/src/vg/civcraft/mc/citadel/reinforcementtypes/NaturalReinforcementType.java deleted file mode 100644 index c7db5737..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcementtypes/NaturalReinforcementType.java +++ /dev/null @@ -1,59 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcementtypes; - -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; - -import org.bukkit.Material; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; - -public class NaturalReinforcementType { - - public static Map types = - new HashMap(); - - private Material mat; - private int dur; - - public NaturalReinforcementType(Material mat, int breakcount){ - this.mat = mat; - this.dur = breakcount; - types.put(mat, this); - } - - public static void initializeNaturalReinforcementsTypes(){ - for (String type: CitadelConfigManager.getNaturalReinforcementTypes()){ - Material mat = CitadelConfigManager.getNaturalReinforcementMaterial(type); - int dur = CitadelConfigManager.getNaturalReinforcementHitPoints(type); - new NaturalReinforcementType(mat, dur); - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Adding Natural Reinforcement: {0} w/ health {1}", - new Object[] {mat.toString(), dur}); - } - } - } - /** - * Get a NaturalReinforcementType from the specified material. - * @param The Material of the block. - * @return Returns the NaturalReinforcementType or null if none was found. - */ - public static NaturalReinforcementType getNaturalReinforcementType(Material mat){ - return types.containsKey(mat) ? types.get(mat) : null; - } - /** - * Get the Material of a NaturalReinforcementType - * @return Returns the Material of a NaturalReinforcementType. - */ - public Material getMaterial(){ - return mat; - } - /** - * - * @return Returns the durability of the NaturalReinforcementType. - */ - public int getDurability(){ - return dur; - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcementtypes/NonReinforceableType.java b/src/vg/civcraft/mc/citadel/reinforcementtypes/NonReinforceableType.java deleted file mode 100644 index 12be25df..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcementtypes/NonReinforceableType.java +++ /dev/null @@ -1,29 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcementtypes; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; - -import org.bukkit.Material; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; - -public class NonReinforceableType { - - public static List mats = new ArrayList(); - - public static void initializeNonReinforceableTypes(){ - List materials = CitadelConfigManager.getNonReinforceableTypes(); - for (String x: materials){ - mats.add(Material.getMaterial(x)); - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Adding Non-reinforceable: {0}", x); - } - } - } - - public static boolean isNonReinforceable(Material mat){ - return mats.contains(mat); - } -} diff --git a/src/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementType.java b/src/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementType.java deleted file mode 100644 index 72d305e8..00000000 --- a/src/vg/civcraft/mc/citadel/reinforcementtypes/ReinforcementType.java +++ /dev/null @@ -1,145 +0,0 @@ -package vg.civcraft.mc.citadel.reinforcementtypes; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import vg.civcraft.mc.citadel.Citadel; -import vg.civcraft.mc.citadel.CitadelConfigManager; - -public class ReinforcementType { - - private int amount; - private double percentReturn; - private int returnValue; - private int hitpoints; - private Material mat; - private int maturationTime; - private int acidTime; - private int scale; - private ItemStack stack; - - private static Map types = - new HashMap(); - - public ReinforcementType(Material mat, int amount, double percentReturn, - int returnValue, int hitpoints, int maturationTime, int acidTime, - int scale, List lore) { - this.mat = mat; - this.amount = amount; - this.percentReturn = percentReturn/100; - this.returnValue = returnValue; - this.hitpoints = hitpoints; - this.maturationTime = maturationTime; - this.acidTime = acidTime; - this.scale = scale; - ItemStack stack = new ItemStack(mat, amount); - ItemMeta meta = stack.getItemMeta(); - meta.setLore(lore); - stack.setItemMeta(meta); - this.stack = stack; - types.put(stack, this); - } - - public static void initializeReinforcementTypes(){ - List types = CitadelConfigManager.getReinforcementTypes(); - for (String type: types){ - Material mat = CitadelConfigManager.getMaterial(type); - int amount = CitadelConfigManager.getRequireMents(type); - int percentReturn = CitadelConfigManager.getPercentReturn(type); - int returnValue = CitadelConfigManager.getReturns(type); - int hitpoints = CitadelConfigManager.getHitPoints(type); - int maturation = CitadelConfigManager.getMaturationTime(type); - int acid = CitadelConfigManager.getAcidTime(type); - int maturation_scale = CitadelConfigManager.getMaturationScale(type); - List lore = CitadelConfigManager.getLoreValues(type); - new ReinforcementType(mat, amount, percentReturn, returnValue, - hitpoints, maturation, acid, maturation_scale, lore); - if (CitadelConfigManager.shouldLogInternal()) { - Citadel.getInstance().getLogger().log(Level.INFO, "Adding Reinforcement {0} with:\n material {1} \n amount {2} " + - "\n return rate {3} \n return? {4} \n health {5} \n maturation {6} " + - "\n acid {7} \n scaling {8} \n lore: {9}", new Object[] { - type, mat.toString(), amount, percentReturn, returnValue, hitpoints, - maturation, acid, maturation_scale, (lore != null ? String.join(" ", lore) : "")}); - } - } - } - /** - * @return Returns the Material associated with this ReinforcementType. - */ - public Material getMaterial() { - return mat; - } - /** - * @return Returns the required amount of items for this ReinforcementType. - */ - public int getRequiredAmount() { - return amount; - } - /** - * @return The percent chance that a block will return the reinforcements. Scales with damage. 1 means it is 100% and .5 means 50% - */ - public double getPercentReturn() { - return percentReturn; - } - /** - * @return The amount of materials to return on breakage. - */ - public int getReturnValue() { - return returnValue; - } - /** - * @return Returns the durability of a ReinforcementType. - */ - public int getHitPoints() { - return hitpoints; - } - /** - * @return Returns the Maturation time needed until this block is mature. - */ - public int getMaturationTime(){ - return maturationTime; - } - /** - * @return Returns the Acid time needed until this acid block is ready. - */ - public int getAcidTime() { - return acidTime; - } - /** - * @return Get the scale of amount of damage a block should take when it is not fully mature. - */ - public int getMaturationScale(){ - return scale; - } - /** - * Returns the ReinforcementType for a given ItemStack. - * @param The ItemStack that a player may be holding. - * @return Returns null if no ReinforcementType is found. - * @return Returns the ReinforcementType if found. - */ - public static ReinforcementType getReinforcementType(ItemStack stack){ - for (ItemStack storedStack: types.keySet()) - if (storedStack.isSimilar(stack)) - return types.get(storedStack); - return null; - } - /** - * @return Returns the ItemStack of a ReinforcementType. - */ - public ItemStack getItemStack(){ - return stack; - } - - public static List getReinforcementTypes(){ - List type = new ArrayList(); - type.addAll(types.values()); - return type; - } -}