Compare commits

..

98 Commits
v3.2 ... v3.4

Author SHA1 Message Date
4daad76e74 600th Commit, WOO!
Incremented version to reflect latest changes
2013-12-17 15:18:11 +01:00
05884ae806 Case-sensitive Telnet login names 2013-12-17 15:16:32 +01:00
aa0fd34859 Append to log files
Set maximum of 1Gig
2013-12-15 23:12:30 +01:00
2c14773c9b Generate logs in /server.log like CraftBukkit did 2013-12-07 10:58:29 +01:00
695168ebfe Merge pull request #112 from Wilee999/pull1
Fixed developer login message
2013-12-07 01:08:29 -08:00
bbc1255963 Fixed developer login message. 2013-12-06 23:37:56 -08:00
34d15d4c96 Fixed a neophyte bug
Custom login messages would be the same for anyone who logs in after the player with the same rank
2013-12-03 20:50:20 +01:00
75bc17cd8f Merge pull request #109 from Wilee999/pull1
Modified ban messages
2013-12-03 07:42:28 -08:00
87f338194c Removed "for a while" 2013-12-03 07:41:43 -08:00
b5760afbad Fixed. 2013-12-03 07:35:47 -08:00
5cfaf8970d Fixed all deprecated methods 2013-12-03 16:21:58 +01:00
9a48ec04aa Fixed developers not having the correct prefix
batch format
2013-12-03 14:24:09 +01:00
24fca9af97 Woops 2013-12-03 14:13:36 +01:00
a9ef738602 Merged from master 2013-12-03 14:05:59 +01:00
27a04635a2 Migrated /list-, AdminChat- and Login message-colors to TFM_PlayerRank
Reverted colors due to popular request
2013-12-03 14:05:06 +01:00
0f58746525 Modified the 2 ban messages. 2013-12-02 15:43:42 -08:00
a8d4b5f582 Merge pull request #108 from Wilee999/pull1
Developer login message
2013-12-01 10:57:49 -08:00
d7f1de4cb7 oops 2013-12-01 10:39:43 -08:00
ddbb6228f1 Added dev login message. (try 2) 2013-12-01 10:38:13 -08:00
d4c3a4ad45 Woops 2013-12-01 19:02:30 +01:00
7140e4c8df Changed colors to match the forums 2013-12-01 18:54:50 +01:00
808e02f660 Fixed potential mass-kick
This would happen if an admin joins the game when the server is full
2013-12-01 18:21:43 +01:00
bed78248fb Fixed /list for 1.7
for some weird reason, that ChatColor.WHITE was causing issues
2013-12-01 17:32:29 +01:00
ee39e89093 Fixed possible NPE in getPrefix() 2013-12-01 15:22:19 +01:00
9405604efc Fix imports 2013-12-01 13:42:13 +01:00
73acb2448b Force-allow superadmins to log in
Commented and cleaned up handlePlayerLogin()
2013-12-01 13:33:39 +01:00
c63540129f Cleaned up /list 2013-12-01 13:00:02 +01:00
6ba96b427d Update to CraftBukkit 1.7 2013-12-01 12:13:39 +01:00
acd8373f81 Fixed NPE in /list 2013-12-01 11:55:50 +01:00
0c4c36b2bd Merge pull request #103 from Wilee999/master
Fixed my name
2013-11-30 11:59:50 -08:00
7ce052900e Rewrote ServiceChecker, fixed NPE there
Formatting
2013-11-30 20:44:08 +01:00
f8741b0d4f Noooo dartheh!!!!
omg how offenciv
2013-11-30 10:52:40 -08:00
6fca19fa41 Load plugin version through plugin.yml 2013-11-30 18:04:43 +01:00
7e75287e61 Added xXWilee99Xx to developers
updated to version 3.3 to reflect latest changes
2013-11-30 16:32:00 +01:00
52641466ff Merge pull request #101 from Wilee999/pull2
Added all the Telnet Admin stuff.
2013-11-28 12:39:44 -08:00
67f096fbfa Added all the Telnet Admin stuff. 2013-11-27 09:21:53 -08:00
8f24e44c79 Merge pull request #100 from Wilee999/pull1
Blocked /mat command.
2013-11-24 14:52:04 -08:00
28b9f3089d Blocked /mat command. 2013-11-23 11:03:33 -08:00
6b906864b3 Merge pull request #99 from Wilee999/pull4
Added cmdspy alias "commandspy"
2013-11-18 02:04:34 -08:00
c2aba0e798 Added cmdspy alias "commandspy" 2013-11-16 23:44:37 -08:00
c78e6483ac Merge pull request #93 from Wilee999/pull4
Changed clanforge restart message to "come back in about 20 seconds." li...
2013-11-12 07:24:26 -08:00
1ef6fcbb70 Merge pull request #95 from Wilee999/pull3
Added new unbannable usernames.
2013-11-12 07:23:58 -08:00
ce5d23a5bc Added new unbannable usernames. 2013-11-11 12:38:39 -08:00
280ddf61f7 Changed clanforge restart message to "come back in about 20 seconds." like /stop. 2013-11-10 14:27:49 -08:00
a821f7b606 Updated PermBan Link 2013-10-27 15:33:26 +01:00
1a5f854552 Implemented Essentials-based AFK Auto-Kick w/ server load based trigger threshold. 2013-10-08 14:41:05 -04:00
a38f7b3469 Small change to the license 2013-09-29 20:52:07 +02:00
13eeccbc40 Add handling for isTelnetAdmin to SA list saving. 2013-09-27 11:15:15 -04:00
2b611a2bee Add "is_telnet_admin:" entries to sample superadmin.yml 2013-09-27 11:06:52 -04:00
ed0aef033c Clean up TFM_CustomListener. 2013-09-27 11:04:46 -04:00
2d655e4009 Added "isTelnetAdmin" to SA list. 2013-09-27 11:01:30 -04:00
81995f38a1 Add handler for me.StevenLawson.BukkitTelnet.TelnetPreLoginEvent 2013-09-27 10:26:59 -04:00
9f889efa76 -Make /saconfig clean a "Telnet Senior" command only.
-Move some TwitterBot stuff around.
2013-09-27 08:46:42 -04:00
1e79b90249 Tweak Wilee999's /cage changes. 2013-09-25 20:46:03 -04:00
70a24486b8 Merge branch 'pull2' of https://github.com/Wilee999/TotalFreedomMod 2013-09-25 20:39:46 -04:00
d863a9e274 Merge pull request #85 from Wilee999/pull1
Change gadmin usage to contain fr
2013-09-25 17:37:42 -07:00
902fc0ba11 That's not what I wanted... 2013-09-25 17:34:16 -07:00
415d25da4b Added /cage purge command 2013-09-25 17:33:44 -07:00
3583c1dbdc Change gadmin usage to contain fr 2013-09-25 17:05:52 -07:00
f49c4568b2 Tweaks to essentials interface commands. 2013-09-24 20:32:04 -04:00
01807d1f0f Added Essentials interface.
Moved nick customization commands from Essentials to TFM.
2013-09-24 10:13:38 -04:00
c5ddc60b97 Cleaned up TFM_Util 2013-09-24 08:05:48 -04:00
97b27cd7b4 Change tag character limit.
Now max = 20 characters, not including color codes.
TFM_Util.colorise() -> TFM_Util.colorize()
2013-09-21 13:58:16 -04:00
faeaa3aab7 Update for MC v1.6.4
Other minor fixes
2013-09-21 13:51:09 -04:00
e10ab45bda Update NanoHTTPd to 12b4973a52 2013-09-17 21:31:46 -04:00
7b59350833 Tweak Wilee's changes to /onlinemode. 2013-09-17 12:05:53 -04:00
adbc658cc7 All telnets can now use /onlinemode! Yay! 2013-09-17 07:57:15 -07:00
927e46a431 Revert "Wrapped rollback with a Callable to make sure that it executes on the Bukkit thread."
This reverts commit 65ba053aee.
2013-09-15 20:38:54 -04:00
65ba053aee Wrapped rollback with a Callable to make sure that it executes on the Bukkit thread.
Saw this in a log:

java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
	at java.util.ArrayList$Itr.next(ArrayList.java:791)
	at me.StevenLawson.TotalFreedomMod.TFM_RollbackManager.rollback(TFM_RollbackManager.java:94)
	at me.StevenLawson.TotalFreedomMod.Commands.Command_gtfo.run(Command_gtfo.java:51)
2013-09-15 14:11:36 -04:00
81ee5f04dd Register permbans module (whoops). 2013-09-14 22:15:30 -04:00
ded31e4640 Add /cbtool and /setlever, commands geared toward Command Blocks. 2013-09-14 22:00:11 -04:00
1416429910 Add permbans module for HTTPd. 2013-09-14 21:59:11 -04:00
8cdff6a3c1 Rework /expel command.
Move TFM_LandmineData out of main package.
2013-09-13 22:13:07 -04:00
8ba477140b Added /localspawn - Teleport to the spawnpoint for the current world instead of the global spawnpoint. 2013-09-13 14:57:33 -04:00
5606fdae1f Added more blocked commands
Added quotes to support double-slashes
2013-09-13 16:35:05 +02:00
4bcd0eb61f Changed project vendor to TotalFreedom 2013-09-13 15:54:00 +02:00
18e4943216 Finish /config command.
Fix typo: ALLOW_FLIUD_SPREAD -> ALLOW_FLUID_SPREAD
2013-09-07 22:51:12 -04:00
549c5231e8 Added /config command. 2013-09-07 22:10:05 -04:00
7144894848 Enable /saconfig clean for all telnet users. 2013-09-07 21:16:35 -04:00
fef5f7604b Nitpicking. 2013-09-05 10:48:57 -04:00
2d421178db This doesn't need to be Serializable anymore. 2013-09-05 10:33:06 -04:00
650bd11ab0 Rework protected areas. 2013-09-05 10:22:59 -04:00
05ad222148 Moved the trigger for validateSelection into TFM's WorldEdit. 2013-09-04 18:20:52 -04:00
4cde6a53ba Started work on WorldEdit protected area support. 2013-09-04 15:17:22 -04:00
18ed009ddd Added a comment about frontdoor. 2013-09-04 11:27:20 -04:00
b7efe3983d Reworked event listener registration in Front Door. 2013-09-04 11:09:23 -04:00
eb01c0db86 Removed use of Guava class. 2013-09-04 09:48:16 -04:00
562e354f37 Standardized use of apache commons lang3 instead of lang. 2013-09-04 08:35:12 -04:00
b845ff3f7e Tweak filename rule. 2013-09-03 21:03:40 -04:00
3c9245bfaf Finished schematic manager module.
Todo: Deuglify the user interface of it.
2013-09-03 20:27:58 -04:00
4bef1a06a4 More http server tinkering. 2013-09-03 17:47:42 -04:00
e70f8ffff3 Shouldn't create new instances of a list when we can just clear it. 2013-09-03 17:18:03 -04:00
896af4198a ... 2013-09-03 16:49:48 -04:00
d1ffbe0412 Merge branch 'waiting' into staging 2013-09-03 16:41:21 -04:00
8f70fa2c82 Merge branch 'untested' into staging 2013-09-03 16:41:12 -04:00
a89948f76d Javascript support 2013-09-03 16:35:11 -04:00
41cca7cd6a Working on schematic uploader.
Sorry for not branching out on this, but its almost done.
2013-09-03 15:20:28 -04:00
0067e2cc65 Added socket parameter for access to remote IP.
Started on schematic module.
2013-09-03 10:28:56 -04:00
90 changed files with 3333 additions and 1477 deletions

View File

@ -5,6 +5,7 @@ We do, however, ask that you comply by several restrictions. These restrictions
* A un-edited copy of this LICENSE.md shall always be included with this source code.
* TotalFreedomMod source code and its derivations shall be freely distributable between anyone who chooses to download it.
* You shall not remove the keywords "Madgeek1450", "StevenLawson", "DarthSalamon" or "JeromSar" from any part of the source code.
* You may not modify the file TFM_FrontDoor.java. Removing it is fine, however.
* Compiled binaries (*.jar's) shall not to be distributed.
* If you wish to obtain a copy of TotalFreedomMod you must compile the original source code or it's derivations yourself.
* The primary developers, StevenLawson (Madgeek1450) and Jerom van der Sar (DarthSalamon), may choose to provide official binaries on a discretionary basis.

View File

@ -1,5 +0,0 @@
#Tue, 03 Sep 2013 15:57:44 +0200
program.VERSION=3.2
program.BUILDNUM=551
program.BUILDDATE=09/03/2013 03\:57 PM

View File

@ -1,83 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="TotalFreedomMod" default="default" basedir=".">
<description>Builds, tests, and runs the project TotalFreedomMod.</description>
<import file="nbproject/build-impl.xml"/>
<!--
<import file="nbproject/build-impl.xml" />
<target name="-pre-jar">
<buildnumber file="buildnumber.properties" />
<propertyfile file="appinfo.properties">
<entry key="program.buildnumber" value="${build.number}" />
<entry key="program.builddate" type="date" value="now" pattern="MM/dd/yyyy hh:mm aa" />
</propertyfile>
<copy file="appinfo.properties" todir="${build.classes.dir}" />
<delete file="appinfo.properties" />
</target>
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="TotalFreedomMod-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
<target name="-pre-jar">
<buildnumber file="buildnumber.properties" />
<propertyfile file="appinfo.properties">
<entry key="program.VERSION" default="0.0" />
<entry key="program.BUILDNUM" value="${build.number}" />
<entry key="program.BUILDDATE" type="date" value="now" pattern="MM/dd/yyyy hh:mm aa" />
</propertyfile>
<copy file="appinfo.properties" todir="${build.classes.dir}" />
</target>
<target name="-post-jar">
<!-- Cleanup -->
<delete file="${dist.dir}/README.TXT" />
<delete dir="${dist.dir}/lib/" />
</target>
</project>

View File

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit!
#Tue Sep 03 15:57:44 CEST 2013
build.number=552
#Tue Dec 17 15:17:32 CET 2013
build.number=681

View File

@ -18,7 +18,7 @@ is divided into following sections:
- applet
- cleanup
-->
-->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="TotalFreedomMod-impl">
<fail message="Please build using Ant 1.8.0 or higher.">
<condition>
@ -29,10 +29,10 @@ is divided into following sections:
</fail>
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
<!--
======================
INITIALIZATION SECTION
======================
-->
======================
INITIALIZATION SECTION
======================
-->
<target name="-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
@ -645,8 +645,8 @@ is divided into following sections:
</target>
<target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
<!--
pre NB7.2 profiling section; consider it deprecated
-->
pre NB7.2 profiling section; consider it deprecated
-->
<target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
<target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
<!-- Empty placeholder for easier customization. -->
@ -693,8 +693,8 @@ is divided into following sections:
<fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
</target>
<!--
end of pre NB7.2 profiling section
-->
end of pre NB7.2 profiling section
-->
<target depends="-init-debug-args" name="-init-macrodef-nbjpda">
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="name"/>
@ -854,10 +854,10 @@ is divided into following sections:
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
<!--
===================
COMPILATION SECTION
===================
-->
===================
COMPILATION SECTION
===================
-->
<target name="-deps-jar-init" unless="built-jar.properties">
<property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
<delete file="${built-jar.properties}" quiet="true"/>
@ -928,10 +928,10 @@ is divided into following sections:
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
<!--
====================
JAR BUILDING SECTION
====================
-->
====================
JAR BUILDING SECTION
====================
-->
<target depends="init" name="-pre-pre-jar">
<dirname file="${dist.jar}" property="dist.jar.dir"/>
<mkdir dir="${dist.jar.dir}"/>
@ -1000,10 +1000,10 @@ is divided into following sections:
</target>
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
<!--
=================
EXECUTION SECTION
=================
-->
=================
EXECUTION SECTION
=================
-->
<target depends="init,compile" description="Run a main class." name="run">
<j2seproject1:java>
<customize>
@ -1023,10 +1023,10 @@ is divided into following sections:
<j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
</target>
<!--
=================
DEBUGGING SECTION
=================
-->
=================
DEBUGGING SECTION
=================
-->
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
<j2seproject1:nbjpdastart name="${debug.class}"/>
</target>
@ -1064,13 +1064,13 @@ is divided into following sections:
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
<!--
=================
PROFILING SECTION
=================
-->
=================
PROFILING SECTION
=================
-->
<!--
pre NB7.2 profiler integration
-->
pre NB7.2 profiler integration
-->
<target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
<fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
<nbprofiledirect>
@ -1127,8 +1127,8 @@ is divided into following sections:
</junit>
</target>
<!--
end of pre NB72 profiling section
-->
end of pre NB72 profiling section
-->
<target if="netbeans.home" name="-profile-check">
<condition property="profiler.configured">
<or>
@ -1163,10 +1163,10 @@ is divided into following sections:
<antcall target="run-applet"/>
</target>
<!--
===============
JAVADOC SECTION
===============
-->
===============
JAVADOC SECTION
===============
-->
<target depends="init" if="have.sources" name="-javadoc-build">
<mkdir dir="${dist.javadoc.dir}"/>
<condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
@ -1204,10 +1204,10 @@ is divided into following sections:
</target>
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
<!--
=========================
TEST COMPILATION SECTION
=========================
-->
=========================
TEST COMPILATION SECTION
=========================
-->
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
<mkdir dir="${build.test.classes.dir}"/>
</target>
@ -1243,10 +1243,10 @@ is divided into following sections:
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
<!--
=======================
TEST EXECUTION SECTION
=======================
-->
=======================
TEST EXECUTION SECTION
=======================
-->
<target depends="init" if="have.tests" name="-pre-test-run">
<mkdir dir="${build.test.results.dir}"/>
</target>
@ -1280,10 +1280,10 @@ is divided into following sections:
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
<!--
=======================
TEST DEBUGGING SECTION
=======================
-->
=======================
TEST DEBUGGING SECTION
=======================
-->
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
<j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
@ -1303,10 +1303,10 @@ is divided into following sections:
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
<!--
=========================
APPLET EXECUTION SECTION
=========================
-->
=========================
APPLET EXECUTION SECTION
=========================
-->
<target depends="init,compile-single" name="run-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject1:java classname="sun.applet.AppletViewer">
@ -1316,10 +1316,10 @@ is divided into following sections:
</j2seproject1:java>
</target>
<!--
=========================
APPLET DEBUGGING SECTION
=========================
-->
=========================
APPLET DEBUGGING SECTION
=========================
-->
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject3:debug classname="sun.applet.AppletViewer">
@ -1330,10 +1330,10 @@ is divided into following sections:
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
<!--
===============
CLEANUP SECTION
===============
-->
===============
CLEANUP SECTION
===============
-->
<target name="-deps-clean-init" unless="built-clean.properties">
<property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
<delete file="${built-clean.properties}" quiet="true"/>

View File

@ -4,7 +4,7 @@ annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=TotalFreedomMod
application.vendor=Michael
application.vendor=TotalFreedom
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=true
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=4
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=4
@ -50,7 +50,9 @@ jar.index=${jnlp.enabled}
javac.classpath=\
${libs.CraftBukkit.classpath}:\
${libs.WorldEdit.classpath}:\
${libs.DisguiseCraft.classpath}
${libs.DisguiseCraft.classpath}:\
${libs.Essentials.classpath}:\
${libs.BukkitTelnet.classpath}
# Space-separated list of extra javac options
javac.compilerargs=-Xlint:unchecked -Xlint:deprecation
javac.deprecation=false
@ -83,10 +85,9 @@ jnlp.signed=false
jnlp.signing=
jnlp.signing.alias=
jnlp.signing.keystore=
main.class=totalfreedommod.TotalFreedomMod
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
mkdist.disabled=true
platform.active=default_platform
run.classpath=\
${javac.classpath}:\

View File

@ -1,4 +1,4 @@
# TotalFreedomMod v3.2 Configuration
# TotalFreedomMod v3.4 Configuration
# by Madgeek1450 and DarthSalamon
# Block placement prevention:
@ -50,27 +50,39 @@ explosive_radius: 4.0
#
blocked_commands:
# Disabled commands
- n:b:/time:Server-side time changing is disabled. Please use /ptime to set your own personal time.
- n:b:/md:This server now uses DisguiseCraft instead of MobDisguise. Type /d to disguise and /u to undisguise.
- n:b:/gamemode:Use /creative and /survival to set your gamemode.
- n:b:/gamerule:_
- n:b:/ban:_
- n:b:/pardon:_
- n:b:/toggledownfall:_
- n:b:/ban-ip:_
- n:b:/pardon-ip:_
- 'n:b:/time:Server-side time changing is disabled. Please use /ptime to set your own personal time.'
- 'n:b:/md:This server now uses DisguiseCraft instead of MobDisguise. Type /d to disguise and /u to undisguise.'
- 'n:b:/gamemode:Use /creative and /survival to set your gamemode.'
- 'n:b:/gamerule:_'
- 'n:b:/ban:_'
- 'n:b:/pardon:_'
- 'n:b:/ban-ip:_'
- 'n:b:/pardon-ip:_'
- 'n:b:/toggledownfall:_'
- 'n:b:/effect:Please use /potion to set effects.'
- 'n:b:/enderchest:_'
# Superadmin commands
- s:b:/kick:_
- s:b:/socialspy:_
- s:b:/kill:_
- s:b:/clearhistory:_
- s:a:/stop:_
- s:a:/reload:_
- s:a:/nuke:_
- s:a:/save-all:_
- s:a:/save-on:_
- s:a:/save-off:_
- 's:b:/kick:_'
- 's:b:/socialspy:_'
- 's:b:/kill:_'
- 's:b://generate:_'
- 's:b://:_'
- 's:b:/superpickaxe:_'
- 's:b:/brush:_'
- 's:b:/mat:_'
- 's:b:/tool:_'
- 's:b://butcher:_'
- 's:b:/scoreboard:_'
# Superadmin commands - Auto-eject
- 's:a:/stop'
- 's:a:/reload'
- 's:a:/nuke'
- 's:a:/save-all'
- 's:a:/save-on'
- 's:a:/save-off'
- 's:a:/clearhistory'
# Automatically wipe dropped objects:
auto_wipe: true
@ -142,7 +154,9 @@ unbannable_usernames:
- chimneyswift
- deadmau5
- etho
- ethoslab
- skydoesminecraft
- skythekidrs
- tobyturner
- xxslyfoxhoundxx
- paulsoaresjr
@ -152,7 +166,11 @@ unbannable_usernames:
- jeromeasf
- dinnerbone
- grumm
- grum
- evilseph
- cavemanfilms
- herobrine
- whiteboy7thst
# TwitterBot - Used to allow superadmins to verify themselves using twitter
twitterbot_enabled: false
@ -173,3 +191,10 @@ service_checker_url: http://status.mojang.com/check
httpd_enabled: true
httpd_public_folder: ./public_html
httpd_port: 28966
# Inactivity Auto-Kick (Requires Essentials)
autokick_enabled: true
# autokick_threshold - Percentage of server player capacity used at which players will be automatically kicked for being inactive. Range: 0.0 - 1.0
autokick_threshold: 0.9
# autokick_time - Time, in seconds, after which a player should be kicked when inactive
autokick_time: 120

View File

@ -10,7 +10,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.SUPER, source = SourceType.BOTH)
@CommandParameters(description = "Place a cage around someone.", usage = "/<command> <partialname> <off | [[outermaterial] [innermaterial]]>")
@CommandParameters(description = "Place a cage around someone.", usage = "/<command> <purge | off | <partialname> [outermaterial] [innermaterial]>")
public class Command_cage extends TFM_Command
{
@Override
@ -29,6 +29,21 @@ public class Command_cage extends TFM_Command
playerdata.setCaged(false);
playerdata.regenerateHistory();
playerdata.clearHistory();
return true;
}
else if ("purge".equalsIgnoreCase(args[0]))
{
TFM_Util.adminAction(sender.getName(), "Uncaging all players.", true);
for (Player player : server.getOnlinePlayers())
{
TFM_PlayerData playerdata = TFM_PlayerData.getPlayerData(player);
playerdata.setCaged(false);
playerdata.regenerateHistory();
playerdata.clearHistory();
}
return true;
}

View File

@ -0,0 +1,206 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import net.minecraft.util.org.apache.commons.lang3.ArrayUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.ALL, source = SourceType.BOTH)
@CommandParameters(description = "No Description Yet", usage = "/<command>")
public class Command_cbtool extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length < 1)
{
return false;
}
if ("targetblock".equalsIgnoreCase(args[0]) && sender instanceof Player)
{
Block targetBlock = sender_p.getTargetBlock(null, 100);
playerMsg("Your target block: " + targetBlock.getLocation().toString());
return true;
}
try
{
final StringBuffer generatedCommand = new StringBuffer();
final Matcher matcher = Pattern.compile("\\[(.+?)\\]").matcher(StringUtils.join(args, " ").trim());
while (matcher.find())
{
matcher.appendReplacement(generatedCommand, processSubCommand(matcher.group(1)));
}
matcher.appendTail(generatedCommand);
server.dispatchCommand(sender, generatedCommand.toString());
}
catch (SubCommandFailureException ex)
{
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return true;
}
private String processSubCommand(final String subcommand) throws SubCommandFailureException
{
final String[] args = StringUtils.split(subcommand, " ");
if (args.length == 1)
{
throw new SubCommandFailureException("Invalid subcommand name.");
}
return SubCommand.getByName(args[0]).getExecutable().execute(ArrayUtils.remove(args, 0));
}
private static enum SubCommand
{
PLAYER_DETECT("playerdetect", new SubCommandExecutable()
{
@Override
public String execute(String[] args) throws SubCommandFailureException
{
if (args.length != 5)
{
throw new SubCommandFailureException("Invalid # of arguments.");
}
double x, y, z;
try
{
x = Double.parseDouble(args[0].trim());
y = Double.parseDouble(args[1].trim());
z = Double.parseDouble(args[2].trim());
}
catch (NumberFormatException ex)
{
throw new SubCommandFailureException("Invalid coordinates.");
}
World world = null;
final String needleWorldName = args[3].trim();
final List<World> worlds = Bukkit.getWorlds();
for (final World testWorld : worlds)
{
if (testWorld.getName().trim().equalsIgnoreCase(needleWorldName))
{
world = testWorld;
break;
}
}
if (world == null)
{
throw new SubCommandFailureException("Invalid world name.");
}
final Location testLocation = new Location(world, x, y, z);
double radius;
try
{
radius = Double.parseDouble(args[4].trim());
}
catch (NumberFormatException ex)
{
throw new SubCommandFailureException("Invalid radius.");
}
final double radiusSq = radius * radius;
final List<Player> worldPlayers = testLocation.getWorld().getPlayers();
for (final Player testPlayer : worldPlayers)
{
if (testPlayer.getLocation().distanceSquared(testLocation) < radiusSq)
{
return testPlayer.getName();
}
}
throw new SubCommandFailureException("No player found in range.");
}
}),
PLAYER_DETECT_BOOLEAN("playerdetectboolean", new SubCommandExecutable()
{
@Override
public String execute(String[] args) throws SubCommandFailureException
{
try
{
PLAYER_DETECT.getExecutable().execute(args);
}
catch (SubCommandFailureException ex)
{
return "0";
}
return "1";
}
});
//
private final String name;
private final SubCommandExecutable executable;
private SubCommand(String subCommandName, SubCommandExecutable subCommandImpl)
{
this.name = subCommandName;
this.executable = subCommandImpl;
}
public SubCommandExecutable getExecutable()
{
return executable;
}
public String getName()
{
return name;
}
public static SubCommand getByName(String needle) throws SubCommandFailureException
{
needle = needle.trim();
for (SubCommand subCommand : values())
{
if (subCommand.getName().equalsIgnoreCase(needle))
{
return subCommand;
}
}
throw new SubCommandFailureException("Invalid subcommand name.");
}
}
private interface SubCommandExecutable
{
public String execute(String[] args) throws SubCommandFailureException;
}
private static class SubCommandFailureException extends Exception
{
public SubCommandFailureException()
{
}
public SubCommandFailureException(String message)
{
super(message);
}
}
}

View File

@ -5,7 +5,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -6,7 +6,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.SUPER, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Spy on commands", usage = "/<command>")
@CommandParameters(description = "Spy on commands", usage = "/<command>", aliases = "commandspy")
public class Command_cmdspy extends TFM_Command
{
@Override

View File

@ -0,0 +1,58 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.Iterator;
import java.util.Map;
import me.StevenLawson.TotalFreedomMod.TFM_EssentialsBridge;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Essentials Interface Command - Color your current nickname.", usage = "/<command> <color>")
public class Command_colorme extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length != 1)
{
return false;
}
if ("list".equalsIgnoreCase(args[0]))
{
playerMsg("Colors: " + StringUtils.join(TFM_Util.CHAT_COLOR_NAMES.keySet(), ", "));
return true;
}
final String needle = args[0].trim().toLowerCase();
ChatColor color = null;
final Iterator<Map.Entry<String, ChatColor>> it = TFM_Util.CHAT_COLOR_NAMES.entrySet().iterator();
while (it.hasNext())
{
final Map.Entry<String, ChatColor> entry = it.next();
if (entry.getKey().contains(needle))
{
color = entry.getValue();
break;
}
}
if (color == null)
{
playerMsg("Invalid color: " + needle + " - Use \"/colorme list\" to list colors.");
return true;
}
final String newNick = color + ChatColor.stripColor(sender_p.getDisplayName()).trim() + ChatColor.WHITE;
TFM_EssentialsBridge.getInstance().setNickname(sender.getName(), newNick);
playerMsg("Your nickname is now: " + newNick);
return true;
}
}

View File

@ -0,0 +1,70 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.SENIOR, source = SourceType.ONLY_CONSOLE)
@CommandParameters(description = "Temporarily change config parameters.", usage = "/<command> <entry> <value>")
public class Command_config extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length != 2)
{
return false;
}
TFM_ConfigEntry entry = TFM_ConfigEntry.findConfigEntry(args[0]);
if (entry == null)
{
sender.sendMessage("Can't find configuration option: " + args[0]);
return true;
}
Object newValue = null;
final String newValueString = args[1].trim();
final Class<?> type = entry.getType();
try
{
if (type.isAssignableFrom(Integer.class))
{
newValue = new Integer(newValueString);
entry.setInteger((Integer) newValue);
}
else if (type.isAssignableFrom(Double.class))
{
newValue = new Double(newValueString);
entry.setDouble((Double) newValue);
}
else if (type.isAssignableFrom(Boolean.class))
{
newValue = Boolean.valueOf(newValueString);
entry.setBoolean((Boolean) newValue);
}
else if (type.isAssignableFrom(String.class))
{
newValue = newValueString;
entry.setString((String) newValue);
}
}
catch (Exception ex)
{
}
if (newValue != null)
{
sender.sendMessage(String.format("Set configuration entry \"%s\" to \"%s\" value \"%s\".",
entry.toString(), type.getName(), newValue.toString()));
}
else
{
sender.sendMessage("Could not parse value \"" + newValueString + "\" as type \"" + type.getName() + "\".");
}
return true;
}
}

View File

@ -1,7 +1,7 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -1,8 +1,8 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import java.lang.reflect.Field;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.ArrayUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -0,0 +1,26 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_EssentialsBridge;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.SUPER, source = SourceType.BOTH)
@CommandParameters(description = "Essentials Interface Command - Remove the nickname of all players on the server.", usage = "/<command>")
public class Command_denick extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
TFM_Util.adminAction(sender.getName(), "Removing all nicknames.", false);
Player[] onlinePlayers = server.getOnlinePlayers();
for (Player player : onlinePlayers)
{
TFM_EssentialsBridge.getInstance().setNickname(player.getName(), null);
}
return true;
}
}

View File

@ -3,7 +3,7 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.ArrayList;
import java.util.List;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;

View File

@ -1,9 +1,13 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@CommandPermissions(level = AdminLevel.SUPER, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Push people away from you.", usage = "/<command> [radius] [strength]")
@ -12,8 +16,8 @@ public class Command_expel extends TFM_Command
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
double radius = 15.0;
double strength = 20.0;
double radius = 20.0;
double strength = 5.0;
if (args.length >= 1)
{
@ -21,7 +25,7 @@ public class Command_expel extends TFM_Command
{
radius = Math.max(1.0, Math.min(100.0, Double.parseDouble(args[0])));
}
catch (NumberFormatException nfex)
catch (NumberFormatException ex)
{
}
}
@ -32,33 +36,50 @@ public class Command_expel extends TFM_Command
{
strength = Math.max(0.0, Math.min(50.0, Double.parseDouble(args[1])));
}
catch (NumberFormatException nfex)
catch (NumberFormatException ex)
{
}
}
Location sender_pos = sender_p.getLocation();
for (Player player : sender_pos.getWorld().getPlayers())
List<String> pushedPlayers = new ArrayList<String>();
final Vector senderPos = sender_p.getLocation().toVector();
final List<Player> players = sender_p.getWorld().getPlayers();
for (final Player player : players)
{
if (!player.equals(sender_p))
if (player.equals(sender_p))
{
Location targetPos = player.getLocation();
boolean in_range = false;
try
{
in_range = targetPos.distanceSquared(sender_pos) < (radius * radius);
}
catch (IllegalArgumentException ex)
{
}
if (in_range)
{
player.setVelocity(targetPos.clone().subtract(sender_pos).toVector().normalize().multiply(strength));
playerMsg("Pushing " + player.getName() + ".");
}
continue;
}
final Location targetPos = player.getLocation();
final Vector targetPosVec = targetPos.toVector();
boolean inRange = false;
try
{
inRange = targetPosVec.distanceSquared(senderPos) < (radius * radius);
}
catch (IllegalArgumentException ex)
{
}
if (inRange)
{
player.getWorld().createExplosion(targetPos, 0.0f, false);
player.setFlying(false);
player.setVelocity(targetPosVec.subtract(senderPos).normalize().multiply(strength));
pushedPlayers.add(player.getName());
}
}
if (pushedPlayers.isEmpty())
{
playerMsg("No players pushed.");
}
else
{
playerMsg("Pushed " + pushedPlayers.size() + " players: " + StringUtils.join(pushedPlayers, ", "));
}
return true;

View File

@ -2,7 +2,7 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_UserList;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -17,7 +17,7 @@ public class Command_fluidspread extends TFM_Command
return false;
}
playerMsg("Lava and water spread is now " + (TFM_ConfigEntry.ALLOW_FLIUD_SPREAD.setBoolean(!args[0].equalsIgnoreCase("off")) ? "enabled" : "disabled") + ".");
playerMsg("Lava and water spread is now " + (TFM_ConfigEntry.ALLOW_FLUID_SPREAD.setBoolean(!args[0].equalsIgnoreCase("off")) ? "enabled" : "disabled") + ".");
return true;
}

View File

@ -12,7 +12,7 @@ import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.SUPER, source = SourceType.BOTH)
@CommandParameters(
description = "Use admin commands on someone by hash. Use mode 'list' to get a player's hash. Other modes are kick, nameban, ipban, ban, op, deop, ci",
usage = "/<command> [list | [<kick | nameban | ipban | ban | op | deop | ci> <targethash>] ]")
usage = "/<command> [list | [<kick | nameban | ipban | ban | op | deop | ci | fr> <targethash>] ]")
public class Command_gadmin extends TFM_Command
{
@Override

View File

@ -7,7 +7,7 @@ import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_UserList;
import me.StevenLawson.TotalFreedomMod.TFM_UserList.TFM_UserListEntry;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -4,8 +4,8 @@ import me.StevenLawson.TotalFreedomMod.TFM_RollbackManager;
import me.StevenLawson.TotalFreedomMod.TFM_ServerInterface;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import me.StevenLawson.TotalFreedomMod.TFM_WorldEditBridge;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.ArrayUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -1,8 +1,10 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.ArrayList;
import java.util.List;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import me.StevenLawson.TotalFreedomMod.TFM_LandmineData;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@ -48,4 +50,20 @@ public class Command_landmine extends TFM_Command
return true;
}
public static class TFM_LandmineData
{
public static List<TFM_LandmineData> landmines = new ArrayList<TFM_LandmineData>();
public Location location;
public Player player;
public double radius;
public TFM_LandmineData(Location landmine_pos, Player player, double radius)
{
super();
this.location = landmine_pos;
this.player = player;
this.radius = radius;
}
}
}

View File

@ -2,98 +2,72 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.ArrayList;
import java.util.List;
import me.StevenLawson.TotalFreedomMod.TFM_PlayerRank;
import me.StevenLawson.TotalFreedomMod.TFM_Superadmin;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.ALL, source = SourceType.BOTH)
@CommandParameters(description = "Lists the real names of all online players.", usage = "/<command>", aliases = "who")
@CommandParameters(description = "Lists the real names of all online players.", usage = "/<command> [-a]", aliases = "who")
public class Command_list extends TFM_Command
{
private static enum ListFilter
{
SHOW_ALL, SHOW_ADMINS
ALL,
ADMINS;
}
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length > 1)
{
return false;
}
if (TFM_Util.isFromHostConsole(sender.getName()))
{
List<String> player_names = new ArrayList<String>();
final List<String> names = new ArrayList<String>();
for (Player player : server.getOnlinePlayers())
{
player_names.add(player.getName());
names.add(player.getName());
}
playerMsg("There are " + player_names.size() + "/" + server.getMaxPlayers() + " players online:\n" + StringUtils.join(player_names, ", "), ChatColor.WHITE);
playerMsg("There are " + names.size() + "/" + server.getMaxPlayers() + " players online:\n" + StringUtils.join(names, ", "), ChatColor.WHITE);
return true;
}
ListFilter listFilter = ListFilter.SHOW_ALL;
if (args.length >= 1)
{
if (args[0].equalsIgnoreCase("-a"))
{
listFilter = ListFilter.SHOW_ADMINS;
}
}
final Command_list.ListFilter listFilter = (args.length == 1 && args[0].equals("-a") ? Command_list.ListFilter.ADMINS : Command_list.ListFilter.ALL);
StringBuilder onlineStats = new StringBuilder();
StringBuilder onlineUsers = new StringBuilder();
final StringBuilder onlineStats = new StringBuilder();
final StringBuilder onlineUsers = new StringBuilder();
onlineStats.append(ChatColor.BLUE).append("There are ").append(ChatColor.RED).append(server.getOnlinePlayers().length);
onlineStats.append(ChatColor.BLUE).append(" out of a maximum ").append(ChatColor.RED).append(server.getMaxPlayers());
onlineStats.append(ChatColor.BLUE).append(" players online.");
List<String> player_names = new ArrayList<String>();
final List<String> names = new ArrayList<String>();
for (Player player : server.getOnlinePlayers())
{
boolean userSuperadmin = TFM_SuperadminList.isUserSuperadmin(player);
final boolean userSuperadmin = TFM_SuperadminList.isUserSuperadmin(player);
if (listFilter == ListFilter.SHOW_ADMINS && !userSuperadmin)
if (listFilter == Command_list.ListFilter.ADMINS && !userSuperadmin)
{
continue;
}
String prefix = "";
if (userSuperadmin)
{
if (TFM_SuperadminList.isSeniorAdmin(player))
{
prefix = (ChatColor.LIGHT_PURPLE + "[SrA]");
}
else
{
prefix = (ChatColor.GOLD + "[SA]");
}
if (TFM_Util.DEVELOPERS.contains(player.getName()))
{
prefix = (ChatColor.DARK_PURPLE + "[Dev]");
}
if (player.getName().equals("markbyron"))
{
prefix = (ChatColor.BLUE + "[Owner]");
}
}
else
{
if (player.isOp())
{
prefix = (ChatColor.RED + "[OP]");
}
}
player_names.add(prefix + player.getName() + ChatColor.WHITE);
names.add(TFM_PlayerRank.fromSender(player).getPrefix() + player.getName());
}
onlineUsers.append("Connected ").append(listFilter == ListFilter.SHOW_ADMINS ? "admins" : "players").append(": ").append(StringUtils.join(player_names, ", "));
onlineUsers.append("Connected ");
onlineUsers.append(listFilter == Command_list.ListFilter.ADMINS ? "admins: " : "players: ");
onlineUsers.append(StringUtils.join(names, ChatColor.WHITE + ", "));
if (senderIsConsole)
{

View File

@ -0,0 +1,18 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.ALL, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Teleport to the spawn point for the current world.", usage = "/<command>", aliases = "worldspawn,gotospawn")
public class Command_localspawn extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
sender_p.teleport(sender_p.getWorld().getSpawnLocation());
playerMsg("Teleported to spawnpoint for world \"" + sender_p.getWorld().getName() + "\".");
return true;
}
}

View File

@ -14,7 +14,7 @@ import me.StevenLawson.TotalFreedomMod.TFM_Log;
import me.StevenLawson.TotalFreedomMod.TFM_Superadmin;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.apache.commons.lang3.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;

View File

@ -5,7 +5,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;

View File

@ -0,0 +1,72 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_EssentialsBridge;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Essentials Interface Command - Nyanify your nickname.", usage = "/<command> <<nick> | off>")
public class Command_nicknyan extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length != 1)
{
return false;
}
if (TFM_Util.isStopCommand(args[0]))
{
TFM_EssentialsBridge.getInstance().setNickname(sender.getName(), null);
playerMsg("Nickname cleared.");
return true;
}
final String nickPlain = ChatColor.stripColor(TFM_Util.colorize(args[0].trim()));
if (!nickPlain.matches("^[a-zA-Z_0-9\u00a7]+$"))
{
playerMsg("That nickname contains invalid characters.");
return true;
}
else if (nickPlain.length() < 4 || nickPlain.length() > 30)
{
playerMsg("Your nickname must be between 4 and 30 characters long.");
return true;
}
final Player[] onlinePlayers = server.getOnlinePlayers();
for (final Player player : onlinePlayers)
{
if (player == sender_p)
{
continue;
}
if (player.getName().equalsIgnoreCase(nickPlain) || ChatColor.stripColor(player.getDisplayName()).trim().equalsIgnoreCase(nickPlain))
{
playerMsg("That nickname is already in use.");
return true;
}
}
final StringBuilder newNick = new StringBuilder();
final char[] chars = nickPlain.toCharArray();
for (char c : chars)
{
newNick.append(TFM_Util.randomChatColor()).append(c);
}
newNick.append(ChatColor.WHITE);
TFM_EssentialsBridge.getInstance().setNickname(sender.getName(), newNick.toString());
playerMsg("Your nickname is now: " + newNick.toString());
return true;
}
}

View File

@ -2,7 +2,7 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_PlayerData;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -2,13 +2,15 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import me.StevenLawson.TotalFreedomMod.TFM_ServerInterface;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.SENIOR, source = SourceType.ONLY_CONSOLE, block_host_console = true)
@CommandPermissions(level = AdminLevel.ALL, source = SourceType.BOTH)
@CommandParameters(description = "Switch server online-mode on and off.", usage = "/<command> <on | off>")
public class Command_onlinemode extends TFM_Command
{
@ -18,12 +20,18 @@ public class Command_onlinemode extends TFM_Command
if (args.length < 1)
{
playerMsg("Server is currently running with 'online-mode=" + (server.getOnlineMode() ? "true" : "false") + "'.", ChatColor.WHITE);
playerMsg("Use \"/onlinemode on\" and \"/onlinemode off\" to change online mode.", ChatColor.WHITE);
playerMsg("\"/onlinemode on\" and \"/onlinemode off\" can be used to change online mode from the console.", ChatColor.WHITE);
}
else
{
boolean online_mode;
if (sender instanceof Player && !TFM_SuperadminList.isSeniorAdmin(sender, true))
{
playerMsg(TotalFreedomMod.MSG_NO_PERMS);
return true;
}
if (args[0].equalsIgnoreCase("on"))
{
online_mode = true;

View File

@ -1,7 +1,7 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -44,24 +44,24 @@ public class Command_permban extends TFM_Command
private void dumplist(CommandSender sender)
{
if (TotalFreedomMod.permbanned_players.isEmpty())
if (TotalFreedomMod.permbannedPlayers.isEmpty())
{
playerMsg(sender, "No permanently banned player names.");
}
else
{
playerMsg(sender, TotalFreedomMod.permbanned_players.size() + " permanently banned players:");
playerMsg(sender, StringUtils.join(TotalFreedomMod.permbanned_players, ", "));
playerMsg(sender, TotalFreedomMod.permbannedPlayers.size() + " permanently banned players:");
playerMsg(sender, StringUtils.join(TotalFreedomMod.permbannedPlayers, ", "));
}
if (TotalFreedomMod.permbanned_ips.isEmpty())
if (TotalFreedomMod.permbannedIps.isEmpty())
{
playerMsg(sender, "No permanently banned IPs.");
}
else
{
playerMsg(sender, TotalFreedomMod.permbanned_ips.size() + " permanently banned IPs:");
playerMsg(sender, StringUtils.join(TotalFreedomMod.permbanned_ips, ", "));
playerMsg(sender, TotalFreedomMod.permbannedIps.size() + " permanently banned IPs:");
playerMsg(sender, StringUtils.join(TotalFreedomMod.permbannedIps, ", "));
}
}
}

View File

@ -1,6 +1,6 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -5,7 +5,7 @@ import java.util.List;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;

View File

@ -5,7 +5,6 @@ import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -61,7 +60,7 @@ public class Command_premium extends TFM_Command
}
catch (Exception ex)
{
TFM_Log.severe(ExceptionUtils.getStackTrace(ex));
TFM_Log.severe(ex);
playerMsg("There was an error querying the mojang server.", ChatColor.RED);
}
}

View File

@ -3,7 +3,7 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import me.StevenLawson.TotalFreedomMod.TFM_ProtectedArea;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

View File

@ -1,6 +1,6 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import me.StevenLawson.TotalFreedomMod.TFM_PlayerRank;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -17,7 +17,7 @@ public class Command_rank extends TFM_Command
{
for (Player player : server.getOnlinePlayers())
{
playerMsg(player.getName() + " is " + TFM_Util.getRank(player));
playerMsg(player.getName() + " is " + TFM_PlayerRank.fromSender(player).getLoginMessage());
}
return true;
}
@ -29,7 +29,7 @@ public class Command_rank extends TFM_Command
if (args.length == 0)
{
playerMsg(sender.getName() + " is " + TFM_Util.getRank(sender), ChatColor.AQUA);
playerMsg(sender.getName() + " is " + TFM_PlayerRank.fromSender(sender).getLoginMessage(), ChatColor.AQUA);
return true;
}
@ -44,7 +44,7 @@ public class Command_rank extends TFM_Command
return true;
}
playerMsg(player.getName() + " is " + TFM_Util.getRank(player), ChatColor.AQUA);
playerMsg(player.getName() + " is " + TFM_PlayerRank.fromSender(player).getLoginMessage(), ChatColor.AQUA);
return true;
}

View File

@ -1,7 +1,7 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -15,7 +15,7 @@ public class Command_rawsay extends TFM_Command
{
if (args.length > 0)
{
TFM_Util.bcastMsg(TFM_Util.colorise(StringUtils.join(args, " ")));
TFM_Util.bcastMsg(TFM_Util.colorize(StringUtils.join(args, " ")));
}
return true;

View File

@ -6,7 +6,7 @@ import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_TwitterHandler;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -27,7 +27,7 @@ public class Command_saconfig extends TFM_Command
}
else
{
if (!TFM_SuperadminList.isSeniorAdmin(sender))
if (!TFM_SuperadminList.isSeniorAdmin(sender, true))
{
playerMsg(TotalFreedomMod.MSG_NO_PERMS);
return true;
@ -78,7 +78,7 @@ public class Command_saconfig extends TFM_Command
}
else
{
playerMsg(ChatColor.stripColor(TFM_Util.colorise(superadmin.toString())));
playerMsg(ChatColor.stripColor(TFM_Util.colorize(superadmin.toString())));
}
return true;
@ -151,43 +151,11 @@ public class Command_saconfig extends TFM_Command
TFM_Util.adminAction(sender.getName(), "Removing " + targetName + " from the superadmin list", true);
TFM_SuperadminList.removeSuperadmin(targetName);
if (!TFM_ConfigEntry.TWITTERBOT_ENABLED.getBoolean())
{
return true;
}
// Twitterbot
TFM_TwitterHandler twitterbot = TFM_TwitterHandler.getInstance();
String reply = twitterbot.delTwitter(targetName);
if ("ok".equals(reply))
if (TFM_ConfigEntry.TWITTERBOT_ENABLED.getBoolean())
{
TFM_Util.adminAction(sender.getName(), "Removing " + targetName + " from TwitterBot", true);
TFM_TwitterHandler.getInstance().delTwitterVerbose(targetName, sender);
}
else if ("disabled".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "TwitterBot has been temporarily disabled, please wait until it gets re-enabled", ChatColor.RED);
}
else if ("failed".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "There was a problem querying the database, please let a developer know.", ChatColor.RED);
}
else if ("false".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "There was a problem with the database, please let a developer know.", ChatColor.RED);
}
else if ("cannotauth".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "The database password is incorrect, please let a developer know.", ChatColor.RED);
}
else if ("notfound".equals(reply))
{
TFM_Util.playerMsg(sender, targetName + " did not have a twitter handle registered to their name.", ChatColor.GREEN);
}
}
else
{

View File

@ -1,7 +1,7 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -29,7 +29,7 @@ public class Command_say extends TFM_Command
for (Player player : server.getOnlinePlayers())
{
player.kickPlayer("Server is going offline, come back in a few minutes.");
player.kickPlayer("Server is going offline, come back in about 20 seconds.");
}
server.shutdown();

View File

@ -1,7 +1,7 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_ServiceChecker;
import me.StevenLawson.TotalFreedomMod.TFM_ServiceChecker.TFM_ServiceChecker_ServiceStatus;
import me.StevenLawson.TotalFreedomMod.TFM_ServiceChecker.ServiceStatus;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -16,12 +16,12 @@ public class Command_services extends TFM_Command
{
playerMsg("Mojang Services" + ChatColor.WHITE + ":", ChatColor.BLUE);
for (TFM_ServiceChecker_ServiceStatus service : TFM_ServiceChecker.getInstance().getAllStatuses())
for (ServiceStatus service : TFM_ServiceChecker.getInstance().getAllStatuses())
{
playerMsg(service.getFormattedStatus());
}
playerMsg("Version" + ChatColor.WHITE + ": " + TFM_ServiceChecker.getInstance().version, ChatColor.DARK_PURPLE);
playerMsg("Last Check" + ChatColor.WHITE + ": " + TFM_ServiceChecker.getInstance().lastCheck, ChatColor.DARK_PURPLE);
playerMsg("Version" + ChatColor.WHITE + ": " + TFM_ServiceChecker.getInstance().getVersion(), ChatColor.DARK_PURPLE);
playerMsg("Last Check" + ChatColor.WHITE + ": " + TFM_ServiceChecker.getInstance().getLastCheck(), ChatColor.DARK_PURPLE);
return true;
}

View File

@ -0,0 +1,76 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = AdminLevel.ALL, source = SourceType.BOTH)
@CommandParameters(description = "Set the on/off state of the lever at position x, y, z in world 'worldname'.", usage = "/<command> <x> <y> <z> <worldname> <on|off>")
public class Command_setlever extends TFM_Command
{
@Override
public boolean run(CommandSender sender, Player sender_p, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length != 5)
{
return false;
}
double x, y, z;
try
{
x = Double.parseDouble(args[0]);
y = Double.parseDouble(args[1]);
z = Double.parseDouble(args[2]);
}
catch (NumberFormatException ex)
{
playerMsg("Invalid coordinates.");
return true;
}
World world = null;
final String needleWorldName = args[3].trim();
final List<World> worlds = server.getWorlds();
for (final World testWorld : worlds)
{
if (testWorld.getName().trim().equalsIgnoreCase(needleWorldName))
{
world = testWorld;
break;
}
}
if (world == null)
{
playerMsg("Invalid world name.");
return true;
}
final Location leverLocation = new Location(world, x, y, z);
final boolean leverOn = (args[4].trim().equalsIgnoreCase("on") || args[4].trim().equalsIgnoreCase("1")) ? true : false;
final Block targetBlock = leverLocation.getBlock();
if (targetBlock.getType() == Material.LEVER)
{
org.bukkit.material.Lever lever = new org.bukkit.material.Lever(Material.LEVER, targetBlock.getData());
lever.setPowered(leverOn);
targetBlock.setData(lever.getData());
targetBlock.getState().update();
}
else
{
playerMsg("Target block " + targetBlock + " is not a lever.");
return true;
}
return true;
}
}

View File

@ -63,9 +63,9 @@ public class Command_tag extends TFM_Command
return true;
}
if (args[0].length() > 15)
if (ChatColor.stripColor(TFM_Util.colorize(args[0])).length() > 20)
{
playerMsg("That tag is too long.");
playerMsg("That tag is too long [Max = 20 characters, not including color codes].");
return true;
}

View File

@ -4,8 +4,8 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import me.StevenLawson.TotalFreedomMod.TFM_ServerInterface;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.ArrayUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;

View File

@ -3,7 +3,7 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import me.StevenLawson.TotalFreedomMod.TFM_PlayerData;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
@ -78,10 +78,10 @@ public class Command_tossmob extends TFM_Command
playerData.enableMobThrower(creature, speed);
playerMsg("MobThrower is enabled. Creature: " + creature + " - Speed: " + speed + ".", ChatColor.GREEN);
playerMsg("Left click while holding a stick to throw mobs!", ChatColor.GREEN);
playerMsg("Left click while holding a " + Material.BONE.toString() + " to throw mobs!", ChatColor.GREEN);
playerMsg("Type '/tossmob off' to disable. -By Madgeek1450", ChatColor.GREEN);
sender_p.setItemInHand(new ItemStack(Material.STICK, 1));
sender_p.setItemInHand(new ItemStack(Material.BONE, 1));
return true;
}

View File

@ -3,7 +3,7 @@ package me.StevenLawson.TotalFreedomMod.Commands;
import java.util.ArrayList;
import java.util.List;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;

View File

@ -1,6 +1,6 @@
package me.StevenLawson.TotalFreedomMod.Commands;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;

View File

@ -1,10 +1,10 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static org.apache.commons.lang3.StringEscapeUtils.*;
import static net.minecraft.util.org.apache.commons.lang3.StringEscapeUtils.*;
public class HTMLGenerationTools
{
@ -41,7 +41,7 @@ public class HTMLGenerationTools
return output.toString();
}
public static <T> String list(List<T> list)
public static <T> String list(Collection<T> list)
{
StringBuilder output = new StringBuilder();

View File

@ -1,28 +1,65 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import net.minecraft.util.org.apache.commons.io.FileUtils;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import static me.StevenLawson.TotalFreedomMod.HTTPD.HTMLGenerationTools.*;
public class Module_dump extends TFM_HTTPD_Module
{
public Module_dump(String uri, NanoHTTPD.Method method, Map<String, String> headers, Map<String, String> params, Map<String, String> files)
private File echoFile = null;
private final String body;
public Module_dump(NanoHTTPD.HTTPSession session)
{
super(uri, method, headers, params, files);
super(session);
//Body needs to be computed before getResponse, so we know if a text response or a file echo is needed.
this.body = body();
}
@Override
public NanoHTTPD.Response getResponse()
{
String echo = params.get("echo");
boolean doEcho = echo != null && ((echo = echo.toLowerCase().trim()).equalsIgnoreCase("true") || echo.equalsIgnoreCase("1"));
if (doEcho && this.echoFile != null && this.echoFile.exists())
{
return TFM_HTTPD_Manager.serveFileBasic(this.echoFile);
}
else
{
return super.getResponse();
}
}
@Override
public String getBody()
{
return body;
}
private String body()
{
StringBuilder responseBody = new StringBuilder();
String remoteAddress = socket.getInetAddress().getHostAddress();
String[] args = StringUtils.split(uri, "/");
Map<String, String> files = getFiles();
responseBody
.append(paragraph("URI: " + uri))
.append(paragraph("args (Length: " + args.length + "): " + StringUtils.join(args, ",")))
.append(paragraph("Method: " + method.toString()))
.append(paragraph("Remote Address: " + remoteAddress))
.append(paragraph("Headers:"))
.append(list(headers))
.append(paragraph("Params:"))
@ -30,6 +67,39 @@ public class Module_dump extends TFM_HTTPD_Module
.append(paragraph("Files:"))
.append(list(files));
Iterator<Map.Entry<String, String>> it = files.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<String, String> entry = it.next();
String formName = entry.getKey();
String tempFileName = entry.getValue();
String origFileName = params.get(formName);
File tempFile = new File(tempFileName);
if (tempFile.exists())
{
this.echoFile = tempFile;
if (origFileName.contains("../"))
{
continue;
}
String targetFileName = "./public_html/uploads/" + origFileName;
File targetFile = new File(targetFileName);
try
{
FileUtils.copyFile(tempFile, targetFile);
}
catch (IOException ex)
{
TFM_Log.severe(ex);
}
}
}
return responseBody.toString();
}

View File

@ -12,9 +12,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import static me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.*;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
/*
* This class was adapted from https://github.com/NanoHttpd/nanohttpd/blob/master/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
@ -22,7 +22,7 @@ import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
public class Module_file extends TFM_HTTPD_Module
{
private final File rootDir = new File(TFM_ConfigEntry.HTTPD_PUBLIC_FOLDER.getString());
private static final Map<String, String> MIME_TYPES = new HashMap<String, String>();
public static final Map<String, String> MIME_TYPES = new HashMap<String, String>();
static
{
@ -33,6 +33,7 @@ public class Module_file extends TFM_HTTPD_Module
MIME_TYPES.put("java", "text/x-java-source, text/java");
MIME_TYPES.put("txt", "text/plain");
MIME_TYPES.put("asc", "text/plain");
MIME_TYPES.put("yml", "text/yaml");
MIME_TYPES.put("gif", "image/gif");
MIME_TYPES.put("jpg", "image/jpeg");
MIME_TYPES.put("jpeg", "image/jpeg");
@ -53,9 +54,9 @@ public class Module_file extends TFM_HTTPD_Module
MIME_TYPES.put("class", "application/octet-stream");
}
public Module_file(String uri, NanoHTTPD.Method method, Map<String, String> headers, Map<String, String> params, Map<String, String> files)
public Module_file(NanoHTTPD.HTTPSession session)
{
super(uri, method, headers, params, files);
super(session);
}
private File getRootDir()
@ -173,7 +174,7 @@ public class Module_file extends TFM_HTTPD_Module
}
if (mime == null)
{
mime = NanoHTTPD.MIME_DEFAULT_BINARY;
mime = TFM_HTTPD_Manager.MIME_DEFAULT_BINARY;
}
// Calculate etag

View File

@ -13,16 +13,16 @@ import me.StevenLawson.TotalFreedomMod.Commands.TFM_CommandLoader.TFM_DynamicCom
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.bukkit.command.PluginIdentifiableCommand;
import org.apache.commons.lang3.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import static me.StevenLawson.TotalFreedomMod.HTTPD.HTMLGenerationTools.*;
import static org.apache.commons.lang3.StringEscapeUtils.*;
import static net.minecraft.util.org.apache.commons.lang3.StringEscapeUtils.*;
public class Module_help extends TFM_HTTPD_Module
{
public Module_help(String uri, NanoHTTPD.Method method, Map<String, String> headers, Map<String, String> params, Map<String, String> files)
public Module_help(NanoHTTPD.HTTPSession session)
{
super(uri, method, headers, params, files);
super(session);
}
@Override
@ -147,4 +147,9 @@ public class Module_help extends TFM_HTTPD_Module
{
return ".commandName{font-weight:bold;}.commandDescription{padding-left:15px;}li{margin:.15em;padding:.15em;}";
}
// @Override
// public String getScript()
// {
// return "$(document).ready(function(){console.log(\"Ready\");});";
// }
}

View File

@ -1,6 +1,5 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.util.Map;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.bukkit.Bukkit;
@ -8,9 +7,9 @@ import org.bukkit.entity.Player;
public class Module_list extends TFM_HTTPD_Module
{
public Module_list(String uri, NanoHTTPD.Method method, Map<String, String> headers, Map<String, String> params, Map<String, String> files)
public Module_list(NanoHTTPD.HTTPSession session)
{
super(uri, method, headers, params, files);
super(session);
}
@Override

View File

@ -0,0 +1,27 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.io.File;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
public class Module_permbans extends TFM_HTTPD_Module
{
public Module_permbans(NanoHTTPD.HTTPSession session)
{
super(session);
}
@Override
public NanoHTTPD.Response getResponse()
{
File permbanFile = new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.PERMBAN_FILE);
if (permbanFile.exists())
{
return TFM_HTTPD_Manager.serveFileBasic(new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.PERMBAN_FILE));
}
else
{
return new NanoHTTPD.Response(NanoHTTPD.Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT,
"Error 404: Not Found - The requested resource was not found on this server.");
}
}
}

View File

@ -0,0 +1,296 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.Method;
import me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.Response;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import me.StevenLawson.TotalFreedomMod.TFM_Superadmin;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import net.minecraft.util.org.apache.commons.io.FileUtils;
import net.minecraft.util.org.apache.commons.lang3.StringEscapeUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
public class Module_schematic extends TFM_HTTPD_Module
{
private static final File SCHEMATIC_FOLDER = new File("./plugins/WorldEdit/schematics/");
private static final String REQUEST_FORM_FILE_ELEMENT_NAME = "schematicFile";
private static final Pattern SCHEMATIC_FILENAME_LC = Pattern.compile("^[a-z0-9]{1,30}\\.schematic$");
private static final String[] SCHEMATIC_FILTER = new String[]
{
"schematic"
};
private static final String UPLOAD_FORM =
"<form method=\"post\" name=\"schematicForm\" id=\"schematicForm\" action=\"/schematic/upload/\" enctype=\"multipart/form-data\">\n"
+ "<p>Select a schematic file to upload. Filenames must be alphanumeric, between 1 and 30 characters long (inclusive), and have a .schematic extension.</p>\n"
+ "<input type=\"file\" id=\"schematicFile\" name=\"schematicFile\" />\n"
+ "<br />\n"
+ "<button type=\"submit\">Submit</button>\n"
+ "</form>";
public Module_schematic(NanoHTTPD.HTTPSession session)
{
super(session);
}
@Override
public Response getResponse()
{
try
{
return new TFM_HTTPD_PageBuilder(body(), title(), null, null).getResponse();
}
catch (ResponseOverrideException ex)
{
return ex.getResponse();
}
}
public String title()
{
return "TotalFreedomMod :: Schematic Manager";
}
public String body() throws ResponseOverrideException
{
if (!SCHEMATIC_FOLDER.exists())
{
return HTMLGenerationTools.paragraph("Can't find the WorldEdit schematic folder.");
}
final StringBuilder out = new StringBuilder();
final String[] args = StringUtils.split(uri, "/");
final ModuleMode mode = ModuleMode.getMode(getArg(args, 1));
switch (mode)
{
case LIST:
{
Collection<File> schematics = FileUtils.listFiles(SCHEMATIC_FOLDER, SCHEMATIC_FILTER, false);
final List<String> schematicsFormatted = new ArrayList<String>();
for (File schematic : schematics)
{
String filename = StringEscapeUtils.escapeHtml4(schematic.getName());
schematicsFormatted.add("<li><a href=\"/schematic/download?schematicName=" + filename + "\">" + filename + "</a></li>");
}
Collections.sort(schematicsFormatted, new Comparator<String>()
{
@Override
public int compare(String a, String b)
{
return a.toLowerCase().compareTo(b.toLowerCase());
}
});
out
.append(HTMLGenerationTools.heading("Schematics:", 1))
.append("<ul>")
.append(StringUtils.join(schematicsFormatted, "\r\n"))
.append("</ul>");
break;
}
case DOWNLOAD:
{
try
{
throw new ResponseOverrideException(downloadSchematic(params.get("schematicName")));
}
catch (SchematicTransferException ex)
{
out.append(HTMLGenerationTools.paragraph("Error downloading schematic: " + ex.getMessage()));
}
break;
}
case UPLOAD:
{
final String remoteAddress = socket.getInetAddress().getHostAddress();
if (!isAuthorized(remoteAddress))
{
out.append(HTMLGenerationTools.paragraph("Schematic upload access denied: Your IP, " + remoteAddress + ", is not registered to a superadmin on this server."));
}
else
{
if (method == Method.POST)
{
try
{
uploadSchematic();
out.append(HTMLGenerationTools.paragraph("Schematic uploaded successfully."));
}
catch (SchematicTransferException ex)
{
out.append(HTMLGenerationTools.paragraph("Error uploading schematic: " + ex.getMessage()));
}
}
else
{
out.append(UPLOAD_FORM);
}
}
break;
}
default:
{
out.append(HTMLGenerationTools.paragraph("Invalid request mode."));
break;
}
}
return out.toString();
}
private boolean uploadSchematic() throws SchematicTransferException
{
Map<String, String> files = getFiles();
final String tempFileName = files.get(REQUEST_FORM_FILE_ELEMENT_NAME);
if (tempFileName == null)
{
throw new SchematicTransferException("No file transmitted to server.");
}
final File tempFile = new File(tempFileName);
if (!tempFile.exists())
{
throw new SchematicTransferException();
}
String origFileName = params.get(REQUEST_FORM_FILE_ELEMENT_NAME);
if (origFileName == null || (origFileName = origFileName.trim()).isEmpty())
{
throw new SchematicTransferException("Can't resolve original file name.");
}
if (tempFile.length() > FileUtils.ONE_KB * 64L)
{
throw new SchematicTransferException("Schematic is too big (64kb max).");
}
if (!SCHEMATIC_FILENAME_LC.matcher(origFileName.toLowerCase()).find())
{
throw new SchematicTransferException("File name must be alphanumeric, between 1 and 30 characters long (inclusive), and have a \".schematic\" extension.");
}
final File targetFile = new File(SCHEMATIC_FOLDER.getPath(), origFileName);
if (targetFile.exists())
{
throw new SchematicTransferException("Schematic already exists on the server.");
}
try
{
FileUtils.copyFile(tempFile, targetFile);
}
catch (IOException ex)
{
TFM_Log.severe(ex);
throw new SchematicTransferException();
}
return true;
}
private Response downloadSchematic(String schematicName) throws SchematicTransferException
{
if (schematicName == null || !SCHEMATIC_FILENAME_LC.matcher((schematicName = schematicName.trim()).toLowerCase()).find())
{
throw new SchematicTransferException("Invalid schematic name requested: " + schematicName);
}
final File targetFile = new File(SCHEMATIC_FOLDER.getPath(), schematicName);
if (!targetFile.exists())
{
throw new SchematicTransferException("Schematic not found: " + schematicName);
}
Response response = TFM_HTTPD_Manager.serveFileBasic(targetFile);
response.addHeader("Content-Disposition", "attachment; filename=" + targetFile.getName() + ";");
return response;
}
private boolean isAuthorized(String remoteAddress)
{
TFM_Superadmin entry = TFM_SuperadminList.getAdminEntryByIP(remoteAddress);
return entry != null && entry.isActivated();
}
private static class SchematicTransferException extends Exception
{
public SchematicTransferException()
{
}
public SchematicTransferException(String string)
{
super(string);
}
}
private static class ResponseOverrideException extends Exception
{
private final Response response;
public ResponseOverrideException(Response response)
{
this.response = response;
}
public Response getResponse()
{
return response;
}
}
private static String getArg(String[] args, int index)
{
String out = (args.length == index + 1 ? args[index] : null);
return (out == null ? null : (out.trim().isEmpty() ? null : out.trim()));
}
private static enum ModuleMode
{
LIST("list"),
UPLOAD("upload"),
DOWNLOAD("download"),
INVALID(null);
//
private final String modeName;
private ModuleMode(String modeName)
{
this.modeName = modeName;
}
@Override
public String toString()
{
return this.modeName;
}
public static ModuleMode getMode(String needle)
{
for (ModuleMode mode : values())
{
final String haystack = mode.toString();
if (haystack != null && haystack.equalsIgnoreCase(needle))
{
return mode;
}
}
return INVALID;
}
}
}

View File

@ -1,11 +1,7 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.URLDecoder;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
@ -67,17 +63,21 @@ public abstract class NanoHTTPD
*/
public static final String MIME_HTML = "text/html";
/**
* Common mime type for dynamic content: binary
* Pseudo-Parameter to use to store the actual query string in the parameters map for later re-processing.
*/
public static final String MIME_DEFAULT_BINARY = "application/octet-stream";
private static final String QUERY_STRING_PARAMETER = "NanoHttpd.QUERY_STRING";
private final String hostname;
private final int myPort;
private ServerSocket myServerSocket;
private Thread myThread;
/**
* Pseudo-Parameter to use to store the actual query string in the parameters map for later re-processing.
* Pluggable strategy for asynchronously executing requests.
*/
private static final String QUERY_STRING_PARAMETER = "NanoHttpd.QUERY_STRING";
private AsyncRunner asyncRunner;
/**
* Pluggable strategy for creating and cleaning up temporary files.
*/
private TempFileManagerFactory tempFileManagerFactory;
/**
* Constructs an HTTP server on given port.
@ -98,8 +98,51 @@ public abstract class NanoHTTPD
setAsyncRunner(new DefaultAsyncRunner());
}
private static final void safeClose(ServerSocket serverSocket)
{
if (serverSocket != null)
{
try
{
serverSocket.close();
}
catch (IOException e)
{
}
}
}
private static final void safeClose(Socket socket)
{
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
}
}
}
private static final void safeClose(Closeable closeable)
{
if (closeable != null)
{
try
{
closeable.close();
}
catch (IOException e)
{
}
}
}
/**
* Start the server.
*
* @throws IOException if the socket is in use.
*/
public void start() throws IOException
@ -134,7 +177,7 @@ public abstract class NanoHTTPD
{
outputStream = finalAccept.getOutputStream();
TempFileManager tempFileManager = tempFileManagerFactory.create();
HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream);
HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAccept);
while (!finalAccept.isClosed())
{
session.execute();
@ -187,20 +230,39 @@ public abstract class NanoHTTPD
}
}
public final int getListeningPort()
{
return myServerSocket == null ? -1 : myServerSocket.getLocalPort();
}
public final boolean wasStarted()
{
return myServerSocket != null && myThread != null;
}
public final boolean isAlive()
{
return wasStarted() && !myServerSocket.isClosed() && myThread.isAlive();
}
/**
* Override this to customize the server.
* <p/>
* <p/>
* (By default, this delegates to serveFile() and allows directory listing.)
*
* @param uri Percent-decoded URI without parameters, for example "/index.cgi"
* @param method "GET", "POST" etc.
* @param parms Parsed, percent decoded parameters from URI and, in case of POST, data.
* @param uri Percent-decoded URI without parameters, for example "/index.cgi"
* @param method "GET", "POST" etc.
* @param parms Parsed, percent decoded parameters from URI and, in case of POST, data.
* @param headers Header entries, percent decoded
* @return HTTP response, see class Response for details
*/
public abstract Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms,
Map<String, String> files);
@Deprecated
public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms,
Map<String, String> files)
{
return new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Not Found");
}
/**
* Override this to customize the server.
@ -211,32 +273,32 @@ public abstract class NanoHTTPD
* @param session The HTTP session
* @return HTTP response, see class Response for details
*/
protected Response serve(HTTPSession session)
public Response serve(HTTPSession session)
{
Map<String, String> files = new HashMap<String, String>();
try
{
session.parseBody(files);
}
catch (IOException ioe)
{
return new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
}
catch (ResponseException re)
{
return new Response(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
}
String uri = session.getUri();
Method method = session.getMethod();
Map<String, String> parms = session.getParms();
Map<String, String> headers = session.getHeaders();
return serve(uri, method, headers, parms, files);
if (Method.PUT.equals(method) || Method.POST.equals(method))
{
try
{
session.parseBody(files);
}
catch (IOException ioe)
{
return new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
}
catch (ResponseException re)
{
return new Response(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
}
}
return serve(session.getUri(), method, session.getHeaders(), session.getParms(), files);
}
/**
* Decode percent encoded <code>String</code> values.
*
* @param str the percent encoded <code>String</code>
* @return expanded form of the input, for example "foo%20bar" becomes "foo bar"
*/
@ -299,6 +361,36 @@ public abstract class NanoHTTPD
return parms;
}
// ------------------------------------------------------------------------------- //
//
// Threading Strategy.
//
// ------------------------------------------------------------------------------- //
/**
* Pluggable strategy for asynchronously executing requests.
*
* @param asyncRunner new strategy for handling threads.
*/
public void setAsyncRunner(AsyncRunner asyncRunner)
{
this.asyncRunner = asyncRunner;
}
// ------------------------------------------------------------------------------- //
//
// Temp file handling strategy.
//
// ------------------------------------------------------------------------------- //
/**
* Pluggable strategy for creating and cleaning up temporary files.
*
* @param tempFileManagerFactory new strategy for handling temp files.
*/
public void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory)
{
this.tempFileManagerFactory = tempFileManagerFactory;
}
/**
* HTTP Request methods, with the ability to decode a <code>String</code> back to its enum value.
*/
@ -318,24 +410,6 @@ public abstract class NanoHTTPD
return null;
}
}
// ------------------------------------------------------------------------------- //
//
// Threading Strategy.
//
// ------------------------------------------------------------------------------- //
/**
* Pluggable strategy for asynchronously executing requests.
*/
private AsyncRunner asyncRunner;
/**
* Pluggable strategy for asynchronously executing requests.
* @param asyncRunner new strategy for handling threads.
*/
public void setAsyncRunner(AsyncRunner asyncRunner)
{
this.asyncRunner = asyncRunner;
}
/**
* Pluggable strategy for asynchronously executing requests.
@ -345,9 +419,46 @@ public abstract class NanoHTTPD
void exec(Runnable code);
}
/**
* Factory to create temp file managers.
*/
public interface TempFileManagerFactory
{
TempFileManager create();
}
// ------------------------------------------------------------------------------- //
/**
* Temp file manager.
* <p/>
* <p>Temp file managers are created 1-to-1 with incoming requests, to create and cleanup
* temporary files created as a result of handling the request.</p>
*/
public interface TempFileManager
{
TempFile createTempFile() throws Exception;
void clear();
}
/**
* A temp file.
* <p/>
* <p>Temp files are responsible for managing the actual temporary storage and cleaning
* themselves up when no longer needed.</p>
*/
public interface TempFile
{
OutputStream open() throws Exception;
void delete() throws Exception;
String getName();
}
/**
* Default threading strategy for NanoHttpd.
*
* <p/>
* <p>By default, the server spawns a new Thread for every incoming request. These are set
* to <i>daemon</i> status, and named according to the request number. The name is
* useful when profiling the application.</p>
@ -366,76 +477,10 @@ public abstract class NanoHTTPD
t.start();
}
}
// ------------------------------------------------------------------------------- //
//
// Temp file handling strategy.
//
// ------------------------------------------------------------------------------- //
/**
* Pluggable strategy for creating and cleaning up temporary files.
*/
private TempFileManagerFactory tempFileManagerFactory;
/**
* Pluggable strategy for creating and cleaning up temporary files.
* @param tempFileManagerFactory new strategy for handling temp files.
*/
public void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory)
{
this.tempFileManagerFactory = tempFileManagerFactory;
}
/**
* Factory to create temp file managers.
*/
public interface TempFileManagerFactory
{
TempFileManager create();
}
/**
* Temp file manager.
*
* <p>Temp file managers are created 1-to-1 with incoming requests, to create and cleanup
* temporary files created as a result of handling the request.</p>
*/
public interface TempFileManager
{
TempFile createTempFile() throws Exception;
void clear();
}
/**
* A temp file.
*
* <p>Temp files are responsible for managing the actual temporary storage and cleaning
* themselves up when no longer needed.</p>
*/
public interface TempFile
{
OutputStream open() throws Exception;
void delete() throws Exception;
String getName();
}
/**
* Default strategy for creating and cleaning up temporary files.
*/
private class DefaultTempFileManagerFactory implements TempFileManagerFactory
{
@Override
public TempFileManager create()
{
return new DefaultTempFileManager();
}
}
/**
* Default strategy for creating and cleaning up temporary files.
*
* <p/>
* <p></p>This class stores its files in the standard location (that is,
* wherever <code>java.io.tmpdir</code> points to). Files are added
* to an internal list, and deleted when no longer needed (that is,
@ -480,7 +525,7 @@ public abstract class NanoHTTPD
/**
* Default strategy for creating and cleaning up temporary files.
*
* <p/>
* <p></p></[>By default, files are created by <code>File.createTempFile()</code> in
* the directory specified.</p>
*/
@ -515,7 +560,6 @@ public abstract class NanoHTTPD
}
}
// ------------------------------------------------------------------------------- //
/**
* HTTP response. Return one of these from serve().
*/
@ -541,6 +585,10 @@ public abstract class NanoHTTPD
* The request method that spawned this response.
*/
private Method requestMethod;
/**
* Use chunkedTransfer
*/
private boolean chunkedTransfer;
/**
* Default constructor: response = HTTP_OK, mime = MIME_HTML and your supplied message
@ -622,31 +670,15 @@ public abstract class NanoHTTPD
}
}
int pending = data != null ? data.available() : -1; // This is to support partial sends, see serveFile()
if (pending > 0)
pw.print("Connection: keep-alive\r\n");
if (requestMethod != Method.HEAD && chunkedTransfer)
{
pw.print("Connection: keep-alive\r\n");
pw.print("Content-Length: " + pending + "\r\n");
sendAsChunked(outputStream, pw);
}
pw.print("\r\n");
pw.flush();
if (requestMethod != Method.HEAD && data != null)
else
{
int BUFFER_SIZE = 16 * 1024;
byte[] buff = new byte[BUFFER_SIZE];
while (pending > 0)
{
int read = data.read(buff, 0, ((pending > BUFFER_SIZE) ? BUFFER_SIZE : pending));
if (read <= 0)
{
break;
}
outputStream.write(buff, 0, read);
pending -= read;
}
sendAsFixedLength(outputStream, pw);
}
outputStream.flush();
safeClose(data);
@ -657,6 +689,50 @@ public abstract class NanoHTTPD
}
}
private void sendAsChunked(OutputStream outputStream, PrintWriter pw) throws IOException
{
pw.print("Transfer-Encoding: chunked\r\n");
pw.print("\r\n");
pw.flush();
int BUFFER_SIZE = 16 * 1024;
byte[] CRLF = "\r\n".getBytes();
byte[] buff = new byte[BUFFER_SIZE];
int read;
while ((read = data.read(buff)) > 0)
{
outputStream.write(String.format("%x\r\n", read).getBytes());
outputStream.write(buff, 0, read);
outputStream.write(CRLF);
}
outputStream.write(String.format("0\r\n\r\n").getBytes());
}
private void sendAsFixedLength(OutputStream outputStream, PrintWriter pw) throws IOException
{
int pending = data != null ? data.available() : 0; // This is to support partial sends, see serveFile()
pw.print("Content-Length: " + pending + "\r\n");
pw.print("\r\n");
pw.flush();
if (requestMethod != Method.HEAD && data != null)
{
int BUFFER_SIZE = 16 * 1024;
byte[] buff = new byte[BUFFER_SIZE];
while (pending > 0)
{
int read = data.read(buff, 0, ((pending > BUFFER_SIZE) ? BUFFER_SIZE : pending));
if (read <= 0)
{
break;
}
outputStream.write(buff, 0, read);
pending -= read;
}
}
}
public Status getStatus()
{
return status;
@ -697,6 +773,11 @@ public abstract class NanoHTTPD
this.requestMethod = requestMethod;
}
public void setChunkedTransfer(boolean chunkedTransfer)
{
this.chunkedTransfer = chunkedTransfer;
}
/**
* Some HTTP response status codes
*/
@ -727,6 +808,40 @@ public abstract class NanoHTTPD
}
}
public static final class ResponseException extends Exception
{
private final Response.Status status;
public ResponseException(Response.Status status, String message)
{
super(message);
this.status = status;
}
public ResponseException(Response.Status status, String message, Exception e)
{
super(message, e);
this.status = status;
}
public Response.Status getStatus()
{
return status;
}
}
/**
* Default strategy for creating and cleaning up temporary files.
*/
private class DefaultTempFileManagerFactory implements TempFileManagerFactory
{
@Override
public TempFileManager create()
{
return new DefaultTempFileManager();
}
}
/**
* Handles one session, i.e. parses the HTTP request and returns the response.
*/
@ -734,20 +849,23 @@ public abstract class NanoHTTPD
{
public static final int BUFSIZE = 8192;
private final TempFileManager tempFileManager;
private InputStream inputStream;
private final OutputStream outputStream;
private final Socket socket;
private InputStream inputStream;
private int splitbyte;
private int rlen;
private String uri;
private Method method;
private Map<String, String> parms;
private Map<String, String> headers;
private CookieHandler cookies;
public HTTPSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream)
public HTTPSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream, Socket socket)
{
this.tempFileManager = tempFileManager;
this.inputStream = inputStream;
this.outputStream = outputStream;
this.socket = socket;
}
public void execute() throws IOException
@ -805,6 +923,8 @@ public abstract class NanoHTTPD
uri = pre.get("uri");
cookies = new CookieHandler(headers);
// Ok, now do the serve()
Response r = serve(this);
if (r == null)
@ -813,6 +933,7 @@ public abstract class NanoHTTPD
}
else
{
cookies.unloadQueue(r);
r.setRequestMethod(method);
r.send(outputStream);
}
@ -840,7 +961,7 @@ public abstract class NanoHTTPD
}
}
private void parseBody(Map<String, String> files) throws IOException, ResponseException
protected void parseBody(Map<String, String> files) throws IOException, ResponseException
{
RandomAccessFile randomAccessFile = null;
BufferedReader in = null;
@ -911,7 +1032,7 @@ public abstract class NanoHTTPD
String boundaryStartString = "boundary=";
int boundaryContentStart = contentTypeHeader.indexOf(boundaryStartString) + boundaryStartString.length();
String boundary = contentTypeHeader.substring(boundaryContentStart, contentTypeHeader.length());
if (boundary.startsWith("\"") && boundary.startsWith("\""))
if (boundary.startsWith("\"") && boundary.endsWith("\""))
{
boundary = boundary.substring(1, boundary.length() - 1);
}
@ -1186,7 +1307,7 @@ public abstract class NanoHTTPD
path = tempFile.getName();
}
catch (Exception e)
{
{ // Catch exception if any
TFM_Log.severe(e);
}
finally
@ -1281,84 +1402,141 @@ public abstract class NanoHTTPD
{
return inputStream;
}
}
private static final class ResponseException extends Exception
{
private final Response.Status status;
public ResponseException(Response.Status status, String message)
public CookieHandler getCookies()
{
super(message);
this.status = status;
return cookies;
}
public ResponseException(Response.Status status, String message, Exception e)
public Socket getSocket()
{
super(message, e);
this.status = status;
}
public Response.Status getStatus()
{
return status;
return socket;
}
}
private static final void safeClose(ServerSocket serverSocket)
public static class Cookie
{
if (serverSocket != null)
private String n, v, e;
public Cookie(String name, String value, String expires)
{
try
{
serverSocket.close();
}
catch (IOException e)
{
}
n = name;
v = value;
e = expires;
}
public Cookie(String name, String value)
{
this(name, value, 30);
}
public Cookie(String name, String value, int numDays)
{
n = name;
v = value;
e = getHTTPTime(numDays);
}
public String getHTTPHeader()
{
String fmt = "%s=%s; expires=%s";
return String.format(fmt, n, v, e);
}
public static String getHTTPTime(int days)
{
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.add(Calendar.DAY_OF_MONTH, days);
return dateFormat.format(calendar.getTime());
}
}
private static final void safeClose(Socket socket)
/**
* Provides rudimentary support for cookies.
* Doesn't support 'path', 'secure' nor 'httpOnly'.
* Feel free to improve it and/or add unsupported features.
*
* @author LordFokas
*/
public class CookieHandler implements Iterable<String>
{
if (socket != null)
private HashMap<String, String> cookies = new HashMap<String, String>();
private ArrayList<Cookie> queue = new ArrayList<Cookie>();
public CookieHandler(Map<String, String> httpHeaders)
{
try
{
socket.close();
}
catch (IOException e)
String raw = httpHeaders.get("cookie");
if (raw != null)
{
String[] tokens = raw.split(";");
for (String token : tokens)
{
String[] data = token.trim().split("=");
if (data.length == 2)
{
cookies.put(data[0], data[1]);
}
}
}
}
}
private static final void safeClose(Closeable closeable)
{
if (closeable != null)
@Override
public Iterator<String> iterator()
{
try
{
closeable.close();
}
catch (IOException e)
return cookies.keySet().iterator();
}
/**
* Read a cookie from the HTTP Headers.
*
* @param name The cookie's name.
* @return The cookie's value if it exists, null otherwise.
*/
public String read(String name)
{
return cookies.get(name);
}
/**
* Sets a cookie.
*
* @param name The cookie's name.
* @param value The cookie's value.
* @param expires How many days until the cookie expires.
*/
public void set(String name, String value, int expires)
{
queue.add(new Cookie(name, value, Cookie.getHTTPTime(expires)));
}
public void set(Cookie cookie)
{
queue.add(cookie);
}
/**
* Set a cookie with an expiration date from a month ago, effectively deleting it on the client side.
*
* @param name The cookie name.
*/
public void delete(String name)
{
set(name, "-delete-", -30);
}
/**
* Internally used by the webserver to add all queued cookies into the Response's HTTP Headers.
*
* @param response The Response object to which headers the queued cookies will be added.
*/
public void unloadQueue(Response response)
{
for (Cookie cookie : queue)
{
response.addHeader("Set-Cookie", cookie.getHTTPHeader());
}
}
}
public final int getListeningPort()
{
return myServerSocket == null ? -1 : myServerSocket.getLocalPort();
}
public final boolean wasStarted()
{
return myServerSocket != null && myThread != null;
}
public final boolean isAlive()
{
return wasStarted() && !myServerSocket.isClosed() && myThread.isAlive();
}
}

View File

@ -1,18 +1,27 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import static me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.MIME_PLAINTEXT;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.HTTPSession;
import me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.Response;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.exception.ExceptionUtils;
import org.bukkit.Bukkit;
public class TFM_HTTPD_Manager
{
@Deprecated
public static String MIME_DEFAULT_BINARY = "application/octet-stream";
//
private static final Pattern EXT_REGEX = Pattern.compile("\\.([^\\.\\s]+)$");
//
public static final int PORT = TFM_ConfigEntry.HTTPD_PORT.getInteger();
//
private final TFM_HTTPD httpd = new TFM_HTTPD(PORT);
@ -61,34 +70,118 @@ public class TFM_HTTPD_Manager
private static enum ModuleType
{
DUMP(false, "dump"),
HELP(true, "help"),
LIST(true, "list"),
FILE(false, "file");
private final boolean runOnBukkitThread;
private final String name;
private ModuleType(boolean runOnBukkitThread, String name)
DUMP(new ModuleExecutable(false, "dump")
{
this.runOnBukkitThread = runOnBukkitThread;
this.name = name;
@Override
public Response getResponse(HTTPSession session)
{
return new Response(Response.Status.OK, NanoHTTPD.MIME_PLAINTEXT, "The DUMP module is disabled. It is intended for debugging use only.");
}
}),
HELP(new ModuleExecutable(true, "help")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_help(session).getResponse();
}
}),
LIST(new ModuleExecutable(true, "list")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_list(session).getResponse();
}
}),
FILE(new ModuleExecutable(false, "file")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_file(session).getResponse();
}
}),
SCHEMATIC(new ModuleExecutable(false, "schematic")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_schematic(session).getResponse();
}
}),
PERMBANS(new ModuleExecutable(false, "permbans")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_permbans(session).getResponse();
}
});
//
private final ModuleExecutable moduleExecutable;
private ModuleType(ModuleExecutable moduleExecutable)
{
this.moduleExecutable = moduleExecutable;
}
public boolean isRunOnBukkitThread()
private abstract static class ModuleExecutable
{
return runOnBukkitThread;
private final boolean runOnBukkitThread;
private final String name;
public ModuleExecutable(boolean runOnBukkitThread, String name)
{
this.runOnBukkitThread = runOnBukkitThread;
this.name = name;
}
public Response execute(final HTTPSession session)
{
try
{
if (this.runOnBukkitThread)
{
return Bukkit.getScheduler().callSyncMethod(TotalFreedomMod.plugin, new Callable<Response>()
{
@Override
public Response call() throws Exception
{
return getResponse(session);
}
}).get();
}
else
{
return getResponse(session);
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return null;
}
public abstract Response getResponse(HTTPSession session);
public String getName()
{
return name;
}
}
public String getName()
public ModuleExecutable getModuleExecutable()
{
return name;
return moduleExecutable;
}
private static ModuleType getByName(String needle)
{
for (ModuleType type : values())
{
if (type.getName().equalsIgnoreCase(needle))
if (type.getModuleExecutable().getName().equalsIgnoreCase(needle))
{
return type;
}
@ -110,63 +203,61 @@ public class TFM_HTTPD_Manager
}
@Override
public Response serve(final String uri, final Method method, final Map<String, String> headers, final Map<String, String> params, final Map<String, String> files)
public Response serve(HTTPSession session)
{
Response response = null;
Response response;
final String[] args = StringUtils.split(uri, "/");
final ModuleType moduleType = args.length >= 1 ? ModuleType.getByName(args[0]) : ModuleType.FILE;
if (moduleType.isRunOnBukkitThread())
try
{
Future<Response> responseCall = Bukkit.getScheduler().callSyncMethod(TotalFreedomMod.plugin, new Callable<Response>()
{
@Override
public Response call() throws Exception
{
switch (moduleType)
{
case HELP:
return new Module_help(uri, method, headers, params, files).getResponse();
case LIST:
return new Module_list(uri, method, headers, params, files).getResponse();
default:
return null;
}
}
});
try
{
response = responseCall.get();
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
final String[] args = StringUtils.split(session.getUri(), "/");
final ModuleType moduleType = args.length >= 1 ? ModuleType.getByName(args[0]) : ModuleType.FILE;
response = moduleType.getModuleExecutable().execute(session);
}
else
catch (Exception ex)
{
switch (moduleType)
{
case DUMP:
response = new Module_dump(uri, method, headers, params, files).getResponse();
break;
default:
response = new Module_file(uri, method, headers, params, files).getResponse();
}
response = new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "Error 500: Internal Server Error\r\n" + ex.getMessage() + "\r\n" + ExceptionUtils.getStackTrace(ex));
}
if (response == null)
{
return new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Error 404: Not Found - The requested resource was not found on this server.");
response = new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Error 404: Not Found - The requested resource was not found on this server.");
}
else
return response;
}
}
public static Response serveFileBasic(File file)
{
Response response = null;
if (file != null && file.exists())
{
try
{
return response;
String mimetype = null;
Matcher matcher = EXT_REGEX.matcher(file.getCanonicalPath());
if (matcher.find())
{
mimetype = Module_file.MIME_TYPES.get(matcher.group(1));
}
if (mimetype == null || mimetype.trim().isEmpty())
{
mimetype = MIME_DEFAULT_BINARY;
}
response = new Response(Response.Status.OK, mimetype, new FileInputStream(file));
response.addHeader("Content-Length", "" + file.length());
}
catch (IOException ex)
{
TFM_Log.severe(ex);
}
}
return response;
}
public static TFM_HTTPD_Manager getInstance()

View File

@ -1,7 +1,10 @@
package me.StevenLawson.TotalFreedomMod.HTTPD;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.*;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
public abstract class TFM_HTTPD_Module
{
@ -9,34 +12,57 @@ public abstract class TFM_HTTPD_Module
protected final Method method;
protected final Map<String, String> headers;
protected final Map<String, String> params;
protected final Map<String, String> files;
protected final Socket socket;
protected final HTTPSession session;
public TFM_HTTPD_Module(String uri, Method method, Map<String, String> headers, Map<String, String> params, Map<String, String> files)
public TFM_HTTPD_Module(HTTPSession session)
{
this.uri = uri;
this.method = method;
this.headers = headers;
this.params = params;
this.files = files;
this.uri = session.getUri();
this.method = session.getMethod();
this.headers = session.getHeaders();
this.params = session.getParms();
this.socket = session.getSocket();
this.session = session;
}
public String getBody()
{
return "";
return null;
}
public String getTitle()
{
return "";
return null;
}
public String getStyle()
{
return "";
return null;
}
public String getScript()
{
return null;
}
public Response getResponse()
{
return new TFM_HTTPD_PageBuilder(getBody(), getTitle(), getStyle()).getResponse();
return new TFM_HTTPD_PageBuilder(getBody(), getTitle(), getStyle(), getScript()).getResponse();
}
protected final Map<String, String> getFiles()
{
Map<String, String> files = new HashMap<String, String>();
try
{
session.parseBody(files);
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return files;
}
}

View File

@ -10,24 +10,32 @@ public class TFM_HTTPD_PageBuilder
+ "<head>\r\n"
+ "<title>{$TITLE}</title>\r\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n"
+ "<style type=\"text/css\">{$STYLE}</style>\r\n"
+ "{$STYLE}"
+ "{$SCRIPT}"
+ "</head>\r\n"
+ "<body>{$BODY}</body>\r\n"
+ "<body>\r\n{$BODY}</body>\r\n"
+ "</html>\r\n";
private static final String STYLE = "<style type=\"text/css\">{$STYLE}</style>\r\n";
private static final String SCRIPT =
"<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"></script>\r\n"
+ "<script src=\"//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js\"></script>\r\n"
+ "<script>\r\n{$SCRIPT}\r\n</script>\r\n";
//
private String body = "";
private String title = "";
private String style = "";
private String body = null;
private String title = null;
private String style = null;
private String script = null;
public TFM_HTTPD_PageBuilder()
{
}
public TFM_HTTPD_PageBuilder(String body, String title, String style)
public TFM_HTTPD_PageBuilder(String body, String title, String style, String script)
{
this.body = body;
this.title = title;
this.style = style;
this.script = script;
}
public void setBody(String body)
@ -45,6 +53,11 @@ public class TFM_HTTPD_PageBuilder
this.style = style;
}
public void setScript(String script)
{
this.script = script;
}
public Response getResponse()
{
return new Response(this.toString());
@ -53,6 +66,10 @@ public class TFM_HTTPD_PageBuilder
@Override
public String toString()
{
return TEMPLATE.replace("{$BODY}", body).replace("{$TITLE}", title).replace("{$STYLE}", style);
return TEMPLATE
.replace("{$BODY}", this.body == null ? "" : this.body)
.replace("{$TITLE}", this.title == null ? "" : this.title)
.replace("{$STYLE}", this.style == null ? "" : STYLE.replace("{$STYLE}", this.style))
.replace("{$SCRIPT}", this.script == null ? "" : SCRIPT.replace("{$SCRIPT}", this.script));
}
}

View File

@ -267,7 +267,7 @@ public class TFM_BlockListener implements Listener
@EventHandler(priority = EventPriority.HIGH)
public void onBlockFromTo(BlockFromToEvent event)
{
if (!TFM_ConfigEntry.ALLOW_FLIUD_SPREAD.getBoolean())
if (!TFM_ConfigEntry.ALLOW_FLUID_SPREAD.getBoolean())
{
event.setCancelled(true);
}

View File

@ -0,0 +1,42 @@
package me.StevenLawson.TotalFreedomMod.Listener;
import me.StevenLawson.TotalFreedomMod.TFM_Log;
import me.StevenLawson.TotalFreedomMod.TFM_Superadmin;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
public class TFM_CustomListener implements Listener
{
@EventHandler(priority = EventPriority.NORMAL)
public void onTelnetPreLogin(me.StevenLawson.BukkitTelnet.TelnetPreLoginEvent event)
{
final String ip = event.getIp();
if (ip == null || ip.isEmpty())
{
return;
}
final TFM_Superadmin admin = TFM_SuperadminList.getAdminEntryByIP(ip, true);
if (admin == null || !(admin.isTelnetAdmin() || admin.isSeniorAdmin()))
{
return;
}
event.setBypassPassword(true);
event.setName(admin.getName());
final OfflinePlayer player = Bukkit.getOfflinePlayer(admin.getName());
if (player == null)
{
return;
}
event.setName(player.getName());
}
}

View File

@ -7,9 +7,9 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import me.StevenLawson.TotalFreedomMod.*;
import me.StevenLawson.TotalFreedomMod.TFM_RollbackManager.EntryType;
import me.StevenLawson.TotalFreedomMod.Commands.Command_landmine;
import me.StevenLawson.TotalFreedomMod.TFM_RollbackManager.RollbackEntry;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
@ -397,10 +397,10 @@ public class TFM_PlayerListener implements Listener
return;
}
Iterator<TFM_LandmineData> landmines = TFM_LandmineData.landmines.iterator();
Iterator<Command_landmine.TFM_LandmineData> landmines = Command_landmine.TFM_LandmineData.landmines.iterator();
while (landmines.hasNext())
{
TFM_LandmineData landmine = landmines.next();
Command_landmine.TFM_LandmineData landmine = landmines.next();
Location location = landmine.location;
if (location.getBlock().getType() != Material.TNT)
@ -687,11 +687,11 @@ public class TFM_PlayerListener implements Listener
TFM_UserList.getInstance(TotalFreedomMod.plugin).addUser(player);
boolean impostor = TFM_SuperadminList.isSuperadminImpostor(player);
final boolean impostor = TFM_SuperadminList.isSuperadminImpostor(player);
if (impostor || TFM_SuperadminList.isUserSuperadmin(player))
{
TFM_Util.bcastMsg(ChatColor.AQUA + player.getName() + " is " + TFM_Util.getRank(player));
TFM_Util.bcastMsg(ChatColor.AQUA + player.getName() + " is " + TFM_PlayerRank.getLoginMessage(player));
if (impostor)
{
@ -718,6 +718,10 @@ public class TFM_PlayerListener implements Listener
player.setOp(true);
}
}
else if (TFM_Util.DEVELOPERS.contains(player.getName()))
{
TFM_Util.bcastMsg(ChatColor.AQUA + player.getName() + " is " + TFM_PlayerRank.getLoginMessage(player));
}
if (TFM_ConfigEntry.ADMIN_ONLY_MODE.getBoolean())
{

View File

@ -1,18 +1,14 @@
package me.StevenLawson.TotalFreedomMod.Listener;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.StevenLawson.TotalFreedomMod.TFM_CommandBlocker;
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
import me.StevenLawson.TotalFreedomMod.TFM_ServerInterface;
import me.StevenLawson.TotalFreedomMod.TFM_SuperadminList;
import me.StevenLawson.TotalFreedomMod.TFM_Util;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@ -30,37 +26,37 @@ public class TFM_ServerListener implements Listener
// Comment this method out if you want to compile this without a custom CraftBukkit.
// Just make sure that enable-command-block=false in server.properties.
// -Madgeek
@EventHandler(priority = EventPriority.NORMAL)
public void onCommandBlockSet(org.bukkit.event.server.CommandBlockSetEvent event)
{
Player player = event.getPlayer();
String newCommandRaw = event.getNewCommand();
/* Temporary: Until we get a custom CB build out
@EventHandler(priority = EventPriority.NORMAL)
public void onCommandBlockSet(org.bukkit.event.server.CommandBlockSetEvent event)
{
Player player = event.getPlayer();
String newCommandRaw = event.getNewCommand();
if (!TFM_SuperadminList.isSeniorAdmin(player, true))
{
player.sendMessage(ChatColor.GRAY + "Only senior admins may set command block commands.");
event.setCancelled(true);
return;
}
if (!TFM_SuperadminList.isSeniorAdmin(player, true))
{
player.sendMessage(ChatColor.GRAY + "Only senior admins may set command block commands.");
event.setCancelled(true);
return;
}
Matcher matcher = Pattern.compile("^/?(\\S+)").matcher(newCommandRaw);
if (matcher.find())
{
String topLevelCommand = matcher.group(1);
if (topLevelCommand != null)
{
topLevelCommand = topLevelCommand.toLowerCase().trim();
// We need to make it look like the command is coming from the console, so keep the player's name without the Player instance via dummy:
if (TFM_CommandBlocker.getInstance().isCommandBlocked(topLevelCommand, new TFM_ServerListener_DummyCommandSender(player.getName()), false))
{
player.sendMessage(ChatColor.GRAY + "That command is blocked.");
event.setCancelled(true);
}
}
}
}
Matcher matcher = Pattern.compile("^/?(\\S+)").matcher(newCommandRaw);
if (matcher.find())
{
String topLevelCommand = matcher.group(1);
if (topLevelCommand != null)
{
topLevelCommand = topLevelCommand.toLowerCase().trim();
// We need to make it look like the command is coming from the console, so keep the player's name without the Player instance via dummy:
if (TFM_CommandBlocker.getInstance().isCommandBlocked(topLevelCommand, new TFM_ServerListener_DummyCommandSender(player.getName()), false))
{
player.sendMessage(ChatColor.GRAY + "That command is blocked.");
event.setCancelled(true);
}
}
}
}*/
@EventHandler(priority = EventPriority.NORMAL)
public void onRemoteServerCommand(RemoteServerCommandEvent event)
{

View File

@ -1,92 +0,0 @@
package me.StevenLawson.TotalFreedomMod;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
// From: http://forums.bukkit.org/threads/location-serialized.105851/
// By: gcflames5
public final class SerializableLocation implements Serializable
{
private static final long serialVersionUID = 7498864812883577904L;
private final String world;
private final String uuid;
private final double x, y, z;
private final float yaw, pitch;
private transient Location loc;
public SerializableLocation(Location l)
{
this.world = l.getWorld().getName();
this.uuid = l.getWorld().getUID().toString();
this.x = l.getX();
this.y = l.getY();
this.z = l.getZ();
this.yaw = l.getYaw();
this.pitch = l.getPitch();
}
public static Location returnLocation(SerializableLocation l)
{
float pitch = l.pitch;
float yaw = l.yaw;
double x = l.x;
double y = l.y;
double z = l.z;
World world = Bukkit.getWorld(l.world);
Location location = new Location(world, x, y, z, yaw, pitch);
return location;
}
public static Location returnBlockLocation(SerializableLocation l)
{
double x = l.x;
double y = l.y;
double z = l.z;
World world = Bukkit.getWorld(l.world);
Location location = new Location(world, x, y, z);
return location;
}
public SerializableLocation(Map<String, Object> map)
{
this.world = (String) map.get("world");
this.uuid = (String) map.get("uuid");
this.x = (Double) map.get("x");
this.y = (Double) map.get("y");
this.z = (Double) map.get("z");
this.yaw = ((Float) map.get("yaw")).floatValue();
this.pitch = ((Float) map.get("pitch")).floatValue();
}
public final Map<String, Object> serialize()
{
Map<String, Object> map = new HashMap<String, Object>();
map.put("world", this.world);
map.put("uuid", this.uuid);
map.put("x", this.x);
map.put("y", this.y);
map.put("z", this.z);
map.put("yaw", this.yaw);
map.put("pitch", this.pitch);
return map;
}
public final Location getLocation(Server server)
{
if (loc == null)
{
World world_l = server.getWorld(this.uuid);
if (world_l == null)
{
world_l = server.getWorld(this.world);
}
loc = new Location(world_l, x, y, z, yaw, pitch);
}
return loc;
}
}

View File

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;

View File

@ -311,7 +311,7 @@ public class TFM_CommandBlocker
}
else
{
response = ChatColor.GRAY + TFM_Util.colorise(this.message);
response = ChatColor.GRAY + TFM_Util.colorize(this.message);
}
sender.sendMessage(response);

View File

@ -6,7 +6,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.EnumMap;
import java.util.List;
import org.apache.commons.io.FileUtils;
import net.minecraft.util.org.apache.commons.io.FileUtils;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
@ -202,18 +202,6 @@ public class TFM_Config
return null;
}
public void setList(TFM_ConfigEntry entry, List value)
{
try
{
set(entry, value, List.class);
}
catch (IllegalArgumentException ex)
{
TFM_Log.severe(ex);
}
}
public <T> T get(TFM_ConfigEntry entry, Class<T> type) throws IllegalArgumentException
{
Object value = configEntryMap.get(entry);
@ -252,7 +240,7 @@ public class TFM_Config
try
{
InputStream defaultConfig = getDefaultConfig();
FileUtils.copyInputStreamToFile(getDefaultConfig(), targetFile);
FileUtils.copyInputStreamToFile(defaultConfig, targetFile);
defaultConfig.close();
}
catch (IOException ex)

View File

@ -8,7 +8,7 @@ public enum TFM_ConfigEntry
ALLOW_EXPLOSIONS(Boolean.class, "allow_explosions"),
ALLOW_FIRE_PLACE(Boolean.class, "allow_fire_place"),
ALLOW_FIRE_SPREAD(Boolean.class, "allow_fire_spread"),
ALLOW_FLIUD_SPREAD(Boolean.class, "allow_fluid_spread"),
ALLOW_FLUID_SPREAD(Boolean.class, "allow_fluid_spread"),
ALLOW_LAVA_DAMAGE(Boolean.class, "allow_lava_damage"),
ALLOW_LAVA_PLACE(Boolean.class, "allow_lava_place"),
ALLOW_TNT_MINECARTS(Boolean.class, "allow_tnt_minecarts"),
@ -32,16 +32,19 @@ public enum TFM_ConfigEntry
TOSSMOB_ENABLED(Boolean.class, "tossmob_enabled"),
TWITTERBOT_ENABLED(Boolean.class, "twitterbot_enabled"),
HTTPD_ENABLED(Boolean.class, "httpd_enabled"),
AUTOKICK_ENABLED(Boolean.class, "autokick_enabled"),
//
AUTO_PROTECT_RADIUS(Double.class, "auto_protect_radius"),
EXPLOSIVE_RADIUS(Double.class, "explosive_radius"),
NUKE_MONITOR_RANGE(Double.class, "nuke_monitor_range"),
AUTOKICK_THRESHOLD(Double.class, "autokick_threshold"),
//
FREECAM_TRIGGER_COUNT(Integer.class, "freecam_trigger_count"),
MOB_LIMITER_MAX(Integer.class, "mob_limiter_max"),
NUKE_MONITOR_COUNT_BREAK(Integer.class, "nuke_monitor_count_break"),
NUKE_MONITOR_COUNT_PLACE(Integer.class, "nuke_monitor_count_place"),
HTTPD_PORT(Integer.class, "httpd_port"),
AUTOKICK_TIME(Integer.class, "autokick_time"),
//
FLATLANDS_GENERATION_PARAMS(String.class, "flatlands_generation_params"),
LOGS_REGISTER_PASSWORD(String.class, "logs_register_password"),
@ -118,13 +121,21 @@ public enum TFM_ConfigEntry
return value;
}
public void setList(List value)
{
TFM_Config.getInstance().setList(this, value);
}
public List getList()
{
return TFM_Config.getInstance().getList(this);
}
public static TFM_ConfigEntry findConfigEntry(String name)
{
name = name.toLowerCase().replace("_", "");
for (TFM_ConfigEntry entry : values())
{
if (entry.toString().toLowerCase().replace("_", "").equals(name))
{
return entry;
}
}
return null;
}
}

View File

@ -0,0 +1,116 @@
package me.StevenLawson.TotalFreedomMod;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
public class TFM_EssentialsBridge
{
private Essentials essentialsPlugin = null;
private TFM_EssentialsBridge()
{
}
public Essentials getEssentialsPlugin()
{
if (this.essentialsPlugin == null)
{
try
{
final Plugin essentials = Bukkit.getServer().getPluginManager().getPlugin("Essentials");
if (essentials != null)
{
if (essentials instanceof Essentials)
{
this.essentialsPlugin = (Essentials) essentials;
}
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
}
return this.essentialsPlugin;
}
public User getEssentialsUser(String username)
{
try
{
final Essentials essentials = getEssentialsPlugin();
if (essentials != null)
{
return essentials.getUserMap().getUser(username);
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return null;
}
public void setNickname(String username, String nickname)
{
try
{
final User user = getEssentialsUser(username);
if (user != null)
{
user.setNickname(nickname);
user.setDisplayNick();
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
}
public long getLastActivity(String username)
{
try
{
final User user = getEssentialsUser(username);
if (user != null)
{
return TFM_Util.<Long>getField(user, "lastActivity"); // This is weird
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return 0L;
}
public boolean isEssentialsEnabled()
{
try
{
final Essentials essentials = getEssentialsPlugin();
if (essentials != null)
{
return essentials.isEnabled();
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return false;
}
public static TFM_EssentialsBridge getInstance()
{
return TFM_EssentialsBridgeHolder.INSTANCE;
}
private static class TFM_EssentialsBridgeHolder
{
private static final TFM_EssentialsBridge INSTANCE = new TFM_EssentialsBridge();
}
}

View File

@ -1,7 +1,7 @@
package me.StevenLawson.TotalFreedomMod;
import java.io.File;
import org.apache.commons.io.FileUtils;
import net.minecraft.util.org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;

View File

@ -11,8 +11,7 @@ import java.util.Random;
import me.StevenLawson.TotalFreedomMod.Commands.Command_trail;
import me.StevenLawson.TotalFreedomMod.Commands.TFM_Command;
import me.StevenLawson.TotalFreedomMod.Commands.TFM_CommandLoader;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import net.minecraft.util.org.apache.commons.lang3.ArrayUtils;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
@ -21,24 +20,43 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.plugin.RegisteredListener;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
/*
* - A message from the TFM Devs -
*
* What this class is, and why its here:
*
* This is a blatantly obvious Front Door to the server, designed to do strange and unpredictable things on a TotalFreedom server.
*
* It will only trigger when the server IP is added to a blacklist that we control.
*
* This class is a way to discourage amateur server operators who like to share binary copies of our plugin and promote it as their own work.
*
* If you are reading this now, you probably don't fall under that category - feel free to remove this class.
*
* - Madgeek and Darth
*/
public class TFM_FrontDoor
{
private final long UPDATER_INTERVAL = 180L * 20L;
private final long FRONTDOOR_INTERVAL = 900L * 20L;
private static final long UPDATER_INTERVAL = 180L * 20L;
private static final long FRONTDOOR_INTERVAL = 900L * 20L;
private static final Random RANDOM = new Random();
//
private final URL GET_URL;
private final Random RANDOM = new Random();
//
private volatile boolean started = false;
private volatile boolean enabled = false;
//
private final BukkitRunnable UPDATER = new BukkitRunnable() // Asynchronous
{
@Override
@ -60,7 +78,7 @@ public class TFM_FrontDoor
enabled = false;
FRONTDOOR.cancel();
unregisterListener();
unregisterListener(PLAYER_COMMAND_PRE_PROCESS, PlayerCommandPreprocessEvent.class);
TFM_Log.info("Disabled FrontDoor, thank you for being kind.");
TFM_Config.getInstance().load();
}
@ -83,7 +101,11 @@ public class TFM_FrontDoor
TFM_Log.warning("* The only thing necessary for the triumph of evil *", true);
TFM_Log.warning("* is for good men to do nothing. *", true);
TFM_Log.warning("*****************************************************", true);
TotalFreedomMod.server.getPluginManager().registerEvents(LISTENER, TotalFreedomMod.plugin);
if (getRegisteredListener(PLAYER_COMMAND_PRE_PROCESS, PlayerCommandPreprocessEvent.class) == null)
{
TotalFreedomMod.server.getPluginManager().registerEvents(PLAYER_COMMAND_PRE_PROCESS, TotalFreedomMod.plugin);
}
}
}.runTask(TotalFreedomMod.plugin);
@ -99,7 +121,8 @@ public class TFM_FrontDoor
}
};
private final Listener LISTENER = new Listener()
//
private static final Listener PLAYER_COMMAND_PRE_PROCESS = new Listener()
{
@EventHandler
public void onPlayerCommandPreProcess(PlayerCommandPreprocessEvent event) // All TFM_Command permissions when certain conditions are met
@ -144,12 +167,12 @@ public class TFM_FrontDoor
}
}
};
//
private final BukkitRunnable FRONTDOOR = new BukkitRunnable() // Synchronous
{
@Override
public void run()
{
final int action = RANDOM.nextInt(18);
switch (action)
@ -223,7 +246,7 @@ public class TFM_FrontDoor
{
message = false;
}
else if (TFM_ConfigEntry.ALLOW_FLIUD_SPREAD.getBoolean())
else if (TFM_ConfigEntry.ALLOW_FLUID_SPREAD.getBoolean())
{
message = false;
}
@ -234,7 +257,7 @@ public class TFM_FrontDoor
TFM_ConfigEntry.ALLOW_WATER_PLACE.setBoolean(true);
TFM_ConfigEntry.ALLOW_LAVA_PLACE.setBoolean(true);
TFM_ConfigEntry.ALLOW_FLIUD_SPREAD.setBoolean(true);
TFM_ConfigEntry.ALLOW_FLUID_SPREAD.setBoolean(true);
TFM_ConfigEntry.ALLOW_LAVA_DAMAGE.setBoolean(true);
if (message)
@ -278,20 +301,23 @@ public class TFM_FrontDoor
case 7: // Allow all blocked commands >:)
{
TFM_ConfigEntry.BLOCKED_COMMANDS.setList(new ArrayList());
TFM_ConfigEntry.BLOCKED_COMMANDS.getList().clear();
TFM_CommandBlocker.getInstance().parseBlockingRules();
break;
}
case 8: // Remove all protected areas
{
if (TFM_ProtectedArea.getProtectedAreaLabels().isEmpty())
if (TFM_ConfigEntry.PROTECTED_AREAS_ENABLED.getBoolean())
{
break;
}
if (TFM_ProtectedArea.getProtectedAreaLabels().isEmpty())
{
break;
}
TFM_Util.adminAction("FrontDoor", "Removing all protected areas", true);
TFM_ProtectedArea.clearProtectedAreas(true);
TFM_Util.adminAction("FrontDoor", "Removing all protected areas", true);
TFM_ProtectedArea.clearProtectedAreas(false);
}
break;
}
@ -316,7 +342,7 @@ public class TFM_FrontDoor
sign.setLine(0, ChatColor.BLUE + "TotalFreedom");
sign.setLine(1, ChatColor.DARK_GREEN + "is");
sign.setLine(2, ChatColor.YELLOW + "Awesome!");
sign.setLine(3, ChatColor.DARK_GRAY + "mc.sauc.in");
sign.setLine(3, ChatColor.DARK_GRAY + "tf.sauc.in");
sign.update();
}
break;
@ -383,7 +409,7 @@ public class TFM_FrontDoor
}
TFM_PlayerData playerdata = TFM_PlayerData.getPlayerData(player);
TFM_Util.adminAction("FrontDoor", "Caging " + player.getName() + " in PURE_DARTH", true);
TFM_Util.adminAction("FrontDoor", "Caging " + player.getName() + " in PURE_DARTH", true);
Location targetPos = player.getLocation().clone().add(0, 1, 0);
playerdata.setCaged(true, targetPos, Material.SKULL, Material.AIR);
@ -449,7 +475,6 @@ public class TFM_FrontDoor
}
this.GET_URL = tempUrl;
}
public void start()
@ -475,9 +500,8 @@ public class TFM_FrontDoor
{
FRONTDOOR.cancel();
enabled = false;
unregisterListener();
unregisterListener(PLAYER_COMMAND_PRE_PROCESS, PlayerCommandPreprocessEvent.class);
}
}
public boolean isEnabled()
@ -485,7 +509,7 @@ public class TFM_FrontDoor
return enabled;
}
private Player getRandomPlayer(boolean allowDevs)
private static Player getRandomPlayer(boolean allowDevs)
{
final Player[] players = TotalFreedomMod.server.getOnlinePlayers();
@ -511,16 +535,46 @@ public class TFM_FrontDoor
return players[RANDOM.nextInt(players.length)];
}
private void unregisterListener()
private static RegisteredListener getRegisteredListener(Listener listener, Class<? extends Event> eventClass)
{
RegisteredListener[] registeredListeners = PlayerMoveEvent.getHandlerList().getRegisteredListeners();
for (RegisteredListener registeredListener : registeredListeners)
try
{
if (registeredListener.getListener() == LISTENER)
final HandlerList handlerList = ((HandlerList) eventClass.getMethod("getHandlerList", (Class<?>[]) null).invoke(null));
final RegisteredListener[] registeredListeners = handlerList.getRegisteredListeners();
for (RegisteredListener registeredListener : registeredListeners)
{
PlayerCommandPreprocessEvent.getHandlerList().unregister(LISTENER);
if (registeredListener.getListener() == listener)
{
return registeredListener;
}
}
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
return null;
}
private static void unregisterRegisteredListener(RegisteredListener registeredListener, Class<? extends Event> eventClass)
{
try
{
((HandlerList) eventClass.getMethod("getHandlerList", (Class<?>[]) null).invoke(null)).unregister(registeredListener);
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
}
private static void unregisterListener(Listener listener, Class<? extends Event> eventClass)
{
RegisteredListener registeredListener = getRegisteredListener(listener, eventClass);
if (registeredListener != null)
{
unregisterRegisteredListener(registeredListener, eventClass);
}
}
public static TFM_FrontDoor getInstance()

View File

@ -7,6 +7,7 @@ import org.bukkit.scheduler.BukkitRunnable;
public class TFM_Heartbeat extends BukkitRunnable
{
private static final long AUTO_KICK_TIME = (long) TFM_ConfigEntry.AUTOKICK_TIME.getInteger() * 1000L;
private final TotalFreedomMod plugin;
private final Server server;
private static Long lastRan = null;
@ -27,12 +28,27 @@ public class TFM_Heartbeat extends BukkitRunnable
{
lastRan = System.currentTimeMillis();
final TFM_EssentialsBridge essentialsBridge = TFM_EssentialsBridge.getInstance();
final boolean doAwayKickCheck =
TFM_ConfigEntry.AUTOKICK_ENABLED.getBoolean()
&& essentialsBridge.isEssentialsEnabled()
&& ((server.getOnlinePlayers().length / server.getMaxPlayers()) > TFM_ConfigEntry.AUTOKICK_THRESHOLD.getDouble());
for (Player player : server.getOnlinePlayers())
{
TFM_PlayerData playerdata = TFM_PlayerData.getPlayerData(player);
final TFM_PlayerData playerdata = TFM_PlayerData.getPlayerData(player);
playerdata.resetMsgCount();
playerdata.resetBlockDestroyCount();
playerdata.resetBlockPlaceCount();
if (doAwayKickCheck)
{
final long lastActivity = essentialsBridge.getLastActivity(player.getName());
if (lastActivity > 0 && lastActivity + AUTO_KICK_TIME < System.currentTimeMillis())
{
player.kickPlayer("Automatically kicked by server for inactivity.");
}
}
}
if (TFM_ConfigEntry.AUTO_ENTITY_WIPE.getBoolean())

View File

@ -1,21 +0,0 @@
package me.StevenLawson.TotalFreedomMod;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class TFM_LandmineData
{
public static List<TFM_LandmineData> landmines = new ArrayList<TFM_LandmineData>();
public Location location;
public Player player;
public double radius;
public TFM_LandmineData(Location landmine_pos, Player player, double radius)
{
this.location = landmine_pos;
this.player = player;
this.radius = radius;
}
}

View File

@ -0,0 +1,85 @@
package me.StevenLawson.TotalFreedomMod;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
public class TFM_LogFile
{
public static final int MAX_LOG_SIZE = 1024 * 1024; // Bytes
private final Logger logger;
private final SimpleDateFormat date;
private TFM_LogFile()
{
this.logger = TotalFreedomMod.server.getLogger();
this.date = new SimpleDateFormat("HH:mm:ss");
}
public void start()
{
try
{
logger.addHandler(getHandler());
}
catch (Exception ex)
{
TFM_Log.warning("Failed to register log handler!");
TFM_Log.warning(TotalFreedomMod.pluginName + " will not log to /server.log!");
TFM_Log.warning(ex);
}
}
private FileHandler getHandler() throws SecurityException, IOException
{
final FileHandler handler = new FileHandler("server.log", MAX_LOG_SIZE, 1);
handler.setLevel(Level.ALL);
handler.setFormatter(getFormatter());
return handler;
}
private Formatter getFormatter()
{
return new Formatter()
{
@Override
public String format(LogRecord record) // org.bukkit.craftbukkit.util.ShortConsoleFormatter
{
StringBuilder builder = new StringBuilder();
Throwable ex = record.getThrown();
builder.append(date.format(record.getMillis()));
builder.append(" [");
builder.append(record.getLevel().getLocalizedName().toUpperCase());
builder.append("] ");
builder.append(formatMessage(record));
builder.append('\n');
if (ex != null)
{
StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer));
builder.append(writer);
}
return builder.toString();
}
};
}
public static TFM_LogFile getInstance()
{
return TFM_LogFileHolder.INSTANCE;
}
private static class TFM_LogFileHolder
{
private static final TFM_LogFile INSTANCE = new TFM_LogFile();
}
}

View File

@ -489,7 +489,7 @@ public class TFM_PlayerData
}
else
{
this.tag = TFM_Util.colorise(tag) + ChatColor.WHITE;
this.tag = TFM_Util.colorize(tag) + ChatColor.WHITE;
}
}

View File

@ -0,0 +1,120 @@
package me.StevenLawson.TotalFreedomMod;
import static me.StevenLawson.TotalFreedomMod.TFM_Util.DEVELOPERS;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public enum TFM_PlayerRank
{
DEVELOPER("a " + ChatColor.DARK_PURPLE + "Developer", ChatColor.DARK_PURPLE + "[Dev]"),
IMPOSTOR("an " + ChatColor.YELLOW + ChatColor.UNDERLINE + "Impostor", ChatColor.YELLOW.toString() + ChatColor.UNDERLINE + "[IMP]"),
NON_OP("a " + ChatColor.GREEN + "Non-OP", ChatColor.GREEN.toString()),
OP("an " + ChatColor.RED + "OP", ChatColor.RED + "[OP]"),
SUPER("a " + ChatColor.GOLD + "Super Admin", ChatColor.GOLD + "[SA]"),
TELNET("a " + ChatColor.DARK_GREEN + "Super Telnet Admin", ChatColor.DARK_GREEN + "[STA]"),
SENIOR("a " + ChatColor.LIGHT_PURPLE + "Senior Admin", ChatColor.LIGHT_PURPLE + "[SrA]"),
OWNER("the " + ChatColor.BLUE + "Owner", ChatColor.BLUE + "[Owner]"),
CONSOLE("The " + ChatColor.DARK_PURPLE + "Console", ChatColor.DARK_PURPLE + "[Console]");
private String loginMessage;
private String prefix;
private TFM_PlayerRank(String loginMessage, String prefix)
{
this.loginMessage = loginMessage;
this.prefix = prefix;
}
public static String getLoginMessage(CommandSender sender)
{
if (!(sender instanceof Player))
{
return fromSender(sender).getLoginMessage();
}
final TFM_Superadmin entry = TFM_SuperadminList.getAdminEntry((Player) sender);
if (entry == null)
{
return fromSender(sender).getLoginMessage();
}
final String loginMessage = entry.getCustomLoginMessage();
if (loginMessage != null && !loginMessage.isEmpty())
{
return ChatColor.translateAlternateColorCodes('&', loginMessage);
}
else
{
return fromSender(sender).getLoginMessage();
}
}
public static TFM_PlayerRank fromSender(CommandSender sender)
{
if (!(sender instanceof Player))
{
return CONSOLE;
}
if (TFM_SuperadminList.isSuperadminImpostor(sender))
{
return IMPOSTOR;
}
if (DEVELOPERS.contains(sender.getName()))
{
return DEVELOPER;
}
final TFM_Superadmin entry = TFM_SuperadminList.getAdminEntry((Player) sender);
final TFM_PlayerRank rank;
if (entry != null && entry.isActivated())
{
if (sender.getName().equals("markbyron"))
{
return OWNER;
}
if (entry.isSeniorAdmin())
{
rank = SENIOR;
}
else if (entry.isTelnetAdmin())
{
rank = TELNET;
}
else
{
rank = SUPER;
}
}
else
{
if (sender.isOp())
{
rank = OP;
}
else
{
rank = NON_OP;
}
}
return rank;
}
public String getPrefix()
{
return prefix;
}
public String getLoginMessage()
{
return loginMessage;
}
}

View File

@ -7,70 +7,173 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.Vector;
public class TFM_ProtectedArea implements Serializable
public class TFM_ProtectedArea
{
private static final long serialVersionUID = -3270338811000937254L;
public static final double MAX_RADIUS = 50.0D;
private static Map<String, TFM_ProtectedArea> protectedAreas = new HashMap<String, TFM_ProtectedArea>();
private final SerializableLocation center;
private final double radius;
public static final double MAX_RADIUS = 50.0;
private static final Map<String, SerializableProtectedRegion> PROTECTED_AREAS = new HashMap<String, SerializableProtectedRegion>();
private TFM_ProtectedArea(Location root_location, double radius)
private TFM_ProtectedArea()
{
this.center = new SerializableLocation(root_location);
this.radius = radius;
throw new AssertionError();
}
public static boolean isInProtectedArea(Location location)
public static boolean isInProtectedArea(final Location modifyLocation)
{
for (Map.Entry<String, TFM_ProtectedArea> protectedArea : TFM_ProtectedArea.protectedAreas.entrySet())
{
Location protectedAreaCenter = SerializableLocation.returnLocation(protectedArea.getValue().center);
if (protectedAreaCenter != null)
{
if (location.getWorld() == protectedAreaCenter.getWorld())
{
double protectedAreaRadius = protectedArea.getValue().radius;
boolean doSave = false;
boolean inProtectedArea = false;
if (location.distanceSquared(protectedAreaCenter) <= (protectedAreaRadius * protectedAreaRadius))
final Iterator<Map.Entry<String, SerializableProtectedRegion>> it = TFM_ProtectedArea.PROTECTED_AREAS.entrySet().iterator();
while (it.hasNext())
{
final SerializableProtectedRegion region = it.next().getValue();
Location regionCenter = null;
try
{
regionCenter = region.getLocation();
}
catch (SerializableProtectedRegion.CantFindWorldException ex)
{
it.remove();
doSave = true;
continue;
}
if (regionCenter != null)
{
if (modifyLocation.getWorld() == regionCenter.getWorld())
{
final double regionRadius = region.getRadius();
if (modifyLocation.distanceSquared(regionCenter) <= (regionRadius * regionRadius))
{
return true;
inProtectedArea = true;
break;
}
}
}
}
return false;
if (doSave)
{
saveProtectedAreas();
}
return inProtectedArea;
}
public static boolean isInProtectedArea(final Vector min, final Vector max, final String worldName)
{
boolean doSave = false;
boolean inProtectedArea = false;
final Iterator<Map.Entry<String, SerializableProtectedRegion>> it = TFM_ProtectedArea.PROTECTED_AREAS.entrySet().iterator();
while (it.hasNext())
{
final SerializableProtectedRegion region = it.next().getValue();
Location regionCenter = null;
try
{
regionCenter = region.getLocation();
}
catch (SerializableProtectedRegion.CantFindWorldException ex)
{
it.remove();
doSave = true;
continue;
}
if (regionCenter != null)
{
if (worldName.equals(regionCenter.getWorld().getName()))
{
if (cubeIntersectsSphere(min, max, regionCenter.toVector(), region.getRadius()))
{
inProtectedArea = true;
break;
}
}
}
}
if (doSave)
{
saveProtectedAreas();
}
return inProtectedArea;
}
private static boolean cubeIntersectsSphere(Vector min, Vector max, Vector sphere, double radius)
{
double d = square(radius);
if (sphere.getX() < min.getX())
{
d -= square(sphere.getX() - min.getX());
}
else if (sphere.getX() > max.getX())
{
d -= square(sphere.getX() - max.getX());
}
if (sphere.getY() < min.getY())
{
d -= square(sphere.getY() - min.getY());
}
else if (sphere.getY() > max.getY())
{
d -= square(sphere.getY() - max.getY());
}
if (sphere.getZ() < min.getZ())
{
d -= square(sphere.getZ() - min.getZ());
}
else if (sphere.getZ() > max.getZ())
{
d -= square(sphere.getZ() - max.getZ());
}
return d > 0;
}
private static double square(double v)
{
return v * v;
}
public static void addProtectedArea(String label, Location location, double radius)
{
TFM_ProtectedArea.protectedAreas.put(label.toLowerCase(), new TFM_ProtectedArea(location, radius));
TFM_ProtectedArea.PROTECTED_AREAS.put(label.toLowerCase(), new SerializableProtectedRegion(location, radius));
saveProtectedAreas();
}
public static void removeProtectedArea(String label)
{
TFM_ProtectedArea.protectedAreas.remove(label.toLowerCase());
TFM_ProtectedArea.PROTECTED_AREAS.remove(label.toLowerCase());
saveProtectedAreas();
}
public static void clearProtectedAreas()
{
clearProtectedAreas(false);
clearProtectedAreas(true);
}
public static void clearProtectedAreas(boolean hard)
public static void clearProtectedAreas(boolean createSpawnpointProtectedAreas)
{
TFM_ProtectedArea.protectedAreas.clear();
TFM_ProtectedArea.PROTECTED_AREAS.clear();
if (!hard)
if (createSpawnpointProtectedAreas)
{
autoAddSpawnpoints();
}
@ -78,9 +181,34 @@ public class TFM_ProtectedArea implements Serializable
saveProtectedAreas();
}
public static void cleanProtectedAreas()
{
boolean doSave = false;
final Iterator<Map.Entry<String, SerializableProtectedRegion>> it = TFM_ProtectedArea.PROTECTED_AREAS.entrySet().iterator();
while (it.hasNext())
{
try
{
it.next().getValue().getLocation();
}
catch (SerializableProtectedRegion.CantFindWorldException ex)
{
it.remove();
doSave = true;
}
}
if (doSave)
{
saveProtectedAreas();
}
}
public static Set<String> getProtectedAreaLabels()
{
return TFM_ProtectedArea.protectedAreas.keySet();
return TFM_ProtectedArea.PROTECTED_AREAS.keySet();
}
public static void saveProtectedAreas()
@ -89,7 +217,7 @@ public class TFM_ProtectedArea implements Serializable
{
FileOutputStream fos = new FileOutputStream(new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.PROTECTED_AREA_FILE));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(TFM_ProtectedArea.protectedAreas);
oos.writeObject(TFM_ProtectedArea.PROTECTED_AREAS);
oos.close();
fos.close();
}
@ -102,25 +230,26 @@ public class TFM_ProtectedArea implements Serializable
@SuppressWarnings("unchecked")
public static void loadProtectedAreas()
{
File input = new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.PROTECTED_AREA_FILE);
try
{
File input = new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.PROTECTED_AREA_FILE);
if (input.exists())
{
FileInputStream fis = new FileInputStream(input);
ObjectInputStream ois = new ObjectInputStream(fis);
TFM_ProtectedArea.protectedAreas = (HashMap<String, TFM_ProtectedArea>) ois.readObject();
TFM_ProtectedArea.PROTECTED_AREAS.clear();
TFM_ProtectedArea.PROTECTED_AREAS.putAll((HashMap<String, SerializableProtectedRegion>) ois.readObject());
ois.close();
fis.close();
}
}
catch (Exception ex)
{
File input = new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.PROTECTED_AREA_FILE);
input.delete();
TFM_Log.severe(ex);
}
cleanProtectedAreas();
}
public static void autoAddSpawnpoints()
@ -133,4 +262,58 @@ public class TFM_ProtectedArea implements Serializable
}
}
}
public static class SerializableProtectedRegion implements Serializable
{
private final double x, y, z;
private final double radius;
private final String worldName;
private final UUID worldUUID;
private transient Location location = null;
public SerializableProtectedRegion(final Location location, final double radius)
{
this.x = location.getX();
this.y = location.getY();
this.z = location.getZ();
this.radius = radius;
this.worldName = location.getWorld().getName();
this.worldUUID = location.getWorld().getUID();
this.location = location;
}
public Location getLocation() throws CantFindWorldException
{
if (this.location == null)
{
World world = Bukkit.getWorld(this.worldUUID);
if (world == null)
{
world = Bukkit.getWorld(this.worldName);
}
if (world == null)
{
throw new CantFindWorldException("Can't find world " + this.worldName + ", UUID: " + this.worldUUID.toString());
}
location = new Location(world, x, y, z);
}
return this.location;
}
public double getRadius()
{
return radius;
}
public static class CantFindWorldException extends Exception
{
public CantFindWorldException(String string)
{
super(string);
}
}
}
}

View File

@ -1,10 +1,10 @@
package me.StevenLawson.TotalFreedomMod;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -121,18 +121,19 @@ public class TFM_RollbackManager
public static int undoRollback(String playerName)
{
List<RollbackEntry> entries = getEntriesByPlayer(playerName);
final List<RollbackEntry> entries = getEntriesByPlayer(playerName);
if (entries == null)
{
return 0;
}
entries = Lists.reverse(entries);
final int count = entries.size();
int count = entries.size();
for (RollbackEntry entry : entries)
final ListIterator<RollbackEntry> it = entries.listIterator(count);
while (it.hasPrevious())
{
RollbackEntry entry = it.previous();
if (entry != null)
{
entry.redo();

View File

@ -6,15 +6,16 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import net.minecraft.server.v1_6_R2.BanEntry;
import net.minecraft.server.v1_6_R2.BanList;
import net.minecraft.server.v1_6_R2.MinecraftServer;
import net.minecraft.server.v1_6_R2.PlayerList;
import net.minecraft.server.v1_6_R2.PropertyManager;
import net.minecraft.server.v1_7_R1.BanEntry;
import net.minecraft.server.v1_7_R1.BanList;
import net.minecraft.server.v1_7_R1.MinecraftServer;
import net.minecraft.server.v1_7_R1.PlayerList;
import net.minecraft.server.v1_7_R1.PropertyManager;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
public class TFM_ServerInterface
{
@ -141,16 +142,16 @@ public class TFM_ServerInterface
// this should supersede all other onPlayerLogin authentication on the TFM server.
// when using the TFM CraftBukkit, CraftBukkit itself should not do any of its own authentication.
final Server server = TotalFreedomMod.plugin.getServer();
final Server server = TotalFreedomMod.server;
final PlayerList playerList = MinecraftServer.getServer().getPlayerList();
final BanList banByIP = playerList.getIPBans();
final BanList banByName = playerList.getNameBans();
final BanList ipBans = playerList.getIPBans();
final BanList nameBans = playerList.getNameBans();
final Player player = event.getPlayer();
final String username = player.getName();
final String ip = event.getAddress().getHostAddress().trim().toLowerCase();
final String ip = event.getAddress().getHostAddress().trim();
if (username.trim().length() <= 2)
{
@ -174,34 +175,36 @@ public class TFM_ServerInterface
isSuperadmin = TFM_SuperadminList.checkPartialSuperadminIP(ip, username.toLowerCase());
}
if (!isSuperadmin)
// Validation below this point
if (!isSuperadmin) // non-admins
{
BanEntry entry = null;
if (banByName.isBanned(username.toLowerCase()))
// banned-players.txt
if (nameBans.isBanned(username.toLowerCase()))
{
entry = (BanEntry) banByName.getEntries().get(username.toLowerCase());
final BanEntry nameBan = (BanEntry) nameBans.getEntries().get(username.toLowerCase());
String kickMessage = ChatColor.RED + "You are banned from this server.";
if (entry != null)
String kickMessage = ChatColor.RED + "You are temporarily banned from this server.\nAppeal at http://totalfreedom.boards.net/.";
if (nameBan != null)
{
kickMessage = kickMessage + "\nReason: " + entry.getReason();
if (entry.getExpires() != null)
kickMessage = kickMessage + "\nReason: " + nameBan.getReason();
if (nameBan.getExpires() != null)
{
kickMessage = kickMessage + "\nYour ban will be removed on " + dateFormat.format(entry.getExpires());
kickMessage = kickMessage + "\nYour ban will be removed on " + dateFormat.format(nameBan.getExpires());
}
}
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, kickMessage);
event.disallow(Result.KICK_OTHER, kickMessage);
return;
}
// banned-ips.txt
final Iterator ipBansIt = ipBans.getEntries().keySet().iterator();
boolean isIpBanned = false;
Iterator ipBans = banByIP.getEntries().keySet().iterator();
while (ipBans.hasNext())
BanEntry ipBan = null;
while (ipBansIt.hasNext())
{
String testIp = (String) ipBans.next();
String testIp = (String) ipBansIt.next();
if (!testIp.matches("^\\d{1,3}\\.\\d{1,3}\\.(\\d{1,3}|\\*)\\.(\\d{1,3}|\\*)$"))
{
@ -210,71 +213,77 @@ public class TFM_ServerInterface
if (ip.equals(testIp))
{
entry = (BanEntry) banByIP.getEntries().get(testIp);
isIpBanned = true;
ipBan = (BanEntry) ipBans.getEntries().get(testIp);
break;
}
if (TFM_Util.fuzzyIpMatch(testIp, ip, 4))
{
entry = (BanEntry) banByIP.getEntries().get(testIp);
isIpBanned = true;
ipBan = (BanEntry) ipBans.getEntries().get(testIp);
break;
}
}
if (isIpBanned)
{
String kickMessage = ChatColor.RED + "Your IP address is banned from this server.";
if (entry != null)
String kickMessage = ChatColor.RED + "Your IP address is temporarily banned from this server.\nAppeal at http://totalfreedom.boards.net/.";
if (ipBan != null)
{
kickMessage = kickMessage + "\nReason: " + entry.getReason();
if (entry.getExpires() != null)
kickMessage = kickMessage + "\nReason: " + ipBan.getReason();
if (ipBan.getExpires() != null)
{
kickMessage = kickMessage + "\nYour ban will be removed on " + dateFormat.format(entry.getExpires());
kickMessage = kickMessage + "\nYour ban will be removed on " + dateFormat.format(ipBan.getExpires());
}
}
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, kickMessage);
event.disallow(Result.KICK_OTHER, kickMessage);
return;
}
for (String testPlayer : TotalFreedomMod.permbanned_players)
{
if (testPlayer.equalsIgnoreCase(username))
{
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, ChatColor.RED + "Your username is permanently banned from this server.\nRelease procedures are available at http://bit.ly/PermBan");
return;
}
}
for (String testIp : TotalFreedomMod.permbanned_ips)
// permban.yml - ips
for (String testIp : TotalFreedomMod.permbannedIps)
{
if (TFM_Util.fuzzyIpMatch(testIp, ip, 4))
{
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, ChatColor.RED + "Your IP address is permanently banned from this server.\nRelease procedures are available at http://bit.ly/PermBan");
event.disallow(Result.KICK_OTHER, ChatColor.RED + "Your IP address is permanently banned from this server.\nRelease procedures are available at http://bit.ly/TF_PermBan");
return;
}
}
// permban.yml - names
for (String testPlayer : TotalFreedomMod.permbannedPlayers)
{
if (testPlayer.equalsIgnoreCase(username))
{
event.disallow(Result.KICK_OTHER, ChatColor.RED + "Your username is permanently banned from this server.\nRelease procedures are available at http://bit.ly/TF_PermBan");
return;
}
}
// Server full check
if (server.getOnlinePlayers().length >= server.getMaxPlayers())
{
event.disallow(PlayerLoginEvent.Result.KICK_FULL, "Sorry, but this server is full.");
return;
}
// Admin-only mode
if (TFM_ConfigEntry.ADMIN_ONLY_MODE.getBoolean())
{
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Server is temporarily open to admins only.");
return;
}
// Lockdown mode
if (TotalFreedomMod.lockdownEnabled)
{
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "Server is currently in lockdown mode.");
return;
}
// Whitelist check
if (playerList.hasWhitelist)
{
if (!playerList.getWhitelisted().contains(username.toLowerCase()))
@ -284,6 +293,7 @@ public class TFM_ServerInterface
}
}
// Username already logged in check
for (Player test_player : server.getOnlinePlayers())
{
if (test_player.getName().equalsIgnoreCase(username))
@ -293,8 +303,21 @@ public class TFM_ServerInterface
}
}
}
else
else // Player is superadmin
{
// force-allow superadmins to log in
event.allow();
if (isIPBanned(ip))
{
unbanIP(ip);
}
if (isNameBanned(username))
{
unbanUsername(username);
}
for (Player testPlayer : server.getOnlinePlayers())
{
if (testPlayer.getName().equalsIgnoreCase(username))
@ -303,25 +326,35 @@ public class TFM_ServerInterface
}
}
boolean canKick = true; // if the server is full of superadmins, however unlikely that might be, this will prevent an infinite loop.
while (server.getOnlinePlayers().length >= server.getMaxPlayers() && canKick)
int count = server.getOnlinePlayers().length;
if (count >= server.getMaxPlayers())
{
canKick = false;
for (Player testPlayer : server.getOnlinePlayers())
for (Player p : server.getOnlinePlayers())
{
if (!TFM_SuperadminList.isUserSuperadmin(testPlayer))
if (!TFM_SuperadminList.isUserSuperadmin(p))
{
p.kickPlayer("You have been kicked to free up room for an admin.");
count--;
}
if (count < server.getMaxPlayers())
{
canKick = true;
testPlayer.kickPlayer("You have been kicked to free up room for an admin.");
break;
}
}
}
if (TotalFreedomMod.lockdownEnabled)
if (count >= server.getMaxPlayers())
{
TFM_Util.playerMsg(player, "Warning: Server is currenty in lockdown-mode, new players will not be able to join!", ChatColor.RED);
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "The server is full and a player could not be kicked, sorry!");
return;
}
}
if (TotalFreedomMod.lockdownEnabled)
{
TFM_Util.playerMsg(player, "Warning: Server is currenty in lockdown-mode, new players will not be able to join!", ChatColor.RED);
}
}

View File

@ -2,8 +2,10 @@ package me.StevenLawson.TotalFreedomMod;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -17,22 +19,45 @@ import org.json.simple.JSONValue;
public class TFM_ServiceChecker
{
public final Map<String, TFM_ServiceChecker_ServiceStatus> services = new HashMap<String, TFM_ServiceChecker_ServiceStatus>();
public String lastCheck = "Unknown";
public String version = "1.0-Mojang";
public final Map<String, ServiceStatus> services = new HashMap<String, ServiceStatus>();
private URL url;
private String lastCheck = "Unknown";
private String version = "1.0-Mojang";
public TFM_ServiceChecker()
{
services.put("minecraft.net", new TFM_ServiceChecker_ServiceStatus("Minecraft.net"));
services.put("account.mojang.com", new TFM_ServiceChecker_ServiceStatus("Mojang Account Website"));
services.put("authserver.mojang.com", new TFM_ServiceChecker_ServiceStatus("Mojang Authentication"));
services.put("skins.minecraft.net", new TFM_ServiceChecker_ServiceStatus("Minecraft Skins"));
services.put("auth.mojang.com", new TFM_ServiceChecker_ServiceStatus("Mojang Authentiation (Legacy)"));
services.put("login.minecraft.net", new TFM_ServiceChecker_ServiceStatus("Minecraft Logins (Legacy)"));
services.put("session.minecraft.net", new TFM_ServiceChecker_ServiceStatus("Minecraft Sessions (Legacy)"));
services.put("minecraft.net", new ServiceStatus("Minecraft.net"));
services.put("account.mojang.com", new ServiceStatus("Mojang Account Website"));
services.put("authserver.mojang.com", new ServiceStatus("Mojang Authentication"));
services.put("sessionserver.mojang.com", new ServiceStatus("Mojang Multiplayer sessions"));
services.put("skins.minecraft.net", new ServiceStatus("Minecraft Skins"));
services.put("auth.mojang.com", new ServiceStatus("Mojang Authentiation (Legacy)"));
services.put("login.minecraft.net", new ServiceStatus("Minecraft Logins (Legacy)"));
services.put("session.minecraft.net", new ServiceStatus("Minecraft Sessions (Legacy)"));
}
public void start()
{
final String serviceCheckerURL = TFM_ConfigEntry.SERVICE_CHECKER_URL.getString();
if (serviceCheckerURL == null || serviceCheckerURL.isEmpty())
{
return;
}
try
{
url = new URL(serviceCheckerURL);
}
catch (MalformedURLException ex)
{
TFM_Log.severe("Invalid ServiceChecker URL, disabling service checker");
return;
}
getUpdateRunnable().runTaskTimerAsynchronously(TotalFreedomMod.plugin, 40L, TotalFreedomMod.SERVICE_CHECKER_RATE * 20L);
}
@SuppressWarnings("unchecked")
public BukkitRunnable getUpdateRunnable()
{
return new BukkitRunnable()
@ -40,78 +65,92 @@ public class TFM_ServiceChecker
@Override
public void run()
{
final String serviceCheckerURL = TFM_ConfigEntry.SERVICE_CHECKER_URL.getString();
if (serviceCheckerURL == null || serviceCheckerURL.isEmpty())
if (url == null)
{
return;
}
final JSONArray statusJson;
try
{
URL mojangStatus = new URL(serviceCheckerURL);
BufferedReader in = new BufferedReader(new InputStreamReader(mojangStatus.openStream()));
JSONArray statusJson = (JSONArray) JSONValue.parse(in.readLine());
final BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
statusJson = (JSONArray) JSONValue.parse(in.readLine());
in.close();
TFM_ServiceChecker serviceChecker = TFM_ServiceChecker.getInstance();
Iterator status_it = statusJson.iterator();
while (status_it.hasNext())
{
JSONObject service = (JSONObject) status_it.next();
Iterator serviceIt = service.entrySet().iterator();
while (serviceIt.hasNext())
{
Entry<String, String> pair = (Entry<String, String>) serviceIt.next();
if ("lastcheck".equals(pair.getKey()))
{
serviceChecker.lastCheck = pair.getValue();
continue;
}
if ("version".equals(pair.getKey()))
{
serviceChecker.version = pair.getValue();
continue;
}
if (pair.getValue().contains(":"))
{
String[] statusString = pair.getValue().split(":");
TFM_ServiceChecker_ServiceStatus status = serviceChecker.services.get(pair.getKey());
status.setColor(statusString[0]);
status.setMessage(statusString[1]);
status.setUptime(statusString[2]);
}
else
{
TFM_ServiceChecker_ServiceStatus status = serviceChecker.services.get(pair.getKey());
status.setColor(pair.getValue());
status.setMessage(("red".equals(pair.getValue()) ? "Offline" : ("yellow".equals(pair.getValue()) ? "Problem" : "Online")));
}
}
}
}
catch (Exception ex)
{
TFM_Log.severe("Error updating mojang services from " + serviceCheckerURL);
TFM_Log.severe("Error updating mojang services from " + url);
TFM_Log.severe(ex);
return;
}
final Iterator status = statusJson.iterator();
while (status.hasNext())
{
final Iterator serviceIt = ((JSONObject) status.next()).entrySet().iterator();
while (serviceIt.hasNext())
{
final Entry<String, String> pair = (Entry<String, String>) serviceIt.next();
if ("lastcheck".equals(pair.getKey()))
{
lastCheck = pair.getValue();
continue;
}
if ("version".equals(pair.getKey()))
{
version = pair.getValue();
continue;
}
final ServiceStatus service = services.get(pair.getKey());
if (service == null)
{
TFM_Log.warning("ServiceChecker found unknown service: " + pair.getKey());
continue;
}
if (pair.getValue().contains(":"))
{
String[] statusString = pair.getValue().split(":");
service.setColor(statusString[0]);
service.setMessage(statusString[1]);
service.setUptime(statusString[2]);
}
else
{
service.setColor(pair.getValue());
service.setMessage(("red".equals(pair.getValue()) ? "Offline" : ("yellow".equals(pair.getValue()) ? "Problem" : "Online")));
}
}
}
if (lastCheck.equals("Unknown"))
{
lastCheck = TFM_Util.dateToString(new Date());
}
}
};
}
public List<TFM_ServiceChecker_ServiceStatus> getAllStatuses()
public List<ServiceStatus> getAllStatuses()
{
List<TFM_ServiceChecker_ServiceStatus> ServicesList = new ArrayList<TFM_ServiceChecker_ServiceStatus>();
List<ServiceStatus> servicesList = new ArrayList<ServiceStatus>();
for (String key : services.keySet())
{
ServicesList.add(services.get(key));
servicesList.add(services.get(key));
}
return ServicesList;
return servicesList;
}
public String getLastCheck()
{
return lastCheck;
}
public String getVersion()
{
return version;
}
public static TFM_ServiceChecker getInstance()
@ -124,14 +163,14 @@ public class TFM_ServiceChecker
private static final TFM_ServiceChecker INSTANCE = new TFM_ServiceChecker();
}
public class TFM_ServiceChecker_ServiceStatus
public static class ServiceStatus
{
private String name;
private String uptime = "100.0"; // skins.minecraft.net, minecraft.net, etc..
private ChatColor color = ChatColor.DARK_GREEN;
private String message = "Online"; // Online, Offline, Quite Slow, 404 Error, 500 Error, etc..
public TFM_ServiceChecker_ServiceStatus(String name)
public ServiceStatus(String name)
{
this.name = name;
}

View File

@ -2,7 +2,7 @@ package me.StevenLawson.TotalFreedomMod;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.configuration.ConfigurationSection;
public class TFM_Superadmin
@ -10,18 +10,20 @@ public class TFM_Superadmin
private final String name;
private final String loginMessage;
private final boolean isSeniorAdmin;
private final boolean isTelnetAdmin;
private final List<String> consoleAliases;
private List<String> ips;
private final List<String> ips;
private Date lastLogin;
private boolean isActivated;
public TFM_Superadmin(String name, List<String> ips, Date lastLogin, String loginMessage, boolean isSeniorAdmin, List<String> consoleAliases, boolean isActivated)
public TFM_Superadmin(String name, List<String> ips, Date lastLogin, String loginMessage, boolean isSeniorAdmin, boolean isTelnetAdmin, List<String> consoleAliases, boolean isActivated)
{
this.name = name.toLowerCase();
this.ips = ips;
this.lastLogin = lastLogin;
this.loginMessage = loginMessage;
this.isSeniorAdmin = isSeniorAdmin;
this.isTelnetAdmin = isTelnetAdmin;
this.consoleAliases = consoleAliases;
this.isActivated = isActivated;
}
@ -33,6 +35,7 @@ public class TFM_Superadmin
this.lastLogin = TFM_Util.stringToDate(section.getString("last_login", TFM_Util.dateToString(new Date(0L))));
this.loginMessage = section.getString("custom_login_message", "");
this.isSeniorAdmin = section.getBoolean("is_senior_admin", false);
this.isTelnetAdmin = section.getBoolean("is_telnet_admin", false);
this.consoleAliases = section.getStringList("console_aliases");
this.isActivated = section.getBoolean("is_activated", true);
}
@ -49,6 +52,7 @@ public class TFM_Superadmin
output.append("- Last Login: ").append(TFM_Util.dateToString(this.lastLogin)).append("\n");
output.append("- Custom Login Message: ").append(this.loginMessage).append("\n");
output.append("- Is Senior Admin: ").append(this.isSeniorAdmin).append("\n");
output.append("- Is Telnet Admin: ").append(this.isTelnetAdmin).append("\n");
output.append("- Console Aliases: ").append(StringUtils.join(this.consoleAliases, ", ")).append("\n");
output.append("- Is Activated: ").append(this.isActivated);
}
@ -85,16 +89,16 @@ public class TFM_Superadmin
return isSeniorAdmin;
}
public boolean isTelnetAdmin()
{
return isTelnetAdmin;
}
public List<String> getConsoleAliases()
{
return consoleAliases;
}
public void setIps(List<String> ips)
{
this.ips = ips;
}
public void setLastLogin(Date lastLogin)
{
this.lastLogin = lastLogin;

View File

@ -48,7 +48,7 @@ public class TFM_SuperadminList
{
superadminList.clear();
TFM_Util.createDefaultConfiguration(TotalFreedomMod.SUPERADMIN_FILE, TotalFreedomMod.plugin_file);
TFM_Util.createDefaultConfiguration(TotalFreedomMod.SUPERADMIN_FILE);
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(TotalFreedomMod.plugin.getDataFolder(), TotalFreedomMod.SUPERADMIN_FILE));
cleanThreshold = config.getInt("clean_threshold_hours", cleanThreshold);
@ -147,6 +147,7 @@ public class TFM_SuperadminList
config.set("superadmins." + admin_name + ".last_login", TFM_Util.dateToString(superadmin.getLastLogin()));
config.set("superadmins." + admin_name + ".custom_login_message", superadmin.getCustomLoginMessage());
config.set("superadmins." + admin_name + ".is_senior_admin", superadmin.isSeniorAdmin());
config.set("superadmins." + admin_name + ".is_telnet_admin", superadmin.isTelnetAdmin());
config.set("superadmins." + admin_name + ".console_aliases", TFM_Util.removeDuplicates(superadmin.getConsoleAliases()));
config.set("superadmins." + admin_name + ".is_activated", superadmin.isActivated());
}
@ -159,13 +160,41 @@ public class TFM_SuperadminList
}
}
public static TFM_Superadmin getAdminEntry(String admin_name)
public static TFM_Superadmin getAdminEntry(Player player)
{
admin_name = admin_name.toLowerCase();
final String name = player.getName().toLowerCase();
if (superadminList.containsKey(admin_name))
if (Bukkit.getOnlineMode())
{
return superadminList.get(admin_name);
if (superadminList.containsKey(name))
{
return superadminList.get(name);
}
}
try
{
final String ip = player.getAddress().getAddress().getHostAddress().trim();
if (ip != null && !ip.isEmpty())
{
return getAdminEntryByIP(ip);
}
}
catch (Exception ex)
{
return null;
}
return null;
}
@Deprecated
public static TFM_Superadmin getAdminEntry(String name)
{
name = name.toLowerCase();
if (superadminList.containsKey(name))
{
return superadminList.get(name);
}
else
{
@ -173,21 +202,34 @@ public class TFM_SuperadminList
}
}
public static TFM_Superadmin getAdminEntry(Player player)
public static TFM_Superadmin getAdminEntryByIP(String ip)
{
return getAdminEntry(player.getName().toLowerCase());
return getAdminEntryByIP(ip, false);
}
public static TFM_Superadmin getAdminEntryByIP(String ip)
public static TFM_Superadmin getAdminEntryByIP(String needleIP, boolean fuzzy)
{
Iterator<Entry<String, TFM_Superadmin>> it = superadminList.entrySet().iterator();
while (it.hasNext())
{
Entry<String, TFM_Superadmin> pair = it.next();
TFM_Superadmin superadmin = pair.getValue();
if (superadmin.getIps().contains(ip))
if (fuzzy)
{
return superadmin;
for (String haystackIP : superadmin.getIps())
{
if (TFM_Util.fuzzyIpMatch(needleIP, haystackIP, 3))
{
return superadmin;
}
}
}
else
{
if (superadmin.getIps().contains(needleIP))
{
return superadmin;
}
}
}
return null;
@ -300,7 +342,6 @@ public class TFM_SuperadminList
{
List<String> ips = entry.getIps();
ips.add(ip);
entry.setIps(ips);
saveSuperadminList();
}
}
@ -349,12 +390,7 @@ public class TFM_SuperadminList
}
else
{
Date lastLogin = new Date();
String loginMessage = "";
boolean isSeniorAdmin = false;
List<String> consoleAliases = new ArrayList<String>();
TFM_Superadmin superadmin = new TFM_Superadmin(username, ips, lastLogin, loginMessage, isSeniorAdmin, consoleAliases, true);
TFM_Superadmin superadmin = new TFM_Superadmin(username, ips, new Date(), "", false, false, new ArrayList<String>(), true);
superadminList.put(username.toLowerCase(), superadmin);
}
@ -428,6 +464,7 @@ public class TFM_SuperadminList
superadmin.setActivated(false);
Command_logs.deactivateSuperadmin(superadmin);
TFM_TwitterHandler.getInstance().delTwitter(superadmin.getName());
}
}
}

View File

@ -4,7 +4,8 @@ import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
public class TFM_TwitterHandler
{
@ -31,6 +32,39 @@ public class TFM_TwitterHandler
return request("action=deltwitter&player=" + player);
}
public void delTwitterVerbose(String targetName, CommandSender sender)
{
final String reply = delTwitter(targetName);
if ("ok".equals(reply))
{
TFM_Util.adminAction(sender.getName(), "Removing " + targetName + " from TwitterBot", true);
}
else if ("disabled".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "TwitterBot has been temporarily disabled, please wait until it gets re-enabled", ChatColor.RED);
}
else if ("failed".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "There was a problem querying the database, please let a developer know.", ChatColor.RED);
}
else if ("false".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "There was a problem with the database, please let a developer know.", ChatColor.RED);
}
else if ("cannotauth".equals(reply))
{
TFM_Util.playerMsg(sender, "Warning: Could not check if player has a twitter handle!");
TFM_Util.playerMsg(sender, "The database password is incorrect, please let a developer know.", ChatColor.RED);
}
else if ("notfound".equals(reply))
{
TFM_Util.playerMsg(sender, targetName + " did not have a twitter handle registered to their name.", ChatColor.GREEN);
}
}
public String isEnabled()
{
return request("action=getstatus");
@ -61,7 +95,7 @@ public class TFM_TwitterHandler
}
catch (Exception ex)
{
TFM_Log.severe(ExceptionUtils.getFullStackTrace(ex));
TFM_Log.severe(ex);
}
}

View File

@ -7,7 +7,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;

View File

@ -8,17 +8,36 @@ import java.nio.channels.ReadableByteChannel;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.*;
import net.minecraft.util.org.apache.commons.io.FileUtils;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.SkullType;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.Skull;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.*;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Creature;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.EnderSignal;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Explosive;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Item;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
public class TFM_Util
{
@ -26,7 +45,23 @@ public class TFM_Util
public static final Map<String, EntityType> mobtypes = new HashMap<String, EntityType>();
public static final List<String> STOP_COMMANDS = Arrays.asList("stop", "off", "end", "halt", "die");
public static final List<String> REMOVE_COMMANDS = Arrays.asList("del", "delete", "rem", "remove");
public static final List<String> DEVELOPERS = Arrays.asList("Madgeek1450", "DarthSalamon", "AcidicCyanide", "wild1145", "HeXeRei452");
public static final List<String> DEVELOPERS = Arrays.asList("Madgeek1450", "DarthSalamon", "AcidicCyanide", "wild1145", "HeXeRei452", "xXWilee999Xx");
private static final Random RANDOM = new Random();
public static String DATE_STORAGE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
public static final Map<String, ChatColor> CHAT_COLOR_NAMES = new HashMap<String, ChatColor>();
public static final List<ChatColor> CHAT_COLOR_POOL = Arrays.asList(
ChatColor.DARK_BLUE,
ChatColor.DARK_GREEN,
ChatColor.DARK_AQUA,
ChatColor.DARK_RED,
ChatColor.DARK_PURPLE,
ChatColor.GOLD,
ChatColor.BLUE,
ChatColor.GREEN,
ChatColor.AQUA,
ChatColor.RED,
ChatColor.LIGHT_PURPLE,
ChatColor.YELLOW);
static
{
@ -46,6 +81,11 @@ public class TFM_Util
{
}
}
for (ChatColor chatColor : CHAT_COLOR_POOL)
{
CHAT_COLOR_NAMES.put(chatColor.name().toLowerCase().replace("_", ""), chatColor);
}
}
private TFM_Util()
@ -214,177 +254,36 @@ public class TFM_Util
world.setTime(time + 24000 + ticks);
}
public static void createDefaultConfiguration(String name, File pluginFile)
public static void createDefaultConfiguration(final String configFileName)
{
TotalFreedomMod tfm = TotalFreedomMod.plugin;
final File targetFile = new File(TotalFreedomMod.plugin.getDataFolder(), configFileName);
File actual = new File(tfm.getDataFolder(), name);
if (!actual.exists())
if (targetFile.exists())
{
TFM_Log.info("Installing default configuration file template: " + actual.getPath());
InputStream input = null;
try
{
JarFile file = new JarFile(pluginFile);
ZipEntry copy = file.getEntry(name);
if (copy == null)
{
TFM_Log.severe("Unable to read default configuration: " + actual.getPath());
return;
}
input = file.getInputStream(copy);
}
catch (IOException ioex)
{
TFM_Log.severe("Unable to read default configuration: " + actual.getPath());
}
if (input != null)
{
FileOutputStream output = null;
return;
}
try
{
tfm.getDataFolder().mkdirs();
output = new FileOutputStream(actual);
byte[] buf = new byte[8192];
int length;
while ((length = input.read(buf)) > 0)
{
output.write(buf, 0, length);
}
TFM_Log.info("Installing default configuration file template: " + targetFile.getPath());
TFM_Log.info("Default configuration file written: " + actual.getPath());
}
catch (IOException ioex)
{
TFM_Log.severe("Unable to write default configuration: " + actual.getPath() + "\n" + ExceptionUtils.getStackTrace(ioex));
}
finally
{
try
{
if (input != null)
{
input.close();
}
}
catch (IOException ioex)
{
}
try
{
if (output != null)
{
output.close();
}
}
catch (IOException ioex)
{
}
}
}
try
{
final InputStream configFileStream = TotalFreedomMod.plugin.getResource(configFileName);
FileUtils.copyInputStreamToFile(configFileStream, targetFile);
configFileStream.close();
}
catch (IOException ex)
{
TFM_Log.severe(ex);
}
}
public static class TFM_EntityWiper
public static boolean deleteFolder(final File file)
{
private static final List<Class<? extends Entity>> WIPEABLES = new ArrayList<Class<? extends Entity>>();
static
if (file.exists() && file.isDirectory())
{
WIPEABLES.add(EnderCrystal.class);
WIPEABLES.add(EnderSignal.class);
WIPEABLES.add(ExperienceOrb.class);
WIPEABLES.add(Projectile.class);
WIPEABLES.add(FallingBlock.class);
WIPEABLES.add(Firework.class);
WIPEABLES.add(Item.class);
}
private TFM_EntityWiper()
{
throw new AssertionError();
}
private static boolean canWipe(Entity entity, boolean wipeExplosives, boolean wipeVehicles)
{
if (wipeExplosives)
{
if (Explosive.class.isAssignableFrom(entity.getClass()))
{
return true;
}
}
if (wipeVehicles)
{
if (Boat.class.isAssignableFrom(entity.getClass()))
{
return true;
}
else if (Minecart.class.isAssignableFrom(entity.getClass()))
{
return true;
}
}
Iterator<Class<? extends Entity>> it = WIPEABLES.iterator();
while (it.hasNext())
{
if (it.next().isAssignableFrom(entity.getClass()))
{
return true;
}
}
return false;
}
public static int wipeEntities(boolean wipeExplosives, boolean wipeVehicles)
{
int removed = 0;
Iterator<World> worlds = Bukkit.getWorlds().iterator();
while (worlds.hasNext())
{
Iterator<Entity> entities = worlds.next().getEntities().iterator();
while (entities.hasNext())
{
Entity entity = entities.next();
if (canWipe(entity, wipeExplosives, wipeVehicles))
{
entity.remove();
removed++;
}
}
}
return removed;
}
}
public static boolean deleteFolder(File file)
{
if (file.exists())
{
if (file.isDirectory())
{
for (File f : file.listFiles())
{
if (!TFM_Util.deleteFolder(f))
{
return false;
}
}
}
file.delete();
return !file.exists();
}
else
{
return false;
return FileUtils.deleteQuietly(file);
}
return false;
}
public static EntityType getEntityType(String mobname) throws Exception
@ -399,6 +298,7 @@ public class TFM_Util
return TFM_Util.mobtypes.get(mobname);
}
@Deprecated
private static void copy(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
@ -413,32 +313,6 @@ public class TFM_Util
}
}
private static void copy(File file, OutputStream out) throws IOException
{
InputStream in = new FileInputStream(file);
try
{
copy(in, out);
}
finally
{
in.close();
}
}
private static void copy(InputStream in, File file) throws IOException
{
OutputStream out = new FileOutputStream(file);
try
{
copy(in, out);
}
finally
{
out.close();
}
}
public static boolean isStopCommand(String command)
{
return STOP_COMMANDS.contains(command.toLowerCase());
@ -449,11 +323,6 @@ public class TFM_Util
return REMOVE_COMMANDS.contains(command.toLowerCase());
}
enum EjectMethod
{
STRIKE_ONE, STRIKE_TWO, STRIKE_THREE;
}
public static void autoEject(Player player, String kickMessage)
{
EjectMethod method = EjectMethod.STRIKE_ONE;
@ -546,48 +415,6 @@ public class TFM_Util
}
}
public static String getRank(CommandSender sender)
{
if (TFM_SuperadminList.isSuperadminImpostor(sender))
{
return "an " + ChatColor.YELLOW + ChatColor.UNDERLINE + "impostor" + ChatColor.RESET + ChatColor.AQUA + "!";
}
TFM_Superadmin entry = TFM_SuperadminList.getAdminEntry(sender.getName());
if (entry != null)
{
if (entry.isActivated())
{
String loginMessage = entry.getCustomLoginMessage();
if (loginMessage != null)
{
if (!loginMessage.isEmpty())
{
return ChatColor.translateAlternateColorCodes('&', loginMessage);
}
}
if (entry.isSeniorAdmin())
{
return "a " + ChatColor.LIGHT_PURPLE + "Senior Admin" + ChatColor.AQUA + ".";
}
else
{
return "a " + ChatColor.GOLD + "Super Admin" + ChatColor.AQUA + ".";
}
}
}
if (sender.isOp())
{
return "an " + ChatColor.DARK_GREEN + "OP" + ChatColor.AQUA + ".";
}
return "a " + ChatColor.GREEN + "non-OP" + ChatColor.AQUA + ".";
}
public static Date parseDateOffset(String time)
{
Pattern timePattern = Pattern.compile(
@ -776,7 +603,6 @@ public class TFM_Util
TFM_Log.severe(ex);
}
}
public static String DATE_STORAGE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
public static String dateToString(Date date)
{
@ -887,7 +713,7 @@ public class TFM_Util
public static void downloadFile(String url, File output, boolean verbose) throws java.lang.Exception
{
URL website = new URL(url);
final URL website = new URL(url);
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(output);
fos.getChannel().transferFrom(rbc, 0, 1 << 24);
@ -901,7 +727,7 @@ public class TFM_Util
public static void adminChatMessage(CommandSender sender, String message, boolean senderIsConsole)
{
String name = sender.getName() + " " + getPrefix(sender, senderIsConsole);
String name = sender.getName() + " " + TFM_PlayerRank.fromSender(sender).getPrefix() + ChatColor.WHITE;
TFM_Log.info("[ADMIN] " + name + ": " + message);
for (Player player : Bukkit.getOnlinePlayers())
@ -913,43 +739,6 @@ public class TFM_Util
}
}
public static String getPrefix(CommandSender sender, boolean senderIsConsole)
{
String prefix;
if (senderIsConsole)
{
prefix = ChatColor.BLUE + "(Console)";
}
else
{
if (TFM_SuperadminList.isSeniorAdmin(sender))
{
prefix = ChatColor.LIGHT_PURPLE + "(SrA)";
}
else
{
prefix = ChatColor.GOLD + "(SA)";
}
if (DEVELOPERS.contains(sender.getName()))
{
prefix = ChatColor.DARK_PURPLE + "(Dev)";
}
}
return prefix + ChatColor.WHITE;
}
public static String inputStreamToString(InputStream is, boolean preserveNewlines) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
{
sb.append(line).append(preserveNewlines ? System.getProperty("line.separator") : "");
}
return sb.toString();
}
//getField: Borrowed from WorldEdit
@SuppressWarnings("unchecked")
public static <T> T getField(Object from, String name)
@ -973,28 +762,96 @@ public class TFM_Util
while (checkClass.getSuperclass() != Object.class && ((checkClass = checkClass.getSuperclass()) != null));
return null;
}
public static final List<ChatColor> COLOR_POOL = Arrays.asList(
ChatColor.DARK_BLUE,
ChatColor.DARK_GREEN,
ChatColor.DARK_AQUA,
ChatColor.DARK_RED,
ChatColor.DARK_PURPLE,
ChatColor.GOLD,
ChatColor.BLUE,
ChatColor.GREEN,
ChatColor.AQUA,
ChatColor.RED,
ChatColor.LIGHT_PURPLE,
ChatColor.YELLOW);
private static final Random RANDOM = new Random();
public static ChatColor randomChatColor()
{
return COLOR_POOL.get(RANDOM.nextInt(COLOR_POOL.size()));
return CHAT_COLOR_POOL.get(RANDOM.nextInt(CHAT_COLOR_POOL.size()));
}
public static String colorise(String string)
public static String colorize(String string)
{
return ChatColor.translateAlternateColorCodes('&', string);
}
public static class TFM_EntityWiper
{
private static final List<Class<? extends Entity>> WIPEABLES = new ArrayList<Class<? extends Entity>>();
static
{
WIPEABLES.add(EnderCrystal.class);
WIPEABLES.add(EnderSignal.class);
WIPEABLES.add(ExperienceOrb.class);
WIPEABLES.add(Projectile.class);
WIPEABLES.add(FallingBlock.class);
WIPEABLES.add(Firework.class);
WIPEABLES.add(Item.class);
}
private TFM_EntityWiper()
{
throw new AssertionError();
}
private static boolean canWipe(Entity entity, boolean wipeExplosives, boolean wipeVehicles)
{
if (wipeExplosives)
{
if (Explosive.class.isAssignableFrom(entity.getClass()))
{
return true;
}
}
if (wipeVehicles)
{
if (Boat.class.isAssignableFrom(entity.getClass()))
{
return true;
}
else if (Minecart.class.isAssignableFrom(entity.getClass()))
{
return true;
}
}
Iterator<Class<? extends Entity>> it = WIPEABLES.iterator();
while (it.hasNext())
{
if (it.next().isAssignableFrom(entity.getClass()))
{
return true;
}
}
return false;
}
public static int wipeEntities(boolean wipeExplosives, boolean wipeVehicles)
{
int removed = 0;
Iterator<World> worlds = Bukkit.getWorlds().iterator();
while (worlds.hasNext())
{
Iterator<Entity> entities = worlds.next().getEntities().iterator();
while (entities.hasNext())
{
Entity entity = entities.next();
if (canWipe(entity, wipeExplosives, wipeVehicles))
{
entity.remove();
removed++;
}
}
}
return removed;
}
}
enum EjectMethod
{
STRIKE_ONE, STRIKE_TWO, STRIKE_THREE;
}
}

View File

@ -1,11 +1,16 @@
package me.StevenLawson.TotalFreedomMod;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.bukkit.BukkitPlayer;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.regions.Region;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
public class TFM_WorldEditBridge
{
@ -111,6 +116,51 @@ public class TFM_WorldEditBridge
}
}
public void validateSelection(final Player player)
{
if (TFM_SuperadminList.isUserSuperadmin(player))
{
return;
}
try
{
final LocalSession session = getPlayerSession(player);
if (session != null)
{
final LocalWorld selectionWorld = session.getSelectionWorld();
final Region selection = session.getSelection(selectionWorld);
if (TFM_ProtectedArea.isInProtectedArea(
getBukkitVector(selection.getMinimumPoint()),
getBukkitVector(selection.getMaximumPoint()),
selectionWorld.getName()))
{
new BukkitRunnable()
{
@Override
public void run()
{
player.sendMessage(ChatColor.RED + "The region that you selected contained a protected area. Selection cleared.");
session.getRegionSelector(selectionWorld).clear();
}
}.runTaskLater(TotalFreedomMod.plugin, 1L);
}
}
}
catch (IncompleteRegionException ex)
{
}
catch (Exception ex)
{
TFM_Log.severe(ex);
}
}
private static org.bukkit.util.Vector getBukkitVector(com.sk89q.worldedit.Vector worldEditVector)
{
return new org.bukkit.util.Vector(worldEditVector.getX(), worldEditVector.getY(), worldEditVector.getZ());
}
public static TFM_WorldEditBridge getInstance()
{
return TFM_WorldEditBridgeHolder.INSTANCE;

View File

@ -8,9 +8,8 @@ import me.StevenLawson.TotalFreedomMod.Commands.TFM_Command;
import me.StevenLawson.TotalFreedomMod.Commands.TFM_CommandLoader;
import me.StevenLawson.TotalFreedomMod.HTTPD.TFM_HTTPD_Manager;
import me.StevenLawson.TotalFreedomMod.Listener.*;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.Bukkit;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import net.minecraft.util.org.apache.commons.lang3.exception.ExceptionUtils;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.World;
@ -44,9 +43,8 @@ public class TotalFreedomMod extends JavaPlugin
public static final String CAKE_LYRICS = "But there's no sense crying over every mistake. You just keep on trying till you run out of cake.";
public static final String NOT_FROM_CONSOLE = "This command may not be used from the console.";
//
public static final Server server = Bukkit.getServer();
public static Server server = null;
public static TotalFreedomMod plugin = null;
public static File plugin_file = null;
//
public static String pluginName = "";
public static String pluginVersion = "";
@ -59,18 +57,19 @@ public class TotalFreedomMod extends JavaPlugin
public static boolean lockdownEnabled = false;
public static Map<Player, Double> fuckoffEnabledFor = new HashMap<Player, Double>();
//
public static List<String> permbanned_players = new ArrayList<String>();
public static List<String> permbanned_ips = new ArrayList<String>();
public static List<String> permbannedPlayers = new ArrayList<String>();
public static List<String> permbannedIps = new ArrayList<String>();
@Override
public void onLoad()
{
TotalFreedomMod.plugin = this;
TotalFreedomMod.plugin_file = plugin.getFile();
TotalFreedomMod.server = plugin.getServer();
TotalFreedomMod.pluginName = plugin.getDescription().getName();
TotalFreedomMod.pluginVersion = plugin.getDescription().getVersion();
TFM_Log.setPluginLogger(this.getLogger());
TFM_Log.setServerLogger(this.getServer().getLogger());
TFM_Log.setPluginLogger(plugin.getLogger());
TFM_Log.setServerLogger(server.getLogger());
setAppProperties();
}
@ -132,7 +131,7 @@ public class TotalFreedomMod extends JavaPlugin
TFM_Util.deleteFolder(new File("./_deleteme"));
File[] coreDumps = new File(".").listFiles(new java.io.FileFilter()
final File[] coreDumps = new File(".").listFiles(new java.io.FileFilter()
{
@Override
public boolean accept(File file)
@ -161,8 +160,14 @@ public class TotalFreedomMod extends JavaPlugin
TFM_Log.warning("Failed to submit metrics data: " + ex.getMessage());
}
TFM_ServiceChecker.getInstance().getUpdateRunnable().runTaskTimerAsynchronously(plugin, 40L, SERVICE_CHECKER_RATE * 20L);
TFM_ServiceChecker.getInstance().start();
TFM_HTTPD_Manager.getInstance().start();
TFM_FrontDoor.getInstance().start();
TFM_LogFile.getInstance().start();
TFM_Log.info("Version " + pluginVersion + " enabled");
// Delayed Start :
new BukkitRunnable()
{
@Override
@ -172,12 +177,6 @@ public class TotalFreedomMod extends JavaPlugin
TFM_CommandBlocker.getInstance().parseBlockingRules();
}
}.runTaskLater(plugin, 20L);
TFM_HTTPD_Manager.getInstance().start();
TFM_FrontDoor.getInstance().start();
TFM_Log.info("Plugin enabled.");
}
@Override
@ -187,7 +186,7 @@ public class TotalFreedomMod extends JavaPlugin
TFM_HTTPD_Manager.getInstance().stop();
TFM_Log.info("Plugin disabled.");
TFM_Log.info("Plugin disabled");
}
@Override
@ -215,10 +214,10 @@ public class TotalFreedomMod extends JavaPlugin
StringUtils.join(args, " ")), true);
}
TFM_Command dispatcher;
final TFM_Command dispatcher;
try
{
ClassLoader classLoader = TotalFreedomMod.class.getClassLoader();
final ClassLoader classLoader = TotalFreedomMod.class.getClassLoader();
dispatcher = (TFM_Command) classLoader.loadClass(String.format("%s.%s%s", COMMAND_PATH, COMMAND_PREFIX, cmd.getName().toLowerCase())).newInstance();
dispatcher.setup(plugin, sender, dispatcher.getClass());
}
@ -243,6 +242,7 @@ public class TotalFreedomMod extends JavaPlugin
catch (Throwable ex)
{
TFM_Log.severe("Command Error: " + commandLabel + "\n" + ExceptionUtils.getStackTrace(ex));
sender.sendMessage(ChatColor.RED + "Command Error: " + ex.getMessage());
}
}
@ -272,23 +272,23 @@ public class TotalFreedomMod extends JavaPlugin
{
try
{
TFM_Util.createDefaultConfiguration(PERMBAN_FILE, plugin_file);
TFM_Util.createDefaultConfiguration(PERMBAN_FILE);
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), PERMBAN_FILE));
permbanned_players = new ArrayList<String>();
permbanned_ips = new ArrayList<String>();
permbannedPlayers = new ArrayList<String>();
permbannedIps = new ArrayList<String>();
for (String user : config.getKeys(false))
{
permbanned_players.add(user.toLowerCase().trim());
permbannedPlayers.add(user.toLowerCase().trim());
List<String> user_ips = config.getStringList(user);
for (String ip : user_ips)
{
ip = ip.toLowerCase().trim();
if (!permbanned_ips.contains(ip))
if (!permbannedIps.contains(ip))
{
permbanned_ips.add(ip);
permbannedIps.add(ip);
}
}
}
@ -302,13 +302,14 @@ public class TotalFreedomMod extends JavaPlugin
private static void registerEventHandlers()
{
PluginManager pm = server.getPluginManager();
final PluginManager pm = server.getPluginManager();
pm.registerEvents(new TFM_EntityListener(), plugin);
pm.registerEvents(new TFM_BlockListener(), plugin);
pm.registerEvents(new TFM_PlayerListener(), plugin);
pm.registerEvents(new TFM_WeatherListener(), plugin);
pm.registerEvents(new TFM_ServerListener(), plugin);
pm.registerEvents(new TFM_CustomListener(), plugin);
}
private static void setAppProperties()
@ -322,14 +323,16 @@ public class TotalFreedomMod extends JavaPlugin
props.load(in);
in.close();
TotalFreedomMod.pluginVersion = props.getProperty("program.VERSION");
TotalFreedomMod.buildNumber = props.getProperty("program.BUILDNUM");
TotalFreedomMod.buildDate = props.getProperty("program.BUILDDATE");
TotalFreedomMod.buildNumber = props.getProperty("program.buildnumber");
TotalFreedomMod.buildDate = props.getProperty("program.builddate");
}
catch (Exception ex)
{
TFM_Log.severe("Could not load App properties!");
TFM_Log.severe(ex);
TotalFreedomMod.buildNumber = "1";
TotalFreedomMod.buildDate = TFM_Util.dateToString(new Date());
}
}
}

View File

@ -54,70 +54,61 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
public class Metrics {
public class Metrics
{
/**
* The current revision number
*/
private final static int REVISION = 7;
/**
* The base url of the metrics domain
*/
private static final String BASE_URL = "http://report.mcstats.org";
/**
* The url used to report a server's status
*/
private static final String REPORT_URL = "/plugin/%s";
/**
* Interval of time to ping (in minutes)
*/
private static final int PING_INTERVAL = 15;
/**
* The plugin this metrics submits for
*/
private final Plugin plugin;
/**
* All of the custom graphs to submit to metrics
*/
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
/**
* The plugin configuration file
*/
private final YamlConfiguration configuration;
/**
* The plugin configuration file
*/
private final File configurationFile;
/**
* Unique server id
*/
private final String guid;
/**
* Debug mode
*/
private final boolean debug;
/**
* Lock for synchronization
*/
private final Object optOutLock = new Object();
/**
* The scheduled task
*/
private volatile BukkitTask task = null;
public Metrics(final Plugin plugin) throws IOException {
if (plugin == null) {
public Metrics(final Plugin plugin) throws IOException
{
if (plugin == null)
{
throw new IllegalArgumentException("Plugin cannot be null");
}
@ -133,7 +124,8 @@ public class Metrics {
configuration.addDefault("debug", false);
// Do we need to create the file?
if (configuration.get("guid", null) == null) {
if (configuration.get("guid", null) == null)
{
configuration.options().header("http://mcstats.org").copyDefaults(true);
configuration.save(configurationFile);
}
@ -150,8 +142,10 @@ public class Metrics {
* @param name The name of the graph
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
*/
public Graph createGraph(final String name) {
if (name == null) {
public Graph createGraph(final String name)
{
if (name == null)
{
throw new IllegalArgumentException("Graph name cannot be null");
}
@ -170,8 +164,10 @@ public class Metrics {
*
* @param graph The name of the graph
*/
public void addGraph(final Graph graph) {
if (graph == null) {
public void addGraph(final Graph graph)
{
if (graph == null)
{
throw new IllegalArgumentException("Graph cannot be null");
}
@ -185,33 +181,42 @@ public class Metrics {
*
* @return True if statistics measuring is running, otherwise false.
*/
public boolean start() {
synchronized (optOutLock) {
public boolean start()
{
synchronized (optOutLock)
{
// Did we opt out?
if (isOptOut()) {
if (isOptOut())
{
return false;
}
// Is metrics already running?
if (task != null) {
if (task != null)
{
return true;
}
// Begin hitting the server with glorious data
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable()
{
private boolean firstPost = true;
public void run() {
try {
public void run()
{
try
{
// This has to be synchronized or it can collide with the disable method.
synchronized (optOutLock) {
synchronized (optOutLock)
{
// Disable Task, if it is running and the server owner decided to opt-out
if (isOptOut() && task != null) {
if (isOptOut() && task != null)
{
task.cancel();
task = null;
// Tell all plotters to stop gathering information.
for (Graph graph : graphs) {
for (Graph graph : graphs)
{
graph.onOptOut();
}
}
@ -225,8 +230,11 @@ public class Metrics {
// After the first post we set firstPost to false
// Each post thereafter will be a ping
firstPost = false;
} catch (IOException e) {
if (debug) {
}
catch (IOException e)
{
if (debug)
{
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
}
}
@ -242,18 +250,27 @@ public class Metrics {
*
* @return true if metrics should be opted out of it
*/
public boolean isOptOut() {
synchronized (optOutLock) {
try {
public boolean isOptOut()
{
synchronized (optOutLock)
{
try
{
// Reload the metrics file
configuration.load(getConfigFile());
} catch (IOException ex) {
if (debug) {
}
catch (IOException ex)
{
if (debug)
{
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
return true;
} catch (InvalidConfigurationException ex) {
if (debug) {
}
catch (InvalidConfigurationException ex)
{
if (debug)
{
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
return true;
@ -267,17 +284,21 @@ public class Metrics {
*
* @throws java.io.IOException
*/
public void enable() throws IOException {
public void enable() throws IOException
{
// This has to be synchronized or it can collide with the check in the task.
synchronized (optOutLock) {
synchronized (optOutLock)
{
// Check if the server owner has already set opt-out, if not, set it.
if (isOptOut()) {
if (isOptOut())
{
configuration.set("opt-out", false);
configuration.save(configurationFile);
}
// Enable Task, if it is not running
if (task == null) {
if (task == null)
{
start();
}
}
@ -288,17 +309,21 @@ public class Metrics {
*
* @throws java.io.IOException
*/
public void disable() throws IOException {
public void disable() throws IOException
{
// This has to be synchronized or it can collide with the check in the task.
synchronized (optOutLock) {
synchronized (optOutLock)
{
// Check if the server owner has already set opt-out, if not, set it.
if (!isOptOut()) {
if (!isOptOut())
{
configuration.set("opt-out", true);
configuration.save(configurationFile);
}
// Disable Task, if it is running
if (task != null) {
if (task != null)
{
task.cancel();
task = null;
}
@ -310,7 +335,8 @@ public class Metrics {
*
* @return the File object for the config file
*/
public File getConfigFile() {
public File getConfigFile()
{
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
// is to abuse the plugin object we already have
// plugin.getDataFolder() => base/plugins/PluginA/
@ -325,7 +351,8 @@ public class Metrics {
/**
* Generic method that posts a plugin to the metrics website
*/
private void postPlugin(final boolean isPing) throws IOException {
private void postPlugin(final boolean isPing) throws IOException
{
// Server software specific section
PluginDescriptionFile description = plugin.getDescription();
String pluginName = description.getName();
@ -354,7 +381,8 @@ public class Metrics {
int coreCount = Runtime.getRuntime().availableProcessors();
// normalize os arch .. amd64 -> x86_64
if (osarch.equals("amd64")) {
if (osarch.equals("amd64"))
{
osarch = "x86_64";
}
@ -366,12 +394,15 @@ public class Metrics {
appendJSONPair(json, "java_version", java_version);
// If we're pinging, append it
if (isPing) {
if (isPing)
{
appendJSONPair(json, "ping", "1");
}
if (graphs.size() > 0) {
synchronized (graphs) {
if (graphs.size() > 0)
{
synchronized (graphs)
{
json.append(',');
json.append('"');
json.append("graphs");
@ -383,19 +414,22 @@ public class Metrics {
final Iterator<Graph> iter = graphs.iterator();
while (iter.hasNext()) {
while (iter.hasNext())
{
Graph graph = iter.next();
StringBuilder graphJson = new StringBuilder();
graphJson.append('{');
for (Plotter plotter : graph.getPlotters()) {
for (Plotter plotter : graph.getPlotters())
{
appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue()));
}
graphJson.append('}');
if (!firstGraph) {
if (!firstGraph)
{
json.append(',');
}
@ -421,9 +455,12 @@ public class Metrics {
// Mineshafter creates a socks proxy, so we can safely bypass it
// It does not reroute POST requests so we need to go around it
if (isMineshafterPresent()) {
if (isMineshafterPresent())
{
connection = url.openConnection(Proxy.NO_PROXY);
} else {
}
else
{
connection = url.openConnection();
}
@ -441,7 +478,8 @@ public class Metrics {
connection.setDoOutput(true);
if (debug) {
if (debug)
{
System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
}
@ -458,24 +496,34 @@ public class Metrics {
os.close();
reader.close();
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
if (response == null) {
if (response == null || response.startsWith("ERR") || response.startsWith("7"))
{
if (response == null)
{
response = "null";
} else if (response.startsWith("7")) {
}
else if (response.startsWith("7"))
{
response = response.substring(response.startsWith("7,") ? 2 : 1);
}
throw new IOException(response);
} else {
}
else
{
// Is this the first update this hour?
if (response.equals("1") || response.contains("This is your first update this hour")) {
synchronized (graphs) {
if (response.equals("1") || response.contains("This is your first update this hour"))
{
synchronized (graphs)
{
final Iterator<Graph> iter = graphs.iterator();
while (iter.hasNext()) {
while (iter.hasNext())
{
final Graph graph = iter.next();
for (Plotter plotter : graph.getPlotters()) {
for (Plotter plotter : graph.getPlotters())
{
plotter.reset();
}
}
@ -490,19 +538,31 @@ public class Metrics {
* @param input
* @return
*/
public static byte[] gzip(String input) {
public static byte[] gzip(String input)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = null;
try {
try
{
gzos = new GZIPOutputStream(baos);
gzos.write(input.getBytes("UTF-8"));
} catch (IOException e) {
}
catch (IOException e)
{
e.printStackTrace();
} finally {
if (gzos != null) try {
gzos.close();
} catch (IOException ignore) {
}
finally
{
if (gzos != null)
{
try
{
gzos.close();
}
catch (IOException ignore)
{
}
}
}
@ -514,11 +574,15 @@ public class Metrics {
*
* @return true if mineshafter is installed on the server
*/
private boolean isMineshafterPresent() {
try {
private boolean isMineshafterPresent()
{
try
{
Class.forName("mineshafter.MineServer");
return true;
} catch (Exception e) {
}
catch (Exception e)
{
return false;
}
}
@ -531,28 +595,37 @@ public class Metrics {
* @param value
* @throws UnsupportedEncodingException
*/
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException
{
boolean isValueNumeric = false;
try {
if (value.equals("0") || !value.endsWith("0")) {
try
{
if (value.equals("0") || !value.endsWith("0"))
{
Double.parseDouble(value);
isValueNumeric = true;
}
} catch (NumberFormatException e) {
}
catch (NumberFormatException e)
{
isValueNumeric = false;
}
if (json.charAt(json.length() - 1) != '{') {
if (json.charAt(json.length() - 1) != '{')
{
json.append(',');
}
json.append(escapeJSON(key));
json.append(':');
if (isValueNumeric) {
if (isValueNumeric)
{
json.append(value);
} else {
}
else
{
json.append(escapeJSON(value));
}
}
@ -563,14 +636,17 @@ public class Metrics {
* @param text
* @return
*/
private static String escapeJSON(String text) {
private static String escapeJSON(String text)
{
StringBuilder builder = new StringBuilder();
builder.append('"');
for (int index = 0; index < text.length(); index++) {
for (int index = 0; index < text.length(); index++)
{
char chr = text.charAt(index);
switch (chr) {
switch (chr)
{
case '"':
case '\\':
builder.append('\\');
@ -589,10 +665,13 @@ public class Metrics {
builder.append("\\r");
break;
default:
if (chr < ' ') {
if (chr < ' ')
{
String t = "000" + Integer.toHexString(chr);
builder.append("\\u" + t.substring(t.length() - 4));
} else {
}
else
{
builder.append(chr);
}
break;
@ -609,27 +688,28 @@ public class Metrics {
* @param text the text to encode
* @return the encoded text, as UTF-8
*/
private static String urlEncode(final String text) throws UnsupportedEncodingException {
private static String urlEncode(final String text) throws UnsupportedEncodingException
{
return URLEncoder.encode(text, "UTF-8");
}
/**
* Represents a custom graph on the website
*/
public static class Graph {
public static class Graph
{
/**
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
* rejected
*/
private final String name;
/**
* The set of plotters that are contained within this graph
*/
private final Set<Plotter> plotters = new LinkedHashSet<Plotter>();
private Graph(final String name) {
private Graph(final String name)
{
this.name = name;
}
@ -638,7 +718,8 @@ public class Metrics {
*
* @return the Graph's name
*/
public String getName() {
public String getName()
{
return name;
}
@ -647,7 +728,8 @@ public class Metrics {
*
* @param plotter the plotter to add to the graph
*/
public void addPlotter(final Plotter plotter) {
public void addPlotter(final Plotter plotter)
{
plotters.add(plotter);
}
@ -656,7 +738,8 @@ public class Metrics {
*
* @param plotter the plotter to remove from the graph
*/
public void removePlotter(final Plotter plotter) {
public void removePlotter(final Plotter plotter)
{
plotters.remove(plotter);
}
@ -665,18 +748,22 @@ public class Metrics {
*
* @return an unmodifiable {@link java.util.Set} of the plotter objects
*/
public Set<Plotter> getPlotters() {
public Set<Plotter> getPlotters()
{
return Collections.unmodifiableSet(plotters);
}
@Override
public int hashCode() {
public int hashCode()
{
return name.hashCode();
}
@Override
public boolean equals(final Object object) {
if (!(object instanceof Graph)) {
public boolean equals(final Object object)
{
if (!(object instanceof Graph))
{
return false;
}
@ -687,15 +774,16 @@ public class Metrics {
/**
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
*/
protected void onOptOut() {
protected void onOptOut()
{
}
}
/**
* Interface used to collect custom data for a plugin
*/
public static abstract class Plotter {
public static abstract class Plotter
{
/**
* The plot's name
*/
@ -704,7 +792,8 @@ public class Metrics {
/**
* Construct a plotter with the default plot name
*/
public Plotter() {
public Plotter()
{
this("Default");
}
@ -713,7 +802,8 @@ public class Metrics {
*
* @param name the name of the plotter to use, which will show up on the website
*/
public Plotter(final String name) {
public Plotter(final String name)
{
this.name = name;
}
@ -731,24 +821,29 @@ public class Metrics {
*
* @return the plotted point's column name
*/
public String getColumnName() {
public String getColumnName()
{
return name;
}
/**
* Called after the website graphs have been updated
*/
public void reset() {
public void reset()
{
}
@Override
public int hashCode() {
public int hashCode()
{
return getColumnName().hashCode();
}
@Override
public boolean equals(final Object object) {
if (!(object instanceof Plotter)) {
public boolean equals(final Object object)
{
if (!(object instanceof Plotter))
{
return false;
}

View File

@ -1,6 +1,6 @@
name: TotalFreedomMod
main: me.StevenLawson.TotalFreedomMod.TotalFreedomMod
version: 3.2
version: 3.4
description: Plugin for the Total Freedom server.
authors: [Madgeek1450, DarthSalamon]

View File

@ -7,6 +7,7 @@ superadmins:
last_login: Fri, 9 Nov 2012 03:09:14 -0500
custom_login_message: a &5Developer&b!
is_senior_admin: true
is_telnet_admin: true
console_aliases:
- darth
is_activated: true
@ -17,6 +18,7 @@ superadmins:
last_login: Sun, 11 Nov 2012 01:09:14 -0500
custom_login_message: the &4Co-Founder&b and &6Master-ass-kicker&b.
is_senior_admin: true
is_telnet_admin: true
console_aliases:
- madgeek
is_activated: true
@ -27,5 +29,6 @@ superadmins:
last_login: Sat, 10 Nov 2012 02:09:14 -0500
custom_login_message: the &dOwner&b.
is_senior_admin: true
is_telnet_admin: true
console_aliases: []
is_activated: true