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;
- }
-}