diff --git a/BuildAll/build.xml b/BuildAll/build.xml
new file mode 100644
index 000000000..496f85c34
--- /dev/null
+++ b/BuildAll/build.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+ Builds, tests, and runs the project BuildAll.
+
+
+
diff --git a/BuildAll/build/built-jar.properties b/BuildAll/build/built-jar.properties
new file mode 100644
index 000000000..a4a800fd0
--- /dev/null
+++ b/BuildAll/build/built-jar.properties
@@ -0,0 +1,31 @@
+#Sun, 27 Feb 2011 20:29:24 -0500
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\BuildAll=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\Essentials=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsBan=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsChat=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsEco=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsGod=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsGroupBridge=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsGroupManager=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsHelp=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsHome=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsProtect=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsServerlist=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsSpawn=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsTele=
+
+C\:\\Users\\Paul\\Documents\\NetBeansProjects\\essentials~svn\\EssentialsWarp=
diff --git a/BuildAll/nbproject/build-impl.xml b/BuildAll/nbproject/build-impl.xml
new file mode 100644
index 000000000..dd0e3d5e1
--- /dev/null
+++ b/BuildAll/nbproject/build-impl.xml
@@ -0,0 +1,1156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set JVM to use for profiling in profiler.info.jvm
+ Must set profiler agent JVM arguments in profiler.info.jvmargs.agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+
+
+
+
+
+ java -cp "${run.classpath.with.dist.jar}" ${main.class}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set profile.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BuildAll/nbproject/genfiles.properties b/BuildAll/nbproject/genfiles.properties
new file mode 100644
index 000000000..7775180ad
--- /dev/null
+++ b/BuildAll/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=36e85771
+build.xml.script.CRC32=7a797370
+build.xml.stylesheet.CRC32=28e38971@1.42.1.45
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=36e85771
+nbproject/build-impl.xml.script.CRC32=eaedfa13
+nbproject/build-impl.xml.stylesheet.CRC32=19debb58@1.42.1.45
diff --git a/BuildAll/nbproject/private/config.properties b/BuildAll/nbproject/private/config.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/BuildAll/nbproject/private/private.properties b/BuildAll/nbproject/private/private.properties
new file mode 100644
index 000000000..bea25eb65
--- /dev/null
+++ b/BuildAll/nbproject/private/private.properties
@@ -0,0 +1,6 @@
+compile.on.save=true
+do.depend=false
+do.jar=true
+javac.debug=true
+javadoc.preview=true
+user.properties.file=C:\\Users\\Paul\\.netbeans\\7.0beta2\\build.properties
diff --git a/BuildAll/nbproject/project.properties b/BuildAll/nbproject/project.properties
new file mode 100644
index 000000000..e598ad76c
--- /dev/null
+++ b/BuildAll/nbproject/project.properties
@@ -0,0 +1,93 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+application.title=BuildAll
+application.vendor=Paul
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/BuildAll.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=\
+ ${reference.Essentials.jar}:\
+ ${reference.EssentialsChat.jar}:\
+ ${reference.EssentialsGroupBridge.jar}:\
+ ${reference.EssentialsGroupManager.jar}:\
+ ${reference.EssentialsProtect.jar}:\
+ ${reference.EssentialsServerlist.jar}:\
+ ${reference.EssentialsSpawn.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}:\
+ ${libs.junit_4.classpath}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+project.Essentials=../Essentials
+project.EssentialsChat=../EssentialsChat
+project.EssentialsGroupBridge=../EssentialsGroupBridge
+project.EssentialsGroupManager=../EssentialsGroupManager
+project.EssentialsProtect=../EssentialsProtect
+project.EssentialsServerlist=../EssentialsServerlist
+project.EssentialsSpawn=../EssentialsSpawn
+reference.Essentials.jar=${project.Essentials}/dist/Essentials.jar
+reference.EssentialsChat.jar=${project.EssentialsChat}/dist/EssentialsChat.jar
+reference.EssentialsGroupBridge.jar=${project.EssentialsGroupBridge}/dist/EssentialsGroupBridge.jar
+reference.EssentialsGroupManager.jar=${project.EssentialsGroupManager}/dist/EssentialsGroupManager.jar
+reference.EssentialsProtect.jar=${project.EssentialsProtect}/dist/original-EssentialsProtect.jar
+reference.EssentialsServerlist.jar=${project.EssentialsServerlist}/dist/EssentialsServerlist.jar
+reference.EssentialsSpawn.jar=${project.EssentialsSpawn}/dist/EssentialsSpawn.jar
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/BuildAll/nbproject/project.xml b/BuildAll/nbproject/project.xml
new file mode 100644
index 000000000..8f87bed74
--- /dev/null
+++ b/BuildAll/nbproject/project.xml
@@ -0,0 +1,76 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ BuildAll
+
+
+
+
+
+
+
+
+ ..\lib\nblibraries.properties
+
+
+
+ Essentials
+ jar
+
+ jar
+ clean
+ jar
+
+
+ EssentialsChat
+ jar
+
+ jar
+ clean
+ jar
+
+
+ EssentialsGroupBridge
+ jar
+
+ jar
+ clean
+ jar
+
+
+ EssentialsGroupManager
+ jar
+
+ jar
+ clean
+ jar
+
+
+ EssentialsProtect
+ jar
+
+ jar
+ clean
+ jar
+
+
+ EssentialsServerlist
+ jar
+
+ jar
+ clean
+ jar
+
+
+ EssentialsSpawn
+ jar
+
+ jar
+ clean
+ jar
+
+
+
+
diff --git a/Essentials/.gitignore b/Essentials/.gitignore
new file mode 100644
index 000000000..437c8c683
--- /dev/null
+++ b/Essentials/.gitignore
@@ -0,0 +1,7 @@
+# NetBeans cruft
+/build
+/dist
+/nbproject/private
+
+# Mac cruft
+.DS_Store
diff --git a/Essentials/build.xml b/Essentials/build.xml
new file mode 100644
index 000000000..0742d234f
--- /dev/null
+++ b/Essentials/build.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+ Builds, tests, and runs the project Essentials.
+
+
+
diff --git a/Essentials/nbproject/build-impl.xml b/Essentials/nbproject/build-impl.xml
new file mode 100644
index 000000000..131d7414d
--- /dev/null
+++ b/Essentials/nbproject/build-impl.xml
@@ -0,0 +1,1058 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set JVM to use for profiling in profiler.info.jvm
+ Must set profiler agent JVM arguments in profiler.info.jvmargs.agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+
+
+
+
+
+ java -cp "${run.classpath.with.dist.jar}" ${main.class}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set profile.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Essentials/nbproject/genfiles.properties b/Essentials/nbproject/genfiles.properties
new file mode 100644
index 000000000..169fb44fa
--- /dev/null
+++ b/Essentials/nbproject/genfiles.properties
@@ -0,0 +1,11 @@
+build.xml.data.CRC32=7d758acf
+build.xml.script.CRC32=3233ee78
+build.xml.stylesheet.CRC32=28e38971@1.38.2.45
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=ab78ce15
+nbproject/build-impl.xml.script.CRC32=4b464ee6
+nbproject/build-impl.xml.stylesheet.CRC32=19debb58@1.42.1.45
+nbproject/profiler-build-impl.xml.data.CRC32=ab78ce15
+nbproject/profiler-build-impl.xml.script.CRC32=abda56ed
+nbproject/profiler-build-impl.xml.stylesheet.CRC32=f10cf54c@1.11.1
diff --git a/Essentials/nbproject/project.properties b/Essentials/nbproject/project.properties
new file mode 100644
index 000000000..67c5646c9
--- /dev/null
+++ b/Essentials/nbproject/project.properties
@@ -0,0 +1,76 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+application.title=Essentials
+application.vendor=Paul
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/Essentials.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
+excludes=
+file.reference.craftbukkit-0.0.1-SNAPSHOT.jar=..\\lib\\craftbukkit-0.0.1-SNAPSHOT.jar
+file.reference.iConomy.jar=..\\lib\\iConomy.jar
+file.reference.Permissions.jar=..\\lib\\Permissions.jar
+includes=**
+jar.compress=false
+javac.classpath=\
+ ${file.reference.iConomy.jar}:\
+ ${file.reference.Permissions.jar}:\
+ ${file.reference.craftbukkit-0.0.1-SNAPSHOT.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=-Djline.terminal=jline.UnsupportedTerminal
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/Essentials/nbproject/project.xml b/Essentials/nbproject/project.xml
new file mode 100644
index 000000000..aa1a9f770
--- /dev/null
+++ b/Essentials/nbproject/project.xml
@@ -0,0 +1,19 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ Essentials
+
+
+
+
+
+
+
+
+ ../lib\nblibraries.properties
+
+
+
+
diff --git a/Essentials/settings/Editor.zip b/Essentials/settings/Editor.zip
new file mode 100644
index 000000000..7635328f8
Binary files /dev/null and b/Essentials/settings/Editor.zip differ
diff --git a/Essentials/src/com/earth2me/essentials/Backup.java b/Essentials/src/com/earth2me/essentials/Backup.java
new file mode 100644
index 000000000..aa0cb1476
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/Backup.java
@@ -0,0 +1,82 @@
+package com.earth2me.essentials;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bukkit.command.CommandSender;
+import org.bukkit.craftbukkit.CraftServer;
+
+public class Backup implements Runnable {
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private CraftServer server;
+ private boolean running = false;
+ private int taskId = -1;
+ private boolean active = false;
+
+ public Backup() {
+ server = (CraftServer)Essentials.getStatic().getServer();
+ if (server.getOnlinePlayers().length > 0) {
+ startTask();
+ }
+ }
+
+ void onPlayerJoin() {
+ startTask();
+ }
+
+ private void startTask() {
+ if (!running) {
+ long interval = Essentials.getSettings().getBackupInterval()*1200; // minutes -> ticks
+ if (interval < 1200) {
+ return;
+ }
+ taskId = server.getScheduler().scheduleSyncRepeatingTask(Essentials.getStatic(), this, interval, interval);
+ running = true;
+ }
+ }
+
+ public void run() {
+ if (active) return;
+ active = true;
+ final String command = Essentials.getSettings().getBackupCommand();
+ if (command == null || "".equals(command)) {
+ return;
+ }
+ logger.log(Level.INFO, "Backup started");
+ final CommandSender cs = server.getServer().console;
+ server.dispatchCommand(cs, "save-all");
+ server.dispatchCommand(cs, "save-off");
+
+ server.getScheduler().scheduleAsyncDelayedTask(Essentials.getStatic(),
+ new Runnable() {
+
+ public void run() {
+ try {
+ Process child = Runtime.getRuntime().exec(command);
+ child.waitFor();
+ } catch (InterruptedException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ } finally {
+ server.getScheduler().scheduleSyncDelayedTask(Essentials.getStatic(),
+ new Runnable() {
+
+ public void run() {
+ server.dispatchCommand(cs, "save-on");
+ if (server.getOnlinePlayers().length == 0) {
+ running = false;
+ if (taskId != -1) {
+ server.getScheduler().cancelTask(taskId);
+ }
+ }
+ active = false;
+ logger.log(Level.INFO, "Backup finished");
+ }
+ });
+ }
+ }
+ });
+ }
+
+}
diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java
new file mode 100644
index 000000000..73c6aade9
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/Essentials.java
@@ -0,0 +1,688 @@
+package com.earth2me.essentials;
+
+import com.earth2me.essentials.commands.EssentialsCommand;
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
+import org.bukkit.*;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import com.earth2me.essentials.commands.IEssentialsCommand;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.craftbukkit.scheduler.CraftScheduler;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event.Priority;
+import org.bukkit.event.Event.Type;
+import org.bukkit.plugin.*;
+import org.bukkit.plugin.java.*;
+import org.yaml.snakeyaml.*;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
+import org.yaml.snakeyaml.reader.UnicodeReader;
+
+
+public class Essentials extends JavaPlugin
+{
+ public static final String AUTHORS = "Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo and ceulemans.";
+ public static final int minBukkitBuildVersion = 556;
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private static final Yaml yaml = new Yaml(new SafeConstructor());
+ private static Map users;
+ private static Settings settings;
+ private static final Object usersLock = new Object();
+ public static Object permissions = null;
+ public final Map tpcRequests = new HashMap();
+ public final Map tpcHere = new HashMap();
+ public final List away = new ArrayList();
+ private EssentialsPlayerListener playerListener;
+ private EssentialsBlockListener blockListener;
+ private EssentialsEntityListener entityListener;
+ private static Essentials staticThis = null;
+ public Spawn spawn;
+ private Jail jail;
+ private Warps warps;
+ private List confList;
+ public ArrayList bans = new ArrayList();
+ public ArrayList bannedIps = new ArrayList();
+ public Backup backup;
+
+ public Essentials() throws IOException
+ {
+ loadClasses();
+ }
+
+ public static void ensureEnabled(Server server)
+ {
+ PluginManager pm = server.getPluginManager();
+ Essentials ess = (Essentials)pm.getPlugin("Essentials");
+ if (!ess.isEnabled())
+ pm.enablePlugin(ess);
+ loadClasses();
+ }
+
+ @SuppressWarnings("CallToThreadDumpStack")
+ public static void loadClasses()
+ {
+ final String[] classes = new String[]
+ {
+ "commands.IEssentialsCommand",
+ "commands.EssentialsCommand",
+ "User",
+ "TargetBlock",
+ "Spawn",
+ "Settings",
+ "OfflinePlayer",
+ "ItemDb",
+ "Mob"
+ };
+
+ try
+ {
+ for (String c : classes)
+ Essentials.class.getClassLoader().loadClass("com.earth2me.essentials." + c);
+ }
+ catch (Throwable ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public static Essentials getStatic()
+ {
+ return staticThis;
+ }
+
+ public static Settings getSettings()
+ {
+ return settings;
+ }
+
+ public void setupPermissions()
+ {
+ Plugin permPlugin = this.getServer().getPluginManager().getPlugin("Permissions");
+ if (permissions == null && permPlugin != null) permissions = permPlugin;
+ }
+
+ public Player getPlayer(String[] args, int pos)
+ throws IndexOutOfBoundsException, NoSuchFieldException
+ {
+ if (args.length <= pos) throw new IndexOutOfBoundsException("§cInvalid command syntax. Did you forget an argument?");
+ List matches = getServer().matchPlayer(args[0]);
+ if (matches.size() < 1) throw new NoSuchFieldException("§cNo matching players could be found.");
+ return matches.get(0);
+ }
+
+ public void setStatic()
+ {
+ staticThis = this;
+ }
+
+ @SuppressWarnings("LoggerStringConcat")
+ public void onEnable()
+ {
+ setStatic();
+ confList = new ArrayList();
+ settings = new Settings(this.getDataFolder());
+ confList.add(settings);
+ this.spawn = new Spawn(getServer(), this.getDataFolder());
+ confList.add(spawn);
+ warps = new Warps(getServer(), this.getDataFolder());
+ confList.add(warps);
+ reload();
+ this.backup = new Backup();
+
+ PluginManager pm = getServer().getPluginManager();
+ for (Plugin plugin : pm.getPlugins()) {
+ if (plugin.getDescription().getName().startsWith("Essentials")) {
+ if (!plugin.getDescription().getVersion().equals(this.getDescription().getVersion())) {
+ logger.log(Level.WARNING, "Version mismatch! Please update "+plugin.getDescription().getName()+" to the same version.");
+ }
+ }
+ }
+ Matcher versionMatch = Pattern.compile("git-Bukkit-([0-9]+).([0-9]+).([0-9]+)-[0-9]+-[0-9a-z]+-b([0-9]+)jnks.*").matcher(getServer().getVersion());
+ if (versionMatch.matches()) {
+ int versionNumber = Integer.parseInt(versionMatch.group(4));
+ if (versionNumber < minBukkitBuildVersion) {
+ logger.log(Level.WARNING, "Bukkit version is not the recommended build for Essentials.");
+ }
+ } else {
+ logger.log(Level.INFO, "Bukkit version format changed. Version not checked.");
+ }
+
+
+ playerListener = new EssentialsPlayerListener(this);
+ pm.registerEvent(Type.PLAYER_JOIN, playerListener, Priority.Monitor, this);
+ pm.registerEvent(Type.PLAYER_QUIT, playerListener, Priority.Monitor, this);
+ pm.registerEvent(Type.PLAYER_CHAT, playerListener, Priority.Monitor, this);
+ if (getSettings().getNetherPortalsEnabled())
+ pm.registerEvent(Type.PLAYER_MOVE, playerListener, Priority.High, this);
+ pm.registerEvent(Type.PLAYER_LOGIN, playerListener, Priority.High, this);
+ pm.registerEvent(Type.PLAYER_TELEPORT, playerListener, Priority.High, this);
+
+ blockListener = new EssentialsBlockListener(this);
+ pm.registerEvent(Type.SIGN_CHANGE, blockListener, Priority.Monitor, this);
+ pm.registerEvent(Type.BLOCK_RIGHTCLICKED, blockListener, Priority.Monitor, this);
+ pm.registerEvent(Type.BLOCK_INTERACT, blockListener, Priority.Monitor, this);
+ pm.registerEvent(Type.BLOCK_BREAK, blockListener, Priority.Monitor, this);
+ pm.registerEvent(Type.BLOCK_PLACED, blockListener, Priority.Monitor, this);
+
+ entityListener = new EssentialsEntityListener(this);
+ pm.registerEvent(Type.ENTITY_DAMAGED, entityListener, Priority.Lowest, this);
+ pm.registerEvent(Type.ENTITY_COMBUST, entityListener, Priority.Lowest, this);
+ pm.registerEvent(Type.ENTITY_DEATH, entityListener, Priority.Lowest, this);
+
+ jail = new Jail(this.getDataFolder());
+ confList.add(jail);
+ pm.registerEvent(Type.BLOCK_BREAK, jail, Priority.High, this);
+ pm.registerEvent(Type.BLOCK_DAMAGED, jail, Priority.High, this);
+ pm.registerEvent(Type.BLOCK_INTERACT, jail, Priority.High, this);
+ pm.registerEvent(Type.BLOCK_PLACED, jail, Priority.High, this);
+
+ attachEcoListeners();
+
+ if (settings.isNetherEnabled() && getServer().getWorlds().size() < 2)
+ {
+ getServer().createWorld(settings.getNetherName(), World.Environment.NETHER);
+ }
+
+ logger.info("Loaded " + this.getDescription().getName() + " build " + this.getDescription().getVersion() + " maintained by " + AUTHORS);
+ }
+
+ public void onDisable()
+ {
+ staticThis = null;
+ }
+
+ public void reload()
+ {
+ loadData();
+ loadBanList();
+
+ for (IConf iConf : confList)
+ {
+ iConf.reloadConfig();
+ }
+
+ try
+ {
+ ItemDb.load(getDataFolder(), "items.csv");
+ }
+ catch (Exception ex)
+ {
+ logger.log(Level.WARNING, "Could not load items.csv.", ex);
+ }
+ }
+
+ public static Map getData(User player)
+ {
+ return getData(player.getName());
+ }
+
+ public static Map getData(String player)
+ {
+ try
+ {
+ Map retval;
+ synchronized (usersLock)
+ {
+ retval = (Map)users.get(player.toLowerCase());
+ }
+ return retval == null ? new HashMap() : retval;
+ }
+ catch (Throwable ex)
+ {
+ return new HashMap();
+ }
+ }
+
+ public static void flushData()
+ {
+ Thread run = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ if (!Essentials.getStatic().getDataFolder().exists())
+ Essentials.getStatic().getDataFolder().mkdirs();
+ File file = new File(Essentials.getStatic().getDataFolder(), "users.yml");
+ if (!file.exists())
+ file.createNewFile();
+
+ FileWriter tx = new FileWriter(file);
+ synchronized (usersLock)
+ {
+ tx.write(yaml.dump(users));
+ }
+ tx.flush();
+ tx.close();
+ }
+ catch (Throwable ex)
+ {
+ Logger.getLogger(Essentials.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ });
+ run.setDaemon(false);
+ run.start();
+ }
+
+ public static void loadData()
+ {
+ try
+ {
+ if (!Essentials.getStatic().getDataFolder().exists()) Essentials.getStatic().getDataFolder().mkdirs();
+ File file = new File(Essentials.getStatic().getDataFolder(), "users.yml");
+ if (!file.exists()) file.createNewFile();
+
+ FileInputStream rx = new FileInputStream(file);
+ synchronized (usersLock)
+ {
+ users = (Map)yaml.load(new UnicodeReader(rx));
+ }
+ rx.close();
+ }
+ catch (Exception ex)
+ {
+ Logger.getLogger(Essentials.class.getName()).log(Level.SEVERE, null, ex);
+ synchronized (usersLock)
+ {
+ users = new HashMap();
+ }
+ }
+ finally
+ {
+ synchronized (usersLock)
+ {
+ if (users == null) users = new HashMap();
+ }
+ }
+ }
+
+ public static void setData(User player, Map data)
+ {
+ setData(player.getName(), data);
+ }
+
+ public static void setData(String player, Map data)
+ {
+ synchronized (usersLock)
+ {
+ users.put(player.toLowerCase(), data);
+ }
+ }
+
+ public static List readMail(User player)
+ {
+ return readMail(player.getName());
+ }
+
+ public static List readMail(String player)
+ {
+ try
+ {
+ Map data = getData(player);
+ List retval = (List)data.get("mail");
+ return retval == null ? new ArrayList() : retval;
+ }
+ catch (Throwable ex)
+ {
+ return new ArrayList();
+ }
+ }
+
+ public static void clearMail(User player)
+ {
+ try
+ {
+ Map data = getData(player);
+ data.put("mail", new ArrayList());
+ setData(player, data);
+ flushData();
+ }
+ catch (Throwable ex)
+ {
+ }
+ }
+
+ public static void sendMail(User from, String to, String message)
+ throws Exception
+ {
+ try
+ {
+ Map data = getData(ChatColor.stripColor(to));
+ List mail = readMail(to);
+ mail.add(ChatColor.stripColor(from.getDisplayName()) + ": " + message);
+ data.put("mail", mail);
+ setData(to, data);
+ flushData();
+ }
+ catch (Throwable ex)
+ {
+ throw new Exception("An error was encountered while sending the mail.", ex);
+ }
+ }
+
+ public String readNickname(User player)
+ {
+ try
+ {
+ Map data = getData(player);
+ String nick = (String)data.get("nickname");
+ if (nick == null)
+ return player.getName();
+ if (nick.equals(player.getName()))
+ return player.getName();
+ return getSettings().getNicknamePrefix() + nick;
+ }
+ catch (Exception ex)
+ {
+ return player.getName();
+ }
+ }
+
+ public void saveNickname(User player, String nickname) throws Exception
+ {
+ try
+ {
+ Map data = getData(player);
+ data.put("nickname", nickname);
+ setData(player, data);
+ flushData();
+ }
+ catch (Throwable ex)
+ {
+ throw new Exception("An error was encountered while saving the nickname.", ex);
+ }
+ }
+
+ public String[] getMotd(CommandSender sender, String def)
+ {
+ return getLines(sender, "motd", def);
+ }
+
+ public String[] getLines(CommandSender sender, String node, String def)
+ {
+ List lines = (List)getConfiguration().getProperty(node);
+ if (lines == null) return new String[0];
+ String[] retval = new String[lines.size()];
+
+ if (lines == null || lines.isEmpty() || lines.get(0) == null)
+ {
+ try
+ {
+ lines = new ArrayList();
+ // "[]" in YaML indicates empty array, so respect that
+ if (!getConfiguration().getString(node, def).equals("[]"))
+ {
+ lines.add(getConfiguration().getString(node, def));
+ retval = new String[lines.size()];
+ }
+ }
+ catch (Throwable ex2)
+ {
+ System.out.println(ChatColor.DARK_RED + "Notice: Your configuration file has a corrupt " + node + " node.");
+ return new String[0];
+ }
+ }
+
+ // if still empty, call it a day
+ if (lines == null || lines.isEmpty() || lines.get(0) == null)
+ return new String[0];
+
+ for (int i = 0; i < lines.size(); i++)
+ {
+ String m = lines.get(i);
+ if (m == null)
+ continue;
+ m = m.replace('&', '§').replace("§§", "&");
+
+ if (sender instanceof User || sender instanceof Player)
+ {
+ User user = User.get(sender);
+ m = m.replace("{PLAYER}", user.getDisplayName());
+ m = m.replace("{IP}", user.getAddress().toString());
+ m = m.replace("{BALANCE}", Double.toString(user.getMoney()));
+ }
+
+ m = m.replace("{ONLINE}", Integer.toString(getServer().getOnlinePlayers().length));
+
+ if (m.matches(".*\\{PLAYERLIST\\}.*"))
+ {
+ StringBuilder online = new StringBuilder();
+ for (Player p : getServer().getOnlinePlayers())
+ {
+ if (online.length() > 0)
+ online.append(", ");
+ online.append(p.getDisplayName());
+ }
+ m = m.replace("{PLAYERLIST}", online.toString());
+ }
+
+ if (sender instanceof Player)
+ {
+ try
+ {
+ Class User = getClassLoader().loadClass("bukkit.Vandolis.User");
+ Object vuser = User.getConstructor(User.class).newInstance((Player)sender);
+ m = m.replace("{RED:BALANCE}", User.getMethod("getMoney").invoke(vuser).toString());
+ m = m.replace("{RED:BUYS}", User.getMethod("getNumTransactionsBuy").invoke(vuser).toString());
+ m = m.replace("{RED:SELLS}", User.getMethod("getNumTransactionsSell").invoke(vuser).toString());
+ }
+ catch (Throwable ex)
+ {
+ m = m.replace("{RED:BALANCE}", "N/A");
+ m = m.replace("{RED:BUYS}", "N/A");
+ m = m.replace("{RED:SELLS}", "N/A");
+ }
+ }
+
+ retval[i] = m + " ";
+ }
+ return retval;
+ }
+
+ public static String FormatTime(long Milliseconds)
+ { // format time into a string showing hours, minutes, or seconds
+ if (Milliseconds > 3600000)
+ {
+ double val = Math.round((double)Milliseconds / 360000D) / 10D;
+ return val + " hour" + (val > 1 ? "s" : "");
+ }
+ else if (Milliseconds > 60000)
+ {
+ double val = Math.round((double)Milliseconds / 6000D) / 10D;
+ return val + " minute" + (val > 1 ? "s" : "");
+ }
+ else if (Milliseconds <= 1000)
+ return "1 second";
+ else
+ return (Milliseconds / 1000L) + " seconds";
+ }
+
+ @SuppressWarnings("LoggerStringConcat")
+ public static void previewCommand(CommandSender sender, Command command, String commandLabel, String[] args)
+ {
+ if (sender instanceof Player)
+ logger.info(ChatColor.BLUE + "[PLAYER_COMMAND] " + ((Player)sender).getName() + ": /" + commandLabel + " " + EssentialsCommand.getFinalArg(args, 0));
+ }
+
+ @Override
+ @SuppressWarnings(
+ {
+ "LoggerStringConcat", "CallToThreadDumpStack"
+ })
+ public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args)
+ {
+ // Allow plugins to override the command via onCommand
+ for (Plugin p : getServer().getPluginManager().getPlugins())
+ {
+ if (p == this)
+ continue;
+
+ PluginDescriptionFile desc = p.getDescription();
+ if (desc == null)
+ continue;
+
+ if (desc.getName() == null)
+ continue;
+
+ if (!(desc.getCommands() instanceof Map))
+ continue;
+
+ Map cmds = (Map)desc.getCommands();
+ if (!cmds.containsKey(command.getName()))
+ continue;
+
+ PluginCommand pcmd = getServer().getPluginCommand(desc.getName() + ":" + commandLabel);
+
+ if (pcmd == null)
+ continue;
+
+ return getServer().getPluginCommand(p.getDescription().getName() + ":" + commandLabel).execute(sender, commandLabel, args);
+ }
+
+ try
+ {
+ previewCommand(sender, command, commandLabel, args);
+ User user = sender instanceof Player ? User.get(sender) : null;
+
+ // New mail notification
+ if (user != null && !Essentials.getSettings().isCommandDisabled("mail") && !commandLabel.equals("mail"))
+ {
+ List mail = Essentials.readMail(user);
+ if (!mail.isEmpty()) user.sendMessage(ChatColor.RED + "You have " + mail.size() + " messages!§f Type §7/mail read§f to view your mail.");
+ }
+
+ // Check for disabled commands
+ if (Essentials.getSettings().isCommandDisabled(commandLabel)) return true;
+
+ IEssentialsCommand cmd;
+ try
+ {
+ cmd = (IEssentialsCommand)Essentials.class.getClassLoader().loadClass("com.earth2me.essentials.commands.Command" + command.getName()).newInstance();
+ }
+ catch (Exception ex)
+ {
+ sender.sendMessage(ChatColor.RED + "That command is improperly loaded.");
+ ex.printStackTrace();
+ return true;
+ }
+
+ // Check authorization
+ if (user != null && !user.isAuthorized(cmd))
+ {
+ logger.warning(user.getName() + " was denied access to command.");
+ user.sendMessage(ChatColor.RED + "You do not have access to that command.");
+ return true;
+ }
+
+ // Run the command
+ try
+ {
+ if (user == null)
+ cmd.run(getServer(), this, sender, commandLabel, command, args);
+ else
+ cmd.run(getServer(), this, user, commandLabel, command, args);
+ return true;
+ }
+ catch (Throwable ex)
+ {
+ sender.sendMessage(ChatColor.RED + "Error: " + ex.getMessage());
+ return true;
+ }
+ }
+ catch (Throwable ex)
+ {
+ ex.printStackTrace();
+ return true;
+ }
+ }
+
+ public void loadBanList()
+ {
+ //I don't like this but it needs to be done until CB fixors
+ File file = new File("banned-players.txt");
+ File ipFile = new File("banned-ips.txt");
+ try
+ {
+ if (!file.exists()) throw new FileNotFoundException("banned-players.txt not found");
+
+ BufferedReader rx = new BufferedReader(new FileReader(file));
+ bans.clear();
+ try
+ {
+ for (int i = 0; rx.ready(); i++)
+ {
+
+ String line = rx.readLine().trim().toLowerCase();
+ if (line.startsWith("#")) continue;
+ bans.add(line);
+
+ }
+ }
+ catch (IOException io)
+ {
+ logger.log(Level.SEVERE, "Error reading banned-players.txt", io);
+ }
+ }
+ catch (FileNotFoundException ex)
+ {
+ logger.log(Level.SEVERE, "Error reading banned-players.txt", ex);
+ }
+
+ try
+ {
+ if (!ipFile.exists()) throw new FileNotFoundException("banned-ips.txt not found");
+
+ BufferedReader rx = new BufferedReader(new FileReader(ipFile));
+ bannedIps.clear();
+ try
+ {
+ for (int i = 0; rx.ready(); i++)
+ {
+
+ String line = rx.readLine().trim().toLowerCase();
+ if (line.startsWith("#")) continue;
+ bannedIps.add(line);
+
+ }
+ }
+ catch (IOException io)
+ {
+ logger.log(Level.SEVERE, "Error reading banned-ips.txt", io);
+ }
+ }
+ catch (FileNotFoundException ex)
+ {
+ logger.log(Level.SEVERE, "Error reading banned-ips.txt", ex);
+ }
+ }
+
+ private void attachEcoListeners()
+ {
+ PluginManager pm = getServer().getPluginManager();
+ EssentialsEcoBlockListener blockListener = new EssentialsEcoBlockListener();
+ pm.registerEvent(Type.BLOCK_INTERACT, blockListener, Priority.Lowest, this);
+ pm.registerEvent(Type.BLOCK_RIGHTCLICKED, blockListener, Priority.High, this);
+ pm.registerEvent(Type.BLOCK_BREAK, blockListener, Priority.High, this);
+ pm.registerEvent(Type.SIGN_CHANGE, blockListener, Priority.Monitor, this);
+ }
+
+ public CraftScheduler getScheduler()
+ {
+ return (CraftScheduler)this.getServer().getScheduler();
+ }
+
+ public static Jail getJail()
+ {
+ return getStatic().jail;
+ }
+
+ public static Warps getWarps()
+ {
+ return getStatic().warps;
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java b/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java
new file mode 100644
index 000000000..5873b3c1e
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java
@@ -0,0 +1,307 @@
+package com.earth2me.essentials;
+
+import java.util.ArrayList;
+import java.util.List;
+import net.minecraft.server.InventoryPlayer;
+import org.bukkit.*;
+import org.bukkit.block.*;
+import org.bukkit.craftbukkit.block.CraftSign;
+import org.bukkit.craftbukkit.inventory.CraftInventoryPlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.event.block.*;
+import org.bukkit.inventory.ItemStack;
+
+
+public class EssentialsBlockListener extends BlockListener
+{
+ private final Essentials parent;
+ private final static ArrayList protectedBlocks = new ArrayList(4);
+
+ static
+ {
+ protectedBlocks.add(Material.CHEST);
+ protectedBlocks.add(Material.BURNING_FURNACE);
+ protectedBlocks.add(Material.FURNACE);
+ protectedBlocks.add(Material.DISPENSER);
+ }
+
+ public EssentialsBlockListener(Essentials parent)
+ {
+ this.parent = parent;
+ }
+
+ @Override
+ public void onBlockBreak(BlockBreakEvent event)
+ {
+ if (event.isCancelled()) return;
+ if (Essentials.getSettings().areSignsDisabled()) return;
+ User user = User.get(event.getPlayer());
+ if (protectedBlocks.contains(event.getBlock().getType()) && !user.isAuthorized("essentials.signs.protection.override"))
+ {
+ if (isBlockProtected(event.getBlock(), user))
+ {
+ event.setCancelled(true);
+ user.sendMessage("§cYou do not have permission to destroy that chest.");
+ return;
+ }
+ }
+
+ if (checkProtectionSign(event.getBlock(), user) == NOT_ALLOWED)
+ {
+ event.setCancelled(true);
+ user.sendMessage("§cYou do not have permission to destroy that sign.");
+ }
+ }
+
+ @Override
+ public void onBlockInteract(BlockInteractEvent event)
+ {
+ if (event.isCancelled()) return;
+ if (!(event.getEntity() instanceof Player)) return;
+
+ User user = User.get((Player)event.getEntity());
+
+ if (!Essentials.getSettings().areSignsDisabled() && protectedBlocks.contains(event.getBlock().getType()))
+ {
+ if (!user.isAuthorized("essentials.signs.protection.override"))
+ {
+ if (isBlockProtected(event.getBlock(), user))
+ {
+ event.setCancelled(true);
+ user.sendMessage("§cYou do not have permission to access that chest.");
+ return;
+ }
+ }
+ }
+
+ if (Essentials.getSettings().getBedSetsHome() && event.getBlock().getType() == Material.BED_BLOCK)
+ {
+ try
+ {
+ user.setHome();
+ user.sendMessage("§7Your home is now set to this bed.");
+ }
+ catch (Throwable ex)
+ {
+ }
+ }
+ }
+
+ @Override
+ public void onSignChange(SignChangeEvent event)
+ {
+ if (event.isCancelled()) return;
+ if (Essentials.getSettings().areSignsDisabled()) return;
+ User user = User.get(event.getPlayer());
+
+ try
+ {
+ if (event.getLine(0).equalsIgnoreCase("[Protection]"))
+ {
+ Block block = event.getBlock();
+ if (user.isAuthorized("essentials.signs.protection.create") && hasAdjacentChest(block) && !isBlockProtected(block, user))
+ event.setLine(0, "§1[Protection]");
+ else
+ event.setLine(0, "§4[Protection]");
+ event.setLine(3, user.getName());
+ return;
+ }
+ if (event.getLine(0).equalsIgnoreCase("[Disposal]"))
+ {
+ if (user.isAuthorized("essentials.signs.disposal.create"))
+ event.setLine(0, "§1[Disposal]");
+ else
+ event.setLine(0, "§4[Disposal]");
+ return;
+ }
+ if (event.getLine(0).equalsIgnoreCase("[Heal]"))
+ {
+ if (user.isAuthorized("essentials.signs.heal.create"))
+ event.setLine(0, "§1[Heal]");
+ else
+ event.setLine(0, "§4[Heal]");
+ return;
+ }
+ if (event.getLine(0).equalsIgnoreCase("[Free]"))
+ {
+ event.setLine(0, "§4[Free]");
+ ItemDb.get(event.getLine(1));
+ if (user.isAuthorized("essentials.signs.free.create"))
+ event.setLine(0, "§1[Free]");
+ return;
+ }
+ if (event.getLine(0).equalsIgnoreCase("[Mail]"))
+ {
+ if (user.isAuthorized("essentials.signs.mail.create"))
+
+ event.setLine(0, "§1[Mail]");
+ else
+ event.setLine(0, "§4[Mail]");
+ return;
+ }
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ }
+ }
+
+ @Override
+ public void onBlockRightClick(BlockRightClickEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ if (user.isJailed()) return;
+ if (Essentials.getSettings().areSignsDisabled()) return;
+ if (event.getBlock().getType() != Material.WALL_SIGN && event.getBlock().getType() != Material.SIGN_POST)
+ return;
+ Sign sign = new CraftSign(event.getBlock());
+
+ try
+ {
+ if (sign.getLine(0).equals("§1[Free]") && user.isAuthorized("essentials.signs.free.use"))
+ {
+ ItemStack item = ItemDb.get(sign.getLine(1));
+ CraftInventoryPlayer inv = new CraftInventoryPlayer(new InventoryPlayer(user.getHandle()));
+ inv.clear();
+ item.setAmount(9 * 4 * 64);
+ inv.addItem(item);
+ user.showInventory(inv);
+ return;
+ }
+ if (sign.getLine(0).equals("§1[Disposal]") && user.isAuthorized("essentials.signs.disposal.use"))
+ {
+ CraftInventoryPlayer inv = new CraftInventoryPlayer(new InventoryPlayer(user.getHandle()));
+ inv.clear();
+ user.showInventory(inv);
+ return;
+ }
+ if (sign.getLine(0).equals("§1[Heal]") && user.isAuthorized("essentials.signs.heal.use"))
+ {
+ user.setHealth(20);
+ user.sendMessage("§7You have been healed.");
+ return;
+ }
+ if (sign.getLine(0).equals("§1[Mail]") && user.isAuthorized("essentials.signs.mail.use") && user.isAuthorized("essentials.mail"))
+ {
+ List mail = Essentials.readMail(user);
+ if (mail.isEmpty())
+ {
+ user.sendMessage("§cYou do not have any mail!");
+ return;
+ }
+ for (String s : mail) user.sendMessage(s);
+ user.sendMessage("§cTo mark your mail as read, type §c/mail clear");
+ return;
+ }
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ }
+ }
+
+ @Override
+ public void onBlockPlace(BlockPlaceEvent event) {
+ Block signBlock = event.getBlockAgainst();
+ if (signBlock.getType() == Material.WALL_SIGN || signBlock.getType() == Material.SIGN_POST) {
+ Sign sign = new CraftSign(signBlock);
+ if (sign.getLine(0).matches("§1\\[[a-zA-Z]+\\]")) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+
+
+
+ public boolean hasAdjacentChest(Block block)
+ {
+ Block[] faces = getAdjacentBlocks(block);
+ for (Block b : faces)
+ {
+ if (protectedBlocks.contains(b.getType()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ private static final int NOT_ALLOWED = 0;
+ private static final int ALLOWED = 1;
+ private static final int NOSIGN = 2;
+
+ private int checkProtectionSign(Block block, User user)
+ {
+ if (block.getType() == Material.SIGN_POST || block.getType() == Material.WALL_SIGN)
+ {
+ Sign sign = new CraftSign(block);
+ if (sign.getLine(0).equalsIgnoreCase("§1[Protection]") && !user.isAuthorized("essentials.signs.protection.override"))
+ {
+ if (sign.getLine(1).equalsIgnoreCase(user.getName()))
+ {
+ return ALLOWED;
+ }
+ if (sign.getLine(2).equalsIgnoreCase(user.getName()))
+ {
+ return ALLOWED;
+ }
+ if (sign.getLine(3).equalsIgnoreCase(user.getName()))
+ {
+ return ALLOWED;
+ }
+ return NOT_ALLOWED;
+ }
+ }
+ return NOSIGN;
+ }
+
+ private Block[] getAdjacentBlocks(Block block)
+ {
+ return new Block[]
+ {
+ block.getFace(BlockFace.NORTH),
+ block.getFace(BlockFace.SOUTH),
+ block.getFace(BlockFace.EAST),
+ block.getFace(BlockFace.WEST),
+ block.getFace(BlockFace.DOWN),
+ block.getFace(BlockFace.UP)
+ };
+ }
+
+ private boolean isBlockProtected(Block block, User user)
+ {
+ Block[] faces = getAdjacentBlocks(block);
+ boolean protect = false;
+ for (Block b : faces)
+ {
+ int check = checkProtectionSign(b, user);
+ if (check == NOT_ALLOWED)
+ {
+ protect = true;
+ }
+ if (check == ALLOWED)
+ {
+ return false;
+ }
+
+ if (protectedBlocks.contains(b.getType()))
+ {
+ Block[] faceChest = getAdjacentBlocks(b);
+
+ for (Block a : faceChest)
+ {
+ check = checkProtectionSign(a, user);
+ if (check == NOT_ALLOWED)
+ {
+ protect = true;
+ }
+ if (check == ALLOWED)
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return protect;
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/EssentialsConf.java b/Essentials/src/com/earth2me/essentials/EssentialsConf.java
new file mode 100644
index 000000000..616f39a6c
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/EssentialsConf.java
@@ -0,0 +1,120 @@
+package com.earth2me.essentials;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bukkit.util.config.Configuration;
+
+
+public class EssentialsConf extends Configuration
+{
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private File configFile;
+ private String templateName = null;
+ private Class> resourceClass = EssentialsConf.class;
+
+ public EssentialsConf(File configFile)
+ {
+ super(configFile);
+ this.configFile = configFile;
+ if (this.root == null) {
+ this.root = new HashMap();
+ }
+ }
+
+ @Override
+ public void load()
+ {
+ configFile = configFile.getAbsoluteFile();
+ if (!configFile.getParentFile().exists())
+ {
+ configFile.getParentFile().mkdirs();
+ }
+ if (!configFile.exists())
+ {
+ if (templateName != null)
+ {
+ logger.log(Level.INFO, "Creating config from template: " + configFile.toString());
+ createFromTemplate();
+ }
+ else
+ {
+ try
+ {
+ logger.log(Level.INFO, "Creating empty config: " + configFile.toString());
+ configFile.createNewFile();
+ }
+ catch (IOException ex)
+ {
+ logger.log(Level.SEVERE, "Failed to create config " + configFile.toString(), ex);
+ }
+ }
+ }
+ super.load();
+ if (this.root == null) {
+ this.root = new HashMap();
+ }
+ }
+
+ private void createFromTemplate()
+ {
+ OutputStream ostr = null;
+ try
+ {
+ InputStream istr = resourceClass.getResourceAsStream(templateName);
+ if (istr == null)
+ {
+ logger.log(Level.SEVERE, "Could not find template " + templateName);
+ return;
+ }
+ ostr = new FileOutputStream(configFile);
+ byte[] buffer = new byte[1024];
+ int length = 0;
+ length = istr.read(buffer);
+ while (length > 0)
+ {
+ ostr.write(buffer, 0, length);
+ length = istr.read(buffer);
+ }
+ ostr.close();
+ istr.close();
+ }
+ catch (IOException ex)
+ {
+ logger.log(Level.SEVERE, "Failed to write config " + configFile.toString(), ex);
+ return;
+ }
+ finally
+ {
+ try
+ {
+ ostr.close();
+ }
+ catch (IOException ex)
+ {
+ logger.log(Level.SEVERE, "Failed to close config " + configFile.toString(), ex);
+ return;
+ }
+ }
+ }
+
+ public void setTemplateName(String templateName)
+ {
+ this.templateName = templateName;
+ }
+
+ public File getFile()
+ {
+ return configFile;
+ }
+
+ public void setTemplateName(String templateName, Class> resClass) {
+ this.templateName = templateName;
+ this.resourceClass = resClass;
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/EssentialsEcoBlockListener.java b/Essentials/src/com/earth2me/essentials/EssentialsEcoBlockListener.java
new file mode 100644
index 000000000..907b836e2
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/EssentialsEcoBlockListener.java
@@ -0,0 +1,289 @@
+package com.earth2me.essentials;
+
+import com.earth2me.essentials.Essentials;
+import com.earth2me.essentials.ItemDb;
+import com.earth2me.essentials.User;
+import org.bukkit.Material;
+import org.bukkit.block.Sign;
+import org.bukkit.craftbukkit.block.CraftSign;
+import org.bukkit.craftbukkit.inventory.CraftInventory;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockListener;
+import org.bukkit.event.block.BlockRightClickEvent;
+import org.bukkit.event.block.SignChangeEvent;
+import org.bukkit.inventory.ItemStack;
+
+
+public class EssentialsEcoBlockListener extends BlockListener
+{
+ @Override
+ public void onBlockBreak(BlockBreakEvent event)
+ {
+ if (event.isCancelled()) return;
+ if (Essentials.getSettings().areSignsDisabled()) return;
+ User user = User.get(event.getPlayer());
+ if (event.getBlock().getType() != Material.WALL_SIGN && event.getBlock().getType() != Material.SIGN_POST)
+ return;
+ Sign sign = new CraftSign(event.getBlock());
+
+ if (sign.getLine(0).equals("§1[Trade]"))
+ {
+ if (!sign.getLine(3).substring(2).equals(user.getName())) {
+ if (!user.isOp()) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ try
+ {
+ String[] l1 = sign.getLines()[1].split("[ :-]+");
+ String[] l2 = sign.getLines()[2].split("[ :-]+");
+ boolean m1 = l1[0].matches("\\$[0-9]+");
+ boolean m2 = l2[0].matches("\\$[0-9]+");
+ int q1 = Integer.parseInt(m1 ? l1[0].substring(1) : l1[0]);
+ int q2 = Integer.parseInt(m2 ? l2[0].substring(1) : l2[0]);
+ int r1 = Integer.parseInt(l1[m1 ? 1 : 2]);
+ int r2 = Integer.parseInt(l2[m2 ? 1 : 2]);
+ if (q1 < 1 || q2 < 1) throw new Exception("Quantities must be greater than 0.");
+
+ ItemStack i1 = m1 || r1 <= 0 ? null : ItemDb.get(l1[1], r1);
+ ItemStack i2 = m2 || r2 <= 0 ? null : ItemDb.get(l2[1], r2);
+
+ if (m1)
+ user.giveMoney(r1);
+ else if (i1 != null)
+ user.getWorld().dropItem(user.getLocation(), i1);
+
+ if (m2)
+ user.giveMoney(r2);
+ else if (i2 != null)
+ user.getWorld().dropItem(user.getLocation(), i2);
+
+ sign.setType(Material.AIR);
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ }
+ return;
+ }
+ }
+
+ @Override
+ public void onBlockRightClick(BlockRightClickEvent event)
+ {
+ if (Essentials.getSettings().areSignsDisabled()) return;
+ User user = User.get(event.getPlayer());
+ if (event.getBlock().getType() != Material.WALL_SIGN && event.getBlock().getType() != Material.SIGN_POST)
+ return;
+ Sign sign = new CraftSign(event.getBlock());
+
+ if (sign.getLine(0).equals("§1[Buy]") && user.isAuthorized("essentials.signs.buy.use"))
+ {
+ try
+ {
+ int amount = Integer.parseInt(sign.getLine(1));
+ ItemStack item = ItemDb.get(sign.getLine(2), amount);
+ int cost = Integer.parseInt(sign.getLine(3).substring(1));
+ if (user.getMoney() < cost) throw new Exception("You do not have sufficient funds.");
+ user.takeMoney(cost);
+ user.getInventory().addItem(item);
+ user.updateInventory();
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ }
+ return;
+ }
+
+ if (sign.getLine(0).equals("§1[Sell]") && user.isAuthorized("essentials.signs.sell.use"))
+ {
+ try
+ {
+ int amount = Integer.parseInt(sign.getLine(1));
+ ItemStack item = ItemDb.get(sign.getLine(2), amount);
+ int cost = Integer.parseInt(sign.getLine(3).substring(1));
+ if (!InventoryWorkaround.containsItem((CraftInventory)user.getInventory(), true, item)) throw new Exception("You do not have enough items to sell.");
+ user.giveMoney(cost);
+ InventoryWorkaround.removeItem((CraftInventory)user.getInventory(), true, item);
+ user.updateInventory();
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ }
+ return;
+ }
+
+ if (sign.getLine(0).equals("§1[Trade]") && user.isAuthorized("essentials.signs.trade.use"))
+ {
+ try
+ {
+ String[] l1 = sign.getLines()[1].split("[ :-]+");
+ String[] l2 = sign.getLines()[2].split("[ :-]+");
+ boolean m1 = l1[0].matches("\\$[0-9]+");
+ boolean m2 = l2[0].matches("\\$[0-9]+");
+ int q1 = Integer.parseInt(m1 ? l1[0].substring(1) : l1[0]);
+ int q2 = Integer.parseInt(m2 ? l2[0].substring(1) : l2[0]);
+ int r1 = Integer.parseInt(l1[m1 ? 1 : 2]);
+ int r2 = Integer.parseInt(l2[m2 ? 1 : 2]);
+ r1 = r1 - r1 % q1;
+ r2 = r2 - r2 % q2;
+ if (q1 < 1 || q2 < 1) throw new Exception("Quantities must be greater than 0.");
+
+ ItemStack i1 = m1 || r1 <= 0? null : ItemDb.get(l1[1], r1);
+ ItemStack qi1 = m1 ? null : ItemDb.get(l1[1], q1);
+ ItemStack qi2 = m2 ? null : ItemDb.get(l2[1], q2);
+
+ if (user.getName().equals(sign.getLines()[3].substring(2)))
+ {
+ if (m1)
+ {
+ user.giveMoney(r1);
+ }
+ else if (i1 != null)
+ {
+ user.getInventory().addItem(i1);
+ user.updateInventory();
+ }
+ r1 = 0;
+ sign.setLine(1, (m1 ? "$" + q1 : q1 + " " + l1[1]) + ":" + r1);
+ }
+ else
+ {
+ if (m1)
+ {
+ if (user.getMoney() < q1)
+ throw new Exception("You do not have sufficient funds.");
+ }
+ else
+ {
+ if (!InventoryWorkaround.containsItem((CraftInventory)user.getInventory(), true, qi1))
+ throw new Exception("You do not have " + q1 + "x " + l1[1] + ".");
+ }
+
+ if (r2 < q2) throw new Exception("The trade sign does not have enough supply left.");
+
+ if (m1)
+ user.takeMoney(q1);
+ else
+ InventoryWorkaround.removeItem((CraftInventory)user.getInventory(), true, qi1);
+
+ if (m2)
+ user.giveMoney(q2);
+ else
+ user.getInventory().addItem(qi2);
+
+ user.updateInventory();
+
+ r1 += q1;
+ r2 -= q2;
+
+ sign.setLine(0, "§1[Trade]");
+ sign.setLine(1, (m1 ? "$" + q1 : q1 + " " + l1[1]) + ":" + r1);
+ sign.setLine(2, (m2 ? "$" + q2 : q2 + " " + l2[1]) + ":" + r2);
+
+ user.sendMessage("§7Trade completed.");
+ }
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ }
+ return;
+ }
+ }
+
+ @Override
+ public void onSignChange(SignChangeEvent event)
+ {
+ if (Essentials.getSettings().areSignsDisabled()) return;
+ User user = User.get(event.getPlayer());
+
+ if (event.getLine(0).equalsIgnoreCase("[Buy]") && user.isAuthorized("essentials.signs.buy.create"))
+ {
+ try
+ {
+ event.setLine(0, "§1[Buy]");
+ event.setLine(1, "" + Math.abs(Integer.parseInt(event.getLine(1))));
+ ItemDb.get(event.getLine(2));
+ event.setLine(3, "$" + Integer.parseInt(event.getLine(3).replaceAll("[^0-9]", "")));
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ event.setLine(0, "§4[Buy]");
+ event.setLine(1, "#");
+ event.setLine(2, "Item");
+ event.setLine(3, "$Price");
+ }
+ return;
+ }
+
+ if (event.getLine(0).equalsIgnoreCase("[Sell]") && user.isAuthorized("essentials.signs.sell.create"))
+ {
+ try
+ {
+ event.setLine(0, "§1[Sell]");
+ event.setLine(1, "" + Math.abs(Integer.parseInt(event.getLine(1))));
+ ItemDb.get(event.getLine(2));
+ event.setLine(3, "$" + Integer.parseInt(event.getLine(3).replaceAll("[^0-9]", "")));
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ event.setLine(0, "§4[Sell]");
+ event.setLine(1, "#");
+ event.setLine(2, "Item");
+ event.setLine(3, "$Price");
+ }
+ return;
+ }
+
+ if (event.getLine(0).equalsIgnoreCase("[Trade]") && user.isAuthorized("essentials.signs.trade.create"))
+ {
+ try
+ {
+ String[] l1 = event.getLines()[1].split("[ :-]+");
+ String[] l2 = event.getLines()[2].split("[ :-]+");
+ boolean m1 = l1[0].matches("\\$[0-9]+");
+ boolean m2 = l2[0].matches("\\$[0-9]+");
+ int q1 = Integer.parseInt(m1 ? l1[0].substring(1) : l1[0]);
+ int q2 = Integer.parseInt(m2 ? l2[0].substring(1) : l2[0]);
+ int r2 = Integer.parseInt(l2[m2 ? 1 : 2]);
+ r2 = r2 - r2 % q2;
+ if (q1 < 1 || q2 < 1 || r2 < 1) throw new Exception("Quantities must be greater than 0.");
+ if (!m1) ItemDb.get(l1[1]);
+
+ if (m2)
+ {
+ if (user.getMoney() < r2) throw new Exception("You do not have sufficient funds.");
+ user.takeMoney(r2);
+ user.sendMessage("r2: " + r2 + " q2: " + q2);
+ }
+ else
+ {
+ ItemStack i2 = ItemDb.get(l2[1], r2);
+ if (!InventoryWorkaround.containsItem((CraftInventory)user.getInventory(), true, i2)) throw new Exception("You do not have " + r2 + "x " + l2[1] + ".");
+ InventoryWorkaround.removeItem((CraftInventory)user.getInventory(), true, i2);
+ user.updateInventory();
+ }
+
+ event.setLine(0, "§1[Trade]");
+ event.setLine(1, (m1 ? "$" + q1 : q1 + " " + l1[1]) + ":0");
+ event.setLine(2, (m2 ? "$" + q2 : q2 + " " + l2[1]) + ":" + r2);
+ event.setLine(3, "§8" + user.getName());
+ }
+ catch (Throwable ex)
+ {
+ user.sendMessage("§cError: " + ex.getMessage());
+ event.setLine(0, "§4[Trade]");
+ event.setLine(1, "# ItemOr$");
+ event.setLine(2, "# ItemOr$:#");
+ event.setLine(3, "§8" + user.getName());
+ }
+ return;
+ }
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/EssentialsEntityListener.java b/Essentials/src/com/earth2me/essentials/EssentialsEntityListener.java
new file mode 100644
index 000000000..15355021a
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/EssentialsEntityListener.java
@@ -0,0 +1,65 @@
+package com.earth2me.essentials;
+
+import org.bukkit.Server;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.EntityCombustEvent;
+import org.bukkit.event.entity.EntityDamageByBlockEvent;
+import org.bukkit.event.entity.EntityDamageByProjectileEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.event.entity.EntityListener;
+
+
+public class EssentialsEntityListener extends EntityListener
+{
+ private final Server server;
+ private final Essentials parent;
+
+ public EssentialsEntityListener(Essentials parent)
+ {
+ this.parent = parent;
+ this.server = parent.getServer();
+ }
+
+ @Override
+ public void onEntityDamage(EntityDamageEvent event)
+ {
+ if (event instanceof EntityDamageEvent || event instanceof EntityDamageByBlockEvent || event instanceof EntityDamageByProjectileEvent)
+ {
+
+ if (event.getEntity() instanceof Player && User.get(event.getEntity()).isGodModeEnabled())
+ {
+ CraftPlayer player = (CraftPlayer)event.getEntity();
+ player.getHandle().fireTicks = 0;
+ player.setRemainingAir(player.getMaximumAir());
+ event.setCancelled(true);
+ }
+ }
+ }
+
+
+ @Override
+ public void onEntityCombust(EntityCombustEvent event)
+ {
+ if (event.getEntity() instanceof Player && User.get(event.getEntity()).isGodModeEnabled())
+ {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onEntityDeath(EntityDeathEvent event)
+ {
+ if (event.getEntity() instanceof Player)
+ {
+ User user = User.get(event.getEntity());
+ if(user.isAuthorized("essentials.back.ondeath"))
+ {
+ user.lastLocation = user.getLocation();
+ user.sendMessage("§7Use the /back command to return to your death point");
+ }
+ }
+ }
+
+}
diff --git a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java
new file mode 100644
index 000000000..e4f743ddd
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java
@@ -0,0 +1,226 @@
+package com.earth2me.essentials;
+
+import java.util.List;
+import java.util.logging.Logger;
+import org.bukkit.*;
+import org.bukkit.block.Block;
+import org.bukkit.event.player.*;
+import org.bukkit.event.player.PlayerLoginEvent.Result;
+
+
+public class EssentialsPlayerListener extends PlayerListener
+{
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private final Server server;
+ private final Essentials parent;
+
+ public EssentialsPlayerListener(Essentials parent)
+ {
+ this.parent = parent;
+ this.server = parent.getServer();
+ }
+
+ @Override
+ public void onPlayerRespawn(PlayerRespawnEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ user.setDisplayName(user.getNick());
+ updateCompass(user);
+ }
+
+ @Override
+ public void onPlayerChat(PlayerChatEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ if (user.isMuted())
+ {
+ event.setCancelled(true);
+ logger.info(user.getName() + " tried to speak, but is muted.");
+ }
+ }
+
+ @Override
+ public void onPlayerMove(PlayerMoveEvent event)
+ {
+ if (event.isCancelled()) return;
+ final User user = User.get(event.getPlayer());
+
+ if (!Essentials.getSettings().getNetherPortalsEnabled()) return;
+
+ final Block block = event.getPlayer().getWorld().getBlockAt(event.getTo().getBlockX(), event.getTo().getBlockY(), event.getTo().getBlockZ());
+ List worlds = server.getWorlds();
+
+ if (block.getType() == Material.PORTAL && worlds.size() > 1 && user.isAuthorized("essentials.portal"))
+ {
+ if (user.getJustPortaled()) return;
+
+ Location loc = event.getTo();
+ final World world = worlds.get(user.getWorld() == worlds.get(0) ? 1 : 0);
+
+ double factor;
+ if (user.getWorld().getEnvironment() == World.Environment.NETHER && world.getEnvironment() == World.Environment.NORMAL)
+ factor = 16.0;
+ else if (user.getWorld().getEnvironment() != world.getEnvironment())
+ factor = 1.0 / 16.0;
+ else
+ factor = 1.0;
+
+ int x = loc.getBlockX();
+ int y = loc.getBlockY();
+ int z = loc.getBlockZ();
+
+ if (user.getWorld().getBlockAt(x, y, z - 1).getType() == Material.PORTAL)
+ z--;
+ if (user.getWorld().getBlockAt(x - 1, y, z).getType() == Material.PORTAL)
+ x--;
+
+ x = (int)(x * factor);
+ z = (int)(z * factor);
+ loc = new Location(world, x + .5, y, z + .5);
+
+ Block dest = world.getBlockAt(x, y, z);
+ NetherPortal portal = NetherPortal.findPortal(dest);
+ if (portal == null)
+ {
+ if (world.getEnvironment() == World.Environment.NETHER || Essentials.getSettings().getGenerateExitPortals())
+ {
+ portal = NetherPortal.createPortal(dest);
+ logger.info(event.getPlayer().getName() + " used a portal and generated an exit portal.");
+ user.sendMessage("§7Generating an exit portal.");
+ loc = portal.getSpawn();
+ }
+ }
+ else
+ {
+ logger.info(event.getPlayer().getName() + " used a portal and used an existing exit portal.");
+ user.sendMessage("§7Teleporting via portal to an existing portal.");
+ loc = portal.getSpawn();
+ }
+
+ event.setFrom(loc);
+ event.setTo(loc);
+ try {
+ user.teleportToNow(loc);
+ } catch (Exception ex) {
+ user.sendMessage(ex.getMessage());
+ }
+ user.setJustPortaled(true);
+ user.sendMessage("§7Teleporting via portal.");
+
+ event.setCancelled(true);
+ return;
+ }
+
+ user.setJustPortaled(false);
+ }
+
+ @Override
+ public void onPlayerQuit(PlayerEvent event)
+ {
+ if (!Essentials.getSettings().getReclaimSetting())
+ {
+ return;
+ }
+ User.get(event.getPlayer()).dispose();
+ Thread thread = new Thread(new Runnable()
+ {
+ @SuppressWarnings("LoggerStringConcat")
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(1000);
+ Runtime rt = Runtime.getRuntime();
+ double mem = rt.freeMemory();
+ rt.runFinalization();
+ rt.gc();
+ mem = rt.freeMemory() - mem;
+ mem /= 1024 * 1024;
+ logger.info("Freed " + mem + " MB.");
+ }
+ catch (InterruptedException ex)
+ {
+ return;
+ }
+ }
+ });
+ thread.setPriority(Thread.MIN_PRIORITY);
+ thread.start();
+ }
+
+ @Override
+ public void onPlayerJoin(PlayerEvent event)
+ {
+ Essentials.getStatic().backup.onPlayerJoin();
+ User user = User.get(event.getPlayer());
+
+ //we do not know the ip address on playerlogin so we need to do this here.
+ if (user.isIpBanned())
+ {
+ user.kickPlayer("The Ban Hammer has spoken!");
+ return;
+ }
+
+ user.setDisplayName(user.getNick());
+
+ if (!Essentials.getSettings().isCommandDisabled("motd") && user.isAuthorized("essentials.motd"))
+ {
+ for (String m : parent.getMotd(user, null))
+ {
+ if (m == null) continue;
+ user.sendMessage(m);
+ }
+ }
+
+ if (!Essentials.getSettings().isCommandDisabled("mail"))
+ {
+ List mail = Essentials.readMail(user);
+ if (mail.isEmpty()) user.sendMessage("§7You have no new mail.");
+ else user.sendMessage("§cYou have " + mail.size() + " messages!§f Type §7/mail read§f to view your mail.");
+ }
+ }
+
+ @Override
+ public void onPlayerLogin(PlayerLoginEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ if (event.getResult() != Result.ALLOWED)
+ return;
+
+ if (user.isBanned())
+ {
+ event.disallow(Result.KICK_BANNED, "The Ban Hammer has spoken!");
+ return;
+ }
+
+ if (server.getOnlinePlayers().length >= server.getMaxPlayers() && !user.isOp())
+ {
+ event.disallow(Result.KICK_FULL, "Server is full");
+ return;
+ }
+
+ updateCompass(user);
+ }
+
+ private void updateCompass(User user)
+ {
+ try
+ {
+ if (server.getPluginManager().isPluginEnabled("EssentialsHome"))
+ user.setCompassTarget(user.getHome());
+ }
+ catch (Throwable ex)
+ {
+ }
+ }
+
+ @Override
+ public void onPlayerTeleport(PlayerMoveEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ if (user.currentJail == null || user.currentJail.isEmpty())
+ return;
+ event.setCancelled(true);
+ user.sendMessage(ChatColor.RED + "You do the crime, you do the time.");
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/IConf.java b/Essentials/src/com/earth2me/essentials/IConf.java
new file mode 100644
index 000000000..a523f8638
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/IConf.java
@@ -0,0 +1,5 @@
+package com.earth2me.essentials;
+
+public interface IConf {
+ public void reloadConfig();
+}
diff --git a/Essentials/src/com/earth2me/essentials/InventoryWorkaround.java b/Essentials/src/com/earth2me/essentials/InventoryWorkaround.java
new file mode 100644
index 000000000..aabd7b02b
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/InventoryWorkaround.java
@@ -0,0 +1,136 @@
+package com.earth2me.essentials;
+
+import java.util.HashMap;
+import org.bukkit.craftbukkit.inventory.CraftInventory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.inventory.ItemStack;
+
+/*
+ * This class can be removed when
+ * https://github.com/Bukkit/CraftBukkit/pull/193
+ * is accepted to CraftBukkit
+ */
+public class InventoryWorkaround {
+
+ public static int first(CraftInventory ci, ItemStack item, boolean forceDurability, boolean forceAmount) {
+ return next(ci, item, 0, forceDurability, forceAmount);
+ }
+
+ public static int next(CraftInventory ci, ItemStack item, int start, boolean forceDurability, boolean forceAmount) {
+ CraftItemStack[] inventory = ci.getContents();
+ for (int i = start; i < inventory.length; i++) {
+ CraftItemStack cItem = inventory[i];
+ if (item.getTypeId() == cItem.getTypeId() && (!forceAmount || item.getAmount() == cItem.getAmount()) && (!forceDurability || cItem.getDurability() == item.getDurability())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static HashMap removeItem(CraftInventory ci, boolean forceDurability, ItemStack... items) {
+ HashMap leftover = new HashMap();
+
+ // TODO: optimization
+
+ for (int i = 0; i < items.length; i++) {
+ ItemStack item = items[i];
+ if (item == null) {
+ continue;
+ }
+ int toDelete = item.getAmount();
+
+ while (true) {
+
+ // Bail when done
+ if (toDelete <= 0) {
+ break;
+ }
+
+ // get first Item, ignore the amount
+ int first = first(ci, item, forceDurability, false);
+
+ // Drat! we don't have this type in the inventory
+ if (first == -1) {
+ item.setAmount(toDelete);
+ leftover.put(i, item);
+ break;
+ } else {
+ CraftItemStack itemStack = ci.getItem(first);
+ int amount = itemStack.getAmount();
+
+ if (amount <= toDelete) {
+ toDelete -= amount;
+ // clear the slot, all used up
+ ci.clear(first);
+ } else {
+ // split the stack and store
+ itemStack.setAmount(amount - toDelete);
+ ci.setItem(first, itemStack);
+ toDelete = 0;
+ }
+ }
+ }
+ }
+ return leftover;
+ }
+
+ public static boolean containsItem(CraftInventory ci, boolean forceDurability, ItemStack... items) {
+ HashMap leftover = new HashMap();
+
+ // TODO: optimization
+
+ // combine items
+
+ ItemStack[] combined = new ItemStack[items.length];
+ for (int i = 0; i < items.length; i++) {
+ if (items[i] == null) {
+ continue;
+ }
+ for (int j = 0; j < combined.length; j++) {
+ if (combined[j] == null) {
+ combined[j] = new ItemStack(items[i].getType(), items[i].getAmount(), items[i].getDurability());
+ break;
+ }
+ if (combined[j].getTypeId() == items[i].getTypeId() && (!forceDurability || combined[j].getDurability() == items[i].getDurability())) {
+ combined[j].setAmount(combined[j].getAmount() + items[i].getAmount());
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < combined.length; i++) {
+ ItemStack item = combined[i];
+ if (item == null) {
+ continue;
+ }
+ int mustHave = item.getAmount();
+ int position = 0;
+
+ while (true) {
+ // Bail when done
+ if (mustHave <= 0) {
+ break;
+ }
+
+ int slot = next(ci, item, position, forceDurability, false);
+
+ // Drat! we don't have this type in the inventory
+ if (slot == -1) {
+ leftover.put(i, item);
+ break;
+ } else {
+ CraftItemStack itemStack = ci.getItem(slot);
+ int amount = itemStack.getAmount();
+
+ if (amount <= mustHave) {
+ mustHave -= amount;
+ } else {
+ mustHave = 0;
+ }
+ position = slot + 1;
+ }
+ }
+ }
+ return leftover.isEmpty();
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/ItemDb.java b/Essentials/src/com/earth2me/essentials/ItemDb.java
new file mode 100644
index 000000000..8c3c47bab
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/ItemDb.java
@@ -0,0 +1,110 @@
+package com.earth2me.essentials;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+import java.util.logging.Logger;
+import org.bukkit.inventory.ItemStack;
+
+
+public class ItemDb
+{
+ private final static Logger logger = Logger.getLogger("Minecraft");
+ private static Map items = new HashMap();
+ private static Map durabilities = new HashMap();
+
+ @SuppressWarnings("LoggerStringConcat")
+ public static void load(File folder, String fname) throws IOException
+ {
+ folder.mkdirs();
+ File file = new File(folder, fname);
+
+ if (!file.exists())
+ {
+ file.createNewFile();
+ InputStream res = ItemDb.class.getResourceAsStream("/items.csv");
+ FileWriter tx = new FileWriter(file);
+ try
+ {
+ for (int i = 0; (i = res.read()) > 0;) tx.write(i);
+ }
+ finally
+ {
+ try
+ {
+ tx.flush();
+ tx.close();
+ res.close();
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ }
+
+ BufferedReader rx = new BufferedReader(new FileReader(file));
+ try
+ {
+ items.clear();
+
+ for (int i = 0; rx.ready(); i++)
+ {
+ try
+ {
+ String line = rx.readLine().trim().toLowerCase();
+ if (line.startsWith("#"))
+ continue;
+
+ String[] parts = line.split("[^a-z0-9]");
+ if (parts.length < 2)
+ continue;
+
+ int numeric = Integer.parseInt(parts[1]);
+
+ durabilities.put(parts[0], parts.length > 2 && !parts[2].equals("0") ? Short.parseShort(parts[2]) : 0);
+ items.put(parts[0], numeric);
+ }
+ catch (Exception ex)
+ {
+ logger.warning("Error parsing " + fname + " on line " + i);
+ }
+ }
+ }
+ finally
+ {
+ rx.close();
+ }
+ }
+
+ public static ItemStack get(String id, int quantity) throws Exception {
+ ItemStack retval = get(id);
+ retval.setAmount(quantity);
+ return retval;
+ }
+
+ public static ItemStack get(String id) throws Exception
+ {
+ ItemStack retval = new ItemStack(getUnsafe(id));
+ retval.setAmount(Essentials.getSettings().getDefaultStackSize());
+ retval.setDurability(durabilities.containsKey(id) ? durabilities.get(id) : 0);
+ if (items.containsValue(retval.getTypeId()) || true) return retval;
+ throw new Exception("Unknown item numeric: " + retval);
+ }
+
+ private static int getUnsafe(String id) throws Exception
+ {
+ try
+ {
+ return Integer.parseInt(id);
+ }
+ catch (NumberFormatException ex)
+ {
+ if (items.containsKey(id)) return items.get(id);
+ throw new Exception("Unknown item name: " + id);
+ }
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/Jail.java b/Essentials/src/com/earth2me/essentials/Jail.java
new file mode 100644
index 000000000..0ed2774e2
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/Jail.java
@@ -0,0 +1,115 @@
+package com.earth2me.essentials;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockDamageEvent;
+import org.bukkit.event.block.BlockInteractEvent;
+import org.bukkit.event.block.BlockListener;
+import org.bukkit.event.block.BlockPlaceEvent;
+
+public class Jail extends BlockListener implements IConf {
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private EssentialsConf config;
+
+ public Jail(File dataFolder) {
+ config = new EssentialsConf(new File(dataFolder, "jail.yml"));
+ config.load();
+ }
+
+ public void setJail(Location loc, String jailName) throws Exception {
+ Map map = new HashMap();
+ map.put("world", loc.getWorld().getName());
+ map.put("x", loc.getX());
+ map.put("y", loc.getY());
+ map.put("z", loc.getZ());
+ map.put("yaw", loc.getYaw());
+ map.put("pitch", loc.getPitch());
+ config.setProperty(jailName.toLowerCase(), map);
+ config.save();
+ }
+
+ public Location getJail(String jailName) throws Exception {
+ if (config.getProperty(jailName.toLowerCase()) == null) {
+ throw new Exception("That jail does not exist");
+ }
+
+ World jWorld = null;
+ String world = config.getString(jailName + ".world", ""); // wh.spawnX
+ double x = config.getDouble(jailName + ".x", 0); // wh.spawnX
+ double y = config.getDouble(jailName + ".y", 0); // wh.spawnY
+ double z = config.getDouble(jailName + ".z", 0); // wh.spawnZ
+ float yaw = (float) config.getDouble(jailName + ".yaw", 0);
+ float pitch = (float) config.getDouble(jailName + ".pitch", 0);
+ for (World w : Essentials.getStatic().getServer().getWorlds()) {
+ if (w.getName().equalsIgnoreCase(world)) {
+ jWorld = w;
+ break;
+ }
+
+ }
+ return new Location(jWorld, x, y, z, yaw, pitch);
+ }
+
+ public void sendToJail(User user, String jail) throws Exception {
+ user.teleportTo(getJail(jail));
+ user.currentJail = jail;
+ }
+
+ public void delJail(String jail) throws Exception {
+ config.removeProperty(jail.toLowerCase());
+ config.save();
+ }
+
+ public List getJails() throws Exception {
+ return config.getKeys(null);
+ }
+
+ public void reloadConfig() {
+ config.load();
+ }
+
+ @Override
+ public void onBlockBreak(BlockBreakEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ if (user.isJailed()) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onBlockInteract(BlockInteractEvent event)
+ {
+ if (!event.isPlayer()) {
+ return;
+ }
+ User user = User.get((Player)event.getEntity());
+ if (user.isJailed()) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onBlockPlace(BlockPlaceEvent event)
+ {
+ User user = User.get(event.getPlayer());
+ if (user.isJailed()) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onBlockDamage(BlockDamageEvent event) {
+ User user = User.get(event.getPlayer());
+ if (user.isJailed()) {
+ event.setCancelled(true);
+ }
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/Mob.java b/Essentials/src/com/earth2me/essentials/Mob.java
new file mode 100644
index 000000000..3c0d9bd1e
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/Mob.java
@@ -0,0 +1,122 @@
+package com.earth2me.essentials;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.logging.Logger;
+import net.minecraft.server.Entity;
+import net.minecraft.server.WorldServer;
+import org.bukkit.Server;
+import org.bukkit.craftbukkit.entity.CraftEntity;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.entity.Player;
+
+
+public enum Mob
+{
+ CHICKEN("Chicken", Enemies.FRIENDLY),
+ COW("Cow", Enemies.FRIENDLY),
+ CREEPER("Creeper", Enemies.ENEMY),
+ GHAST("Ghast", Enemies.ENEMY),
+ GIANT("Giant", "GiantZombie", Enemies.ENEMY),
+ PIG("Pig", Enemies.FRIENDLY),
+ PIGZOMB("PigZombie", Enemies.NEUTRAL),
+ SHEEP("Sheep", Enemies.FRIENDLY, ""),
+ SKELETON("Skeleton", Enemies.ENEMY),
+ SLIME("Slime", Enemies.ENEMY),
+ SPIDER("Spider", Enemies.ENEMY),
+ SQUID("Squid", Enemies.FRIENDLY),
+ ZOMBIE("Zombie", Enemies.ENEMY),
+ MONSTER("Monster", Enemies.ENEMY);
+
+ public static final Logger logger = Logger.getLogger("Minecraft");
+
+ private Mob(String n, Enemies en, String s)
+ {
+ this.s = s;
+ this.name = n;
+ this.craftClass = n;
+ this.entityClass = n;
+ this.type = en;
+ }
+
+ private Mob(String n, Enemies en)
+ {
+ this.name = n;
+ this.craftClass = n;
+ this.entityClass = n;
+ this.type = en;
+ }
+
+ private Mob(String n, String ec, Enemies en)
+ {
+ this.name = n;
+ this.craftClass = n;
+ this.entityClass = ec;
+ this.type = en;
+ }
+
+ private Mob(String n, String ec, String cc, Enemies en)
+ {
+ this.name = n;
+ this.entityClass = ec;
+ this.craftClass = cc;
+ this.type = en;
+ }
+ public String s = "s";
+ public String name;
+ public Enemies type;
+ private String entityClass;
+ private String craftClass;
+ private static final HashMap hashMap = new HashMap();
+
+ static
+ {
+ for (Mob mob : Mob.values())
+ {
+ hashMap.put(mob.name, mob);
+ }
+ }
+
+ @SuppressWarnings({"unchecked", "CallToThreadDumpStack"})
+ public CraftEntity spawn(Player player, Server server) throws MobException
+ {
+ try
+ {
+ WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)player.getWorld()).getHandle();
+ Constructor craft = (Constructor)ClassLoader.getSystemClassLoader().loadClass("org.bukkit.craftbukkit.entity.Craft" + craftClass).getConstructors()[0];
+ Constructor entity = (Constructor)ClassLoader.getSystemClassLoader().loadClass("net.minecraft.server.Entity" + entityClass).getConstructors()[0];
+ return craft.newInstance((CraftServer)server, entity.newInstance(world));
+ }
+ catch (Exception ex)
+ {
+ logger.warning("Unable to spawn mob.");
+ ex.printStackTrace();
+ throw new MobException();
+ }
+ }
+
+
+ public enum Enemies
+ {
+ FRIENDLY("friendly"),
+ NEUTRAL("neutral"),
+ ENEMY("enemy");
+
+ private Enemies(String t)
+ {
+ this.type = t;
+ }
+ protected String type;
+ }
+
+
+ public class MobException extends Exception
+ {
+ private static final long serialVersionUID = 1L;
+ }
+
+ public static Mob fromName(String n)
+ {
+ return hashMap.get(n);
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/NetherPortal.java b/Essentials/src/com/earth2me/essentials/NetherPortal.java
new file mode 100644
index 000000000..25ebe5e23
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/NetherPortal.java
@@ -0,0 +1,167 @@
+/**
+ * @author SpaceManiac
+ * @licent MIT
+ * @origin https://github.com/SpaceManiac/Nether/blob/master/org/innectis/Nether/NetherPortal.java
+ */
+package com.earth2me.essentials;
+
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+public class NetherPortal
+{
+ private Block block;
+
+ public NetherPortal(Block b)
+ {
+ block = b;
+ }
+
+ public Block getBlock()
+ {
+ return block;
+ }
+
+ public void setBlock(Block b)
+ {
+ block = b;
+ }
+
+ // Return a random spawnable location
+ public Location getSpawn()
+ {
+ if (block.getWorld().getBlockAt(block.getX() + 1, block.getY(), block.getZ()).getType().equals(Material.PORTAL)
+ || block.getWorld().getBlockAt(block.getX() - 1, block.getY(), block.getZ()).getType().equals(Material.PORTAL))
+ {
+ // portal is in X direction
+ return new Location(block.getWorld(), block.getX() + 1,
+ block.getY(), block.getZ() + 1.5 - 2 * Math.round(Math.random()));
+ }
+ else
+ {
+ // portal is in Z direction
+ return new Location(block.getWorld(), block.getX() + 1.5 - 2 * Math.round(Math.random()),
+ block.getY(), block.getZ() + 1);
+ }
+ }
+
+ // ==============================
+ // Find a nearby portal within 16 blocks of the given block
+ // Not guaranteed to be the nearest
+ public static NetherPortal findPortal(Block dest)
+ {
+ World world = dest.getWorld();
+
+ // Get list of columns in a circle around the block
+ ArrayList columns = new ArrayList();
+ for (int x = dest.getX() - 16; x <= dest.getX() + 16; ++x)
+ {
+ for (int z = dest.getZ() - 16; z <= dest.getZ() + 16; ++z)
+ {
+ int dx = dest.getX() - x, dz = dest.getZ() - z;
+ if (dx * dx + dz * dz <= 256)
+ {
+ columns.add(world.getBlockAt(x, 0, z));
+ }
+ }
+ }
+
+ // For each column try to find a portal block
+ for (Block col : columns)
+ {
+ for (int y = 127; y >= 0; --y)
+ {
+ Block b = world.getBlockAt(col.getX(), y, col.getZ());
+ if (b.getType().equals(Material.PORTAL) && Math.abs(dest.getY() - y) <= 16)
+ {
+ // Huzzah!
+ return new NetherPortal(b);
+ }
+ }
+ }
+
+ // Nope!
+ return null;
+ }
+
+ // Create a new portal at the specified block, fudging position if needed
+ // Will occasionally end up making portals in bad places, but let's hope not
+ public static NetherPortal createPortal(Block dest)
+ {
+ World world = dest.getWorld();
+
+ // Try not to spawn within water or lava
+ Material m = dest.getType();
+ while (((m.equals(Material.LAVA) || m.equals(Material.WATER) || m.equals(Material.STATIONARY_LAVA)
+ || m.equals(Material.STATIONARY_WATER) || m.equals(Material.SAND) || m.equals(Material.GRAVEL))) &&
+ dest.getY() < 120)
+ {
+ dest = world.getBlockAt(dest.getX(), dest.getY() + 4, dest.getZ());
+ m = dest.getType();
+ }
+
+ // Not too high or too low overall
+ if (dest.getY() > 120)
+ {
+ dest = world.getBlockAt(dest.getX(), 120, dest.getZ());
+ }
+ else if (dest.getY() < 8)
+ {
+ dest = world.getBlockAt(dest.getX(), 8, dest.getZ());
+ }
+
+ // Create the physical portal
+ // For now, don't worry about direction
+
+ int x = dest.getX(), y = dest.getY(), z = dest.getZ();
+ Logger.getLogger("Minecraft").log(Level.INFO, "Creating portal at "+x+","+y+","+z+".");
+
+ // Clear area around portal
+ ArrayList columns = new ArrayList();
+ for (int x2 = x - 4; x2 <= x + 4; ++x2)
+ {
+ for (int z2 = z - 4; z2 <= z + 4; ++z2)
+ {
+ double dx = x + 0.5f - x2, dz = z - z2;
+ if (dx * dx + dz * dz <= 13)
+ {
+ columns.add(world.getBlockAt(x2, 0, z2));
+ }
+ }
+ }
+
+ // Clear area around portal
+ for (Block col : columns)
+ {
+ // Stone platform
+ world.getBlockAt(col.getX(), y - 1, col.getZ()).setType(Material.STONE);
+ for (int yd = 0; yd < 4; ++yd)
+ {
+ world.getBlockAt(col.getX(), y + yd, col.getZ()).setType(Material.AIR);
+ }
+ }
+
+ // Build obsidian frame
+ for (int xd = -1; xd < 3; ++xd)
+ {
+ for (int yd = -1; yd < 4; ++yd)
+ {
+ if (xd == -1 || yd == -1 || xd == 2 || yd == 3)
+ {
+ world.getBlockAt(x + xd, y + yd, z).setType(Material.OBSIDIAN);
+ }
+ }
+ }
+
+ // Set it alight!
+ dest.setType(Material.FIRE);
+
+ return new NetherPortal(dest);
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/OfflinePlayer.java b/Essentials/src/com/earth2me/essentials/OfflinePlayer.java
new file mode 100644
index 000000000..f1bac2ae4
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/OfflinePlayer.java
@@ -0,0 +1,286 @@
+package com.earth2me.essentials;
+
+import java.net.InetSocketAddress;
+import java.util.HashSet;
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.Server;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Arrow;
+import org.bukkit.entity.Egg;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Snowball;
+import org.bukkit.entity.Vehicle;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+import org.bukkit.util.Vector;
+
+
+public class OfflinePlayer implements Player
+{
+ private final String name;
+ private Location location = new Location(null, 0, 0, 0, 0, 0);
+
+ public OfflinePlayer(String name)
+ {
+ this.name = name;
+ }
+
+ public boolean isOnline()
+ {
+ return false;
+ }
+
+ public boolean isOp()
+ {
+ return false;
+ }
+
+ public void sendMessage(String string)
+ {
+ }
+
+ public String getDisplayName()
+ {
+ return name;
+ }
+
+ public void setDisplayName(String string)
+ {
+ }
+
+ public void setCompassTarget(Location lctn)
+ {
+ }
+
+ public InetSocketAddress getAddress()
+ {
+ return null;
+ }
+
+ public void kickPlayer(String string)
+ {
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public PlayerInventory getInventory()
+ {
+ return null;
+ }
+
+ public ItemStack getItemInHand()
+ {
+ return null;
+ }
+
+ public void setItemInHand(ItemStack is)
+ {
+ }
+
+ public int getHealth()
+ {
+ return 0;
+ }
+
+ public void setHealth(int i)
+ {
+ }
+
+ public Egg throwEgg()
+ {
+ return null;
+ }
+
+ public Snowball throwSnowball()
+ {
+ return null;
+ }
+
+ public Arrow shootArrow()
+ {
+ return null;
+ }
+
+ public boolean isInsideVehicle()
+ {
+ return false;
+ }
+
+ public boolean leaveVehicle()
+ {
+ return false;
+ }
+
+ public Vehicle getVehicle()
+ {
+ return null;
+ }
+
+ public Location getLocation()
+ {
+ return location;
+ }
+
+ public World getWorld()
+ {
+ return null;
+ }
+
+ public void teleportTo(Location lctn)
+ {
+ }
+
+ public void teleportTo(Entity entity)
+ {
+ }
+
+ public int getEntityId()
+ {
+ return -1;
+ }
+
+ public boolean performCommand(String string)
+ {
+ return false;
+ }
+
+ public boolean isPlayer()
+ {
+ return false;
+ }
+
+ public int getRemainingAir()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setRemainingAir(int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public int getMaximumAir()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setMaximumAir(int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public boolean isSneaking()
+ {
+ return false;
+ }
+
+ public void setSneaking(boolean bln)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void updateInventory()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void chat(String string)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public double getEyeHeight()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public double getEyeHeight(boolean bln)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public List getLineOfSight(HashSet hs, int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Block getTargetBlock(HashSet hs, int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public List getLastTwoTargetBlocks(HashSet hs, int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public int getFireTicks()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public int getMaxFireTicks()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setFireTicks(int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Server getServer()
+ {
+ return Essentials.getStatic() == null ? null : Essentials.getStatic().getServer();
+ }
+
+ public Vector getMomentum()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setMomentum(Vector vector)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void setVelocity(Vector vector)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Vector getVelocity()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void damage(int i)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void damage(int i, Entity entity)
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public Location getEyeLocation()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void sendRawMessage(String string) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/PlayerExtension.java b/Essentials/src/com/earth2me/essentials/PlayerExtension.java
new file mode 100644
index 000000000..758f8076d
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/PlayerExtension.java
@@ -0,0 +1,141 @@
+package com.earth2me.essentials;
+
+import org.bukkit.*;
+import org.bukkit.block.Block;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import net.minecraft.server.EntityPlayer;
+import net.minecraft.server.IInventory;
+import org.bukkit.craftbukkit.inventory.CraftInventoryPlayer;
+import org.bukkit.entity.*;
+
+
+public class PlayerExtension extends PlayerWrapper
+{
+ public PlayerExtension(Player base)
+ {
+ super(base);
+ }
+
+ public boolean isBanned()
+ {
+ return Essentials.getStatic().bans.contains(getName());
+ }
+
+ public boolean isIpBanned()
+ {
+ return Essentials.getStatic().bannedIps.contains(getAddress().getAddress().toString().replace("/", ""));
+ }
+
+ public float getCorrectedYaw()
+ {
+ float angle = (getLocation().getYaw() - 90) % 360;
+ if (angle < 0) angle += 360.0F;
+ return angle;
+ }
+
+ public void showInventory(IInventory inventory)
+ {
+ getHandle().a(inventory);
+ }
+
+ public void showInventory(CraftInventoryPlayer inventory)
+ {
+ showInventory((IInventory)inventory.getInventory());
+ }
+
+ public Location getSafeDestination(Location loc) throws Exception
+ {
+ World world = loc.getWorld();
+ double x = loc.getX();
+ double y = loc.getY();
+ double z = loc.getZ();
+
+ while (isBlockAboveAir(world, x, y, z))
+ {
+ y -= 1.0D;
+ if (y < 0) {
+ throw new Exception("Hole in floor");
+ }
+ }
+
+ while (isBlockUnsafe(world, x, y, z))
+ {
+ y += 1.0D;
+ if (y >= 110.0D) {
+ x += 1.0D;
+ break;
+ }
+ }
+ while (isBlockUnsafe(world, x, y, z))
+ {
+ y -= 1.0D;
+ if (y <= 1.0D)
+ {
+ y = 110.0D;
+ x += 1.0D;
+ }
+ }
+ return new Location(world, x, y, z, loc.getYaw(), loc.getPitch());
+ }
+
+ private boolean isBlockAboveAir(World world, double x, double y, double z)
+ {
+ return world.getBlockAt((int)Math.floor(x), (int)Math.floor(y - 1.0D), (int)Math.floor(z)).getType() == Material.AIR;
+ }
+
+ public boolean isBlockUnsafe(World world, double x, double y, double z)
+ {
+ Block below = world.getBlockAt((int)Math.floor(x), (int)Math.floor(y - 1.0D), (int)Math.floor(z));
+ if (below.getType() == Material.LAVA || below.getType() == Material.STATIONARY_LAVA)
+ return true;
+
+ if (below.getType() == Material.FIRE)
+ return true;
+
+ if ((world.getBlockAt((int)Math.floor(x), (int)Math.floor(y), (int)Math.floor(z)).getType() != Material.AIR)
+ || (world.getBlockAt((int)Math.floor(x), (int)Math.floor(y + 1.0D), (int)Math.floor(z)).getType() != Material.AIR))
+ {
+ return true;
+ }
+ return isBlockAboveAir(world, x, y, z);
+ }
+
+ public TargetBlock getTarget()
+ {
+ return new TargetBlock(getBase());
+ }
+
+ public String getGroup()
+ {
+ try
+ {
+ return com.nijikokun.bukkit.Permissions.Permissions.Security.getGroup(getWorld().getName(), getName());
+ }
+ catch (Throwable ex)
+ {
+ return "default";
+ }
+ }
+
+ public boolean canBuild()
+ {
+ try
+ {
+ return com.nijikokun.bukkit.Permissions.Permissions.Security.canGroupBuild(getWorld().getName(), getGroup());
+ }
+ catch (Throwable ex)
+ {
+ return true;
+ }
+ }
+
+ public EntityPlayer getHandle()
+ {
+ return (EntityPlayer)getCraftPlayer().getHandle();
+ }
+
+ public CraftPlayer getCraftPlayer()
+ {
+ return (CraftPlayer)base;
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/PlayerWrapper.java b/Essentials/src/com/earth2me/essentials/PlayerWrapper.java
new file mode 100644
index 000000000..cf3a6db58
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/PlayerWrapper.java
@@ -0,0 +1,335 @@
+package com.earth2me.essentials;
+
+import java.net.InetSocketAddress;
+import java.util.*;
+import org.bukkit.*;
+import org.bukkit.block.Block;
+import org.bukkit.entity.*;
+import org.bukkit.inventory.*;
+import org.bukkit.util.Vector;
+
+public class PlayerWrapper implements Player
+{
+ protected Player base;
+
+ public PlayerWrapper(Player base)
+ {
+ this.base = base;
+ }
+
+ public final Player getBase()
+ {
+ return base;
+ }
+
+ public final Player setBase(Player base)
+ {
+ return this.base = base;
+ }
+
+ @Override
+ public void setDisplayName(String string)
+ {
+ base.setDisplayName(string);
+ }
+
+ @Override
+ public void setCompassTarget(Location lctn)
+ {
+ base.setCompassTarget(lctn);
+ }
+
+ @Override
+ public InetSocketAddress getAddress()
+ {
+ return base.getAddress();
+ }
+
+ @Override
+ public void kickPlayer(String string)
+ {
+ base.kickPlayer(string);
+ }
+
+ @Override
+ public String getName()
+ {
+ return base.getName();
+ }
+
+ @Override
+ public PlayerInventory getInventory()
+ {
+ return base.getInventory();
+ }
+
+ @Override
+ public ItemStack getItemInHand()
+ {
+ return base.getItemInHand();
+ }
+
+ @Override
+ public void setItemInHand(ItemStack is)
+ {
+ base.setItemInHand(is);
+ }
+
+ @Override
+ public int getHealth()
+ {
+ return base.getHealth();
+ }
+
+ @Override
+ public void setHealth(int i)
+ {
+ base.setHealth(i);
+ }
+
+ @Override
+ public Egg throwEgg()
+ {
+ return base.throwEgg();
+ }
+
+ @Override
+ public Snowball throwSnowball()
+ {
+ return base.throwSnowball();
+ }
+
+ @Override
+ public Arrow shootArrow()
+ {
+ return base.shootArrow();
+ }
+
+ @Override
+ public boolean isInsideVehicle()
+ {
+ return base.isInsideVehicle();
+ }
+
+ @Override
+ public boolean leaveVehicle()
+ {
+ return base.leaveVehicle();
+ }
+
+ @Override
+ public Vehicle getVehicle()
+ {
+ return base.getVehicle();
+ }
+
+ @Override
+ public Location getLocation()
+ {
+ return base.getLocation();
+ }
+
+ @Override
+ public World getWorld()
+ {
+ return base.getWorld();
+ }
+
+ @Override
+ public Server getServer()
+ {
+ return base.getServer();
+ }
+
+ @Override
+ public boolean isOnline()
+ {
+ return base.isOnline();
+ }
+
+ @Override
+ public boolean isOp()
+ {
+ return base.isOp();
+ }
+
+ @Override
+ public void teleportTo(Location lctn)
+ {
+ base.teleportTo(lctn);
+ }
+
+ @Override
+ public void teleportTo(Entity entity)
+ {
+ base.teleportTo(entity);
+ }
+
+ @Override
+ public void sendMessage(String string)
+ {
+ base.sendMessage(string);
+ }
+
+ @Override
+ public void setVelocity(Vector vector)
+ {
+ base.setVelocity(vector);
+ }
+
+ @Override
+ public Vector getVelocity()
+ {
+ return base.getVelocity();
+ }
+
+ @Override
+ public double getEyeHeight()
+ {
+ return base.getEyeHeight();
+ }
+
+ @Override
+ public double getEyeHeight(boolean bln)
+ {
+ return base.getEyeHeight(bln);
+ }
+
+ @Override
+ public List getLineOfSight(HashSet hs, int i)
+ {
+ return base.getLineOfSight(hs, i);
+ }
+
+ @Override
+ public Block getTargetBlock(HashSet hs, int i)
+ {
+ return base.getTargetBlock(hs, i);
+ }
+
+ @Override
+ public List getLastTwoTargetBlocks(HashSet hs, int i)
+ {
+ return base.getLastTwoTargetBlocks(hs, i);
+ }
+
+ @Override
+ public int getFireTicks()
+ {
+ return base.getFireTicks();
+ }
+
+ @Override
+ public int getMaxFireTicks()
+ {
+ return base.getMaxFireTicks();
+ }
+
+ @Override
+ public void setFireTicks(int i)
+ {
+ base.setFireTicks(i);
+ }
+
+ @Override
+ public void remove()
+ {
+ base.remove();
+ }
+
+ /**
+ * This is not deprecated because the underlying method isn't really deprecated; rather, it's just "imperfect". By
+ * We will continue to use this method even after the underlying CraftBukkit method is changed, so do not deprecate
+ * it. Chances are Bukkit will also choose to un-deprecate this method at some point.
+ */
+ @Override
+ public void updateInventory()
+ {
+ base.updateInventory();
+ }
+
+ @Override
+ public void chat(String string)
+ {
+ base.chat(string);
+ }
+
+ @Override
+ public boolean isSneaking()
+ {
+ return base.isSneaking();
+ }
+
+ @Override
+ public void setSneaking(boolean bln)
+ {
+ base.setSneaking(bln);
+ }
+
+ @Override
+ public int getEntityId()
+ {
+ return base.getEntityId();
+ }
+
+ @Override
+ public boolean performCommand(String string)
+ {
+ return base.performCommand(string);
+ }
+
+ @Override
+ public int getRemainingAir()
+ {
+ return base.getRemainingAir();
+ }
+
+ @Override
+ public void setRemainingAir(int i)
+ {
+ base.setRemainingAir(i);
+ }
+
+ @Override
+ public int getMaximumAir()
+ {
+ return base.getMaximumAir();
+ }
+
+ @Override
+ public void setMaximumAir(int i)
+ {
+ base.setMaximumAir(i);
+ }
+
+ @Override
+ public String getDisplayName()
+ {
+ if (base.getDisplayName() != null)
+ return base.getDisplayName();
+ else
+ return base.getName();
+ }
+
+ @Override
+ public void damage(int i)
+ {
+ base.damage(i);
+ }
+
+ @Override
+ public void damage(int i, Entity entity)
+ {
+ base.damage(i, entity);
+ }
+
+ @Override
+ public Location getEyeLocation()
+ {
+ return base.getEyeLocation();
+ }
+
+ public void sendRawMessage(String string) {
+ base.sendRawMessage(string);
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/Settings.java b/Essentials/src/com/earth2me/essentials/Settings.java
new file mode 100644
index 000000000..9c774b848
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/Settings.java
@@ -0,0 +1,348 @@
+package com.earth2me.essentials;
+
+import java.util.*;
+import org.bukkit.ChatColor;
+import com.earth2me.essentials.commands.IEssentialsCommand;
+import java.io.File;
+import java.util.ArrayList;
+import org.bukkit.entity.CreatureType;
+
+
+public class Settings implements IConf
+{
+ private EssentialsConf config;
+
+ public Settings(File dataFolder)
+ {
+ config = new EssentialsConf(new File(dataFolder, "config.yml"));
+ config.setTemplateName("/config.yml");
+ config.load();
+ }
+
+ public boolean getRespawnAtHome()
+ {
+ return config.getBoolean("respawn-at-home", false);
+ }
+
+ public boolean getBedSetsHome()
+ {
+ return config.getBoolean("bed-sethome", false);
+ }
+
+ public int getChatRadius()
+ {
+ return config.getInt("chat.radius", config.getInt("chat-radius", 0));
+ }
+
+ public long getTeleportDelay()
+ {
+ return config.getInt("teleport-delay", 0) * 1000L;
+ }
+
+ public int getDefaultStackSize()
+ {
+ return config.getInt("default-stack-size", 64);
+ }
+
+ public int getStartingBalance()
+ {
+ return config.getInt("starting-balance", 0);
+ }
+
+ public boolean getNetherPortalsEnabled()
+ {
+ return isNetherEnabled() && config.getBoolean("nether.portals-enabled", false);
+ }
+
+ public String getMcslKey()
+ {
+ return config.getString("mcsl-key", "").replaceAll("[^a-zA-Z0-9]", "");
+ }
+
+ public boolean getWhitelistEnabled()
+ {
+ return false;
+ }
+
+ public boolean isCommandDisabled(IEssentialsCommand cmd)
+ {
+ return isCommandDisabled(cmd.getName());
+ }
+
+ public boolean isCommandDisabled(String label)
+ {
+ for (String c : config.getStringList("disabled-commands", new ArrayList(0)))
+ {
+ if (!c.equalsIgnoreCase(label)) continue;
+ return true;
+ }
+ return config.getBoolean("disable-" + label.toLowerCase(), false);
+ }
+
+ public boolean isCommandRestricted(IEssentialsCommand cmd)
+ {
+ return isCommandRestricted(cmd.getName());
+ }
+
+ public boolean isCommandRestricted(String label)
+ {
+ for (String c : config.getStringList("restricted-commands", new ArrayList(0)))
+ {
+ if (!c.equalsIgnoreCase(label)) continue;
+ return true;
+ }
+ return config.getBoolean("restrict-" + label.toLowerCase(), false);
+ }
+
+ public int getCommandCost(IEssentialsCommand cmd)
+ {
+ return getCommandCost(cmd.getName());
+ }
+
+ public int getCommandCost(String label)
+ {
+ int cost = config.getInt("command-costs." + label, 0);
+ if (cost == 0)
+ cost = config.getInt("cost-" + label, 0);
+ return cost;
+ }
+
+ public String getCommandPrefix()
+ {
+ return config.getString("command-prefix", "");
+ }
+
+ public String getNicknamePrefix()
+ {
+ return config.getString("nickname-prefix", "");
+ }
+
+ public long getTeleportCooldown()
+ {
+ return (long)config.getInt("teleport-cooldown", 60) * 1000L;
+ }
+
+ public long getHealCooldown()
+ {
+ return (long)config.getInt("heal-cooldown", 60) * 1000L;
+ }
+
+ public Object getKit(String name)
+ {
+ Map kits = (Map)config.getProperty("kits");
+ return kits.get(name.replace('.', '_').replace('/', '_'));
+ }
+
+ public ChatColor getOperatorColor()
+ {
+ String colorName = config.getString("ops-name-color", null);
+
+ if (colorName == null)
+ return ChatColor.RED;
+
+ try
+ {
+ return ChatColor.valueOf(colorName.toUpperCase());
+ }
+ catch (IllegalArgumentException ex)
+ {
+ }
+
+ return ChatColor.getByCode(Integer.parseInt(colorName, 16));
+ }
+
+ public boolean getReclaimSetting()
+ {
+ return config.getBoolean("reclaim-onlogout", true);
+ }
+
+ public String getNetherName()
+ {
+ return config.getString("nether.folder", "nether");
+ }
+
+ public boolean isNetherEnabled()
+ {
+ return config.getBoolean("nether.enabled", true);
+ }
+
+ public int getSpawnMobLimit()
+ {
+ return config.getInt("spawnmob-limit", 10);
+ }
+
+ public boolean showNonEssCommandsInHelp()
+ {
+ return config.getBoolean("non-ess-in-help", true);
+ }
+
+ public HashMap getEpSettings()
+ {
+ HashMap epSettings = new HashMap();
+
+ epSettings.put("protect.protect.signs", config.getBoolean("protect.protect.signs", true));
+ epSettings.put("protect.protect.rails", config.getBoolean("protect.protect.rails", true));
+ epSettings.put("protect.protect.block-below", config.getBoolean("protect.protect.block-below", true));
+ epSettings.put("protect.protect.prevent-block-on-rails", config.getBoolean("protect.protect.prevent-block-on-rails", false));
+ return epSettings;
+ }
+
+ public HashMap getEpDBSettings()
+ {
+ HashMap epSettings = new HashMap();
+ epSettings.put("protect.datatype", config.getString("protect.datatype", "sqlite"));
+ epSettings.put("protect.username", config.getString("protect.username", "root"));
+ epSettings.put("protect.password", config.getString("protect.password", "root"));
+ epSettings.put("protect.mysqlDb", config.getString("protect.mysqlDb", "jdbc:mysql://localhost:3306/minecraft"));
+ return epSettings;
+ }
+
+ public ArrayList getEpAlertOnPlacement()
+ {
+ ArrayList epAlertPlace = new ArrayList();
+ epAlertPlace.addAll(Arrays.asList(config.getString("protect.alert.on-placement", "").split(",")));
+ return epAlertPlace;
+ }
+
+ public ArrayList getEpAlertOnUse()
+ {
+ ArrayList epAlertUse = new ArrayList();
+ epAlertUse.addAll(Arrays.asList(config.getString("protect.alert.on-use", "").split(",")));
+ return epAlertUse;
+ }
+
+ public ArrayList getEpAlertOnBreak()
+ {
+ ArrayList epAlertPlace = new ArrayList();
+ epAlertPlace.addAll(Arrays.asList(config.getString("protect.alert.on-break", "").split(",")));
+ return epAlertPlace;
+ }
+
+ public ArrayList epBlackListPlacement()
+ {
+ ArrayList epBlack = new ArrayList();
+ epBlack.addAll(Arrays.asList(config.getString("protect.blacklist.placement", "").split(",")));
+ return epBlack;
+ }
+
+ public ArrayList epBlackListUsage()
+ {
+ ArrayList epBlack = new ArrayList();
+ epBlack.addAll(Arrays.asList(config.getString("protect.blacklist.usage", "").split(",")));
+ return epBlack;
+ }
+
+ public HashMap getEpGuardSettings()
+ {
+ HashMap epSettings = new HashMap();
+ epSettings.put("protect.prevent.lava-flow", config.getBoolean("protect.prevent.lava-flow", false));
+ epSettings.put("protect.prevent.water-flow", config.getBoolean("protect.prevent.water-flow", false));
+ epSettings.put("protect.prevent.water-bucket-flow", config.getBoolean("protect.prevent.water-bucket-flow", false));
+ epSettings.put("protect.prevent.fire-spread", config.getBoolean("protect.prevent.fire-spread", false));
+ epSettings.put("protect.prevent.flint-fire", config.getBoolean("protect.prevent.flint-fire", false));
+ epSettings.put("protect.prevent.lava-fire-spread", config.getBoolean("protect.prevent.lava-fire-spread", false));
+ epSettings.put("protect.prevent.tnt-explosion", config.getBoolean("protect.prevent.tnt-explosion", false));
+ epSettings.put("protect.prevent.creeper-explosion", config.getBoolean("protect.prevent.creeper-explosion", false));
+ epSettings.put("protect.prevent.creeper-playerdamage", config.getBoolean("protect.prevent.creeper-playerdamage", false));
+ epSettings.put("protect.prevent.creeper-blockdamage", config.getBoolean("protect.prevent.creeper-blockdamage", false));
+ for (CreatureType ct : CreatureType.values()) {
+ String name = ct.toString().toLowerCase();
+ epSettings.put("protect.prevent.spawn."+name, config.getBoolean("protect.prevent.spawn."+name, false));
+ }
+ return epSettings;
+ }
+
+ public HashMap getEpPlayerSettings()
+ {
+ HashMap epPlayerSettings = new HashMap();
+ epPlayerSettings.put("protect.disable.fall", config.getBoolean("protect.disable.fall", false));
+ epPlayerSettings.put("protect.disable.pvp", config.getBoolean("protect.disable.pvp", false));
+ epPlayerSettings.put("protect.disable.drown", config.getBoolean("protect.disable.drown", false));
+ epPlayerSettings.put("protect.disable.suffocate", config.getBoolean("protect.disable.suffocate", false));
+ epPlayerSettings.put("protect.disable.lavadmg", config.getBoolean("protect.disable.lavadmg", false));
+ epPlayerSettings.put("protect.disable.projectiles", config.getBoolean("protect.disable.projectiles", false));
+ epPlayerSettings.put("protect.disable.contactdmg", config.getBoolean("protect.disable.contactdmg", false));
+ epPlayerSettings.put("protect.disable.firedmg", config.getBoolean("protect.disable.firedmg", false));
+ epPlayerSettings.put("protect.disable.build", config.getBoolean("protect.disable.build", false));
+ return epPlayerSettings;
+
+ }
+
+ public int getEpCreeperMaxHeight()
+ {
+ return config.getInt("protect.creeper.max-height", -1);
+ }
+
+ public boolean areSignsDisabled()
+ {
+ return config.getBoolean("signs-disabled", false);
+ }
+
+ public long getBackupInterval()
+ {
+ return config.getInt("backup.interval", 1440); // 1440 = 24 * 60
+ }
+
+ public String getBackupCommand()
+ {
+ return config.getString("backup.command", null);
+ }
+
+ public String getChatFormat(String group)
+ {
+ return config.getString("chat.group-formats." + (group == null ? "Default" : group),
+ config.getString("chat.format", "&7[{GROUP}]&f {DISPLAYNAME}&7:&f {MESSAGE}"));
+ }
+
+ public boolean getGenerateExitPortals()
+ {
+ return config.getBoolean("nether.generate-exit-portals", true);
+ }
+
+ public boolean getAnnounceNewPlayers()
+ {
+ return !config.getString("newbies.announce-format", "-").isEmpty();
+ }
+
+ public String getAnnounceNewPlayerFormat(User user)
+ {
+ return format(config.getString("newbies.announce-format", "&dWelcome {DISPLAYNAME} to the server!"), user);
+ }
+
+ public String format(String format, User user)
+ {
+ return format.replace('&', '§').replace("§§", "&").replace("{PLAYER}", user.getDisplayName()).replace("{DISPLAYNAME}", user.getDisplayName()).replace("{GROUP}", user.getGroup()).replace("{USERNAME}", user.getName()).replace("{ADDRESS}", user.getAddress().toString());
+ }
+
+ public String getNewbieSpawn()
+ {
+ return config.getString("newbies.spawnpoint", "default");
+ }
+ public boolean getPerWarpPermission()
+ {
+ return config.getBoolean("per-warp-permission", false);
+ }
+
+ public boolean getSortListByGroups()
+ {
+ return config.getBoolean("sort-list-by-groups", true);
+ }
+
+ public void reloadConfig() {
+ config.load();
+ }
+
+ public ArrayList itemSpawnBlacklist()
+ {
+ ArrayList epItemSpwn = new ArrayList();
+ epItemSpwn.addAll(Arrays.asList(config.getString("item-spawn-blacklist", "").split(",")));
+ return epItemSpwn;
+ }
+
+ public ArrayList epBlockBreakingBlacklist()
+ {
+ ArrayList epBreakList = new ArrayList();
+ epBreakList.addAll(Arrays.asList(config.getString("protect.blacklist.break", "").split(",")));
+ return epBreakList;
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/Spawn.java b/Essentials/src/com/earth2me/essentials/Spawn.java
new file mode 100644
index 000000000..f3c4de06a
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/Spawn.java
@@ -0,0 +1,87 @@
+package com.earth2me.essentials;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+import org.bukkit.Location;
+import org.bukkit.Server;
+import org.bukkit.World;
+import org.bukkit.World.Environment;
+
+public class Spawn implements IConf {
+
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private EssentialsConf config;
+ private Server server;
+
+ public Spawn(Server server, File dataFolder) {
+ File configFile = new File(dataFolder, "spawn.yml");
+ this.server = server;
+ config = new EssentialsConf(configFile);
+ config.load();
+ }
+
+ public void setSpawn(Location loc, String group) {
+ Map map = new HashMap();
+ map.put("world", loc.getWorld().getName());
+ map.put("x", loc.getX());
+ map.put("y", loc.getY());
+ map.put("z", loc.getZ());
+ map.put("yaw", loc.getYaw());
+ map.put("pitch", loc.getPitch());
+ config.setProperty(group, map);
+ config.save();
+
+ if ("default".equals(group)) {
+ loc.getWorld().setSpawnLocation(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
+ }
+ }
+
+ public Location getSpawn(String group) {
+ if (config.getProperty(group) == null) {
+ group = "default";
+ }
+ if (config.getProperty(group) == null) {
+ for (World w : server.getWorlds()) {
+ if (w.getEnvironment() != Environment.NORMAL) {
+ continue;
+ }
+ return w.getSpawnLocation();
+ }
+ }
+ String worldId = config.getString(group + ".world", "");
+ World world = server.getWorlds().get(server.getWorlds().size() > 1 ? 1 : 0);
+ for (World w : server.getWorlds()) {
+ if (w.getEnvironment() != Environment.NORMAL) {
+ continue;
+ }
+ world = w;
+ break;
+ }
+ for (World w : server.getWorlds()) {
+ if (!w.getName().equals(worldId)) {
+ continue;
+ }
+ world = w;
+ break;
+ }
+
+ double x = config.getDouble(group + ".x", config.getDouble("default.x", 0));
+ double y = config.getDouble(group + ".y", config.getDouble("default.y", 0));
+ double z = config.getDouble(group + ".z", config.getDouble("default.z", 0));
+ float yaw = (float) config.getDouble(group + ".yaw", config.getDouble("default.yaw", 0));
+ float pitch = (float) config.getDouble(group + ".pitch", config.getDouble("default.pitch", 0));
+ Location retval = new Location(world, x, y, z, yaw, pitch);
+
+ if (y < 1) {
+ retval.setY(world.getHighestBlockYAt(retval));
+ }
+
+ return retval;
+ }
+
+ public void reloadConfig() {
+ config.load();
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/TargetBlock.java b/Essentials/src/com/earth2me/essentials/TargetBlock.java
new file mode 100644
index 000000000..d3ac30d2d
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/TargetBlock.java
@@ -0,0 +1,599 @@
+package com.earth2me.essentials;
+
+import java.util.ArrayList;
+import org.bukkit.block.Block;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+/**
+ * @author toi
+ * Thanks to Raphfrk for optimization of this class.
+ */
+public class TargetBlock {
+
+ private Location loc;
+ private double viewHeight;
+ private int maxDistance;
+ private int[] blockToIgnore;
+ private double checkDistance, curDistance;
+ private double xRotation, yRotation;
+ private Vector targetPos = new Vector();
+ private Vector targetPosDouble = new Vector();
+ private Vector prevPos = new Vector();
+ private Vector offset = new Vector();
+
+ /**
+ * Constructor requiring a player, uses default values
+ *
+ * @param player Player to work with
+ */
+ public TargetBlock(Player player)
+ {
+ this.setValues(player.getLocation(), 300, 1.65, 0.2, null);
+ }
+
+ /**
+ * Constructor requiring a location, uses default values
+ *
+ * @param loc Location to work with
+ */
+ public TargetBlock(Location loc)
+ {
+ this.setValues(loc, 300, 0, 0.2, null);
+ }
+
+ /**
+ * Constructor requiring a player, max distance and a checking distance
+ *
+ * @param player Player to work with
+ * @param maxDistance How far it checks for blocks
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ */
+ public TargetBlock(Player player, int maxDistance, double checkDistance)
+ {
+ this.setValues(player.getLocation(), maxDistance, 1.65, checkDistance, null);
+ }
+
+ /**
+ * Constructor requiring a location, max distance and a checking distance
+ *
+ * @param loc What location to work with
+ * @param maxDistance How far it checks for blocks
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ */
+ public TargetBlock(Location loc, int maxDistance, double checkDistance) {
+ this.setValues(loc, maxDistance, 0, checkDistance, null);
+ }
+
+ /**
+ * Constructor requiring a player, max distance, checking distance and an array of blocks to ignore
+ *
+ * @param player What player to work with
+ * @param maxDistance How far it checks for blocks
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ * @param blocksToIgnore Integer array of what block ids to ignore while checking for viable targets
+ */
+ public TargetBlock (Player player, int maxDistance, double checkDistance, int[] blocksToIgnore)
+ {
+ this.setValues(player.getLocation(), maxDistance, 1.65, checkDistance, blocksToIgnore);
+ }
+
+ /**
+ * Constructor requiring a location, max distance, checking distance and an array of blocks to ignore
+ *
+ * @param loc What location to work with
+ * @param maxDistance How far it checks for blocks
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ * @param blocksToIgnore Array of what block ids to ignore while checking for viable targets
+ */
+ public TargetBlock (Location loc, int maxDistance, double checkDistance, int[] blocksToIgnore)
+ {
+ this.setValues(loc, maxDistance, 0, checkDistance, blocksToIgnore);
+ }
+
+ /**
+ * Constructor requiring a player, max distance, checking distance and an array of blocks to ignore
+ *
+ * @param player What player to work with
+ * @param maxDistance How far it checks for blocks
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ * @param blocksToIgnore String ArrayList of what block ids to ignore while checking for viable targets
+ */
+ public TargetBlock (Player player, int maxDistance, double checkDistance, ArrayList blocksToIgnore)
+ {
+ int[] bti = this.convertStringArraytoIntArray(blocksToIgnore);
+ this.setValues(player.getLocation(), maxDistance, 1.65, checkDistance, bti);
+ }
+
+ /**
+ * Constructor requiring a location, max distance, checking distance and an array of blocks to ignore
+ *
+ * @param loc What location to work with
+ * @param maxDistance How far it checks for blocks
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ * @param blocksToIgnore String ArrayList of what block ids to ignore while checking for viable targets
+ */
+ public TargetBlock (Location loc, int maxDistance, double checkDistance, ArrayList blocksToIgnore)
+ {
+ int[] bti = this.convertStringArraytoIntArray(blocksToIgnore);
+ this.setValues(loc, maxDistance, 0, checkDistance, bti);
+ }
+
+ /**
+ * Set the values, all constructors uses this function
+ *
+ * @param loc Location of the view
+ * @param maxDistance How far it checks for blocks
+ * @param viewPos Where the view is positioned in y-axis
+ * @param checkDistance How often to check for blocks, the smaller the more precise
+ * @param blocksToIgnore Ids of blocks to ignore while checking for viable targets
+ */
+ private void setValues(Location loc, int maxDistance, double viewHeight, double checkDistance, int[] blocksToIgnore)
+ {
+ this.loc = loc;
+ this.maxDistance = maxDistance;
+ this.viewHeight = viewHeight;
+ this.checkDistance = checkDistance;
+ this.blockToIgnore = blocksToIgnore;
+ this.curDistance = 0;
+ xRotation = (loc.getYaw() + 90) % 360;
+ yRotation = loc.getPitch() * -1;
+
+ double h = (checkDistance * Math.cos(Math.toRadians(yRotation)));
+ offset.setY((checkDistance * Math.sin(Math.toRadians(yRotation))));
+ offset.setX((h * Math.cos(Math.toRadians(xRotation))));
+ offset.setZ((h * Math.sin(Math.toRadians(xRotation))));
+
+ targetPosDouble = new Vector(loc.getX(), loc.getY() + viewHeight, loc.getZ());
+ targetPos = new Vector( targetPosDouble.getBlockX(), targetPosDouble.getBlockY(), targetPosDouble.getBlockZ());
+ prevPos = targetPos.clone();
+ }
+
+ /**
+ * Call this to reset checking position to allow you to check for a new target with the same TargetBlock instance.
+ */
+ public void reset()
+ {
+ targetPosDouble = new Vector(loc.getX(), loc.getY() + viewHeight, loc.getZ());
+ targetPos = new Vector( targetPosDouble.getBlockX(), targetPosDouble.getBlockY(), targetPosDouble.getBlockZ());
+ prevPos = targetPos.clone();
+ this.curDistance = 0;
+ }
+
+ /**
+ * Gets the distance to a block. Measures from the block underneath the player to the targetblock
+ * Should only be used when passing player as an constructor parameter
+ *
+ * @return double
+ */
+ public double getDistanceToBlock()
+ {
+ Vector blockUnderPlayer = new Vector(
+ (int) Math.floor(loc.getX() + 0.5),
+ (int) Math.floor(loc.getY() - 0.5),
+ (int) Math.floor(loc.getZ() + 0.5));
+
+ Block blk = getTargetBlock();
+ double x = blk.getX() - blockUnderPlayer.getBlockX();
+ double y = blk.getY() - blockUnderPlayer.getBlockY();
+ double z = blk.getZ() - blockUnderPlayer.getBlockZ();
+
+ return Math.sqrt((Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)));
+ }
+
+ /**
+ * Gets the rounded distance to a block. Measures from the block underneath the player to the targetblock
+ * Should only be used when passing player as an constructor parameter
+ *
+ * @return int
+ */
+ public int getDistanceToBlockRounded()
+ {
+ Vector blockUnderPlayer = new Vector(
+ (int) Math.floor(loc.getX() + 0.5),
+ (int) Math.floor(loc.getY() - 0.5),
+ (int) Math.floor(loc.getZ() + 0.5));
+
+ Block blk = getTargetBlock();
+ double x = blk.getX() - blockUnderPlayer.getBlockX();
+ double y = blk.getY() - blockUnderPlayer.getBlockY();
+ double z = blk.getZ() - blockUnderPlayer.getBlockZ();
+
+ return (int) Math.round((Math.sqrt((Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)))));
+ }
+
+ /**
+ * Gets the floored x distance to a block.
+ *
+ * @return int
+ */
+ public int getXDistanceToBlock()
+ {
+ this.reset();
+ return (int) Math.floor(getTargetBlock().getX() - loc.getBlockX() + 0.5);
+ }
+
+ /**
+ * Gets the floored y distance to a block
+ *
+ * @return int
+ */
+ public int getYDistanceToBlock()
+ {
+ this.reset();
+ return (int) Math.floor(getTargetBlock().getY() - loc.getBlockY() + viewHeight);
+ }
+
+ /**
+ * Gets the floored z distance to a block
+ *
+ * @return int
+ */
+ public int getZDistanceToBlock()
+ {
+ this.reset();
+ return (int) Math.floor(getTargetBlock().getZ() - loc.getBlockZ() + 0.5);
+ }
+
+ /**
+ * Returns the block at the sight. Returns null if out of range or if no viable target was found
+ *
+ * @return Block
+ */
+ @SuppressWarnings("empty-statement")
+ public Block getTargetBlock()
+ {
+ this.reset();
+ while ((getNextBlock() != null) && ((getCurrentBlock().getTypeId() == 0) || this.blockToIgnoreHasValue(getCurrentBlock().getTypeId())));
+ return getCurrentBlock();
+ }
+
+ /**
+ * Sets the type of the block at the sight. Returns false if the block wasn't set.
+ *
+ * @param typeID ID of type to set the block to
+ * @return boolean
+ */
+ @SuppressWarnings("empty-statement")
+ public boolean setTargetBlock(int typeID)
+ {
+ if (Material.getMaterial(typeID) != null)
+ {
+ this.reset();
+ while (getNextBlock() != null && getCurrentBlock().getTypeId() == 0);
+ if (getCurrentBlock() != null)
+ {
+ Block blk = loc.getWorld().getBlockAt(targetPos.getBlockX(), targetPos.getBlockY(), targetPos.getBlockZ());
+ blk.setTypeId(typeID);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets the type of the block at the sight. Returns false if the block wasn't set.
+ *
+ * @param type Material to set the block to
+ * @return boolean
+ */
+ @SuppressWarnings("empty-statement")
+ public boolean setTargetBlock(Material type)
+ {
+ this.reset();
+ while ((getNextBlock() != null) && ((getCurrentBlock().getTypeId() == 0) || this.blockToIgnoreHasValue(getCurrentBlock().getTypeId())));
+ if (getCurrentBlock() != null)
+ {
+ Block blk = loc.getWorld().getBlockAt(targetPos.getBlockX(), targetPos.getBlockY(), targetPos.getBlockZ());
+ blk.setType(type);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the type of the block at the sight. Returns false if the block wasn't set.
+ * Observe! At the moment this function is using the built-in enumerator function .valueOf(String) but would preferably be changed to smarter function, when implemented
+ *
+ * @param type Name of type to set the block to
+ * @return boolean
+ */
+ @SuppressWarnings("empty-statement")
+ public boolean setTargetBlock(String type)
+ {
+ Material mat = Material.valueOf(type);
+ if (mat != null)
+ {
+ this.reset();
+ while ((getNextBlock() != null) && ((getCurrentBlock().getTypeId() == 0) || this.blockToIgnoreHasValue(getCurrentBlock().getTypeId())));
+ if (getCurrentBlock() != null)
+ {
+ Block blk = loc.getWorld().getBlockAt(targetPos.getBlockX(), targetPos.getBlockY(), targetPos.getBlockZ());
+ blk.setType(mat);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the block attached to the face at the sight. Returns null if out of range or if no viable target was found
+ *
+ * @return Block
+ */
+ @SuppressWarnings("empty-statement")
+ public Block getFaceBlock()
+ {
+ while ((getNextBlock() != null) && ((getCurrentBlock().getTypeId() == 0) || this.blockToIgnoreHasValue(getCurrentBlock().getTypeId())));
+ if (getCurrentBlock() != null)
+ {
+ return getPreviousBlock();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the type of the block attached to the face at the sight. Returns false if the block wasn't set.
+ *
+ * @param typeID
+ * @return boolean
+ */
+ public boolean setFaceBlock(int typeID)
+ {
+ if (Material.getMaterial(typeID) != null)
+ {
+ if (getCurrentBlock() != null)
+ {
+ Block blk = loc.getWorld().getBlockAt(prevPos.getBlockX(), prevPos.getBlockY(), prevPos.getBlockZ());
+ blk.setTypeId(typeID);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets the type of the block attached to the face at the sight. Returns false if the block wasn't set.
+ *
+ * @param type
+ * @return boolean
+ */
+ public boolean setFaceBlock(Material type)
+ {
+ if (getCurrentBlock() != null)
+ {
+ Block blk = loc.getWorld().getBlockAt(prevPos.getBlockX(), prevPos.getBlockY(), prevPos.getBlockZ());
+ blk.setType(type);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the type of the block attached to the face at the sight. Returns false if the block wasn't set.
+ * Observe! At the moment this function is using the built-in enumerator function .valueOf(String) but would preferably be changed to smarter function, when implemented
+ *
+ * @param type
+ * @return boolean
+ */
+ public boolean setFaceBlock(String type)
+ {
+ Material mat = Material.valueOf(type);
+ if (mat != null)
+ {
+ if (getCurrentBlock() != null)
+ {
+ Block blk = loc.getWorld().getBlockAt(prevPos.getBlockX(), prevPos.getBlockY(), prevPos.getBlockZ());
+ blk.setType(mat);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get next block
+ *
+ * @return Block
+ */
+ public Block getNextBlock()
+ {
+ prevPos = targetPos.clone();
+ do
+ {
+ curDistance += checkDistance;
+
+ targetPosDouble.setX(offset.getX() + targetPosDouble.getX());
+ targetPosDouble.setY(offset.getY() + targetPosDouble.getY());
+ targetPosDouble.setZ(offset.getZ() + targetPosDouble.getZ());
+ targetPos = new Vector( targetPosDouble.getBlockX(), targetPosDouble.getBlockY(), targetPosDouble.getBlockZ());
+ }
+ while (curDistance <= maxDistance && targetPos.getBlockX() == prevPos.getBlockX() && targetPos.getBlockY() == prevPos.getBlockY() && targetPos.getBlockZ() == prevPos.getBlockZ());
+ if (curDistance > maxDistance)
+ {
+ return null;
+ }
+
+ return this.loc.getWorld().getBlockAt(this.targetPos.getBlockX(), this.targetPos.getBlockY(), this.targetPos.getBlockZ());
+ }
+
+ /**
+ * Returns the current block along the line of vision
+ *
+ * @return Block
+ */
+ public Block getCurrentBlock()
+ {
+ if (curDistance > maxDistance)
+ {
+ return null;
+ }
+ else
+ {
+ return this.loc.getWorld().getBlockAt(this.targetPos.getBlockX(), this.targetPos.getBlockY(), this.targetPos.getBlockZ());
+ }
+ }
+
+ /**
+ * Sets current block type. Returns false if the block wasn't set.
+ *
+ * @param typeID
+ */
+ public boolean setCurrentBlock(int typeID)
+ {
+ if (Material.getMaterial(typeID) != null)
+ {
+ Block blk = getCurrentBlock();
+ if (blk != null)
+ {
+ blk.setTypeId(typeID);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets current block type. Returns false if the block wasn't set.
+ *
+ * @param type
+ */
+ public boolean setCurrentBlock(Material type)
+ {
+ Block blk = getCurrentBlock();
+ if (blk != null)
+ {
+ blk.setType(type);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets current block type. Returns false if the block wasn't set.
+ * Observe! At the moment this function is using the built-in enumerator function .valueOf(String) but would preferably be changed to smarter function, when implemented
+ *
+ * @param type
+ */
+ public boolean setCurrentBlock(String type)
+ {
+ Material mat = Material.valueOf(type);
+ if (mat != null)
+ {
+ Block blk = getCurrentBlock();
+ if (blk != null)
+ {
+ blk.setType(mat);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the previous block in the aimed path
+ *
+ * @return Block
+ */
+ public Block getPreviousBlock()
+ {
+ return this.loc.getWorld().getBlockAt(prevPos.getBlockX(), prevPos.getBlockY(), prevPos.getBlockZ());
+ }
+
+ /**
+ * Sets previous block type id. Returns false if the block wasn't set.
+ *
+ * @param typeID
+ */
+ public boolean setPreviousBlock(int typeID)
+ {
+ if (Material.getMaterial(typeID) != null)
+ {
+ Block blk = getPreviousBlock();
+ if (blk != null)
+ {
+ blk.setTypeId(typeID);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets previous block type id. Returns false if the block wasn't set.
+ *
+ * @param type
+ */
+ public boolean setPreviousBlock(Material type)
+ {
+ Block blk = getPreviousBlock();
+ if (blk != null)
+ {
+ blk.setType(type);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets previous block type id. Returns false if the block wasn't set.
+ * Observe! At the moment this function is using the built-in enumerator function .valueOf(String) but would preferably be changed to smarter function, when implemented
+ *
+ * @param type
+ */
+ public boolean setPreviousBlock(String type)
+ {
+ Material mat = Material.valueOf(type);
+ if (mat != null)
+ {
+ Block blk = getPreviousBlock();
+ if (blk != null)
+ {
+ blk.setType(mat);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private int[] convertStringArraytoIntArray(ArrayList array)
+ {
+ if (array != null)
+ {
+ int intarray[] = new int[array.size()];
+ for (int i = 0; i < array.size(); i++)
+ {
+ try
+ {
+ intarray[i] = Integer.parseInt(array.get(i));
+ }
+ catch (NumberFormatException nfe)
+ {
+ intarray[i] = 0;
+ }
+ }
+ return intarray;
+ }
+ return null;
+ }
+
+ private boolean blockToIgnoreHasValue(int value)
+ {
+ if (this.blockToIgnore != null)
+ {
+ if (this.blockToIgnore.length > 0)
+ {
+ for (int i : this.blockToIgnore)
+ {
+ if (i == value)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Essentials/src/com/earth2me/essentials/TeleportTimer.java b/Essentials/src/com/earth2me/essentials/TeleportTimer.java
new file mode 100644
index 000000000..11d65170f
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/TeleportTimer.java
@@ -0,0 +1,73 @@
+package com.earth2me.essentials;
+
+import java.util.TimerTask;
+import java.util.Calendar;
+
+
+public abstract class TeleportTimer implements Runnable
+{
+ private long started; // time this task was initiated
+ private long delay; // how long to delay the teleport
+ public User user; // the person doing the teleport
+ private int health;
+ // note that I initially stored a clone of the location for reference, but...
+ // when comparing locations, I got incorrect mismatches (rounding errors, looked like)
+ // so, the X/Y/Z values are stored instead and rounded off
+ private long initX;
+ private long initY;
+ private long initZ;
+
+ public TeleportTimer(User tUser, long tDelay)
+ {
+ this.started = Calendar.getInstance().getTimeInMillis();
+ this.delay = tDelay;
+ this.user = tUser;
+ this.health = user.getHealth();
+ this.initX = Math.round(user.getLocation().getX() * 10000);
+ this.initY = Math.round(user.getLocation().getY() * 10000);
+ this.initZ = Math.round(user.getLocation().getZ() * 10000);
+ }
+
+ // This function needs to be defined when creating a new TeleportTimer
+ // The actual teleport command by itself should be stuck in there, such as teleportToNow(loc)
+ public abstract void DoTeleport();
+
+ public abstract void DoCancel();
+
+ public void run()
+ {
+ if (user == null || !user.isOnline() || user.getLocation() == null)
+ {
+ DoCancel();
+ return;
+ }
+ if (Math.round(user.getLocation().getX() * 10000) != initX
+ || Math.round(user.getLocation().getY() * 10000) != initY
+ || Math.round(user.getLocation().getZ() * 10000) != initZ
+ || user.getHealth() < health)
+ { // user moved, cancel teleport
+ user.cancelTeleport(true);
+ return;
+ }
+
+ health = user.getHealth(); // in case user healed, then later gets injured
+
+ long now = Calendar.getInstance().getTimeInMillis();
+ if (now > started + delay)
+ {
+ try
+ {
+ user.teleportCooldown(false);
+ user.sendMessage("§7Teleportation commencing...");
+ this.DoTeleport();
+ return;
+ }
+ catch (Exception ex)
+ {
+ user.sendMessage("§cCooldown: " + ex.getMessage());
+ }
+ }
+ //else // uncomment for timing debug
+ // user.sendMessage("§7" + (started + delay - now));
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/User.java b/Essentials/src/com/earth2me/essentials/User.java
new file mode 100644
index 000000000..0853975ca
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/User.java
@@ -0,0 +1,693 @@
+package com.earth2me.essentials;
+
+import java.util.*;
+import java.util.logging.*;
+import java.io.*;
+import org.bukkit.*;
+import com.earth2me.essentials.commands.IEssentialsCommand;
+import net.minecraft.server.EntityHuman;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.entity.*;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.SafeConstructor;
+import org.yaml.snakeyaml.reader.UnicodeReader;
+
+
+public class User extends PlayerExtension implements Comparable
+{
+ private static final Logger logger = Logger.getLogger("Minecraft");
+ private final Yaml yaml = new Yaml(new SafeConstructor());
+ private boolean isLoaded = false;
+ private final File folder;
+ private Map data = new HashMap();
+ private static Map users = new HashMap();
+ private boolean teleEnabled = true;
+ private long lastTeleport = 0;
+ private long lastHeal = 0;
+ private boolean justPortaled = false;
+ //private TimerTask teleTimer = null;
+ private int teleTimer = -1;
+ public Location lastLocation = null;
+ private User replyTo = null;
+ private boolean isNew = false;
+ public String currentJail;
+ public CraftItemStack[] savedInventory;
+
+ private User(Player base)
+ {
+ super(base);
+ this.folder = new File((Essentials.getStatic() == null ? new File(".") : Essentials.getStatic().getDataFolder()), "userdata");
+
+ if (base instanceof EntityHuman)
+ {
+ this.lastLocation = getBase().getLocation();
+ }
+ load();
+ }
+
+ public static int size()
+ {
+ return users.size();
+ }
+
+ public static User get(T base)
+ {
+ if (base instanceof Player)
+ return get((Player)base);
+ return null;
+ }
+
+ public static User get(T base)
+ {
+ if (base == null)
+ return null;
+
+ if (base instanceof User)
+ return (User)base;
+
+ if (users.containsKey(base.getName()))
+ return users.get(base.getName()).update(base);
+
+ User u = new User(base);
+ users.put(u.getName(), u);
+ return u;
+ }
+
+ public static void charge(T base, IEssentialsCommand cmd) throws Exception
+ {
+ if (base instanceof Player)
+ User.get(base).charge(cmd);
+ }
+
+ public boolean isNew()
+ {
+ return isNew;
+ }
+
+ public void respawn(Spawn spawn) throws Exception
+ {
+ respawn(spawn, null);
+ }
+
+ public void respawn(Spawn spawn, final String chargeFor) throws Exception
+ {
+ teleportTo(getSafeDestination(spawn.getSpawn(getGroup())), chargeFor);
+ }
+
+ private User update(Player base)
+ {
+ setBase(base);
+ return this;
+ }
+
+ public boolean isAuthorized(IEssentialsCommand cmd)
+ {
+ return isAuthorized("essentials." + (cmd.getName().equals("r") ? "msg" : cmd.getName()));
+ }
+
+ public boolean isAuthorized(String node)
+ {
+ if (isOp())
+ return true;
+
+ if (isJailed())
+ return false;
+
+ try
+ {
+ return com.nijikokun.bukkit.Permissions.Permissions.Security.permission(base, node);
+ }
+ catch (Throwable ex)
+ {
+ String[] cmds = node.split("\\.", 2);
+ return !Essentials.getSettings().isCommandRestricted(cmds[cmds.length - 1]);
+ }
+ }
+
+ public boolean isTeleEnabled()
+ {
+ return teleEnabled;
+ }
+
+ public boolean toggleTeleEnabled()
+ {
+ return teleEnabled = !teleEnabled;
+ }
+
+ public void teleportCooldown(boolean justCheck) throws Exception
+ {
+ long now = Calendar.getInstance().getTimeInMillis();
+ long cooldown = Essentials.getSettings().getTeleportCooldown();
+ long left = lastTeleport + cooldown - now;
+ if (left > 0 && !isOp() && !isAuthorized("essentials.teleport.cooldown.bypass"))
+ throw new Exception("Time before next teleport: " + Essentials.FormatTime(left));
+ // if justCheck is set, don't update lastTeleport; we're just checking
+ if (!justCheck) lastTeleport = now;
+ }
+
+ public void teleportCooldown() throws Exception
+ {
+ teleportCooldown(true);
+ }
+
+ public void healCooldown() throws Exception
+ {
+ long now = Calendar.getInstance().getTimeInMillis();
+ long cooldown = Essentials.getSettings().getHealCooldown();
+ long left = lastHeal + cooldown - now;
+ if (left > 0 && !isOp() && !isAuthorized("essentials.heal.cooldown.bypass"))
+ throw new Exception("Time before next heal: " + Essentials.FormatTime(left));
+ lastHeal = now;
+ }
+
+ private void load()
+ {
+ if (isLoaded) return;
+ isLoaded = true;
+
+ data = Essentials.getData(this);
+
+ try
+ {
+ if (!folder.exists()) folder.mkdirs();
+ File file = new File(folder, getName() + ".yml");
+ if (!file.exists())
+ {
+ isNew = true;
+ file.createNewFile();
+ logger.info(getName() + " has logged in for the first time.");
+ }
+
+ FileInputStream rx = new FileInputStream(file);
+ Map userData = (Map)yaml.load(new UnicodeReader(rx));
+ if (userData != null) data.putAll(userData);
+ rx.close();
+ }
+ catch (Throwable ex)
+ {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ finally
+ {
+ if (data == null) data = new HashMap();
+ }
+ }
+
+ private void flush()
+ {
+ try
+ {
+ if (!folder.exists()) folder.mkdirs();
+ File file = new File(folder, getName() + ".yml");
+ if (!file.exists()) file.createNewFile();
+
+ FileWriter tx = new FileWriter(file);
+ tx.write(yaml.dump(data));
+ tx.flush();
+ tx.close();
+ }
+ catch (Throwable ex)
+ {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public boolean isGodModeEnabled()
+ {
+ load();
+ return data.containsKey("godmode") && (Boolean)data.get("godmode");
+ }
+
+ public boolean toggleGodMode()
+ {
+ boolean retval = !isGodModeEnabled();
+ data.put("godmode", retval);
+ flush();
+ return retval;
+ }
+
+ public boolean isMuted()
+ {
+ load();
+ return data.containsKey("muted") && (Boolean)data.get("muted");
+ }
+
+ public boolean toggleMuted()
+ {
+ boolean retval = !isMuted();
+ data.put("muted", retval);
+ flush();
+ return retval;
+ }
+
+ public boolean isJailed()
+ {
+ //load(); Do not load config everytime time!
+ return data.containsKey("jailed") && (Boolean)data.get("jailed");
+ }
+
+ public boolean toggleJailed()
+ {
+ boolean retval = !isJailed();
+ data.put("jailed", retval);
+ flush();
+ load();
+ return retval;
+ }
+
+ public double getMoney()
+ {
+ load();
+ if (data.containsKey("money"))
+ {
+ if (data.get("money") instanceof Integer)
+ return (double)((Integer)data.get("money"));
+ return (Double)data.get("money");
+ }
+
+ try
+ {
+ return com.nijiko.coelho.iConomy.iConomy.getBank().getAccount(getName()).getBalance();
+ }
+ catch (Throwable ex)
+ {
+ try
+ {
+ Map idata = Essentials.getData(this);
+ return (Integer)idata.get("money");
+ }
+ catch (Throwable ex2)
+ {
+ return Essentials.getSettings().getStartingBalance();
+ }
+ }
+ }
+
+ public void setMoney(double value)
+ {
+ try
+ {
+ com.nijiko.coelho.iConomy.iConomy.getBank().getAccount(getName()).setBalance(value);
+ }
+ catch (Throwable ex)
+ {
+ data.put("money", value);
+ flush();
+ }
+ }
+
+ public void giveMoney(double value)
+ {
+ if (value == 0) return;
+ setMoney(getMoney() + value);
+ sendMessage("§a$" + value + " has been added to your account.");
+ }
+
+ public void payUser(User reciever, int value) throws Exception
+ {
+ if (value == 0) return;
+ if (!canAfford(value))
+ {
+ throw new Exception("You do not have sufficient funds.");
+ }
+ else
+ {
+ setMoney(getMoney() - value);
+ reciever.setMoney(reciever.getMoney() + value);
+ sendMessage("§a$" + value + " has been sent to " + reciever.getDisplayName());
+ reciever.sendMessage("§a$" + value + " has been recieved from " + getDisplayName());
+ }
+ }
+
+ public void takeMoney(double value)
+ {
+ if (value == 0) return;
+ setMoney(getMoney() - value);
+ sendMessage("§c$" + value + " has been taken from your account.");
+ }
+
+ public void charge(String cmd) throws Exception
+ {
+ double mon = getMoney();
+ double cost = Essentials.getSettings().getCommandCost(cmd.startsWith("/") ? cmd.substring(1) : cmd);
+ if (mon < cost && !isOp())
+ throw new Exception("You do not have sufficient funds.");
+ takeMoney(cost);
+ }
+
+ public void canAfford(String cmd) throws Exception
+ {
+ double mon = getMoney();
+ double cost = Essentials.getSettings().getCommandCost(cmd.startsWith("/") ? cmd.substring(1) : cmd);
+ if (mon < cost && !isOp())
+ throw new Exception("You do not have sufficient funds.");
+ }
+
+ public boolean canAfford(double cost)
+ {
+ double mon = getMoney();
+ if (mon < cost && !isOp())
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ public void canAfford(IEssentialsCommand cmd) throws Exception
+ {
+ canAfford(cmd.getName());
+ }
+
+ public void cancelTeleport(boolean notifyUser)
+ {
+ if (teleTimer == -1) return;
+ try
+ {
+ getServer().getScheduler().cancelTask(teleTimer);
+ if (notifyUser) sendMessage("§cPending teleportation request cancelled.");
+ }
+ catch (Throwable ex)
+ {
+ }
+ finally
+ {
+ teleTimer = -1;
+ }
+ }
+
+ public void cancelTeleport()
+ {
+ cancelTeleport(false);
+ }
+
+ public void teleportTo(final Location loc, final String chargeFor)
+ {
+ final long delay = Essentials.getSettings().getTeleportDelay();
+
+ if (delay <= 0 || isOp() || isAuthorized("essentials.teleport.timer.bypass"))
+ {
+ try
+ {
+ if (chargeFor != null) charge(chargeFor);
+ teleportCooldown(false);
+ teleportToNow(loc);
+ }
+ catch (Throwable ex)
+ {
+ sendMessage("§cError: " + ex.getMessage());
+ }
+ return;
+ }
+
+ cancelTeleport();
+ sendMessage("§7Teleportation will commence in " + Essentials.FormatTime(delay) + ". Don't move.");
+ teleTimer = getServer().getScheduler().scheduleSyncRepeatingTask(Essentials.getStatic(), new TeleportTimer(this, delay)
+ {
+ public void DoTeleport()
+ {
+ try
+ {
+ if (chargeFor != null) charge(chargeFor);
+ teleportToNow(loc);
+ }
+ catch (Throwable ex)
+ {
+ sendMessage("§cError: " + ex.getMessage());
+ }
+ }
+
+ public void DoCancel()
+ {
+ cancelTeleport();
+ }
+ }, 10, 10);
+ }
+
+ @Override
+ public void teleportTo(final Location loc)
+ {
+ teleportTo(loc, null);
+ }
+
+ public void teleportTo(final Entity entity, final String chargeFor)
+ {
+ final long delay = Essentials.getSettings().getTeleportDelay();
+
+ if (delay <= 0 || isOp() || isAuthorized("essentials.teleport.timer.bypass"))
+ {
+ try
+ {
+ if (chargeFor != null) charge(chargeFor);
+ teleportCooldown(false);
+ teleportToNow(entity);
+ }
+ catch (Throwable ex)
+ {
+ sendMessage("§cError: " + ex.getMessage());
+ }
+ return;
+ }
+
+ cancelTeleport();
+ sendMessage("§7Teleportation will commence in " + Essentials.FormatTime(delay) + ". Don't move.");
+ teleTimer = getServer().getScheduler().scheduleSyncRepeatingTask(Essentials.getStatic(), new TeleportTimer(this, delay)
+ {
+ public void DoTeleport()
+ {
+ try
+ {
+ if (chargeFor != null) charge(chargeFor);
+ teleportToNow(entity);
+ }
+ catch (Throwable ex)
+ {
+ sendMessage("§cError: " + ex.getMessage());
+ }
+ }
+
+ public void DoCancel()
+ {
+ cancelTeleport();
+ }
+ }, 10, 10);
+ }
+
+ @Override
+ public void teleportTo(final Entity entity)
+ {
+ teleportTo(entity, null);
+ }
+
+ public Location getHome() throws Exception
+ {
+ if (data.containsKey("home"))
+ {
+ List