Compare commits

...

72 Commits

Author SHA1 Message Date
Tobias Ottenweller
d5d079bfcf Merge pull request #39 from craftinc/bugfix/serialization
fixed broken location/exit serialization of gates.
2017-01-01 19:19:13 +01:00
Tobias Ottenweller
3b16a6372b fixed broken location/exit serialization of gates. 2017-01-01 15:55:12 +01:00
Tobias Ottenweller
f20882e03a Merge pull request #38 from craftinc/feature/command_cleanup
Command cleanup
2017-01-01 15:29:44 +01:00
Tobias Ottenweller
c04aac10f6 bring back help page title. 2017-01-01 15:22:48 +01:00
Tobias Ottenweller
a38e12fbe6 still merging. 2017-01-01 15:20:28 +01:00
Tobias Ottenweller
8a199b4074 Merge branch 'development' into feature/command_cleanup
# Conflicts:
#	src/de/craftinc/gates/models/Gate.java
2017-01-01 15:16:35 +01:00
Tobias Ottenweller
ed5222e5fb Merge pull request #37 from craftinc/refactor/serialization_cleanup
Serialization cleanup
2017-01-01 15:12:08 +01:00
Tobias Ottenweller
1177d6e537 Merge pull request #36 from craftinc/refactor/cleanup2
Cleanup Part 2
2017-01-01 15:10:13 +01:00
Tobias Ottenweller
465533f4fe Added ability to define matrial for each gate seperatly. 2017-01-01 15:07:45 +01:00
Tobias Ottenweller
4c7f1201bd cleanup. 2017-01-01 13:28:58 +01:00
Tobias Ottenweller
64a7ac50fa Command cleanup. Stub commands for material and teleport added. 2017-01-01 13:27:07 +01:00
Tobias Ottenweller
aaf0002105 Removed LocationUtil: directly serialize locations. 2017-01-01 12:13:36 +01:00
Tobias Ottenweller
e34276b729 cleanup. 2017-01-01 11:47:38 +01:00
Tobias Ottenweller
ed32b23823 Fix teleporting players riding a vehicle. 2017-01-01 11:34:33 +01:00
Tobias Ottenweller
790fd5bccd bugfix: allow null gate parameter. 2017-01-01 10:52:13 +01:00
Tobias Ottenweller
acd96607d4 refactor permissions and packaging. 2017-01-01 10:52:00 +01:00
Tobias Ottenweller
96d9316b11 Merge pull request #35 from craftinc/refactor/cleanup2
Cleanup Part 2
2016-12-31 17:00:37 +01:00
Tobias Ottenweller
892f151e38 comments removed. 2016-12-31 15:58:02 +01:00
Tobias Ottenweller
3bc5ba500c Updated access modifiers, fixed all warnings. 2016-12-31 13:51:21 +01:00
Tobias Ottenweller
927b70fd2d Merge pull request #34 from craftinc/refactor/cleanup
Code formatting
2016-12-31 12:05:14 +01:00
Tobias Ottenweller
344e69cefd missing formatting for files. 2016-12-31 12:01:10 +01:00
Tobias Ottenweller
40b396f8a2 code formatter applied. 2016-12-31 11:59:11 +01:00
Mr Ddidderr
efb4b14b79 Merge pull request #32 from craftinc/feature/spigot
Spigot
2016-12-31 11:29:51 +01:00
Tobias Ottenweller
238dbe3e51 bump version to 2.4.1 2016-12-31 11:07:06 +01:00
Tobias Ottenweller
4deb8a3c6d updated dependencies. replaced bukkit with spigot 2016-12-31 11:04:49 +01:00
Tobias Ottenweller
e2903514fe read me updated. 2014-02-07 10:54:45 +01:00
Tobias Ottenweller
44e86059de Bumped version to 2.4.0 2014-02-05 20:48:58 +01:00
Tobias Ottenweller
fe0946117e Read me updated. 2014-02-05 20:48:37 +01:00
Tobias Ottenweller
43dd934f48 Docs updated. 2014-02-05 20:43:08 +01:00
Tobias Ottenweller
b37f1000ab Merge branch 'development' of github.com:craftinc/craftinc-gates into development 2014-02-05 20:36:34 +01:00
Tobias Ottenweller
c7a423ff20 Display information about allowed vehicles when executing the info command. 2014-02-05 20:36:23 +01:00
Tobias Ottenweller
b676af278d Display a not allowed while riding message. 2014-02-05 20:23:59 +01:00
Tobias Ottenweller
a579209037 Do call the exit changed method of the gates manager. 2014-02-05 20:16:16 +01:00
Tobias Ottenweller
ca74b2e3ed Removed invalid to do notes. 2014-02-05 20:15:56 +01:00
Tobias Ottenweller
6924e36249 Added soft-depend for multi-world plugins 2014-01-27 09:51:57 +01:00
Tobias Ottenweller
f8f31640ef Added gate change listener interface used for dynmap. 2014-01-26 14:29:28 +01:00
Tobias Ottenweller
c80b0f0f68 Fix not persistent allow/deny riding flag. 2014-01-19 21:01:28 +01:00
Tobias Ottenweller
2bd8b0ff03 Fixed broken migration for old storage versions. 2014-01-06 17:28:59 +01:00
Tobias Ottenweller
a613b1933a Send messages to players when executing allow/deny riding commands. 2014-01-06 17:21:43 +01:00
Tobias Ottenweller
d8fff26c9e Added a allow riding attribute to the gate class. Added code to guaranty compatibility. Added two new commands for setting the riding attribute. 2014-01-06 17:13:02 +01:00
Tobias Ottenweller
0c13d0d3e3 Fix for missing clone of pig attributes. 2013-12-29 09:51:26 +01:00
Tobias Ottenweller
29592823b6 Bumped version to 2.4.0-DEV 2013-12-29 09:50:14 +01:00
Tobias Ottenweller
56c6af02b1 Keep velocity when teleporing boats and minecarts. This commit completes issue #10 2013-12-28 16:43:18 +01:00
Tobias Ottenweller
8b873a6d60 Added support for vehicles. 2013-12-28 15:11:12 +01:00
Tobias Ottenweller
e36519c246 gitignore updated. 2013-12-28 15:10:30 +01:00
Tobias Ottenweller
125d327a0d Updated bukkit dependency. 2013-12-28 10:25:09 +01:00
Tobias Ottenweller
6c8658f7c5 Fixed typo. Did some cleanup. 2013-12-28 10:24:55 +01:00
Tobias Ottenweller
14041f8cd7 Updated bukkit dependency to 1.7.2-R0.1-SNAPSHOT. 2013-12-08 16:21:18 +01:00
Tobias Ottenweller
bb4a41e782 Readme updated. #2 2013-11-26 09:21:01 +01:00
Tobias Ottenweller
82df684c22 Readme updated. 2013-11-26 09:16:14 +01:00
Tobias Ottenweller
7f89917e81 Updated version to 2.3.0. 2013-11-24 12:55:47 +01:00
Tobias Ottenweller
a1cb0102f8 Changed the executing phase of deployment script. 2013-11-23 15:31:27 +01:00
Paul Schulze
5af520f8ea include mcstats in jar file when packaging with maven 2013-11-23 15:11:13 +01:00
Tobias Ottenweller
28cacfdb19 Updated the changelog and other documents for the upcoming 2.3 release. 2013-11-16 17:54:33 +01:00
Tobias Ottenweller
757d6b5a48 readme updated. 2013-11-16 15:40:53 +01:00
Tobias Ottenweller
056b8896a6 Updated bukkit depency. 2013-11-16 15:40:45 +01:00
Tobias Ottenweller
12a0bba6cc Print the names of nearby gates when executing /gate nb.
Fixed a serious bug when trying to print a very long title.
Made the info command work without a supplied gate id. It then will print information about the closest gate. (Issue #13)
2013-09-17 17:57:31 +02:00
Tobias Ottenweller
e9a454182a Added the ability to change gate block types. Issue #26.
Refactoring: Added a ConfigurationUtil class. Moved all configuration keys into it.
2013-09-15 17:09:17 +02:00
Tobias Ottenweller
260cabc509 Small typo fix. 2013-08-07 16:40:59 +02:00
Tobias Ottenweller
0b29936958 Changed some text getting displayed while executing the info command. 2013-07-27 12:03:38 +02:00
Tobias Ottenweller
efc30d0ae0 Added the nearby command. Issue #12 2013-07-24 10:39:37 +02:00
Tobias Ottenweller
f4111fb34f Added a URL and license to the pom file. 2013-07-21 19:29:12 +02:00
Tobias Ottenweller
37bce23e3d Updated a description inside the plugin.yml. 2013-07-18 12:09:50 +02:00
Tobias Ottenweller
d5ff63c163 Added Plugin Metrics. 2013-07-16 12:09:20 +02:00
Tobias Ottenweller
e60c735153 Removed the .settings folder. 2013-07-16 12:08:24 +02:00
Tobias Ottenweller
013fad2b95 Added a license header to the exitopen command class. 2013-07-11 22:35:55 +02:00
Tobias Ottenweller
5ace80e6d1 Added an exitopen command. This command will set the exit location of a gate and open it afterwards. 2013-07-11 22:35:01 +02:00
Tobias Ottenweller
42b293e6bc Updated the pom file:
* Updated (craft-) bukkit dependencies to 1.6.2-R0.1-SNAPSHOT
* Bumped version 2.3.0-DEV
2013-07-11 22:33:38 +02:00
Tobias Ottenweller
54545a9ee1 Updated the change log. 2013-07-10 22:14:55 +02:00
Tobias Ottenweller
560bbf0394 Updated the pom file for version 2.2.1 2013-07-10 22:02:19 +02:00
Tobias Ottenweller
2150cc66d0 Changed the event priority of the player teleport listener to MONITOR. 2013-07-10 22:02:05 +02:00
Tobias Ottenweller
7673c3f674 Changed to event priority of the block break listener to MONITOR. This will resolve issues with third party protection plugins. See issue #25. 2013-07-10 20:43:52 +02:00
54 changed files with 2712 additions and 2767 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ bukkit/
# bukkit test-server # bukkit test-server
bukkit-testserver/ bukkit-testserver/
dependency-reduced-pom.xml

View File

@ -1,12 +0,0 @@
#Wed Apr 06 16:59:25 CEST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View File

@ -1,12 +1,12 @@
The following persons contributed to Craft Inc. Gates (previously named Ancient Gates): The following persons contributed to Craft Inc. Gates (previously named Ancient Gates):
CURRENT MAINTAINER CURRENT MAINTAINERS
Tobias Ottenweller <mail@ottenweller.net> Tobias Ottenweller <mail@ottenweller.net>
Paul Schulze <info@paul-schulze.de> Paul Schulze <info@paul-schulze.de>
FORMER CONTRIBUTOR (alphabetical order) FORMER CONTRIBUTORS (alphabetical order)
Jacob Brunson <jacob@dimensionsmachine.com> Jacob Brunson <jacob@dimensionsmachine.com>
locutus <bladedpenguin@gmail.com> locutus <bladedpenguin@gmail.com>

View File

@ -1,10 +1,5 @@
# Craft Inc. Gates # # Craft Inc. Gates #
<Logo here>
We are happy to finally announce __Craft Inc. Gates__.
This awesome plugin lets you _travel_ to far away places and worlds _faster than light_! Just create a gate at any location and set an exit somewhere else. This awesome plugin lets you _travel_ to far away places and worlds _faster than light_! Just create a gate at any location and set an exit somewhere else.
This has been made available by the hard work of the research and development department of the _Craft Inc. Corporation_. Under the lead of Professor Ddidderr Craftman scientists worked years to find a way to bend time and space inside the Minecraft universe to enable _ultra fast transportation_. This has been made available by the hard work of the research and development department of the _Craft Inc. Corporation_. Under the lead of Professor Ddidderr Craftman scientists worked years to find a way to bend time and space inside the Minecraft universe to enable _ultra fast transportation_.
@ -13,10 +8,12 @@ Now it is time for _you_ to try out this wonderful plugin. Simply install, creat
The key features of this are: The key features of this are:
* Dynmap integration
* Gates with and without frames * Gates with and without frames
* Gates consisting of portal blocks and gates made of air (so called hidden gates) * Gates consisting of portal blocks and gates made of air (so called hidden gates)
* Gates with destinations in different worlds * Gates with destinations in different worlds
* Gates with custom shapes (gates can look any way you want) * Gates with custom shapes (gates can look any way you want)
* Riding through gates
*The Craft Inc. Corporation won't take any responsibility for seasickness, memory loss and sudden suffocation in walls while traveling with one of our gates! *The Craft Inc. Corporation won't take any responsibility for seasickness, memory loss and sudden suffocation in walls while traveling with one of our gates!
@ -57,8 +54,9 @@ Have a look at the [_Commands_](http://dev.bukkit.org/bukkit-plugins/craftinc-ga
## Installing ## ## Installing ##
1. Download the latest release _[here](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/files/)_ 1. Download the latest release _[here](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/files/)_
2. Extract the content of the zip file into the plugins folder of your Bukkit server. 2. Delete any old versions of _Craft Inc. Gates_ (only the .jar files) including the extra dynmap-plugin of this plugin.
3. Start or reload the server. 3. Extract the content of the zip file into the plugins folder of your Bukkit server.
4. Start or reload the server.
## Craft Inc. ## ## Craft Inc. ##
Check out our __[Craft Inc. Minecraft Server](http://www.craftinc.de)__. Everyone is welcome! Check out our __[Craft Inc. Minecraft Server](http://www.craftinc.de)__. Everyone is welcome!
@ -75,15 +73,8 @@ allows players to build a replicator to replicate blocks and other items. (still
coming soon! coming soon!
## Roadmap ## ## Roadmap ##
* __Version 2.3__ * Per player permissions for using and managing gates.
* Info-Tools for gates. (Get the name of a gate you standing next to.) * Horizontal gates.
* Search command for nearby gates. (Visually highlight nearby gates. Especially useful for hidden gates!)
* __Future__
* Optionally allow animals and mobs to travel via gates.
* Allow players to use gates while sitting inside a minecart or boat
* Dynmap integration.
* Per player permissions for using and managing gates.
* Horizontal gates.
## Bugs and other Problems ## ## Bugs and other Problems ##
Please use our [_issue tracker_](https://github.com/craftinc/craftinc-gates/issues?state=open) on GitHub. Please use our [_issue tracker_](https://github.com/craftinc/craftinc-gates/issues?state=open) on GitHub.
@ -91,3 +82,4 @@ Please use our [_issue tracker_](https://github.com/craftinc/craftinc-gates/issu
## Legal Information ## ## Legal Information ##
This project is a fork of the original [_Ancient Gates_](https://github.com/bladedpenguin/minecraft-ancient-gates). It is licensed under the [_LGPL_](http://www.gnu.org/licenses/lgpl-3.0.txt) just like the Bukkit project. Thanks to all current and previous [_contributors_](https://github.com/craftinc/craftinc-gates/blob/development/AUTHORS.txt). This project is a fork of the original [_Ancient Gates_](https://github.com/bladedpenguin/minecraft-ancient-gates). It is licensed under the [_LGPL_](http://www.gnu.org/licenses/lgpl-3.0.txt) just like the Bukkit project. Thanks to all current and previous [_contributors_](https://github.com/craftinc/craftinc-gates/blob/development/AUTHORS.txt).
The font used for the Craft Inc. Gates logo is called [_MineCrafter 3_](http://www.minecraftforum.net/topic/892789-minecrafter-3-font-simply-easy/) and has been made available under the creative commons license. Thanks to Asherz08, MadPixel and Ashley Denham for this great font. The font used for the Craft Inc. Gates logo is called [_MineCrafter 3_](http://www.minecraftforum.net/topic/892789-minecrafter-3-font-simply-easy/) and has been made available under the creative commons license. Thanks to Asherz08, MadPixel and Ashley Denham for this great font.
This plugin utilizes [_Hidendra's plugin metrics system_](http://mcstats.org), which means that the following information is collected and sent to mcstats.org: a unique identifier, the server's version of Java, whether the server is in offline or online mode, the plugin's version, the server's version, the OS version/name and architecture, the core count for the CPU, the number of players online, the Metrics version. __You can disable the stat collection via /plugins/PluginMetrics/config.yml if you wish.__

View File

@ -1,3 +1,18 @@
## 2.4.0 ##
* Resolved issues with closing gates (special thanks to THCFrosD)
* Added support for riding through gates (with horses, mine carts, pigs and boats)
* Dynmap integration (extra plugin)
## 2.3.0 ##
* Added a command for setting the exit and opening a gate at once.
* Enabled the ability to change the gate block material.
* Added a command printing all nearby gates while highlighting them.
* Changed the info command to highlight gates.
* Updated the info command to print information about the nearest gate if no gate name got supplied.
## 2.2.1 ##
* Changed priority of some event listeners to solve problems with WorldGuard and other protection plugins.
## 2.2.0 ## ## 2.2.0 ##
* Improved gate commands and shortcuts (have a look at the bukkit-dev page for more information). * Improved gate commands and shortcuts (have a look at the bukkit-dev page for more information).
* Improved overall performance. * Improved overall performance.

View File

@ -1,12 +1,21 @@
* __/gate allowRiding, ar [id]__
Update a gate so players can travel through it while riding.
* __/gate close, c [id]__ * __/gate close, c [id]__
Closes a gate to prevent players from using it. Closes a gate to prevent players from using it.
* __/gate denyRiding, dr [id]__
Update a gate so players can NOT travel through it while riding.
* __/gate delete, del, remove [id]__ * __/gate delete, del, remove [id]__
Removes the gate from the game. Removes the gate from the game.
* __/gate exit, e [id]__ * __/gate exit, e [id]__
Changes the location where the gate will teleport players to your current location. Changes the location where the gate will teleport players to your current location.
* __/gate exitopen, eo [id]__
Changes the location where the gate will teleport players to your current location. Also tries to open that gate afterwards.
* __/gate help, ? [page]__ * __/gate help, ? [page]__
Prints help pages. Prints help pages.
@ -14,7 +23,7 @@ Prints help pages.
Makes a gate NOT consist of gate blocks while open. Makes a gate NOT consist of gate blocks while open.
* __/gate info, i [id]__ * __/gate info, i [id]__
Prints details about a certain gate. Prints details about a certain gate. Will print information about the nearest gate if no _id_ is supplied. Also highlights the gate you're requesting information about.
* __/gate list, ls [page]__ * __/gate list, ls [page]__
Prints all available gates. Prints all available gates.
@ -22,6 +31,9 @@ Prints all available gates.
* __/gate location, lo [id]__ * __/gate location, lo [id]__
Sets the entrance of the gate to your current location. Sets the entrance of the gate to your current location.
* __/gate nearby, nb__
Prints the name of nearby gates. Also highlights them.
* __/gate new, n [id]__ * __/gate new, n [id]__
Creates a gate at your current location. Creates a gate at your current location.

View File

@ -41,11 +41,17 @@ be displayed.
* __gateTeleportNoPermissionMessage__ * __gateTeleportNoPermissionMessage__
A string value going to displayed every time when a player enters a gate and is not A string value going to displayed every time when a player enters a gate and is not allowed to use that gate. Will only be displayed if _showTeleportNoPermissionMessage_
allowed to use that gate. Will only be displayed if _showTeleportNoPermissionMessage_
is set to _true_. is set to _true_.
* __gateTeleportVehicleNotAllowedMessage__
A string value being displayed when a player tries to go through a gate while riding when riding through this gate is disabled. Will only be displayed if _showTeleportNoPermissionMessage_ is set to _true_.
* __showTeleportNoPermissionMessage__ * __showTeleportNoPermissionMessage__
A boolean (_true_ or _false_) determining wether the _no permission message_ will A boolean (_true_ or _false_) determining wether the _no permission message_ will
be displayed. be displayed.
* __gateMaterial__
A String representing the material all gates will consist of. Have a look at our [_Gate Material Page_](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/pages/gate-materials/) for all possible values.

27
doc/Gate Materials.md Normal file
View File

@ -0,0 +1,27 @@
Starting with version 2.3.0 different gate materials can be used. You can set them via the configuration file. The following Materials are currently defined:
* sapling
* water
* lava
* cobweb
* grass
* dead bush
* dandelion
* poppy
* brown mushroom
* red mushroom
* torch
* redstone torch (off)
* redstone torch (on)
* fence
* nether portal
* iron bars
* glass pane
* fence gate
* nether brick fence
* nether wart
* end portal
* cobblestone wall
Your favorite material is missing? Please contact us and we will see if we can add it.

View File

@ -1,7 +1,7 @@
name: ${project.name} name: ${project.name}
version: ${project.version} version: ${project.version}
description: A plugin to create gates for fast traveling. description: A plugin to create gates for fast traveling.
softdepend: [Vault] softdepend: [Vault, Multiverse-Core, MultiWorld, RoyalCommands]
author: tomco, s1m0ne author: tomco, s1m0ne
authors: [oloflarsson, locutus, DrAgonmoray, s1m0ne, tomco] authors: [oloflarsson, locutus, DrAgonmoray, s1m0ne, tomco]
website: http://dev.bukkit.org/bukkit-plugins/craftinc-gates/ website: http://dev.bukkit.org/bukkit-plugins/craftinc-gates/
@ -16,7 +16,7 @@ commands:
permissions: permissions:
craftincgates.*: craftincgates.*:
description: Gives access to all ancient gates commands and lets you use open gates. description: Gives access to all Craft Inc. Gates commands.
children: children:
craftincgates.info: true craftincgates.info: true
craftincgates.use: true craftincgates.use: true

88
pom.xml
View File

@ -5,13 +5,27 @@
<groupId>de.craftinc</groupId> <groupId>de.craftinc</groupId>
<artifactId>CraftIncGates</artifactId> <artifactId>CraftIncGates</artifactId>
<name>Craft Inc. Gates</name> <name>Craft Inc. Gates</name>
<url>http://dev.bukkit.org/bukkit-plugins/craftinc-gates/</url>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>2.2.0</version> <version>2.4.1</version>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties> </properties>
<!-- License -->
<licenses>
<license>
<name>GNU Lesser General Public License Version 3</name>
<url>https://www.gnu.org/licenses/lgpl-3.0-standalone.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<build> <build>
<finalName>${project.name} ${project.version}</finalName> <finalName>${project.name} ${project.version}</finalName>
<sourceDirectory>src</sourceDirectory> <sourceDirectory>src</sourceDirectory>
@ -43,7 +57,7 @@
<executions> <executions>
<execution> <execution>
<id>Run Test Bukkit Server</id> <id>Run Test Bukkit Server</id>
<phase>package</phase> <phase>install</phase>
<goals> <goals>
<goal>exec</goal> <goal>exec</goal>
</goals> </goals>
@ -53,41 +67,83 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.7.1</version>
<configuration>
<artifactSet>
<includes>
<include>org.mcstats.bukkit:metrics</include>
</includes>
</artifactSet>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
<dependencies> <dependencies>
<!--Spigot API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Bukkit API-->
<dependency> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId> <artifactId>bukkit</artifactId>
<version>1.5.2-R1.0</version> <version>1.11-R0.1-SNAPSHOT</version>
<type>jar</type> <scope>provided</scope>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5.2-R1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency> </dependency>
<!--Vault-->
<dependency> <dependency>
<groupId>net.milkbowl.vault</groupId> <groupId>net.milkbowl.vault</groupId>
<artifactId>Vault</artifactId> <artifactId>Vault</artifactId>
<version>1.2.26-SNAPSHOT</version> <version>1.6.6</version>
<type>jar</type> <type>jar</type>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!--Metrics-->
<dependency>
<groupId>org.mcstats.bukkit</groupId>
<artifactId>metrics</artifactId>
<version>R8-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
<repository> <repository>
<id>bukkit-repo</id> <id>spigot-repo</id>
<url>http://repo.bukkit.org/content/groups/public</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository> </repository>
<repository> <repository>
<id>vault-repo</id> <id>vault-repo</id>
<url>http://ci.herocraftonline.com/plugin/repository/everything</url> <url>http://nexus.hc.to/content/repositories/pub_releases</url>
</repository> </repository>
<repository>
<id>Plugin Metrics</id>
<url>http://repo.mcstats.org/content/repositories/public</url>
</repository>
</repositories> </repositories>
</project> </project>

View File

@ -1,8 +1,11 @@
maxGateBlocks: 50 maxGateBlocks: 50
playerGateBlockUpdateRadius: 64 playerGateBlockUpdateRadius: 64
highlightDuration: 5
saveOnChanges: true saveOnChanges: true
checkForBrokenGateFrames: true checkForBrokenGateFrames: true
gateTeleportMessage: "Thank you for traveling with Craft Inc. Gates." gateTeleportMessage: "Thank you for traveling with Craft Inc. Gates."
showTeleportMessage: true showTeleportMessage: true
gateTeleportNoPermissionMessage: "You are not allowed to use this gate!" gateTeleportNoPermissionMessage: "You are not allowed to use this gate!"
showTeleportNoPermissionMessage: true showTeleportNoPermissionMessage: true
gateTeleportVehicleNotAllowedMessage: "You must not use that gate while riding!"
gateMaterial: "nether portal"

View File

@ -1,350 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates;
import de.craftinc.gates.util.FloodUtil;
import de.craftinc.gates.persistence.LocationUtil;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import java.util.*;
public class Gate implements ConfigurationSerializable
{
protected Location location; /* saving both location and gateBlockLocations is redundant but makes it easy to allow players to reshape gates */
protected Set<Location> gateBlockLocations = new HashSet<Location>(); /* Locations of the blocks inside the gate */
protected Set<Block> gateFrameBlocks = new HashSet<Block>();
protected Location exit;
protected boolean isHidden = false;
protected boolean isOpen = false;
protected String id;
/**
* You should never create two gates with the same 'id'. Also see 'setId(String id)'.
* @param id This parameter must not be 'null'. An exception will be thrown otherwise!
*/
public Gate(final String id)
{
setId(id);
}
public String toString()
{
return super.toString() + " " + this.getId();
}
/**
*
* @return This method might return a 'null' value.
*/
public Location getLocation()
{
return location;
}
/**
*
* @param location Supplying 'null' is permitted.
* @throws Exception Will throw an exception if the gate is open and an invalid (no gate frame) location is
* supplied. Note that the supplied 'location' will be set even if an exception is thrown. Note that this
* gate will be closed if an exception is thrown.
*/
public void setLocation(final Location location) throws Exception
{
this.location = location;
if (isOpen) {
findPortalBlocks();
validate();
}
else {
this.gateBlockLocations = new HashSet<Location>();
this.gateFrameBlocks = new HashSet<Block>();
}
}
/**
*
* @return This method might return a 'null' value.
*/
public Location getExit()
{
return exit;
}
/**
*
* @param exit Supplying 'null' is permitted.
* @throws Exception An exception will be thrown if 'null' value is supplied and this gate is open. Note that the
* supplied 'exit' will be set even if an exception is thrown. Note that this gate will be closed if an
* exception is thrown.
*/
public void setExit(final Location exit) throws Exception
{
this.exit = exit;
validate();
}
/**
*
* @return This method will never return 'null'.
*/
public String getId()
{
return id;
}
/**
* Every gate should have an unique 'id'. You should therefore check if another gate with the same 'id' exists.
* Note that this method will not check if another gate with the same 'id' exists!
* @param id This parameter must not be 'null'. An exception will be thrown otherwise!
*/
public void setId(final String id)
{
if (id == null) {
throw new IllegalArgumentException("gate 'id' cannot be 'null'");
}
this.id = id.toLowerCase();
}
public boolean isHidden()
{
return isHidden;
}
public void setHidden(boolean isHidden) throws Exception
{
this.isHidden = isHidden;
this.validate();
}
public boolean isOpen()
{
return isOpen;
}
public void setOpen(boolean isOpen) throws Exception
{
if (isOpen && !this.isOpen) {
findPortalBlocks();
}
this.isOpen = isOpen;
validate();
}
/**
*
* @return Will never return 'null' but might return an empty Set.
*/
public Set<Location> getGateBlockLocations()
{
return gateBlockLocations;
}
/**
*
* @return Will never return 'null' but might return an empty Set.
*/
public Set<Block> getGateFrameBlocks()
{
return gateFrameBlocks;
}
protected void findPortalBlocks()
{
gateBlockLocations = new HashSet<Location>();
Set<Block> gateBlocks = FloodUtil.getGatePortalBlocks(location.getBlock());
if (gateBlocks != null) {
for (Block b : gateBlocks) {
gateBlockLocations.add(b.getLocation());
}
}
gateFrameBlocks = FloodUtil.getFrame(gateBlocks);
}
/**
* Checks if values attributes do add up; will close gate on wrong values.
*/
public void validate() throws Exception
{
if (!isOpen) {
return;
}
if (location == null) {
isOpen = false;
this.gateBlockLocations = new HashSet<Location>();
this.gateFrameBlocks = new HashSet<Block>();
throw new Exception("Gate got closed. It has no location.");
}
if (exit == null) {
isOpen = false;
this.gateBlockLocations = new HashSet<Location>();
this.gateFrameBlocks = new HashSet<Block>();
throw new Exception("Gate got closed. It has no exit.");
}
if (gateBlockLocations.size() == 0) {
isOpen = false;
this.gateBlockLocations = new HashSet<Location>();
this.gateFrameBlocks = new HashSet<Block>();
throw new Exception("Gate got closed. The frame is missing or broken. (no gate blocks)");
}
if (!isHidden() && Plugin.getPlugin().getConfig().getBoolean(Plugin.confCheckForBrokenGateFramesKey)) {
for (Block b : gateFrameBlocks) {
if (b.getType() == Material.AIR) {
isOpen = false;
this.gateBlockLocations = new HashSet<Location>();
this.gateFrameBlocks = new HashSet<Block>();
throw new Exception("Gate got closed. The frame is missing or broken. (missing frame block(s))");
}
}
}
}
/*
* INTERFACE: ConfigurationSerializable
*/
static protected String idKey = "id";
static protected String locationKey = "location";
static protected String gateBlocksKey = "gateBlocks";
static protected String exitKey = "exit";
static protected String isHiddenKey = "hidden";
static protected String isOpenKey = "open";
static protected String locationYawKey = "locationYaw";
static protected String locationPitchKey = "locationPitch";
static protected String exitYawKey = "exitYaw";
static protected String exitPitchKey = "exitPitch";
@SuppressWarnings("unchecked")
public Gate(Map<String, Object> map)
{
try {
id = map.get(idKey).toString().toLowerCase();
if (id == null) {
throw new Exception("gates need to have an id");
}
isHidden = (Boolean)map.get(isHiddenKey);
isOpen = (Boolean)map.get(isOpenKey);
location = LocationUtil.deserializeLocation((Map<String, Object>) map.get(locationKey));
exit = LocationUtil.deserializeLocation((Map<String, Object>) map.get(exitKey));
if (map.containsKey(exitPitchKey)) {
exit.setPitch(((Number)map.get(exitPitchKey)).floatValue());
exit.setYaw(((Number)map.get(exitYawKey)).floatValue());
}
if (map.containsKey(locationPitchKey)) {
location.setPitch(((Number)map.get(locationPitchKey)).floatValue());
location.setYaw(((Number)map.get(locationYawKey)).floatValue());
}
gateBlockLocations = new HashSet<Location>();
List<Map<String, Object>> serializedGateBlocks = (List<Map<String, Object>>)map.get(gateBlocksKey);
for (Map<String, Object> sgb : serializedGateBlocks) {
gateBlockLocations.add(LocationUtil.deserializeLocation(sgb));
}
gateFrameBlocks = FloodUtil.getFrameWithLocations(gateBlockLocations);
}
catch (Exception e) {
Plugin.log("ERROR: Failed to load gate '" + id + "'! (" + e.getMessage() + ")");
Plugin.log("NOTE: This gate will be removed from 'gates.yml' and added to 'invalid_gates.yml'!");
Plugin.getPlugin().getGatesManager().storeInvalidGate(map);
}
try {
validate(); // make sure to not write invalid stuff to disk
}
catch (Exception e) {
Plugin.log("The loaded gate " + this.getId() + " seems to be not valid: " + e.getMessage());
}
}
public Map<String, Object> serialize()
{
Map<String, Object> retVal = new HashMap<String, Object>();
retVal.put(idKey, id);
retVal.put(locationKey, LocationUtil.serializeLocation(location));
retVal.put(exitKey, LocationUtil.serializeLocation(exit));
retVal.put(isHiddenKey, isHidden);
retVal.put(isOpenKey, isOpen);
if (exit != null) {
retVal.put(exitPitchKey, exit.getPitch());
retVal.put(exitYawKey, exit.getYaw());
}
if (location != null) {
retVal.put(locationPitchKey, location.getPitch());
retVal.put(locationYawKey, location.getYaw());
}
List<Map<String, Object>> serializedGateBlocks = new ArrayList<Map<String, Object>>();
for (Location l : gateBlockLocations) {
serializedGateBlocks.add(LocationUtil.serializeLocation(l));
}
retVal.put(gateBlocksKey, serializedGateBlocks);
return retVal;
}
}

View File

@ -1,513 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import de.craftinc.gates.persistence.MigrationUtil;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import de.craftinc.gates.util.SimpleChunk;
import de.craftinc.gates.util.SimpleLocation;
public class GatesManager
{
protected File gatesConfigFile;
protected FileConfiguration gatesConfig;
protected static final String gatesPath = "gates"; // path to gates inside the yaml file
protected static final String storageVersionPath = "version";
protected static final int storageVersion = 1;
protected int chunkRadius;
protected Map<String, Gate> gatesById;
protected Map<SimpleChunk, Set<Gate>> gatesByChunk;
protected Map<SimpleLocation, Gate> gatesByLocation;
protected Map<SimpleLocation, Gate> gatesByFrameLocation;
protected List<Gate> gates;
protected boolean storageFileIsInvalid = false;
public Gate getGateWithId(final String id)
{
return gatesById.get(id.toLowerCase());
}
public Set<Gate> getNearbyGates(final Chunk chunk)
{
SimpleChunk simpleChunk = new SimpleChunk(chunk);
return gatesByChunk.get(simpleChunk);
}
public Gate getGateAtLocation(final Location location)
{
SimpleLocation simpleLocation = new SimpleLocation(location);
return gatesByLocation.get(simpleLocation);
}
public Gate getGateAtFrameLocation(final Location location)
{
SimpleLocation simpleLocation = new SimpleLocation(location);
return gatesByFrameLocation.get(simpleLocation);
}
public void saveGatesToDisk()
{
if (storageFileIsInvalid) {
Plugin.log(Level.SEVERE, "ERROR: Not saving gates to disk. Storage file is invalid or corrupted!");
return;
}
gatesConfig.set(gatesPath, gates);
gatesConfig.set(storageVersionPath, storageVersion);
try {
gatesConfig.save(gatesConfigFile);
Plugin.log("Saved gates to disk.");
}
catch (IOException e) {
Plugin.log(Level.SEVERE, "ERROR: Could not save gates to disk.");
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public boolean loadGatesFromDisk()
{
this.gatesConfigFile = new File(Plugin.getPlugin().getDataFolder(), "gates.yml");
if(!this.gatesConfigFile.exists()) {
try {
boolean isNew = this.gatesConfigFile.createNewFile();
if (isNew) {
Plugin.log(Level.FINEST, "Created gate storage file.");
}
}
catch (IOException e) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Cannot create gate storage file! No gates will be persisted.");
return false;
}
}
this.gatesConfig = new YamlConfiguration();
try {
this.gatesConfig.load(this.gatesConfigFile);
}
catch (Exception e) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Gate file on disk is invalid. No gates loaded. Plugin will be disabled! (" + Arrays.toString(e.getStackTrace()) + ")");
return false;
}
this.gates = (List<Gate>)gatesConfig.getList(gatesPath);
if (this.gates == null) {
this.gates = new ArrayList<Gate>();
}
for (Object o : this.gates) {
if (!(o instanceof Gate)) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Gate file on disk is invalid. No gates loaded. Plugin will be disabled! (Invalid gate class detected)");
return false;
}
}
for (Gate g : this.gates) {
try {
g.validate();
}
catch (Exception e) {
try {
g.setOpen(false);
}
catch (Exception ignored) { }
Plugin.log(Level.FINER, "closed gate '" + g.getId() + "' reason: " + e.getMessage());
}
}
fillGatesById();
fillGatesByChunk();
fillGatesByLocation();
fillGatesByFrameLocation();
Plugin.log("Loaded " + this.gates.size() + " gates.");
// migration
int fileStorageVersion = gatesConfig.getInt(storageVersionPath);
if (fileStorageVersion > storageVersion) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Unsupported storage version detected! Make sure you have the latest version of Craft Inc. Gates installed. Plugin will be disabled!");
return false;
}
if (fileStorageVersion < storageVersion && !this.gates.isEmpty()) {
Plugin.log("Outdated storage version detected. Performing data migration...");
boolean success = MigrationUtil.performMigration(fileStorageVersion, storageVersion, this.gates);
this.storageFileIsInvalid = !success;
return success;
}
return true;
}
protected int getChunkRadius()
{
if (this.chunkRadius == 0) {
this.chunkRadius = Plugin.getPlugin().getConfig().getInt(Plugin.confPlayerGateBlockUpdateRadiusKey);
this.chunkRadius = this.chunkRadius >> 4;
}
return this.chunkRadius;
}
protected void fillGatesById()
{
gatesById = new HashMap<String, Gate>((int)(gates.size() * 1.25));
for (Gate g : gates) {
this.addGateWithId(g);
}
}
protected void fillGatesByChunk()
{
HashSet<SimpleChunk> chunksUsedByGates = new HashSet<SimpleChunk>();
for (Gate g : gates) {
if (g.getLocation() != null) {
Chunk c = g.getLocation().getChunk();
int x = c.getX();
int z = c.getZ();
for (int i = x-getChunkRadius(); i < x+getChunkRadius(); i++) {
for (int j = z-getChunkRadius(); j < z+getChunkRadius(); j++) {
chunksUsedByGates.add(new SimpleChunk(i, j, c.getWorld()));
}
}
}
}
gatesByChunk = new HashMap<SimpleChunk, Set<Gate>>((int)(chunksUsedByGates.size() * 1.25));
for (Gate g : gates) {
this.addGateByChunk(g);
}
}
protected void fillGatesByLocation()
{
Set<Location> gateBlocks = new HashSet<Location>();
for (Gate g : gates) {
for (Location l : g.getGateBlockLocations()) {
gateBlocks.add(l);
Location headLocation = new Location(l.getWorld(),
l.getX(),
l.getY()+1,
l.getZ());
gateBlocks.add(headLocation);
}
}
gatesByLocation = new HashMap<SimpleLocation, Gate>((int)(gateBlocks.size()*1.25));
for (Gate g : gates) {
this.addGateByLocations(g);
}
}
protected void fillGatesByFrameLocation()
{
int numFrameBlocks = 0;
for (Gate g : gates) {
numFrameBlocks += g.gateFrameBlocks.size();
}
gatesByFrameLocation = new HashMap<SimpleLocation, Gate>((int)(numFrameBlocks*1.25));
for (Gate g : gates) {
this.addGateByFrameLocations(g);
}
}
protected void removeGateById(final String id)
{
gatesById.remove(id);
}
protected void addGateWithId(final Gate g)
{
gatesById.put(g.getId(), g);
}
protected void removeGateByLocation(final Set<Location> gateBlocks)
{
if (gateBlocks != null) {
for (Location l : gateBlocks) {
SimpleLocation sl = new SimpleLocation(l);
gatesByLocation.remove(sl);
SimpleLocation headLocation = new SimpleLocation(l, true);
gatesByLocation.remove(headLocation);
}
}
}
protected void removeGateByFrameLocation(final Set<Block> gateFrameBlocks)
{
if (gateFrameBlocks != null) {
for (Block block : gateFrameBlocks) {
SimpleLocation sl = new SimpleLocation(block.getLocation());
gatesByFrameLocation.remove(sl);
}
}
}
protected void addGateByLocations(final Gate g)
{
for (Location l : g.getGateBlockLocations()) {
SimpleLocation sl = new SimpleLocation(l);
gatesByLocation.put(sl, g);
SimpleLocation headLocation = new SimpleLocation(l, true);
gatesByLocation.put(headLocation, g);
}
}
protected void addGateByFrameLocations(final Gate g)
{
for (Block block : g.getGateFrameBlocks()) {
SimpleLocation sl = new SimpleLocation(block.getLocation());
gatesByFrameLocation.put(sl, g);
}
}
protected void removeGateFromChunk(final Gate g, final Location l)
{
if (l != null) {
Chunk c = l.getChunk();
int x = c.getX();
int z = c.getZ();
for (int i = x-getChunkRadius(); i < x+getChunkRadius(); i++) {
for (int j = z-getChunkRadius(); j < z+getChunkRadius(); j++) {
SimpleChunk sc = new SimpleChunk(i, j, c.getWorld());
Set<Gate> gatesInChunk = gatesByChunk.get(sc);
if (gatesInChunk != null) {
gatesInChunk.remove(g);
}
}
}
}
}
protected void addGateByChunk(final Gate g)
{
Location gateLocation = g.getLocation();
if (gateLocation != null) {
Chunk c = g.getLocation().getChunk();
int x = c.getX();
int z = c.getZ();
for (int i = x-getChunkRadius(); i < x+getChunkRadius(); i++) {
for (int j = z-getChunkRadius(); j < z+getChunkRadius(); j++) {
SimpleChunk sc = new SimpleChunk(i, j, c.getWorld());
Set<Gate> gatesForC = gatesByChunk.get(sc);
if (gatesForC == null) {
gatesForC = new HashSet<Gate>(); // NOTE: not optimizing size here
gatesByChunk.put(sc, gatesForC);
}
gatesForC.add(g);
}
}
}
}
public void storeInvalidGate(Map<String, Object> map)
{
File invalidGatesFile = new File(Plugin.getPlugin().getDataFolder(), "invalid_gates.yml");
Boolean invalidGatesFileExists = invalidGatesFile.exists();
try {
FileWriter fileWriter = new FileWriter(invalidGatesFile, true);
if (!invalidGatesFileExists) {
fileWriter.write("gates:\n");
}
fileWriter.write("- ==: ");
fileWriter.write(map.get("==").toString() + "\n");
map.remove("==");
fileWriter.write("\topen: false\n");
map.remove("open");
fileWriter.write("\tgateBlocks: []\n");
map.remove("gateBlocks");
for (String key : map.keySet()) {
Object value = map.get(key);
fileWriter.write("\t" + key + ": ");
if (value instanceof Map) {
fileWriter.write("\n");
@SuppressWarnings("unchecked")
Map<String, Object> valueMap = (Map<String, Object>)value;
for (String k : valueMap.keySet()) {
Object v = valueMap.get(k);
fileWriter.write("\t\t" + k + ": " + v.toString() + "\n");
}
}
else {
fileWriter.write(value.toString() + "\n");
}
}
fileWriter.close();
}
catch (IOException e) {
Plugin.log("ERROR: Could not save invalid gates to disk. Reason: \n" + Arrays.toString(e.getStackTrace()));
}
}
public void handleGateIdChange(final Gate g, final String oldId)
{
this.removeGateById(oldId);
this.addGateWithId(g);
}
public void handleGateLocationChange(final Gate g,
final Location oldLocation,
final Set<Location> oldGateBlockLocations,
final Set<Block> oldGateFrameBlocks)
{
this.removeGateFromChunk(g, oldLocation);
this.addGateByChunk(g);
this.removeGateByLocation(oldGateBlockLocations);
this.addGateByLocations(g);
this.removeGateByFrameLocation(oldGateFrameBlocks);
this.addGateByFrameLocations(g);
}
public void handleNewGate(final Gate g)
{
this.gates.add(g);
this.addGateByChunk(g);
this.addGateByLocations(g);
this.addGateWithId(g);
this.addGateByFrameLocations(g);
}
public void handleDeletion(final Gate g)
{
this.gates.remove(g);
this.removeGateById(g.getId());
this.removeGateFromChunk(g, g.getLocation());
this.removeGateByLocation(g.getGateBlockLocations());
this.removeGateByFrameLocation(g.getGateFrameBlocks());
}
public boolean gateExists(final String id)
{
return gatesById.containsKey(id.toLowerCase());
}
public List<Gate> allGates ()
{
return gates;
}
}

View File

@ -16,12 +16,16 @@
*/ */
package de.craftinc.gates; package de.craftinc.gates;
import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import de.craftinc.gates.controllers.GatesManager;
import de.craftinc.gates.listeners.*; import de.craftinc.gates.listeners.*;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.ConfigurationUtil;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
@ -33,135 +37,117 @@ import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import de.craftinc.gates.commands.*; import de.craftinc.gates.commands.*;
import org.mcstats.Metrics;
public class Plugin extends JavaPlugin {
private static Plugin instance;
public class Plugin extends JavaPlugin private String baseCommand;
{ protected List<BaseCommand> commands = new ArrayList<>();
public static final String permissionInfo = "craftincgates.info";
public static final String permissionManage = "craftincgates.manage";
public static final String permissionUse = "craftincgates.use";
public static final String confMaxGateBlocksKey = "maxGateBlocks"; private GatesManager gatesManager = new GatesManager();
public static final String confPlayerGateBlockUpdateRadiusKey = "playerGateBlockUpdateRadius";
public static final String confCheckForBrokenGateFramesKey = "checkForBrokenGateFrames";
public static final String confGateTeleportMessageKey = "gateTeleportMessage";
public static final String confShowTeleportMessageKey = "showTeleportMessage";
public static final String confGateTeleportNoPermissionMessageKey = "gateTeleportNoPermissionMessage";
public static final String confShowTeleportNoPermissionMessageKey = "showTeleportNoPermissionMessage";
public static final String confSaveOnChangesKey = "saveOnChanges";
private static Plugin instance;
private static Permission permission;
protected String baseCommand;
protected List<BaseCommand> commands = new ArrayList<BaseCommand>();
protected GatesManager gatesManager = new GatesManager();
protected PlayerMoveListener moveListener = new PlayerMoveListener(); private PermissionController permissionController = new PermissionController();
protected PlayerTeleportListener teleportListener = new PlayerTeleportListener();
protected PlayerRespawnListener respawnListener = new PlayerRespawnListener();
protected PlayerChangedWorldListener worldChangeListener = new PlayerChangedWorldListener();
protected PlayerJoinListener joinListener = new PlayerJoinListener();
protected BlockBreakListener blockBreakListener = new BlockBreakListener();
public Plugin()
{
instance = this;
}
public static Plugin getPlugin()
{
return instance;
}
public GatesManager getGatesManager()
{
return gatesManager;
}
private PlayerMoveListener moveListener;
private VehicleMoveListener vehicleListener;
private PlayerTeleportListener teleportListener = new PlayerTeleportListener();
private PlayerRespawnListener respawnListener = new PlayerRespawnListener();
private PlayerChangedWorldListener worldChangeListener = new PlayerChangedWorldListener();
private PlayerJoinListener joinListener = new PlayerJoinListener();
private BlockBreakListener blockBreakListener = new BlockBreakListener();
@Override public Plugin() {
public void onLoad() instance = this;
{ moveListener = new PlayerMoveListener(this);
ConfigurationSerialization.registerClass(Gate.class); vehicleListener = new VehicleMoveListener(this);
} }
public static Plugin getPlugin() {
return instance;
}
protected void setupPermissions() public GatesManager getGatesManager() {
{ return gatesManager;
if (getServer().getPluginManager().getPlugin("Vault") == null) { }
@Override
public void onLoad() {
ConfigurationSerialization.registerClass(Gate.class);
}
private void setupPermissions() {
if (getServer().getPluginManager().getPlugin("Vault") == null) {
log("Not using setup permission provider provided by Vault.");
return; return;
} }
RegisteredServiceProvider<Permission> rsp = getServer().getServicesManager().getRegistration(Permission.class); RegisteredServiceProvider<Permission> rsp = getServer().getServicesManager().getRegistration(Permission.class);
if (rsp != null)
{
log("Using permission provider provided by Vault.");
permission = rsp.getProvider();
}
else
{
log("Not using setup permission provider provided by Vault.");
}
}
@Override if (rsp != null) {
public void onDisable() log("Using permission provider provided by Vault.");
{ permissionController.setPermission(rsp.getProvider());
// Save gates } else {
gatesManager.saveGatesToDisk(); log("Not using setup permission provider provided by Vault.");
}
log("Disabled"); }
}
@Override
@Override public void onDisable() {
public void onEnable() gatesManager.saveGatesToDisk();
{ log("Disabled");
// Setup configuration }
@Override
public void onEnable() {
// Setup Metrics
try {
Metrics metrics = new Metrics(this);
metrics.start();
} catch (IOException e) {
log("Failed to start metrics!");
}
// Setup configuration
this.saveDefaultConfig(); this.saveDefaultConfig();
// Setup permissions // Setup permissions
setupPermissions(); setupPermissions();
// Add the commands
commands.add(new CommandHelp());
commands.add(new CommandNew());
commands.add(new CommandRemove());
commands.add(new CommandLocation());
commands.add(new CommandExit());
commands.add(new CommandOpen());
commands.add(new CommandRename());
commands.add(new CommandClose());
commands.add(new CommandList());
commands.add(new CommandInfo());
commands.add(new CommandHide());
commands.add(new CommandUnhide());
// Add the commands
// Register events commands.add(new CommandHelp());
this.registerEventListeners(); commands.add(new CommandNew());
commands.add(new CommandRemove());
// Load gates commands.add(new CommandLocation());
boolean success = gatesManager.loadGatesFromDisk(); commands.add(new CommandExit());
commands.add(new CommandTriggerOpen());
commands.add(new CommandRename());
commands.add(new CommandList());
commands.add(new CommandInfo());
commands.add(new CommandNearby());
commands.add(new CommandTriggerVehicles());
commands.add(new CommandMaterial());
commands.add(new CommandTeleport());
// Register events
this.registerEventListeners();
// Load gates
boolean success = gatesManager.loadGatesFromDisk();
if (success) { if (success) {
log("Enabled"); log("Enabled");
} } else {
else {
PluginManager pm = this.getServer().getPluginManager(); PluginManager pm = this.getServer().getPluginManager();
pm.disablePlugin(this); pm.disablePlugin(this);
} }
} }
public PermissionController getPermissionController() {
return permissionController;
}
protected void registerEventListeners() private void registerEventListeners() {
{
PluginManager pm = this.getServer().getPluginManager(); PluginManager pm = this.getServer().getPluginManager();
pm.registerEvents(this.moveListener, this); pm.registerEvents(this.moveListener, this);
@ -169,80 +155,63 @@ public class Plugin extends JavaPlugin
pm.registerEvents(this.respawnListener, this); pm.registerEvents(this.respawnListener, this);
pm.registerEvents(this.worldChangeListener, this); pm.registerEvents(this.worldChangeListener, this);
pm.registerEvents(this.joinListener, this); pm.registerEvents(this.joinListener, this);
pm.registerEvents(this.vehicleListener, this);
if (getConfig().getBoolean(confCheckForBrokenGateFramesKey)) { if (getConfig().getBoolean(ConfigurationUtil.confCheckForBrokenGateFramesKey)) {
pm.registerEvents(this.blockBreakListener, this); pm.registerEvents(this.blockBreakListener, this);
} }
} }
// -------------------------------------------- //
// -------------------------------------------- // // Commands
// Commands // -------------------------------------------- //
// -------------------------------------------- //
public String getBaseCommand()
{
if (this.baseCommand != null)
return this.baseCommand;
Map<String, Map<String, Object>> Commands = this.getDescription().getCommands();
this.baseCommand = Commands.keySet().iterator().next();
return this.baseCommand;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
{
List<String> parameters = new ArrayList<String>(Arrays.asList(args));
this.handleCommand(sender, parameters);
return true;
}
public void handleCommand(CommandSender sender, List<String> parameters)
{
if (parameters.size() == 0)
{
this.commands.get(0).execute(sender, parameters);
return;
}
String commandName = parameters.get(0).toLowerCase();
parameters.remove(0);
for (BaseCommand fcommand : this.commands)
{
if (fcommand.getAliases().contains(commandName))
{
fcommand.execute(sender, parameters);
return;
}
}
sender.sendMessage(ChatColor.RED + "Unknown gate-command \"" + commandName + "\"." +
ChatColor.GREEN + " Try " + "/" + getBaseCommand() + " help");
}
/*
* Logging
*/
public static void log(String msg)
{
log(Level.INFO, msg);
}
public static void log(Level level, String msg)
{
Logger.getLogger("Minecraft").log(level, "["+instance.getDescription().getFullName()+"] "+msg);
}
public String getBaseCommand() {
if (this.baseCommand != null)
return this.baseCommand;
public static Permission getPermission() { Map<String, Map<String, Object>> Commands = this.getDescription().getCommands();
return permission;
} this.baseCommand = Commands.keySet().iterator().next();
return this.baseCommand;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
List<String> parameters = new ArrayList<>(Arrays.asList(args));
this.handleCommand(sender, parameters);
return true;
}
private void handleCommand(CommandSender sender, List<String> parameters) {
if (parameters.size() == 0) {
this.commands.get(0).execute(sender, parameters);
return;
}
String commandName = parameters.get(0).toLowerCase();
parameters.remove(0);
for (BaseCommand command : this.commands) {
if (command.getAliases().contains(commandName)) {
command.execute(sender, parameters);
return;
}
}
sender.sendMessage(ChatColor.RED + "Unknown gate-command \"" + commandName + "\"." +
ChatColor.GREEN + " Try " + "/" + getBaseCommand() + " help");
}
/*
* Logging
*/
public static void log(String msg) {
log(Level.INFO, msg);
}
public static void log(Level level, String msg) {
Logger.getLogger("Minecraft").log(level, "[" + instance.getDescription().getFullName() + "] " + msg);
}
} }

View File

@ -19,233 +19,174 @@ package de.craftinc.gates.commands;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.ConfigurationUtil;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import de.craftinc.gates.Gate; import de.craftinc.gates.models.Gate;
import de.craftinc.gates.GatesManager; import de.craftinc.gates.controllers.GatesManager;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil; import de.craftinc.gates.util.TextUtil;
public abstract class BaseCommand public abstract class BaseCommand {
{ PermissionController permissionController;
protected List<String> aliases = new ArrayList<String>(); GatesManager gatesManager;
protected List<String> requiredParameters = new ArrayList<String>();
protected List<String> optionalParameters = new ArrayList<String>();
protected String helpDescription = "no description";
protected List<String> parameters;
protected CommandSender sender;
protected Player player;
protected Gate gate;
protected boolean senderMustBePlayer = true;
protected boolean hasGateParam = true;
protected String requiredPermission;
protected boolean needsPermissionAtCurrentLocation;
protected boolean shouldPersistToDisk;
List<String> aliases = new ArrayList<>();
public List<String> getAliases() { List<String> requiredParameters = new ArrayList<>();
return aliases; List<String> optionalParameters = new ArrayList<>();
}
String helpDescription = "no description";
public void execute(CommandSender sender, List<String> parameters) { List<String> parameters;
this.sender = sender; CommandSender sender;
this.parameters = parameters; Player player;
Gate gate;
if (!this.validateCall()) {
return; boolean senderMustBePlayer = true;
} boolean hasGateParam = true;
if (this.senderMustBePlayer) { String requiredPermission;
this.player = (Player)sender; boolean needsPermissionAtCurrentLocation;
}
boolean shouldPersistToDisk;
this.perform();
public List<String> getAliases() {
if (this.shouldPersistToDisk && Plugin.getPlugin().getConfig().getBoolean(Plugin.confSaveOnChangesKey)) { return aliases;
Plugin.getPlugin().getGatesManager().saveGatesToDisk(); }
}
} public BaseCommand() {
gatesManager = Plugin.getPlugin().getGatesManager();
permissionController = Plugin.getPlugin().getPermissionController();
abstract protected void perform(); }
public void execute(CommandSender sender, List<String> parameters) {
protected void sendMessage(String message) { this.sender = sender;
sender.sendMessage(message); this.parameters = parameters;
}
if (!this.validateCall()) {
return;
protected void sendMessage(List<String> messages) { }
for(String message : messages) {
this.sendMessage(message); if (sender instanceof Player) {
} this.player = (Player)sender;
} }
this.perform();
protected boolean validateCall()
{ if (this.shouldPersistToDisk && getSaveOnChanges()) {
boolean allParametersThere = parameters.size() >= requiredParameters.size(); gatesManager.saveGatesToDisk();
boolean senderIsPlayer = this.sender instanceof Player; }
boolean hasGateParameter = false; }
if (this.hasGateParam && this.parameters.size() > 0 && this.setGateUsingParameter(this.parameters.get(0))) { abstract protected void perform();
hasGateParameter = true;
} void sendMessage(String message) {
sender.sendMessage(message);
boolean senderHasPermission = this.hasPermission(); }
boolean valid;
void sendMessage(List<String> messages) {
if (this.senderMustBePlayer && !senderIsPlayer) { for (String message : messages) {
sendMessage(ChatColor.RED + "This command can only be used by ingame players."); this.sendMessage(message);
valid = false; }
} }
else {
boolean setGateUsingParameter(String param) {
if (!gatesManager.gateExists(param)) {
return false;
} else {
gate = gatesManager.getGateWithId(param);
return true;
}
}
/**
* This will return false if a gate is required for this command but this.gate == null.
*/
boolean hasPermission() {
if (needsPermissionAtCurrentLocation) {
return permissionController.hasPermission(sender, requiredPermission);
} else {
return permissionController.hasPermission(sender, gate, requiredPermission);
}
}
/*
Help and usage description
*/
String getUsageTemplate(boolean withDescription) {
String ret = "";
ret += ChatColor.AQUA;
ret += "/" + Plugin.getPlugin().getBaseCommand() + " " + TextUtil.implode(getAliases(), ",") + " ";
List<String> parts = new ArrayList<>();
for (String requiredParameter : requiredParameters) {
parts.add("[" + requiredParameter + "]");
}
for (String optionalParameter : optionalParameters) {
parts.add("*[" + optionalParameter + "]");
}
ret += ChatColor.DARK_AQUA;
ret += TextUtil.implode(parts, " ");
if (withDescription) {
ret += " ";
ret += ChatColor.YELLOW;
ret += helpDescription;
}
return ret;
}
private boolean validateCall() {
boolean allParametersThere = parameters.size() >= requiredParameters.size();
boolean senderIsPlayer = this.sender instanceof Player;
boolean hasGateParameter = false;
if (this.hasGateParam && this.parameters.size() > 0 && this.setGateUsingParameter(this.parameters.get(0))) {
hasGateParameter = true;
}
boolean senderHasPermission = this.hasPermission();
boolean valid;
if (this.senderMustBePlayer && !senderIsPlayer) {
sendMessage(ChatColor.RED + "This command can only be used by in-game players.");
valid = false;
} else {
if (!allParametersThere) { if (!allParametersThere) {
sendMessage(ChatColor.RED + "Some parameters are missing! " + ChatColor.AQUA + "Usage: " + this.getUsageTemplate(true)); sendMessage(ChatColor.RED + "Some parameters are missing! " +
ChatColor.AQUA + "Usage: " +
getUsageTemplate(false)
);
valid = false; valid = false;
} } else if ((!senderHasPermission && this.hasGateParam) ||
else if ((!senderHasPermission && this.hasGateParam) || (!senderHasPermission) ||
(!senderHasPermission) || (this.hasGateParam && !hasGateParameter)) {
(this.hasGateParam && !hasGateParameter)) {
sendMessage(ChatColor.RED + "You either provided a invalid gate or do not have permission to " + this.helpDescription.toLowerCase()); sendMessage(ChatColor.RED +
"You either provided a invalid gate or do not have permission to " +
this.helpDescription.toLowerCase()
);
valid = false; valid = false;
} } else {
else {
valid = true; valid = true;
} }
} }
return valid;
}
protected boolean setGateUsingParameter(String param)
{
GatesManager gateManager = Plugin.getPlugin().getGatesManager();
if (!gateManager.gateExists(param)) {
return false;
}
else {
gate = gateManager.getGateWithId(param);
return true;
}
}
/**
* This will return false if a gate is required for this command but this.gate == null.
*/
protected boolean hasPermission()
{
if (Plugin.getPermission() == null) { // fallback - use the standard bukkit permission system
return this.sender.hasPermission(this.requiredPermission);
}
if (!(this.sender instanceof Player)) { return valid;
// sender is no player - there is no information about the senders locations }
return Plugin.getPermission().has(this.sender, this.requiredPermission);
}
private boolean getSaveOnChanges() {
Player p = (Player) this.sender; FileConfiguration config = Plugin.getPlugin().getConfig();
boolean hasPermission = false; return config.getBoolean(ConfigurationUtil.confSaveOnChangesKey);
}
if (this.requiredPermission.equals(Plugin.permissionInfo)) {
if (this.hasGateParam) {
hasPermission = this.hasPermissionAtGateLocationAndExit(p);
}
else {
hasPermission = Plugin.getPermission().has(p.getWorld(), p.getName(), this.requiredPermission);
}
}
else if (this.requiredPermission.equals(Plugin.permissionUse) ) {
hasPermission = this.hasPermissionAtGateLocationAndExit(p);
}
else if (this.requiredPermission.equals(Plugin.permissionManage)) {
if (this.needsPermissionAtCurrentLocation && this.hasGateParam) {
boolean hasPersmissionAtCurrentLocation = Plugin.getPermission().has(p.getWorld(), p.getName(), this.requiredPermission);
hasPermission = hasPersmissionAtCurrentLocation && this.hasPermissionAtGateLocationAndExit(p);
}
else if (this.needsPermissionAtCurrentLocation) {
hasPermission = Plugin.getPermission().has(p.getWorld(), p.getName(), this.requiredPermission);
}
else {
hasPermission = this.hasPermissionAtGateLocationAndExit(p);
}
}
return hasPermission;
}
protected boolean hasPermissionAtGateLocationAndExit(Player p)
{
if (this.gate == null || p == null) { // make sure we don't run into a nullpointer exception
return false;
}
boolean permAtLocation = this.gate.getLocation() == null || Plugin.getPermission().has(this.gate.getLocation().getWorld(), p.getName(), this.requiredPermission);
boolean permAtExit = this.gate.getExit() == null || Plugin.getPermission().has(this.gate.getExit().getWorld(), p.getName(), this.requiredPermission);
return permAtLocation & permAtExit;
}
// -------------------------------------------- //
// Help and usage description
// -------------------------------------------- //
protected String getUsageTemplate(boolean withColor, boolean withDescription)
{
String ret = "";
if (withColor) {
ret += ChatColor.AQUA;
}
ret += "/" + Plugin.getPlugin().getBaseCommand() + " " + TextUtil.implode(this.getAliases(), ",")+" ";
List<String> parts = new ArrayList<String>();
for (String requiredParameter : this.requiredParameters) {
parts.add("["+requiredParameter+"]");
}
for (String optionalParameter : this.optionalParameters) {
parts.add("*["+optionalParameter+"]");
}
if (withColor) {
ret += ChatColor.DARK_AQUA;
}
ret += TextUtil.implode(parts, " ");
if (withDescription) {
ret += " ";
if (withColor) {
ret += ChatColor.YELLOW;
}
ret += this.helpDescription;
}
return ret;
}
protected String getUsageTemplate(boolean withColor)
{
return getUsageTemplate(withColor, false);
}
} }

View File

@ -21,27 +21,21 @@ import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
public abstract class BaseLocationCommand extends BaseCommand abstract class BaseLocationCommand extends BaseCommand {
{
protected Location getValidPlayerLocation() Location getValidPlayerLocation() {
{ // The player might stand in a half block or a sign or whatever
// The player might stand in a half block or a sign or whatever // Therefore we load some extra locations and blocks
// Therefore we load some extra locations and blocks Location location = player.getLocation().clone();
Block playerBlock = player.getLocation().getBlock(); Block playerBlock = location.getBlock();
Block upBlock = playerBlock.getRelative(BlockFace.UP); Block upBlock = playerBlock.getRelative(BlockFace.UP);
if (playerBlock.getType() == Material.AIR) { if (playerBlock.getType() == Material.AIR) {
return player.getLocation(); return location;
} } else if (upBlock.getType() == Material.AIR) {
else if (upBlock.getType() == Material.AIR) { return location.add(0, 1, 0);
return new Location(player.getLocation().getWorld(), } else {
player.getLocation().getX(), return null;
player.getLocation().getY() + 1, }
player.getLocation().getZ(), }
player.getLocation().getYaw(),
player.getLocation().getPitch());
}
return null;
}
} }

View File

@ -1,64 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.commands;
import java.util.logging.Level;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin;
public class CommandClose extends BaseCommand
{
public CommandClose()
{
aliases.add("close");
aliases.add("c");
requiredParameters.add("id");
helpDescription = "Closes a gate to prevent players from using it.";
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
@Override
public void perform()
{
try
{
gate.setOpen(false);
GateBlockChangeSender.updateGateBlocks(gate);
sendMessage(ChatColor.GREEN + "The gate was closed.");
}
catch(Exception e)
{
sendMessage(ChatColor.RED + "Opening the gate failed! See server log for more information");
Plugin.log(Level.WARNING, e.getMessage());
e.printStackTrace();
}
}
}

View File

@ -18,44 +18,37 @@ package de.craftinc.gates.commands;
import java.util.logging.Level; import java.util.logging.Level;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
import org.bukkit.Location;
public class CommandExit extends BaseCommand {
public class CommandExit extends BaseCommand public CommandExit() {
{ aliases.add("exit");
public CommandExit() aliases.add("e");
{ requiredParameters.add("id");
aliases.add("exit"); helpDescription = "Change exit of location.";
aliases.add("e"); requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = true;
requiredParameters.add("id"); shouldPersistToDisk = true;
senderMustBePlayer = true;
helpDescription = "Change exit of location."; }
requiredPermission = Plugin.permissionManage; public void perform() {
try {
needsPermissionAtCurrentLocation = true; Location oldExit = gate.getExit();
shouldPersistToDisk = true; gate.setExit(player.getLocation());
senderMustBePlayer = true; sendMessage(ChatColor.GREEN + "The exit of gate '" + gate.getId() + "' is now where you stand.");
} gatesManager.handleGateExitChange(gate, oldExit);
} catch (Exception e) {
public void perform()
{
try
{
gate.setExit(player.getLocation());
sendMessage(ChatColor.GREEN + "The exit of gate '" + gate.getId() + "' is now where you stand.");
}
catch (Exception e) {
GateBlockChangeSender.updateGateBlocks(gate); GateBlockChangeSender.updateGateBlocks(gate);
sendMessage(ChatColor.RED + "Setting the exit for the gate failed! See server log for more information"); sendMessage(ChatColor.RED + "Setting the exit for the gate failed! See server log for more information");
Plugin.log(Level.WARNING, e.getMessage()); Plugin.log(Level.WARNING, e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

View File

@ -16,94 +16,53 @@
*/ */
package de.craftinc.gates.commands; package de.craftinc.gates.commands;
import de.craftinc.gates.Plugin; import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.TextUtil; import de.craftinc.gates.util.TextUtil;
import java.util.ArrayList; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class CommandHelp extends BaseCommand public class CommandHelp extends BaseCommand {
{
public static List<List<String>> helpPages;
static
{
// sort the usage strings
List<String> allUsageStrings = new ArrayList<String>();
allUsageStrings.add( new CommandHelp().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandNew().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandRemove().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandLocation().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandExit().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandOpen().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandRename().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandClose().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandList().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandInfo().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandHide().getUsageTemplate(true, true) );
allUsageStrings.add( new CommandUnhide().getUsageTemplate(true, true) );
Collections.sort(allUsageStrings);
// put 5 commands on one page
helpPages = new ArrayList<List<String>>();
while (!allUsageStrings.isEmpty()) {
int toIndex = allUsageStrings.size() >= 6 ? 5 : allUsageStrings.size();
List<String> currentHelpPage = new ArrayList<String>(allUsageStrings.subList(0, toIndex));
helpPages.add(currentHelpPage);
allUsageStrings.removeAll(currentHelpPage);
}
}
public CommandHelp()
{
aliases.add("help");
aliases.add("?");
optionalParameters.add("page");
helpDescription = "prints this help page";
requiredPermission = Plugin.permissionInfo;
hasGateParam = false;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = false;
senderMustBePlayer = false;
}
private static List<String> help;
public void perform() public CommandHelp() {
{ aliases.add("help");
int page; aliases.add("?");
helpDescription = "prints this help page";
if (parameters.size() > 0) { requiredPermission = PermissionController.permissionInfo;
try { hasGateParam = false;
page = Integer.parseInt(parameters.get(0)); needsPermissionAtCurrentLocation = false;
} shouldPersistToDisk = false;
catch (NumberFormatException e) { senderMustBePlayer = false;
// wasn't an integer }
page = 1;
} public void perform() {
} sendMessage(TextUtil.titleSize("Craft Inc. Gates Help"));
else { sendMessage(getHelp());
page = 1; }
private List<String> getHelp() {
if (help == null) {
help = Arrays.asList(
new CommandHelp().getUsageTemplate(true),
new CommandNew().getUsageTemplate(true),
new CommandRemove().getUsageTemplate(true),
new CommandLocation().getUsageTemplate(true),
new CommandExit().getUsageTemplate(true),
new CommandTriggerOpen().getUsageTemplate(true),
new CommandRename().getUsageTemplate(true),
new CommandList().getUsageTemplate(true),
new CommandInfo().getUsageTemplate(true),
new CommandNearby().getUsageTemplate(true),
new CommandTriggerVehicles().getUsageTemplate(true),
new CommandTeleport().getUsageTemplate(true),
new CommandMaterial().getUsageTemplate(true)
);
Collections.sort(help);
} }
sendMessage(TextUtil.titleize("Craft Inc. Gates Help (" + page + "/" + helpPages.size() + ")"));
page -= 1;
if (page < 0 || page >= helpPages.size()) {
sendMessage("This page does not exist");
return;
}
sendMessage(helpPages.get(page));
}
}
return help;
}
}

View File

@ -1,59 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.commands;
import java.util.logging.Level;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin;
public class CommandHide extends BaseCommand
{
public CommandHide()
{
aliases.add("hide");
aliases.add("h");
requiredParameters.add("id");
helpDescription = "Makes a gate NOT consist of gate blocks while open.";
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform()
{
try {
gate.setHidden(true);
GateBlockChangeSender.updateGateBlocks(gate);
sendMessage(ChatColor.GREEN + "The gate '" + gate.getId() + "' is now hidden.");
}
catch (Exception e) {
sendMessage(ChatColor.RED + "Hiding the gate failed! See server log for more information");
Plugin.log(Level.WARNING, e.getMessage());
e.printStackTrace();
}
}
}

View File

@ -16,62 +16,98 @@
*/ */
package de.craftinc.gates.commands; package de.craftinc.gates.commands;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil; import de.craftinc.gates.util.TextUtil;
import org.bukkit.entity.Player;
import java.util.HashSet;
public class CommandInfo extends BaseCommand {
public CommandInfo() {
aliases.add("info");
aliases.add("i");
optionalParameters.add("id");
helpDescription = "Print detailed information about a certain or the closest gate.";
requiredPermission = PermissionController.permissionInfo;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = false;
senderMustBePlayer = false;
hasGateParam = false;
}
public void perform() {
if (this.parameters.size() > 0) {
if (!this.setGateUsingParameter(this.parameters.get(0))) {
sendMessage(ChatColor.RED + "You either provided a invalid gate or do not have permission to " + this.helpDescription.toLowerCase());
return;
}
sendMessage(TextUtil.titleSize("Information about: '" + ChatColor.WHITE + gate.getId() + ChatColor.YELLOW + "'"));
} else {
boolean senderIsPlayer = this.sender instanceof Player;
if (!senderIsPlayer) {
sendMessage(ChatColor.RED + "Only ingame players can perform this command without a supplied gate id!");
return;
}
Player p = (Player) this.sender;
this.gate = gatesManager.getNearestGate(p.getLocation());
if (!this.hasPermission() || this.gate == null) {
sendMessage(ChatColor.RED + "There is either no gate nearby or you do not have permission to " + this.helpDescription.toLowerCase());
return;
}
Plugin.log(this.gate.toString());
sendMessage(TextUtil.titleSize("Information about closest gate: '" + ChatColor.WHITE + gate.getId() + ChatColor.YELLOW + "'"));
}
String openMessage = ChatColor.DARK_AQUA + "This gate is";
if (gate.isOpen())
openMessage += ChatColor.AQUA + " open";
else
openMessage += ChatColor.AQUA + " closed";
openMessage += ".\n";
sendMessage(openMessage);
if (gate.getLocation() != null)
sendMessage(ChatColor.DARK_AQUA + "location: " + ChatColor.AQUA + "( " + (int) gate.getLocation().getX() +
" | " + (int) gate.getLocation().getY() + " | " + (int) gate.getLocation().getZ() + " ) in " +
gate.getLocation().getWorld().getName());
else
sendMessage(ChatColor.DARK_AQUA + "NOTE: this gate has no location");
if (gate.getExit() != null)
sendMessage(ChatColor.DARK_AQUA + "exit: " + ChatColor.AQUA + "( " + (int) gate.getExit().getX() + " | "
+ (int) gate.getExit().getY() + " | " + (int) gate.getExit().getZ() + " ) in " +
gate.getExit().getWorld().getName());
else
sendMessage(ChatColor.DARK_AQUA + "NOTE: this gate has no exit");
public class CommandInfo extends BaseCommand if (gate.getAllowsVehicles())
{ sendMessage(ChatColor.DARK_AQUA + "You can ride through this gate.");
public CommandInfo()
{
aliases.add("info");
aliases.add("i");
requiredParameters.add("id"); sendMessage(ChatColor.DARK_AQUA + "This gate is made of "
+ ChatColor.AQUA + gate.getMaterial() + ChatColor.DARK_AQUA + ".");
helpDescription = "Print detailed information about a certain gate.";
if (this.sender instanceof Player) {
requiredPermission = Plugin.permissionInfo; HashSet<Gate> set = new HashSet<>();
set.add(this.gate);
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = false; GateBlockChangeSender.temporaryHighlightGatesFrames((Player)this.sender, set);
senderMustBePlayer = false; }
} }
public void perform()
{
sendMessage(TextUtil.titleize("Information about: '" + ChatColor.WHITE + gate.getId() + ChatColor.YELLOW + "'"));
String openHiddenMessage = ChatColor.DARK_AQUA + "This gate is";
if (gate.isOpen())
openHiddenMessage += ChatColor.AQUA + " open";
else
openHiddenMessage += ChatColor.AQUA + " closed";
if (gate.isHidden())
openHiddenMessage += ChatColor.DARK_AQUA +" and" + ChatColor.AQUA + " hidden";
openHiddenMessage += ".\n";
sendMessage(openHiddenMessage);
if (gate.getLocation() != null)
sendMessage(ChatColor.DARK_AQUA + "from: " + ChatColor.AQUA + "( " + (int)gate.getLocation().getX() +
" | " + (int)gate.getLocation().getY() + " | " + (int)gate.getLocation().getZ() + " ) in " +
gate.getLocation().getWorld().getName());
else
sendMessage(ChatColor.DARK_AQUA + "NOTE: this gate has no location");
if (gate.getExit() != null)
sendMessage(ChatColor.DARK_AQUA + "to: " + ChatColor.AQUA + "( " + (int)gate.getExit().getX() + " | "
+ (int)gate.getExit().getY() + " | " + (int)gate.getExit().getZ() + " ) in " +
gate.getExit().getWorld().getName());
else
sendMessage(ChatColor.DARK_AQUA + "NOTE: this gate has no exit");
}
} }

View File

@ -21,331 +21,276 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import de.craftinc.gates.Gate; import de.craftinc.gates.models.Gate;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil; import de.craftinc.gates.util.TextUtil;
public class CommandList extends BaseCommand {
public class CommandList extends BaseCommand private static final int linesPerPage = 15;
{
protected static final int linesPerPage = 10;
protected static final int charactersPerLine = 52; /* this is actually no true. the
font used by minecraft is not
monospace. but I don't think
there is a (easy) way for a
bukkit plugin to calculate
the drawing-size of a string.
*/
public CommandList()
{
aliases.add("list");
aliases.add("ls");
optionalParameters.add("page");
hasGateParam = false;
needsPermissionAtCurrentLocation = false;
helpDescription = "lists all availible gates.";
requiredPermission = Plugin.permissionInfo;
shouldPersistToDisk = false;
senderMustBePlayer = false;
}
protected static List<String> linesOfGateIds(List<String> gates)
{
List<String> lines = new ArrayList<String>();
int index = 0;
List<String> gateIdsForCurrentLine = new ArrayList<String>();
int numCharactersInCurrentLine = 0;
while (index < gates.size()) {
String gateId = gates.get(index);
int gateIdLength = gateId.length() + 2; // actual length + comma + whitespace
// special case: very long gate id
if (gateIdLength > charactersPerLine && numCharactersInCurrentLine == 0) {
gateIdsForCurrentLine = new ArrayList<String>();
numCharactersInCurrentLine = 0;
while ((gateId.length() + 2) > charactersPerLine) {
int cutPos = charactersPerLine;
// is the id too long to add comma and whitespace but not longer than the line?
if (gateId.length() <= charactersPerLine) {
cutPos -= 2;
}
lines.add(gateId.substring(0, cutPos));
gateId = gateId.substring(cutPos, gateId.length());
}
gateIdsForCurrentLine.add(gateId); /* this is actually not true. the font used by Minecraft is not
monospaced. but there seems to be no (easy) way to calculate
numCharactersInCurrentLine += gateId.length(); the drawing-size of a string.
index++; */
} private static final int charactersPerLine = 52;
// gate fits into current line public CommandList() {
else if ((numCharactersInCurrentLine + gateIdLength) <= charactersPerLine) { aliases.add("list");
gateIdsForCurrentLine.add(gateId); aliases.add("ls");
numCharactersInCurrentLine += gateIdLength;
optionalParameters.add("page");
index++; hasGateParam = false;
} needsPermissionAtCurrentLocation = false;
// the current gate does not fit on the helpDescription = "lists all availible gates.";
else {
lines.add(TextUtil.implode(gateIdsForCurrentLine, ", ") + ", "); requiredPermission = PermissionController.permissionInfo;
shouldPersistToDisk = false;
gateIdsForCurrentLine = new ArrayList<String>(); senderMustBePlayer = false;
numCharactersInCurrentLine = 0; }
}
} public void perform() {
int page = this.getPageParameter();
lines.add(TextUtil.implode(gateIdsForCurrentLine, ", ")); List<String> allPages = this.pagedGateIds();
return lines;
} if (allPages == null) { // no gates exist
sendMessage(ChatColor.RED + "There are no gates yet. " + ChatColor.RESET +
"(Note that you might not be allowed to get information about certain gates)");
protected static String intToTitleString(int i, boolean addPreviousPageNote, boolean addNextPageNote) return;
{ }
String retVal = ChatColor.DARK_AQUA + "";
if (page > allPages.size() || page < 1) {
if ( i < 26 ) { sendMessage(ChatColor.RED + "The requested page is not available");
retVal += (char)(i+65); return;
} }
else if ( i == 26 ) {
retVal += "0-9"; String message = TextUtil.titleSize("List of all gates (" + page + "/" + allPages.size() + ")") + "\n";
} message += allPages.get(page - 1);
else {
retVal += "!@#$"; sendMessage(message);
} }
if (addPreviousPageNote && addNextPageNote) { private static List<String> linesOfGateIds(List<String> gates) {
retVal += " (more on previous and next page)"; List<String> lines = new ArrayList<>();
}
else if (addPreviousPageNote) { int index = 0;
retVal += " (more on previous page)"; List<String> gateIdsForCurrentLine = new ArrayList<>();
} int numCharactersInCurrentLine = 0;
else if (addNextPageNote) {
retVal += " (more on next page)"; while (index < gates.size()) {
} String gateId = gates.get(index);
int gateIdLength = gateId.length() + 2; // actual length + comma + whitespace
return retVal + "\n";
} if (gateIdLength > charactersPerLine && numCharactersInCurrentLine == 0) { // special case: very long gate id
gateIdsForCurrentLine = new ArrayList<>();
numCharactersInCurrentLine = 0;
/**
* Method for getting a collection of gates the player is allowed to see. while ((gateId.length() + 2) > charactersPerLine) {
*/ int cutPos = charactersPerLine;
protected Collection<Gate> getAllGates()
{ // is the id too long to add comma and whitespace but not longer than the line?
Collection<Gate> gates = Plugin.getPlugin().getGatesManager().allGates(); if (gateId.length() <= charactersPerLine) {
cutPos -= 2;
if (this.sender instanceof Player && Plugin.getPermission() != null) { }
Player p = (Player)this.sender;
lines.add(gateId.substring(0, cutPos));
// create a copy since we cannot iterate over a collection while modifying it! gateId = gateId.substring(cutPos, gateId.length());
Collection<Gate> gatesCopy = new ArrayList<Gate>(gates); }
for (Gate gate : gatesCopy) { gateIdsForCurrentLine.add(gateId);
if (gate.getLocation() != null) { numCharactersInCurrentLine += gateId.length();
boolean permissionAtGateLocation = Plugin.getPermission().has(gate.getLocation().getWorld(), p.getName(), this.requiredPermission); index++;
if (!permissionAtGateLocation) { } else if ((numCharactersInCurrentLine + gateIdLength) <= charactersPerLine) { // gate fits into current line
gates.remove(gate); gateIdsForCurrentLine.add(gateId);
continue; numCharactersInCurrentLine += gateIdLength;
}
} index++;
} else { // the current gate does not fit on the
if (gate.getExit() != null) { lines.add(TextUtil.implode(gateIdsForCurrentLine, ", ") + ", ");
boolean permissionAtGateExit = Plugin.getPermission().has(gate.getExit().getWorld(), p.getName(), this.requiredPermission); gateIdsForCurrentLine = new ArrayList<>();
if (!permissionAtGateExit) { numCharactersInCurrentLine = 0;
gates.remove(gate); }
} }
}
} lines.add(TextUtil.implode(gateIdsForCurrentLine, ", "));
} return lines;
}
return gates;
} private static String intToTitleString(int i, boolean addPreviousPageNote, boolean addNextPageNote) {
String retVal = ChatColor.DARK_AQUA + "";
/** if (i < 26) {
* Sorts all gates by there first character. retVal += (char) (i + 65);
* Puts gates in corresponding Lists: (all returned lists will be sorted alphabetically) } else if (i == 26) {
* list 0-25: a,b,c,..,z retVal += "0-9";
* list 26: 0-9 } else {
* list 27: other retVal += "!@#$";
*/ }
protected static List<List<String>> gatesSortedByName(Collection<Gate> allGates)
{ if (addPreviousPageNote && addNextPageNote) {
// create the lists retVal += " (more on previous and next page)";
List<List<String>> ids = new ArrayList<List<String>>(); } else if (addPreviousPageNote) {
retVal += " (more on previous page)";
for (int i=0; i<28; i++) { } else if (addNextPageNote) {
ids.add(new ArrayList<String>()); retVal += " (more on next page)";
} }
// put all gates into correct lists return retVal + "\n";
for (Gate gate : allGates) { }
String id = gate.getId();
int first = id.charAt(0); /**
* Method for getting a collection of gates the player is allowed to see.
if (first > 96 && first < 123) { // convert lower case chars */
first -= 97; private Collection<Gate> getAllGates() {
} Collection<Gate> gates = gatesManager.allGates();
else if (first > 64 && first < 91) { // convert upper case chars // create a copy since we cannot iterate over a collection while modifying it!
first -= 65; Collection<Gate> gatesCopy = new ArrayList<>(gates);
}
else if (first > 47 && first < 58) { // convert numbers for (Gate gate : gatesCopy) {
first = 26; if (!this.permissionController.hasPermission(this.sender, gate, this.requiredPermission)) {
} gates.remove(gate);
else { // everything else }
first = 27; }
} return gates;
}
ids.get(first).add(id);
} /**
* Sorts all gates by there first character.
// sort everything * Puts gates in corresponding Lists: (all returned lists will be sorted alphabetically)
for (int i=0; i<28; i++) { * list 0-25: a,b,c,..,z
Collections.sort(ids.get(i)); * list 26: 0-9
} * list 27: other
*/
return ids; private static List<List<String>> gatesSortedByName(Collection<Gate> allGates) {
} // create the lists
List<List<String>> ids = new ArrayList<>();
/** for (int i = 0; i < 28; i++) {
* Returns a list of strings. ids.add(new ArrayList<String>());
* Each string is the text for a page. }
* The maximum number of lines per page is 'linesPerPage' minus 1.
* Will return an empty list if no gates are availible. // put all gates into correct lists
*/ for (Gate gate : allGates) {
protected List<String> pagedGateIds() String id = gate.getId();
{ int first = id.charAt(0);
Collection<Gate> gates = this.getAllGates();
if (first > 96 && first < 123) { // convert lower case chars
if (gates.size() == 0) { first -= 97;
return null; } else if (first > 64 && first < 91) { // convert upper case chars
} first -= 65;
} else if (first > 47 && first < 58) { // convert numbers
List<List<String>> gatesSortedByName = gatesSortedByName(gates); first = 26;
List<String> allPages = new ArrayList<String>(); } else { // everything else
int linesLeftOnPage = linesPerPage - 1; first = 27;
String currentPageString = ""; }
for (int i=0; i<gatesSortedByName.size(); i++) { ids.get(first).add(id);
}
List<String> currentGates = gatesSortedByName.get(i);
// sort everything
if(currentGates.isEmpty()) { for (int i = 0; i < 28; i++) {
continue; Collections.sort(ids.get(i));
} }
List<String> currentGatesAsLines = linesOfGateIds(currentGates); return ids;
boolean moreGatesOnLastPage = false; }
while (!currentGatesAsLines.isEmpty()) { /**
* Returns a list of strings.
if (linesLeftOnPage < 2) { * Each string is the text for a page.
currentPageString = currentPageString.substring(0, currentPageString.length()-2); // remove newlines add the end of the page * The maximum number of lines per page is 'linesPerPage' minus 1.
allPages.add(currentPageString); * Will return an empty list if no gates are availible.
currentPageString = ""; */
private List<String> pagedGateIds() {
linesLeftOnPage = linesPerPage - 1; Collection<Gate> gates = this.getAllGates();
}
if (gates.size() == 0) {
// calculate number of lines to add to current page return null;
int linesNecessaryForCurrentGates = currentGatesAsLines.size(); }
int linesToFill;
boolean moreGatesOnNextPage; List<List<String>> gatesSortedByName = gatesSortedByName(gates);
List<String> allPages = new ArrayList<>();
if (linesNecessaryForCurrentGates < linesLeftOnPage) { int linesLeftOnPage = linesPerPage - 1;
linesToFill = linesNecessaryForCurrentGates; String currentPageString = "";
moreGatesOnNextPage = false;
} for (int i = 0; i < gatesSortedByName.size(); i++) {
else {
linesToFill = linesLeftOnPage -1; List<String> currentGates = gatesSortedByName.get(i);
moreGatesOnNextPage = true;
} if (currentGates.isEmpty()) {
continue;
// add title }
currentPageString += intToTitleString(i, moreGatesOnLastPage, moreGatesOnNextPage);
currentPageString += ChatColor.AQUA; List<String> currentGatesAsLines = linesOfGateIds(currentGates);
linesLeftOnPage--; boolean moreGatesOnLastPage = false;
// add gate lines while (!currentGatesAsLines.isEmpty()) {
for (int j=0; j<linesToFill; j++) {
currentPageString += currentGatesAsLines.get(j) + "\n"; if (linesLeftOnPage < 2) {
} currentPageString = currentPageString.substring(0, currentPageString.length() - 2); // remove newlines add the end of the page
allPages.add(currentPageString);
// remove lines added currentPageString = "";
for (int j=0; j<linesToFill; j++) {
currentGatesAsLines.remove(0); linesLeftOnPage = linesPerPage - 1;
} }
// cleanup // calculate number of lines to add to current page
int linesNecessaryForCurrentGates = currentGatesAsLines.size();
int linesToFill;
boolean moreGatesOnNextPage;
if (linesNecessaryForCurrentGates < linesLeftOnPage) {
linesToFill = linesNecessaryForCurrentGates;
moreGatesOnNextPage = false;
} else {
linesToFill = linesLeftOnPage - 1;
moreGatesOnNextPage = true;
}
// add title
currentPageString += intToTitleString(i, moreGatesOnLastPage, moreGatesOnNextPage);
currentPageString += ChatColor.AQUA;
linesLeftOnPage--;
// add gate lines
for (int j = 0; j < linesToFill; j++) {
currentPageString += currentGatesAsLines.get(j) + "\n";
}
// remove lines added
for (int j = 0; j < linesToFill; j++) {
currentGatesAsLines.remove(0);
}
// cleanup
moreGatesOnLastPage = linesNecessaryForCurrentGates >= linesLeftOnPage; moreGatesOnLastPage = linesNecessaryForCurrentGates >= linesLeftOnPage;
linesLeftOnPage -= linesToFill; linesLeftOnPage -= linesToFill;
} }
} }
// add the last page
if (!currentPageString.isEmpty()) {
currentPageString = currentPageString.substring(0, currentPageString.length()-2); // remove newlines add the end of the page
allPages.add(currentPageString);
}
return allPages;
}
protected int getPageParameter()
{
int page = 1;
try {
page = new Integer(parameters.get(0));
}
catch (Exception ignored) { }
return page;
}
public void perform()
{
int page = this.getPageParameter();
List<String> allPages = this.pagedGateIds();
if (allPages == null) { // no gates exist // add the last page
sendMessage(ChatColor.RED + "There are no gates yet. " + ChatColor.RESET + if (!currentPageString.isEmpty()) {
"(Note that you might not be allowed to get information about certain gates)"); currentPageString = currentPageString.substring(0, currentPageString.length() - 2); // remove newlines add the end of the page
return; allPages.add(currentPageString);
} }
if (page > allPages.size() || page < 1) {
sendMessage(ChatColor.RED + "The requested page is not availible");
return;
}
String message = TextUtil.titleize("List of all gates (" + page + "/" + allPages.size() + ")") + "\n";
message += allPages.get(page-1);
sendMessage(message); return allPages;
} }
private int getPageParameter() {
int page = 1;
try {
page = new Integer(parameters.get(0));
} catch (Exception ignored) {
}
return page;
}
} }

View File

@ -16,70 +16,55 @@
*/ */
package de.craftinc.gates.commands; package de.craftinc.gates.commands;
import java.util.Set; import java.util.Set;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import de.craftinc.gates.Plugin;
import org.bukkit.block.Block; import org.bukkit.block.Block;
public class CommandLocation extends BaseLocationCommand {
public class CommandLocation extends BaseLocationCommand public CommandLocation() {
{ aliases.add("location");
aliases.add("lo");
public CommandLocation()
{ requiredParameters.add("id");
aliases.add("location"); helpDescription = "Set the entrance of the gate to your current location.";
aliases.add("lo"); requiredPermission = PermissionController.permissionManage;
requiredParameters.add("id"); needsPermissionAtCurrentLocation = true;
shouldPersistToDisk = true;
helpDescription = "Set the entrance of the gate to your current location."; senderMustBePlayer = true;
}
requiredPermission = Plugin.permissionManage;
public void perform() {
needsPermissionAtCurrentLocation = true; Location playerLocation = getValidPlayerLocation();
shouldPersistToDisk = true;
senderMustBePlayer = true; if (playerLocation == null) {
} sendMessage("There is not enough room for a gate to open here");
return;
}
public void perform()
{
Location playerLocation = getValidPlayerLocation();
if (playerLocation == null)
{
sendMessage("There is not enough room for a gate to open here");
return;
}
Location oldLocation = gate.getLocation(); Location oldLocation = gate.getLocation();
Set<Location> oldGateBlockLocations = gate.getGateBlockLocations(); Set<Location> oldGateBlockLocations = gate.getGateBlockLocations();
Set<Block> oldFrameBlocks = gate.getGateFrameBlocks(); Set<Block> oldFrameBlocks = gate.getGateFrameBlocks();
try try {
{
if (gate.isOpen()) { if (gate.isOpen()) {
GateBlockChangeSender.updateGateBlocks(gate, true); GateBlockChangeSender.updateGateBlocks(gate, true);
} }
gate.setLocation(playerLocation); gate.setLocation(playerLocation);
sendMessage(ChatColor.GREEN + "The location of '" + gate.getId() + "' is now at your current location.");
sendMessage(ChatColor.GREEN + "The location of '" + gate.getId() + "' is now at your current location."); } catch (Exception e) {
}
catch (Exception e)
{
sendMessage(ChatColor.RED + "There seems to be no frame at your new location! The gate got closed!" + ChatColor.AQUA + " You should build a frame now and execute:"); sendMessage(ChatColor.RED + "There seems to be no frame at your new location! The gate got closed!" + ChatColor.AQUA + " You should build a frame now and execute:");
sendMessage(new CommandOpen().getUsageTemplate(true, true)); sendMessage(new CommandTriggerOpen().getUsageTemplate(true));
} } finally {
finally { gatesManager.handleGateLocationChange(gate, oldLocation, oldGateBlockLocations, oldFrameBlocks);
Plugin.getPlugin().getGatesManager().handleGateLocationChange(gate, oldLocation, oldGateBlockLocations, oldFrameBlocks);
GateBlockChangeSender.updateGateBlocks(gate); GateBlockChangeSender.updateGateBlocks(gate);
} }
} }
} }

View File

@ -0,0 +1,45 @@
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.models.GateMaterial;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import java.security.InvalidParameterException;
public class CommandMaterial extends BaseCommand {
public CommandMaterial() {
aliases.add("material");
aliases.add("m");
requiredParameters.add("id");
requiredParameters.add("material");
senderMustBePlayer = false;
hasGateParam = true;
helpDescription = "Change the material of a gate";
requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
}
public void perform() {
GateMaterial material;
try {
material = new GateMaterial(parameters.get(1));
} catch (InvalidParameterException e) {
sendMessage(ChatColor.RED + "Invalid material!");
return;
}
try {
gate.setMaterial(material);
} catch (Exception e) {
sendMessage(ChatColor.RED + "Frame invalid. Gate is now closed!");
}
GateBlockChangeSender.updateGateBlocks(gate);
sendMessage(ChatColor.GREEN + "Gate " + gate.getId() + " uses now " + material.toString() + " as material.");
}
}

View File

@ -0,0 +1,41 @@
package de.craftinc.gates.commands;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender;
import de.craftinc.gates.util.TextUtil;
import java.util.ArrayList;
import java.util.Set;
public class CommandNearby extends BaseLocationCommand {
public CommandNearby() {
aliases.add("nearby");
aliases.add("nb");
helpDescription = "Highlight nearby gates";
requiredPermission = PermissionController.permissionInfo;
needsPermissionAtCurrentLocation = true;
shouldPersistToDisk = false;
senderMustBePlayer = true;
hasGateParam = false;
}
public void perform() {
Set<Gate> nearbyGates = gatesManager.getNearbyGates(player.getLocation().getChunk());
if (nearbyGates == null) {
player.sendMessage("There are no gates near you!");
} else {
GateBlockChangeSender.temporaryHighlightGatesFrames(player, nearbyGates);
ArrayList<String> gateNames = new ArrayList<>();
for (Gate g : nearbyGates) {
gateNames.add(g.getId());
}
player.sendMessage("Nearby gates: " + TextUtil.implode(gateNames, ", "));
}
}
}

View File

@ -16,68 +16,54 @@
*/ */
package de.craftinc.gates.commands; package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import de.craftinc.gates.Gate; import de.craftinc.gates.models.Gate;
import de.craftinc.gates.GatesManager;
import de.craftinc.gates.Plugin;
public class CommandNew extends BaseLocationCommand {
public class CommandNew extends BaseLocationCommand public CommandNew() {
{ aliases.add("new");
public CommandNew() aliases.add("create");
{
aliases.add("new");
aliases.add("n"); aliases.add("n");
requiredParameters.add("id"); requiredParameters.add("id");
senderMustBePlayer = true;
hasGateParam = false;
helpDescription = "Create a gate at your current location.";
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = true;
shouldPersistToDisk = true;
senderMustBePlayer = true;
}
public void perform()
{
String id = parameters.get(0);
GatesManager gatesManager = Plugin.getPlugin().getGatesManager();
if (gatesManager.gateExists(id)) {
sendMessage(ChatColor.RED + "Creating the gate failed! " + "A gate with the supplied id already exists!");
return;
}
gate = new Gate(id);
sendMessage(ChatColor.GREEN + "Gate with id '" + id + "' was created.");
senderMustBePlayer = true;
Location playerLocation = getValidPlayerLocation(); hasGateParam = false;
helpDescription = "Create a gate at your current location.";
if (playerLocation != null) { requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = true;
try { shouldPersistToDisk = true;
gate.setLocation(playerLocation); senderMustBePlayer = true;
sendMessage(ChatColor.AQUA + "The gates location has been set to your current location."); }
}
catch (Exception ignored) {} public void perform() {
} String id = parameters.get(0);
else
{ if (gatesManager.gateExists(id)) {
sendMessage(ChatColor.RED + "Your location is invalid!" + ChatColor.AQUA + "Go somewhere else and execute:"); sendMessage(ChatColor.RED + "Creating the gate failed! " + "A gate with the supplied id already exists!");
sendMessage(new CommandLocation().getUsageTemplate(true, true)); return;
} }
gate = new Gate(id);
sendMessage(ChatColor.GREEN + "Gate with id '" + id + "' was created.");
Location playerLocation = getValidPlayerLocation();
if (playerLocation != null) {
try {
gate.setLocation(playerLocation);
sendMessage(ChatColor.AQUA + "The gates location has been set to your current location.");
} catch (Exception ignored) {
}
} else {
sendMessage(ChatColor.RED + "Your location is invalid!" + ChatColor.AQUA + "Go somewhere else and execute:");
sendMessage(new CommandLocation().getUsageTemplate(true));
}
gatesManager.handleNewGate(gate); gatesManager.handleNewGate(gate);
} }
} }

View File

@ -1,70 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin;
public class CommandOpen extends BaseCommand
{
public CommandOpen()
{
aliases.add("open");
aliases.add("o");
requiredParameters.add("id");
helpDescription = "Open a gate so players can use it.";
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform()
{
try {
boolean needsGateManagerUpdate = false;
if (gate.getGateBlockLocations().isEmpty()) {
needsGateManagerUpdate = true;
}
gate.setOpen(true);
GateBlockChangeSender.updateGateBlocks(gate);
if (needsGateManagerUpdate) {
Plugin.getPlugin().getGatesManager().handleGateLocationChange(gate, null, null, null);
}
sendMessage(ChatColor.GREEN + "The gate was opened.");
}
catch (Exception e) {
sendMessage(ChatColor.RED + e.getMessage());
}
}
}

View File

@ -16,38 +16,33 @@
*/ */
package de.craftinc.gates.commands; package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin; public class CommandRemove extends BaseCommand {
public CommandRemove() {
aliases.add("delete");
aliases.add("del");
aliases.add("remove");
public class CommandRemove extends BaseCommand requiredParameters.add("id");
{
public CommandRemove() senderMustBePlayer = false;
{ helpDescription = "Removes the gate from the game.";
aliases.add("delete");
aliases.add("del"); requiredPermission = PermissionController.permissionManage;
aliases.add("remove");
needsPermissionAtCurrentLocation = false;
requiredParameters.add("id"); shouldPersistToDisk = true;
senderMustBePlayer = false; senderMustBePlayer = false;
helpDescription = "Removes the gate from the game."; }
requiredPermission = Plugin.permissionManage; public void perform() {
gatesManager.handleDeletion(gate);
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform()
{
Plugin.getPlugin().getGatesManager().handleDeletion(gate);
GateBlockChangeSender.updateGateBlocks(gate, true); GateBlockChangeSender.updateGateBlocks(gate, true);
sendMessage(ChatColor.GREEN + "Gate with id '" + gate.getId() + "' was deleted."); sendMessage(ChatColor.GREEN + "Gate with id '" + gate.getId() + "' was deleted.");
} }
} }

View File

@ -16,51 +16,37 @@
*/ */
package de.craftinc.gates.commands; package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import de.craftinc.gates.GatesManager; public class CommandRename extends BaseCommand {
import de.craftinc.gates.Plugin;
public CommandRename() {
aliases.add("rename");
aliases.add("rn");
public class CommandRename extends BaseCommand hasGateParam = true;
{ senderMustBePlayer = false;
public CommandRename() requiredParameters.add("current name");
{ requiredParameters.add("new name");
aliases.add("rename"); helpDescription = "Changes the id of a gate.";
aliases.add("rn"); requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
}
hasGateParam = true; public void perform() {
senderMustBePlayer = false; String newId = parameters.get(1);
requiredParameters.add("current name");
requiredParameters.add("new name");
helpDescription = "Changes the id of a gate.";
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform()
{
String newId = parameters.get(1);
GatesManager gatesManager = Plugin.getPlugin().getGatesManager();
if (gatesManager.gateExists(newId)) {
sendMessage(ChatColor.RED + "Cannot rename " + gate.getId() + ". There is already a gate named " + newId + ".");
}
else {
String oldId = gate.getId();
gate.setId(newId);
gatesManager.handleGateIdChange(gate, oldId);
sendMessage(ChatColor.GREEN + "Gate " + gate.getId() + " is now known as " + newId + ".");
}
}
if (gatesManager.gateExists(newId)) {
sendMessage(ChatColor.RED + "Cannot rename " + gate.getId() + ". There is already a gate named " + newId + ".");
} else {
String oldId = gate.getId();
gate.setId(newId);
gatesManager.handleGateIdChange(gate, oldId);
sendMessage(ChatColor.GREEN + "Gate " + gate.getId() + " is now known as " + newId + ".");
}
}
} }

View File

@ -0,0 +1,23 @@
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
public class CommandTeleport extends BaseCommand {
public CommandTeleport() {
aliases.add("teleport");
aliases.add("t");
requiredParameters.add("id");
senderMustBePlayer = true;
hasGateParam = true;
helpDescription = "Teleport to the location of a gate";
requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = false;
}
public void perform() {
}
}

View File

@ -0,0 +1,54 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
public class CommandTriggerOpen extends BaseCommand {
public CommandTriggerOpen() {
aliases.add("triggerOpen");
aliases.add("o");
requiredParameters.add("id");
helpDescription = "Open/close a gate.";
requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform() {
try {
if (!gate.isOpen() && gate.getExit() == null && player != null) {
gate.setExit(player.getLocation());
sendMessage(ChatColor.GREEN + "The exit of gate '" + gate.getId() + "' is now where you stand.");
}
gate.setOpen(!gate.isOpen());
GateBlockChangeSender.updateGateBlocks(gate);
gatesManager.handleGateLocationChange(gate, null, null, null);
sendMessage(ChatColor.GREEN + "The gate is now " + (gate.isOpen() ? "open." : "closed."));
} catch (Exception e) {
sendMessage(ChatColor.RED + e.getMessage());
}
}
}

View File

@ -0,0 +1,47 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor;
public class CommandTriggerVehicles extends BaseCommand {
public CommandTriggerVehicles() {
aliases.add("vehicles");
aliases.add("v");
requiredParameters.add("id");
helpDescription = "Allow/deny players to travel while riding.";
requiredPermission = PermissionController.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
@Override
protected void perform() {
gate.setAllowsVehicles(gate.getAllowsVehicles());
if (gate.getAllowsVehicles()) {
sendMessage(ChatColor.GREEN + "Traveling while riding is now enabled for this gate.");
} else {
sendMessage(ChatColor.GREEN + "Traveling while riding is now disabled for this gate.");
}
}
}

View File

@ -1,58 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import de.craftinc.gates.Plugin;
public class CommandUnhide extends BaseCommand
{
public CommandUnhide()
{
aliases.add("unhide");
aliases.add("u");
requiredParameters.add("id");
helpDescription = "Make that gate visible";
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform()
{
try
{
gate.setHidden(false);
GateBlockChangeSender.updateGateBlocks(gate);
sendMessage(ChatColor.GREEN + "The gate " + gate.getId() + " is now visible.");
}
catch (Exception e) {
sendMessage(ChatColor.RED + e.getMessage());
}
}
}

View File

@ -0,0 +1,477 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.controllers;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.persistence.MigrationUtil;
import de.craftinc.gates.util.ConfigurationUtil;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import de.craftinc.gates.models.SimpleChunk;
import de.craftinc.gates.models.SimpleLocation;
public class GatesManager {
protected List<Gate> gates;
private static final String gatesPath = "gates"; // path to gates inside the yaml file
private static final String storageVersionPath = "version";
private static final int storageVersion = 3;
private File gatesConfigFile;
private FileConfiguration gatesConfig;
private int chunkRadius;
private Map<String, Gate> gatesById;
private Map<SimpleChunk, Set<Gate>> gatesByChunk;
private Map<SimpleLocation, Gate> gatesByLocation;
private Map<SimpleLocation, Gate> gatesByFrameLocation;
private boolean storageFileIsInvalid = false;
public Gate getGateWithId(final String id) {
return gatesById.get(id.toLowerCase());
}
public Set<Gate> getNearbyGates(final Chunk chunk) {
SimpleChunk simpleChunk = new SimpleChunk(chunk);
return gatesByChunk.get(simpleChunk);
}
/**
* Returns the closest gate.
*
* @param location The location at which to look for a gate.
* @return Might return null if there are no nearby gates.
*/
public Gate getNearestGate(final Location location) {
Set<Gate> nearbyGates = getNearbyGates(location.getChunk());
if (nearbyGates == null) {
return null;
}
double minDist = Double.MAX_VALUE;
Gate nearestGate = null;
for (Gate g : nearbyGates) {
double dist = location.distance(g.getLocation());
if (dist < minDist) {
minDist = dist;
nearestGate = g;
}
}
return nearestGate;
}
Gate getGateAtLocation(final Location location) {
SimpleLocation simpleLocation = new SimpleLocation(location);
return gatesByLocation.get(simpleLocation);
}
public Gate getGateAtFrameLocation(final Location location) {
SimpleLocation simpleLocation = new SimpleLocation(location);
return gatesByFrameLocation.get(simpleLocation);
}
public void saveGatesToDisk() {
if (storageFileIsInvalid) {
Plugin.log(Level.SEVERE, "ERROR: Not saving gates to disk. Storage file is invalid or corrupted!");
return;
}
gatesConfig.set(gatesPath, gates);
gatesConfig.set(storageVersionPath, storageVersion);
try {
gatesConfig.save(gatesConfigFile);
Plugin.log("Saved gates to disk.");
} catch (IOException e) {
Plugin.log(Level.SEVERE, "ERROR: Could not save gates to disk.");
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public boolean loadGatesFromDisk() {
// TODO: refactor: move loading/saving logic into persistence package
this.gatesConfigFile = new File(Plugin.getPlugin().getDataFolder(), "gates.yml");
if (!this.gatesConfigFile.exists()) {
try {
boolean isNew = this.gatesConfigFile.createNewFile();
if (isNew) {
Plugin.log(Level.FINEST, "Created gate storage file.");
}
} catch (IOException e) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Cannot create gate storage file! No gates will be persisted.");
return false;
}
}
this.gatesConfig = new YamlConfiguration();
try {
this.gatesConfig.load(this.gatesConfigFile);
} catch (Exception e) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Gate file on disk is invalid. No gates loaded. Plugin will be disabled! (" + Arrays.toString(e.getStackTrace()) + ")");
return false;
}
this.gates = (List<Gate>) gatesConfig.getList(gatesPath);
if (this.gates == null) {
this.gates = new ArrayList<>();
}
for (Object o : this.gates) {
if (!(o instanceof Gate)) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Gate file on disk is invalid. No gates loaded. Plugin will be disabled! (Invalid gate class detected)");
return false;
}
}
for (Gate g : this.gates) {
try {
g.validate();
} catch (Exception e) {
try {
g.setOpen(false);
} catch (Exception ignored) {
}
Plugin.log(Level.FINER, "closed gate '" + g.getId() + "' reason: " + e.getMessage());
}
}
fillGatesById();
fillGatesByChunk();
fillGatesByLocation();
fillGatesByFrameLocation();
Plugin.log("Loaded " + this.gates.size() + " gates.");
// migration
int fileStorageVersion = gatesConfig.getInt(storageVersionPath);
if (fileStorageVersion > storageVersion) {
this.storageFileIsInvalid = true;
Plugin.log(Level.SEVERE, "Unsupported storage version detected! Make sure you have the latest version of Craft Inc. Gates installed. Plugin will be disabled!");
return false;
}
if (fileStorageVersion < storageVersion && !this.gates.isEmpty()) {
Plugin.log("Outdated storage version detected. Performing data migration...");
boolean success = MigrationUtil.performMigration(fileStorageVersion, storageVersion, this.gates);
this.storageFileIsInvalid = !success;
return success;
}
return true;
}
private int getChunkRadius() {
if (this.chunkRadius == 0) {
this.chunkRadius = Plugin.getPlugin().getConfig().getInt(ConfigurationUtil.confPlayerGateBlockUpdateRadiusKey);
this.chunkRadius = this.chunkRadius >> 4;
}
return this.chunkRadius;
}
private void fillGatesById() {
gatesById = new HashMap<>((int) (gates.size() * 1.25));
for (Gate g : gates) {
this.addGateWithId(g);
}
}
private void fillGatesByChunk() {
HashSet<SimpleChunk> chunksUsedByGates = new HashSet<>();
for (Gate g : gates) {
if (g.getLocation() != null) {
Chunk c = g.getLocation().getChunk();
int x = c.getX();
int z = c.getZ();
for (int i = x - getChunkRadius(); i < x + getChunkRadius(); i++) {
for (int j = z - getChunkRadius(); j < z + getChunkRadius(); j++) {
chunksUsedByGates.add(new SimpleChunk(i, j, c.getWorld()));
}
}
}
}
gatesByChunk = new HashMap<>((int) (chunksUsedByGates.size() * 1.25));
for (Gate g : gates) {
this.addGateByChunk(g);
}
}
private void fillGatesByLocation() {
Set<Location> gateBlocks = new HashSet<>();
for (Gate g : gates) {
for (Location l : g.getGateBlockLocations()) {
gateBlocks.add(l);
Location headLocation = l.clone().add(0, 1, 0);
gateBlocks.add(headLocation);
}
}
gatesByLocation = new HashMap<>((int) (gateBlocks.size() * 1.25));
for (Gate g : gates) {
this.addGateByLocations(g);
}
}
private void fillGatesByFrameLocation() {
int numFrameBlocks = 0;
for (Gate g : gates) {
numFrameBlocks += g.getGateFrameBlocks().size();
}
gatesByFrameLocation = new HashMap<>((int) (numFrameBlocks * 1.25));
for (Gate g : gates) {
this.addGateByFrameLocations(g);
}
}
private void removeGateById(final String id) {
gatesById.remove(id);
}
private void addGateWithId(final Gate g) {
gatesById.put(g.getId(), g);
}
private void removeGateByLocation(final Set<Location> gateBlocks) {
if (gateBlocks != null) {
for (Location l : gateBlocks) {
SimpleLocation sl = new SimpleLocation(l);
gatesByLocation.remove(sl);
SimpleLocation headLocation = new SimpleLocation(l, true);
gatesByLocation.remove(headLocation);
}
}
}
private void removeGateByFrameLocation(final Set<Block> gateFrameBlocks) {
if (gateFrameBlocks != null) {
for (Block block : gateFrameBlocks) {
SimpleLocation sl = new SimpleLocation(block.getLocation());
gatesByFrameLocation.remove(sl);
}
}
}
private void addGateByLocations(final Gate g) {
for (Location l : g.getGateBlockLocations()) {
SimpleLocation sl = new SimpleLocation(l);
gatesByLocation.put(sl, g);
SimpleLocation headLocation = new SimpleLocation(l, true);
gatesByLocation.put(headLocation, g);
}
}
private void addGateByFrameLocations(final Gate g) {
for (Block block : g.getGateFrameBlocks()) {
SimpleLocation sl = new SimpleLocation(block.getLocation());
gatesByFrameLocation.put(sl, g);
}
}
private void removeGateFromChunk(final Gate g, final Location l) {
if (l != null) {
Chunk c = l.getChunk();
int x = c.getX();
int z = c.getZ();
for (int i = x - getChunkRadius(); i < x + getChunkRadius(); i++) {
for (int j = z - getChunkRadius(); j < z + getChunkRadius(); j++) {
SimpleChunk sc = new SimpleChunk(i, j, c.getWorld());
Set<Gate> gatesInChunk = gatesByChunk.get(sc);
if (gatesInChunk != null) {
gatesInChunk.remove(g);
}
}
}
}
}
private void addGateByChunk(final Gate g) {
Location gateLocation = g.getLocation();
if (gateLocation != null) {
Chunk c = g.getLocation().getChunk();
int x = c.getX();
int z = c.getZ();
for (int i = x - getChunkRadius(); i < x + getChunkRadius(); i++) {
for (int j = z - getChunkRadius(); j < z + getChunkRadius(); j++) {
SimpleChunk sc = new SimpleChunk(i, j, c.getWorld());
Set<Gate> gatesForC = gatesByChunk.get(sc);
if (gatesForC == null) {
gatesForC = new HashSet<>(); // NOTE: not optimizing size here
gatesByChunk.put(sc, gatesForC);
}
gatesForC.add(g);
}
}
}
}
public void storeInvalidGate(Map<String, Object> map) {
File invalidGatesFile = new File(Plugin.getPlugin().getDataFolder(), "invalid_gates.yml");
Boolean invalidGatesFileExists = invalidGatesFile.exists();
try {
FileWriter fileWriter = new FileWriter(invalidGatesFile, true);
if (!invalidGatesFileExists) {
fileWriter.write("gates:\n");
}
fileWriter.write("- ==: ");
fileWriter.write(map.get("==").toString() + "\n");
map.remove("==");
fileWriter.write("\topen: false\n");
map.remove("open");
fileWriter.write("\tgateBlocks: []\n");
map.remove("gateBlocks");
for (String key : map.keySet()) {
Object value = map.get(key);
fileWriter.write("\t" + key + ": ");
if (value instanceof Map) {
fileWriter.write("\n");
@SuppressWarnings("unchecked")
Map<String, Object> valueMap = (Map<String, Object>) value;
for (String k : valueMap.keySet()) {
Object v = valueMap.get(k);
fileWriter.write("\t\t" + k + ": " + v.toString() + "\n");
}
} else {
fileWriter.write(value.toString() + "\n");
}
}
fileWriter.close();
} catch (IOException e) {
Plugin.log("ERROR: Could not save invalid gates to disk. Reason: \n" + Arrays.toString(e.getStackTrace()));
}
}
public void handleGateIdChange(final Gate g, final String oldId) {
this.removeGateById(oldId);
this.addGateWithId(g);
}
public void handleGateLocationChange(final Gate g,
final Location oldLocation,
final Set<Location> oldGateBlockLocations,
final Set<Block> oldGateFrameBlocks) {
this.removeGateFromChunk(g, oldLocation);
this.addGateByChunk(g);
this.removeGateByLocation(oldGateBlockLocations);
this.addGateByLocations(g);
this.removeGateByFrameLocation(oldGateFrameBlocks);
this.addGateByFrameLocations(g);
}
public void handleGateExitChange(final Gate g, final Location oldExit) {
// nothing to do
}
public void handleNewGate(final Gate g) {
this.gates.add(g);
this.addGateByChunk(g);
this.addGateByLocations(g);
this.addGateWithId(g);
this.addGateByFrameLocations(g);
}
public void handleDeletion(final Gate g) {
this.gates.remove(g);
this.removeGateById(g.getId());
this.removeGateFromChunk(g, g.getLocation());
this.removeGateByLocation(g.getGateBlockLocations());
this.removeGateByFrameLocation(g.getGateFrameBlocks());
}
public boolean gateExists(final String id) {
return gatesById.containsKey(id.toLowerCase());
}
public List<Gate> allGates() {
return gates;
}
}

View File

@ -0,0 +1,58 @@
package de.craftinc.gates.controllers;
import de.craftinc.gates.models.Gate;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
public class PermissionController {
public static final String permissionInfo = "craftincgates.info";
public static final String permissionManage = "craftincgates.manage";
public static final String permissionUse = "craftincgates.use";
private Permission permission;
public void setPermission(Permission permission) {
this.permission = permission;
}
public boolean hasPermission(CommandSender sender, Gate gate, String permission) {
assert(sender != null);
assert(permission != null);
if (gate == null) {
return hasPermission(sender, permission);
}
final Location location = gate.getLocation();
final Location exit = gate.getExit();
boolean permAtLocation = location == null || hasPermission(sender, location.getWorld(), permission);
boolean permAtExit = exit == null || hasPermission(sender, exit.getWorld(), permission);
return permAtLocation && permAtExit;
}
public boolean hasPermission(CommandSender sender, String permission) {
return hasPermission(sender, (World)null, permission);
}
private boolean hasPermission(CommandSender sender, World world, String permission) {
assert(sender != null);
assert(permission != null);
if (this.permission == null) {
// fallback - use the standard bukkit permission system
return sender.hasPermission(permission);
}
if (!(sender instanceof OfflinePlayer)) {
return this.permission.has(sender, permission);
}
String worldName = world != null ? world.getName() : null;
return this.permission.playerHas(worldName, (OfflinePlayer)sender, permission);
}
}

View File

@ -0,0 +1,126 @@
package de.craftinc.gates.controllers;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.util.ConfigurationUtil;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Calendar;
import java.util.HashMap;
public class TeleportController {
private TeleportMessageUtil messageUtil;
private GatesManager gatesManager;
private PermissionController permissionController;
public TeleportController(Plugin plugin) {
this.gatesManager = plugin.getGatesManager();
this.messageUtil = new TeleportMessageUtil(plugin.getConfig());
this.permissionController = plugin.getPermissionController();
}
/**
* Try teleporting a player at given location.
*/
public void teleport(final Player player, Location toLocation) {
final Gate gateAtLocation = gatesManager.getGateAtLocation(toLocation);
if ((gateAtLocation == null) || !gateAtLocation.isOpen()) {
return;
}
if (!permissionController.hasPermission(player, gateAtLocation, PermissionController.permissionUse)) {
messageUtil.sendNoPermissionMessage(player);
return;
}
this.teleportPlayer(player, gateAtLocation);
}
private void teleportPlayer(final Player player, final Gate gate) {
final Entity vehicle = player.getVehicle();
if (vehicle != null && !gate.getAllowsVehicles()) {
messageUtil.sendVehicleForbiddenMessage(player);
Plugin.log("no vehicle transport");
return;
}
final Location destination = calculateDestination(player, gate);
player.teleport(destination);
if (vehicle != null) {
vehicle.teleport(destination, PlayerTeleportEvent.TeleportCause.PLUGIN);
vehicle.setPassenger(player);
}
messageUtil.sendTeleportMessage(player);
}
private Location calculateDestination(Player player, Gate gate) {
final Location exit = gate.getExit();
final Location pLocation = player.getLocation();
final Float newYaw = exit.getYaw() - gate.getLocation().getYaw() + pLocation.getYaw();
return new Location(exit.getWorld(),
exit.getX(),
exit.getY(),
exit.getZ(),
newYaw,
pLocation.getPitch()
);
}
}
class TeleportMessageUtil {
private HashMap<String, Long> lastNoPermissionMessages = new HashMap<>();
private FileConfiguration config;
TeleportMessageUtil(FileConfiguration config) {
this.config = config;
}
void sendVehicleForbiddenMessage(Player player) {
if (!config.getBoolean(ConfigurationUtil.confShowTeleportNoPermissionMessageKey)) {
return;
}
final String notAllowedMessage = config.getString(ConfigurationUtil.confGateTeleportVehicleNotAllowedMessageKey);
player.sendMessage(ChatColor.DARK_AQUA + notAllowedMessage);
}
void sendNoPermissionMessage(Player player) {
if (!config.getBoolean(ConfigurationUtil.confShowTeleportNoPermissionMessageKey)) {
return;
}
final String playerName = player.getPlayer().getName();
if (playerName == null) {
return;
}
final Long now = Calendar.getInstance().getTimeInMillis();
// do not display messages more often than once per second
if (!this.lastNoPermissionMessages.containsKey(playerName)
|| this.lastNoPermissionMessages.get(playerName) < now - 10000L) {
final String noPermissionString = config.getString(ConfigurationUtil.confGateTeleportNoPermissionMessageKey);
player.sendMessage(ChatColor.RED + noPermissionString);
this.lastNoPermissionMessages.put(playerName, now);
}
}
void sendTeleportMessage(Player player) {
if (!config.getBoolean(ConfigurationUtil.confShowTeleportMessageKey)) {
return;
}
final String teleportMessage = config.getString(ConfigurationUtil.confGateTeleportMessageKey);
player.sendMessage(ChatColor.DARK_AQUA + teleportMessage);
}
}

View File

@ -16,31 +16,29 @@
*/ */
package de.craftinc.gates.listeners; package de.craftinc.gates.listeners;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.Gate;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
public class BlockBreakListener implements Listener public class BlockBreakListener implements Listener {
{
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(BlockBreakEvent event) public void onBlockBreak(BlockBreakEvent event) {
{
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
} }
Gate gate = Plugin.getPlugin().getGatesManager().getGateAtFrameLocation(event.getBlock().getLocation()); Gate gate = Plugin.getPlugin().getGatesManager().getGateAtFrameLocation(event.getBlock().getLocation());
if (gate != null && !gate.isHidden()) { if (gate != null && gate.getMaterial().getMaterial() != Material.AIR) {
try { try {
gate.setOpen(false); gate.setOpen(false);
} } catch (Exception ignored) {}
catch (Exception ignored) { }
GateBlockChangeSender.updateGateBlocks(gate); GateBlockChangeSender.updateGateBlocks(gate);
} }

View File

@ -16,19 +16,18 @@
*/ */
package de.craftinc.gates.listeners; package de.craftinc.gates.listeners;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerChangedWorldEvent;
public class PlayerChangedWorldListener implements Listener {
public class PlayerChangedWorldListener implements Listener
{
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void onPlayerChangeWorld(PlayerChangedWorldEvent event) public void onPlayerChangeWorld(PlayerChangedWorldEvent event) {
{ Player p = event.getPlayer();
GateBlockChangeSender.updateGateBlocks(event.getPlayer()); GateBlockChangeSender.updateGateBlocks(p, p.getLocation());
} }
} }

View File

@ -16,18 +16,18 @@
*/ */
package de.craftinc.gates.listeners; package de.craftinc.gates.listeners;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
public class PlayerJoinListener implements Listener public class PlayerJoinListener implements Listener {
{
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void onPlayerJoin(PlayerJoinEvent event) public void onPlayerJoin(PlayerJoinEvent event) {
{ Player p = event.getPlayer();
GateBlockChangeSender.updateGateBlocks(event.getPlayer()); GateBlockChangeSender.updateGateBlocks(p, p.getLocation());
} }
} }

View File

@ -16,121 +16,31 @@
*/ */
package de.craftinc.gates.listeners; package de.craftinc.gates.listeners;
import java.util.Calendar; import de.craftinc.gates.Plugin;
import java.util.HashMap; import de.craftinc.gates.controllers.TeleportController;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import de.craftinc.gates.Gate; public class PlayerMoveListener implements Listener {
import de.craftinc.gates.GatesManager; private TeleportController teleportController;
import de.craftinc.gates.Plugin;
public PlayerMoveListener(Plugin plugin) {
this.teleportController = new TeleportController(plugin);
}
public class PlayerMoveListener implements Listener @EventHandler(priority = EventPriority.NORMAL)
{ public void onPlayerMove(PlayerMoveEvent event) {
protected HashMap<String, Long> lastNoPermissionMessages = new HashMap<String, Long>(); if (event.isCancelled()) {
return;
@EventHandler(priority = EventPriority.NORMAL) }
public void onPlayerMove(PlayerMoveEvent event)
{
if (event.isCancelled()) {
return;
}
if (event.getFrom().getChunk() != event.getTo().getChunk()) { if (event.getFrom().getChunk() != event.getTo().getChunk()) {
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getTo()); GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getTo());
} }
GatesManager gateManager = Plugin.getPlugin().getGatesManager(); teleportController.teleport(event.getPlayer(), event.getTo());
Gate gateAtLocation = gateManager.getGateAtLocation(event.getTo());
if (gateAtLocation == null) {
// Location headTo = new Location(event.getTo().getWorld(),
// event.getTo().getX(),
// event.getTo().getY()+1.0,
// event.getTo().getZ());
//
// gateAtLocation = gateManager.getGateAtLocation(headTo);
// if (gateAtLocation == null) {
return;
// }
}
if (!gateAtLocation.isOpen()) {
return;
}
// Check for permission
if (!hasPermission(event.getPlayer(), gateAtLocation)
&& Plugin.getPlugin().getConfig().getBoolean(Plugin.confShowTeleportNoPermissionMessageKey)) {
String playerName = event.getPlayer().getName();
if (playerName == null) {
return;
}
// get the current time
Long now = Calendar.getInstance().getTimeInMillis();
// do not display messages more often than once per second
if (!this.lastNoPermissionMessages.containsKey(playerName) || this.lastNoPermissionMessages.get(playerName) < now - 10000L) {
String noPermissionString = Plugin.getPlugin().getConfig().getString(Plugin.confGateTeleportNoPermissionMessageKey);
event.getPlayer().sendMessage(ChatColor.RED + noPermissionString);
this.lastNoPermissionMessages.put(playerName, now);
}
}
else {
this.teleportPlayer(event.getPlayer(), gateAtLocation);
}
}
/**
* Teleports a player.
* @param p The player to teleport.
* @param g The gate to which exit the player will be teleported.
*/
private void teleportPlayer(Player p, Gate g)
{
Float newYaw = g.getExit().getYaw() - g.getLocation().getYaw() + p.getLocation().getYaw();
Location destLocation = new Location( g.getExit().getWorld(),
g.getExit().getX(),
g.getExit().getY(),
g.getExit().getZ(),
newYaw,
p.getLocation().getPitch()
);
p.teleport(destLocation);
if (Plugin.getPlugin().getConfig().getBoolean(Plugin.confShowTeleportMessageKey)) {
String teleporMessage = Plugin.getPlugin().getConfig().getString(Plugin.confGateTeleportMessageKey);
p.sendMessage(ChatColor.DARK_AQUA + teleporMessage);
}
}
protected boolean hasPermission(Player player, Gate gate)
{
if (Plugin.getPermission() == null) { // fallback: use the standard bukkit permission system
return player.hasPermission(Plugin.permissionUse);
}
else {
boolean permAtLocation = Plugin.getPermission().has(gate.getLocation().getWorld(), player.getName(), Plugin.permissionUse);
boolean permAtExit = Plugin.getPermission().has(gate.getExit().getWorld(), player.getName(), Plugin.permissionUse);
return permAtLocation && permAtExit;
}
} }
} }

View File

@ -16,19 +16,15 @@
*/ */
package de.craftinc.gates.listeners; package de.craftinc.gates.listeners;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerRespawnEvent;
public class PlayerRespawnListener implements Listener {
public class PlayerRespawnListener implements Listener
{
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void onPlayerRespawn(PlayerRespawnEvent event) public void onPlayerRespawn(PlayerRespawnEvent event) {
{
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getRespawnLocation(), true); GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getRespawnLocation(), true);
} }
} }

View File

@ -16,18 +16,16 @@
*/ */
package de.craftinc.gates.listeners; package de.craftinc.gates.listeners;
import de.craftinc.gates.util.GateBlockChangeSender; import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
public class PlayerTeleportListener implements Listener public class PlayerTeleportListener implements Listener {
{
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerTeleport(PlayerTeleportEvent event) public void onPlayerTeleport(PlayerTeleportEvent event) {
{
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
} }

View File

@ -0,0 +1,27 @@
package de.craftinc.gates.listeners;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.controllers.TeleportController;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.vehicle.VehicleMoveEvent;
public class VehicleMoveListener implements Listener {
private TeleportController teleportController;
public VehicleMoveListener(Plugin plugin) {
this.teleportController = new TeleportController(plugin);
}
@EventHandler(priority = EventPriority.NORMAL)
public void onVehicleMove(VehicleMoveEvent event) {
Entity passenger = event.getVehicle().getPassenger();
if (passenger instanceof Player) {
teleportController.teleport((Player)passenger, event.getTo());
}
}
}

View File

@ -0,0 +1,298 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.models;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.ConfigurationUtil;
import de.craftinc.gates.util.FloodUtil;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import java.util.*;
public class Gate implements ConfigurationSerializable {
private Location location; /* saving both location and gateBlockLocations is redundant but makes it easy to allow players to reshape gates */
private Set<Location> gateBlockLocations = new HashSet<>(); /* Locations of the blocks inside the gate */
private Set<Block> gateFrameBlocks = new HashSet<>();
private Location exit;
private boolean isOpen = false;
private boolean allowsVehicles = true;
private String id;
private GateMaterial material = new GateMaterial(Material.PORTAL);
/**
* You should never create two gates with the same 'id'. Also see 'setId(String id)'.
*
* @param id This parameter must not be 'null'. An exception will be thrown otherwise!
*/
public Gate(final String id) {
setId(id);
}
public String toString() {
return super.toString() + " " + this.getId();
}
public GateDirection getDirection() {
if (gateBlockLocations.isEmpty()) {
return null;
} else {
Block some = ((Location)gateBlockLocations.toArray()[0]).getBlock();
boolean east = gateBlockLocations.contains(some.getRelative(BlockFace.EAST).getLocation());
boolean west = gateBlockLocations.contains(some.getRelative(BlockFace.WEST).getLocation());
return east || west ? GateDirection.EastWest : GateDirection.NorthSouth;
}
}
public GateMaterial getMaterial() {
return material;
}
public void setMaterial(GateMaterial material) throws Exception {
this.material = material;
validate();
}
/**
* @return This method might return a 'null' data.
*/
public Location getLocation() {
return location;
}
/**
* @param location Supplying 'null' is permitted.
* @throws Exception Will throw an exception if the gate is open and an invalid (no gate frame) location is
* supplied. Note that the supplied 'location' will be set even if an exception is thrown. Note that this
* gate will be closed if an exception is thrown.
*/
public void setLocation(final Location location) throws Exception {
this.location = location;
if (isOpen) {
findPortalBlocks();
validate();
} else {
this.gateBlockLocations = new HashSet<>();
this.gateFrameBlocks = new HashSet<>();
}
}
/**
* @return This method might return a 'null' value.
*/
public Location getExit() {
return exit;
}
/**
* @param exit Supplying 'null' is permitted.
* @throws Exception An exception will be thrown if 'null' data is supplied and this gate is open. Note that the
* supplied 'exit' will be set even if an exception is thrown. Note that this gate will be closed if an
* exception is thrown.
*/
public void setExit(final Location exit) throws Exception {
this.exit = exit;
validate();
}
/**
* @return This method will never return 'null'.
*/
public String getId() {
return id;
}
/**
* Every gate should have an unique 'id'. You should therefore check if another gate with the same 'id' exists.
* Note that this method will not check if another gate with the same 'id' exists!
*
* @param id This parameter must not be 'null'. An exception will be thrown otherwise!
*/
public void setId(final String id) {
if (id == null) {
throw new IllegalArgumentException("gate 'id' cannot be 'null'");
}
this.id = id.toLowerCase();
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) throws Exception {
if (isOpen && !this.isOpen) {
findPortalBlocks();
}
this.isOpen = isOpen;
validate();
}
public void setAllowsVehicles(boolean allowsVehicles) {
this.allowsVehicles = allowsVehicles;
}
public boolean getAllowsVehicles() {
return this.allowsVehicles;
}
/**
* @return Will never return 'null' but might return an empty Set.
*/
public Set<Location> getGateBlockLocations() {
return gateBlockLocations;
}
/**
* @return Will never return 'null' but might return an empty Set.
*/
public Set<Block> getGateFrameBlocks() {
return gateFrameBlocks;
}
private void findPortalBlocks() {
gateBlockLocations = new HashSet<>();
Set<Block> gateBlocks = FloodUtil.getGatePortalBlocks(location.getBlock());
if (gateBlocks != null) {
for (Block b : gateBlocks) {
gateBlockLocations.add(b.getLocation());
}
}
gateFrameBlocks = FloodUtil.getFrame(gateBlocks);
}
/**
* Checks if values attributes do add up; will close gate on wrong values.
*/
public void validate() throws Exception {
if (!isOpen) {
return;
}
if (location == null) {
isOpen = false;
this.gateBlockLocations = new HashSet<>();
this.gateFrameBlocks = new HashSet<>();
throw new Exception("Gate got closed. It has no location.");
}
if (exit == null) {
isOpen = false;
this.gateBlockLocations = new HashSet<>();
this.gateFrameBlocks = new HashSet<>();
throw new Exception("Gate got closed. It has no exit.");
}
if (gateBlockLocations.size() == 0) {
isOpen = false;
this.gateBlockLocations = new HashSet<>();
this.gateFrameBlocks = new HashSet<>();
throw new Exception("Gate got closed. The frame is missing or broken. (no gate blocks)");
}
validateFrame();
}
private void validateFrame() throws Exception {
boolean isAir = material.getMaterial() == Material.AIR;
boolean ignore = !Plugin.getPlugin().getConfig().getBoolean(ConfigurationUtil.confCheckForBrokenGateFramesKey);
if (isAir || ignore) {
return;
}
for (Block b : gateFrameBlocks) {
if (b.getType() == Material.AIR) {
isOpen = false;
this.gateBlockLocations = new HashSet<>();
this.gateFrameBlocks = new HashSet<>();
throw new Exception("Gate got closed. The frame is missing or broken. (missing frame block(s))");
}
}
}
/*
* INTERFACE: ConfigurationSerializable
*/
static private String idKey = "id";
static private String locationKey = "location";
static private String gateBlocksKey = "gateBlocks";
static private String exitKey = "exit";
static private String materialKey = "material";
static private String isOpenKey = "open";
static private String allowsVehiclesKey = "allowsVehiclesKey";
@SuppressWarnings("unchecked")
public Gate(Map<String, Object> map) {
try {
id = map.get(idKey).toString().toLowerCase();
location = (Location) map.get(locationKey);
exit = (Location) map.get(exitKey);
material = new GateMaterial((String)map.get(materialKey));
isOpen = (Boolean) map.get(isOpenKey);
allowsVehicles = (Boolean) map.get(allowsVehiclesKey);
gateBlockLocations = (Set<Location>) map.get(gateBlocksKey);
gateFrameBlocks = FloodUtil.getFrameWithLocations(gateBlockLocations);
} catch (Exception e) {
Plugin.log("ERROR: Failed to load gate '" + id + "'! (" + e.getMessage() + ")");
Plugin.log("NOTE: This gate will be removed from 'gates.yml' and added to 'invalid_gates.yml'!");
Plugin.getPlugin().getGatesManager().storeInvalidGate(map);
}
try {
validate(); // make sure to not write invalid stuff to disk
} catch (Exception e) {
Plugin.log("The loaded gate " + this.getId() + " seems to be not valid: " + e.getMessage());
}
}
public Map<String, Object> serialize() {
Map<String, Object> retVal = new HashMap<>();
retVal.put(idKey, id);
retVal.put(isOpenKey, isOpen);
retVal.put(allowsVehiclesKey, allowsVehicles);
retVal.put(gateBlocksKey, gateBlockLocations);
retVal.put(materialKey, material.toString());
if (exit != null) {
retVal.put(exitKey, exit);
}
if (location != null) {
retVal.put(locationKey, location);
}
return retVal;
}
}

View File

@ -0,0 +1,6 @@
package de.craftinc.gates.models;
public enum GateDirection {
EastWest,
NorthSouth
}

View File

@ -0,0 +1,162 @@
package de.craftinc.gates.models;
import org.bukkit.Material;
import java.security.InvalidParameterException;
public class GateMaterial {
private Material material;
GateMaterial(Material material) {
this.material = material;
}
public GateMaterial(String materialString) throws InvalidParameterException {
Material material;
switch (materialString) {
case "air":
material = Material.AIR;
break;
case "sapling":
material = Material.SAPLING;
break;
case "water":
material = Material.STATIONARY_WATER;
break;
case "lava":
material = Material.STATIONARY_LAVA;
break;
case "cobweb":
material = Material.WEB;
break;
case "grass":
material = Material.LONG_GRASS;
break;
case "dead bush":
material = Material.DEAD_BUSH;
break;
case "dandelion":
material = Material.YELLOW_FLOWER;
break;
case "poppy":
material = Material.RED_ROSE;
break;
case "brown mushroom":
material = Material.BROWN_MUSHROOM;
break;
case "red mushroom":
material = Material.RED_MUSHROOM;
break;
case "torch":
material = Material.TORCH;
break;
case "redstone torch (off)":
material = Material.REDSTONE_TORCH_OFF;
break;
case "redstone torch (on)":
material = Material.REDSTONE_TORCH_ON;
break;
case "fence":
material = Material.FENCE;
break;
case "nether portal":
material = Material.PORTAL;
break;
case "iron bars":
material = Material.IRON_FENCE;
break;
case "glass pane":
material = Material.THIN_GLASS;
break;
case "fence gate":
material = Material.FENCE_GATE;
break;
case "nether brick fence":
material = Material.NETHER_FENCE;
break;
case "nether wart":
material = Material.NETHER_WARTS;
break;
case "end portal":
material = Material.ENDER_PORTAL;
break;
case "cobblestone wall":
material = Material.COBBLE_WALL;
break;
default:
throw new InvalidParameterException();
}
this.material = material;
}
@Override
public String toString() {
switch (material) {
case AIR:
return "air";
case SAPLING:
return "sapling";
case STATIONARY_WATER:
return "water";
case STATIONARY_LAVA:
return "lava";
case WEB:
return "cobweb";
case LONG_GRASS:
return "grass";
case DEAD_BUSH:
return "dead bush";
case YELLOW_FLOWER:
return "dandelion";
case RED_ROSE:
return "poppy";
case BROWN_MUSHROOM:
return "brown mushroom";
case RED_MUSHROOM:
return "red mushroom";
case TORCH:
return "torch";
case REDSTONE_TORCH_OFF:
return "redstone torch (off)";
case REDSTONE_TORCH_ON:
return "redstone torch (on)";
case FENCE:
return "fence";
case PORTAL:
return "nether portal";
case IRON_FENCE:
return "iron bars";
case THIN_GLASS:
return "glass pane";
case FENCE_GATE:
return "fence gate";
case NETHER_FENCE:
return "nether brick fence";
case NETHER_WARTS:
return "nether wart";
case ENDER_PORTAL:
return "end portal";
case COBBLE_WALL:
return "cobblestone wall";
default:
return "nether portal";
}
}
public Material getMaterial() {
return material;
}
public byte getData(GateDirection direction) {
switch (material) {
case PORTAL:
return direction == GateDirection.EastWest ? (byte)0b0 : (byte)0b10;
case GRASS:
return 1;
default:
return 0;
}
}
}

View File

@ -14,66 +14,60 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>. along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.craftinc.gates.util; package de.craftinc.gates.models;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
public class SimpleChunk public class SimpleChunk {
{ private int x;
private int x; private int z;
private int z; private String world;
private String world;
public SimpleChunk(Chunk c) {
public SimpleChunk(Chunk c) this.x = c.getX();
{ this.z = c.getZ();
this.x = c.getX(); this.world = c.getWorld().getName();
this.z = c.getZ(); }
this.world = c.getWorld().getName();
}
public SimpleChunk(int x, int z, World w) public SimpleChunk(int x, int z, World w) {
{
this.x = x; this.x = x;
this.z = z; this.z = z;
this.world = w.getName(); this.world = w.getName();
} }
@Override
public boolean equals(Object o)
{
if (o instanceof SimpleChunk) {
SimpleChunk otherLocation = (SimpleChunk)o;
if (otherLocation.x == this.x
&& otherLocation.z == this.z
&& otherLocation.world.equals(this.world)) {
return true;
}
}
return false;
}
@Override @Override
public int hashCode() public boolean equals(Object o) {
{ if (o instanceof SimpleChunk) {
int hash = 11; SimpleChunk otherLocation = (SimpleChunk) o;
hash = 29 * hash + x;
hash = 37 * hash + z; if (otherLocation.x == this.x
hash = 29 * hash + world.hashCode(); && otherLocation.z == this.z
&& otherLocation.world.equals(this.world)) {
return hash;
return true;
}
}
return false;
} }
@Override @Override
public String toString() public int hashCode() {
{ int hash = 11;
hash = 29 * hash + x;
hash = 37 * hash + z;
hash = 29 * hash + world.hashCode();
return hash;
}
@Override
public String toString() {
return this.getClass().toString() + " (x=" + this.x + " z=" + this.z + " world='" + this.world + "')"; return this.getClass().toString() + " (x=" + this.x + " z=" + this.z + " world='" + this.world + "')";
} }
} }

View File

@ -14,32 +14,27 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>. along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.craftinc.gates.util; package de.craftinc.gates.models;
import org.bukkit.Location; import org.bukkit.Location;
public class SimpleLocation public class SimpleLocation {
{ private String world;
private String world;
private int x; private int x;
private int y; private int y;
private int z; private int z;
public SimpleLocation(Location l) {
public SimpleLocation(Location l) this.world = l.getWorld().getName();
{
this.world = l.getWorld().getName();
// Using Block coordinates makes it possible to compare block locations with player locations. // Using Block coordinates makes it possible to compare block locations with player locations.
// There might be an offset of 1 otherwise. // There might be an offset of 1 otherwise.
this.x = l.getBlockX(); this.x = l.getBlockX();
this.y = l.getBlockY(); this.y = l.getBlockY();
this.z = l.getBlockZ(); this.z = l.getBlockZ();
} }
public SimpleLocation(Location l, boolean isHeadPosition) {
public SimpleLocation(Location l, boolean isHeadPosition)
{
this.world = l.getWorld().getName(); this.world = l.getWorld().getName();
// Using Block coordinates makes it possible to compare block locations with player locations. // Using Block coordinates makes it possible to compare block locations with player locations.
@ -53,43 +48,36 @@ public class SimpleLocation
} }
} }
@Override @Override
public String toString() public String toString() {
{
return super.toString() + " x: " + x + " y: " + y + " z: " + z + " world: " + world; return super.toString() + " x: " + x + " y: " + y + " z: " + z + " world: " + world;
} }
@Override @Override
public boolean equals(final Object o) public boolean equals(final Object o) {
{ if (o instanceof SimpleLocation) {
if (o instanceof SimpleLocation) { SimpleLocation otherLocation = (SimpleLocation) o;
SimpleLocation otherLocation = (SimpleLocation)o;
if (otherLocation.x == this.x
if (otherLocation.x == this.x && otherLocation.y == this.y
&& otherLocation.y == this.y && otherLocation.z == this.z
&& otherLocation.z == this.z && otherLocation.world.equals(this.world)) {
&& otherLocation.world.equals(this.world)) {
return true;
return true; }
} }
}
return false;
return false;
} }
@Override @Override
public int hashCode() public int hashCode() {
{ int hash = 13;
int hash = 13; hash = 37 * hash + x;
hash = 37 * hash + x; hash = 31 * hash + y;
hash = 31 * hash + y; hash = 37 * hash + z;
hash = 37 * hash + z; hash = 31 * hash + world.hashCode();
hash = 31 * hash + world.hashCode();
return hash;
return hash;
} }
} }

View File

@ -1,100 +0,0 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.persistence;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Location;
import org.bukkit.World;
import de.craftinc.gates.Plugin;
public class LocationUtil
{
protected final static String worldKey = "world";
protected final static String xKey = "x";
protected final static String yKey = "y";
protected final static String zKey = "z";
protected static World getWorld(final String name) throws Exception
{
if (name == null) {
throw new IllegalArgumentException("The name of the world must not be 'null");
}
World world = Plugin.getPlugin().getServer().getWorld(name);
if (world == null) {
throw new Exception("World '" + name + "' does not exists anymore! Cannot get instance!");
}
return world;
}
/**
* Serializes a location. Helps storing locations inside yaml files. NOTE: We do not care about yaw
* and pitch for gate locations. So we won't serialize them.
*
* @param l The location to serialize. Supplying 'null' is ok..
* @return A Map object ready for storing inside a yaml file. Will return 'null' if 'l' is null.
*/
public static Map<String, Object> serializeLocation(final Location l)
{
if (l == null) {
return null;
}
Map<String, Object> serializedLocation = new HashMap<String, Object>();
serializedLocation.put(worldKey, l.getWorld().getName());
serializedLocation.put(xKey, l.getX());
serializedLocation.put(yKey, l.getY());
serializedLocation.put(zKey, l.getZ());
return serializedLocation;
}
/**
*
* @param map A map generated with the 'serializeLocation' method. Supplying 'null' is ok.
* @return A deserialized location. This method will return 'null' if 'map' is null!
* @throws Exception This method will throw an exception if the world of the supplied serialized location
* does not exist or if 'map' does not contain all necessary keys!
*/
public static Location deserializeLocation(final Map<String, Object> map) throws Exception
{
if (map == null) {
return null;
}
World w = getWorld((String)map.get(worldKey));
Number x = (Number)map.get(xKey);
Number y = (Number)map.get(yKey);
Number z = (Number)map.get(zKey);
if (x == null || y == null || z == null) {
throw new IllegalArgumentException("Supplied map is invalid x, y or z coordinate was not supplied");
}
return new Location(w, x.doubleValue(), y.doubleValue(), z.doubleValue());
}
}

View File

@ -16,7 +16,7 @@
*/ */
package de.craftinc.gates.persistence; package de.craftinc.gates.persistence;
import de.craftinc.gates.Gate; import de.craftinc.gates.models.Gate;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
import org.bukkit.Location; import org.bukkit.Location;
@ -27,28 +27,14 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
public class MigrationUtil public class MigrationUtil {
{
public static boolean performMigration(int storageVersion, int currentVersion, List<Gate> gates)
{
if (currentVersion == 1 && storageVersion == 0) {
for (Gate g : gates) { public static boolean performMigration(int storageVersion, int currentVersion, List<Gate> gates) {
if (storageVersion != currentVersion) {
for (Location l : g.getGateBlockLocations()) { Plugin.log(Level.SEVERE, "Supplied storage version is currently not supported!" +
Block b = l.getBlock(); "Make sure you have the latest version of Craft Inc. Gates installed. Plugin will be disabled!");
if (b.getType() == Material.PORTAL) {
b.setType(Material.AIR);
}
}
}
return true;
}
else {
Plugin.log(Level.SEVERE, "Supplied storage version is currently not supported! Make sure you have the latest version of Craft Inc. Gates installed. Plugin will be disabled!");
return false; return false;
} }
return true;
} }
} }

View File

@ -0,0 +1,30 @@
/* Craft Inc. Gates
Copyright (C) 2011-2013 Craft Inc. Gates Team (see AUTHORS.txt)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program (LGPLv3). If not, see <http://www.gnu.org/licenses/>.
*/
package de.craftinc.gates.util;
public class ConfigurationUtil {
public static final String confMaxGateBlocksKey = "maxGateBlocks";
public static final String confPlayerGateBlockUpdateRadiusKey = "playerGateBlockUpdateRadius";
public static final String confCheckForBrokenGateFramesKey = "checkForBrokenGateFrames";
public static final String confGateTeleportMessageKey = "gateTeleportMessage";
public static final String confGateTeleportVehicleNotAllowedMessageKey = "gateTeleportVehicleNotAllowedMessage";
public static final String confShowTeleportMessageKey = "showTeleportMessage";
public static final String confGateTeleportNoPermissionMessageKey = "gateTeleportNoPermissionMessage";
public static final String confShowTeleportNoPermissionMessageKey = "showTeleportNoPermissionMessage";
public static final String confSaveOnChangesKey = "saveOnChanges";
public static final String confHighlightDurationKey = "highlightDuration";
}

View File

@ -28,34 +28,31 @@ import org.bukkit.block.BlockFace;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
public class FloodUtil public class FloodUtil {
{ private static final Set<BlockFace> exp1 = new HashSet<>();
protected static final Set<BlockFace> exp1 = new HashSet<BlockFace>(); private static final Set<BlockFace> exp2 = new HashSet<>();
protected static final Set<BlockFace> exp2 = new HashSet<BlockFace>();
static
{
exp1.add(BlockFace.UP);
exp1.add(BlockFace.DOWN);
exp1.add(BlockFace.EAST);
exp1.add(BlockFace.WEST);
exp2.add(BlockFace.UP);
exp2.add(BlockFace.DOWN);
exp2.add(BlockFace.NORTH);
exp2.add(BlockFace.SOUTH);
}
static {
exp1.add(BlockFace.UP);
exp1.add(BlockFace.DOWN);
exp1.add(BlockFace.EAST);
exp1.add(BlockFace.WEST);
exp2.add(BlockFace.UP);
exp2.add(BlockFace.DOWN);
exp2.add(BlockFace.NORTH);
exp2.add(BlockFace.SOUTH);
}
/** /**
* Returns the all frame blocks of an gate. * Returns the all frame blocks of an gate.
*
* @param blocks All blocks inside the gate. * @param blocks All blocks inside the gate.
* @return A Set containing all frame block. Will never return 'null'. * @return A Set containing all frame block. Will never return 'null'.
*/ */
public static Set<Block> getFrame(final Set<Block> blocks) public static Set<Block> getFrame(final Set<Block> blocks) {
{
if (blocks == null || blocks.isEmpty()) { if (blocks == null || blocks.isEmpty()) {
return new HashSet<Block>(); return new HashSet<>();
} }
// try to find gate's direction (north-south or east-west) // try to find gate's direction (north-south or east-west)
@ -64,7 +61,7 @@ public class FloodUtil
for (Block b : blocks) { for (Block b : blocks) {
if (blocks.contains(b.getRelative(BlockFace.EAST)) || if (blocks.contains(b.getRelative(BlockFace.EAST)) ||
blocks.contains(b.getRelative(BlockFace.WEST))) { blocks.contains(b.getRelative(BlockFace.WEST))) {
gateFrameSearchFaces = exp1; gateFrameSearchFaces = exp1;
break; break;
@ -81,8 +78,7 @@ public class FloodUtil
if (gateFrameSearchFaces != null) { if (gateFrameSearchFaces != null) {
return _getFrame(blocks, gateFrameSearchFaces); return _getFrame(blocks, gateFrameSearchFaces);
} } else { // no direction found (the gate might only consist of blocks one over another)
else { // no direction found (the gate might only consist of blocks one over another)
// Try one direction and check if the found blocks are not air. // Try one direction and check if the found blocks are not air.
// If air is found (frame broken or wrong direction) return the other direction // If air is found (frame broken or wrong direction) return the other direction
@ -100,10 +96,8 @@ public class FloodUtil
} }
private static Set<Block> _getFrame(final Set<Block> blocks, final Set<BlockFace> searchDirections) {
protected static Set<Block> _getFrame(final Set<Block> blocks, final Set<BlockFace> searchDirections) Set<Block> frameBlocks = new HashSet<>();
{
Set<Block> frameBlocks = new HashSet<Block>();
for (Block b : blocks) { for (Block b : blocks) {
@ -122,16 +116,16 @@ public class FloodUtil
/** /**
* Returns the all frame blocks of an gate. * Returns the all frame blocks of an gate.
*
* @param locations All locations inside the gate. * @param locations All locations inside the gate.
* @return A Set containing all frame block. Will never return 'null'. * @return A Set containing all frame block. Will never return 'null'.
*/ */
public static Set<Block> getFrameWithLocations(final Set<Location> locations) public static Set<Block> getFrameWithLocations(final Set<Location> locations) {
{
if (locations == null) { if (locations == null) {
throw new IllegalArgumentException("'locations' must not be 'null'"); throw new IllegalArgumentException("'locations' must not be 'null'");
} }
Set<Block> blocks = new HashSet<Block>(); Set<Block> blocks = new HashSet<>();
for (Location l : locations) { for (Location l : locations) {
blocks.add(l.getBlock()); blocks.add(l.getBlock());
@ -140,68 +134,64 @@ public class FloodUtil
return getFrame(blocks); return getFrame(blocks);
} }
// For the same frame and location this set of blocks is deterministic // For the same frame and location this set of blocks is deterministic
public static Set<Block> getGatePortalBlocks(final Block block) public static Set<Block> getGatePortalBlocks(final Block block) {
{
if (block == null) { if (block == null) {
throw new IllegalArgumentException("'block' must not be 'null'"); throw new IllegalArgumentException("'block' must not be 'null'");
} }
int frameBlockSearchLimit = Plugin.getPlugin().getConfig().getInt(Plugin.confMaxGateBlocksKey); int frameBlockSearchLimit = Plugin.getPlugin().getConfig().getInt(ConfigurationUtil.confMaxGateBlocksKey);
Set<Block> blocks1 = getAirFloodBlocks(block, new HashSet<Block>(), exp1, frameBlockSearchLimit); Set<Block> blocks1 = getAirFloodBlocks(block, new HashSet<Block>(), exp1, frameBlockSearchLimit);
Set<Block> blocks2 = getAirFloodBlocks(block, new HashSet<Block>(), exp2, frameBlockSearchLimit); Set<Block> blocks2 = getAirFloodBlocks(block, new HashSet<Block>(), exp2, frameBlockSearchLimit);
if (blocks1 == null && blocks2 == null) {
return null;
}
if (blocks1 == null) {
return blocks2;
}
if (blocks2 == null) {
return blocks1;
}
if (blocks1.size() > blocks2.size()) {
return blocks2;
}
return blocks1;
}
if (blocks1 == null && blocks2 == null) {
protected static Set<Block> getAirFloodBlocks(final Block startBlock, return null;
Set<Block> foundBlocks,
final Set<BlockFace> expandFaces,
int limit)
{
if (foundBlocks == null) {
return null;
}
if (foundBlocks.size() > limit) {
Plugin.log(Level.ALL, "exceeding gate size limit.");
return null;
}
if (foundBlocks.contains(startBlock)) {
return foundBlocks;
} }
if (startBlock.getType() == Material.AIR) { if (blocks1 == null) {
// ... We found a block :D ... return blocks2;
foundBlocks.add(startBlock); }
// ... And flood away ! if (blocks2 == null) {
for (BlockFace face : expandFaces) { return blocks1;
Block potentialBlock = startBlock.getRelative(face); }
foundBlocks = getAirFloodBlocks(potentialBlock, foundBlocks, expandFaces, limit);
} if (blocks1.size() > blocks2.size()) {
} return blocks2;
}
return foundBlocks;
} return blocks1;
}
private static Set<Block> getAirFloodBlocks(final Block startBlock,
Set<Block> foundBlocks,
final Set<BlockFace> expandFaces,
int limit) {
if (foundBlocks == null) {
return null;
}
if (foundBlocks.size() > limit) {
Plugin.log(Level.ALL, "exceeding gate size limit.");
return null;
}
if (foundBlocks.contains(startBlock)) {
return foundBlocks;
}
if (startBlock.getType() == Material.AIR) {
foundBlocks.add(startBlock);
for (BlockFace face : expandFaces) {
Block potentialBlock = startBlock.getRelative(face);
foundBlocks = getAirFloodBlocks(potentialBlock, foundBlocks, expandFaces, limit);
}
}
return foundBlocks;
}
} }

View File

@ -16,37 +16,58 @@
*/ */
package de.craftinc.gates.util; package de.craftinc.gates.util;
import de.craftinc.gates.Plugin; import de.craftinc.gates.Plugin;
import de.craftinc.gates.Gate; import de.craftinc.gates.models.Gate;
import de.craftinc.gates.models.GateMaterial;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set; import java.util.Set;
import static de.craftinc.gates.util.ConfigurationUtil.*;
public class GateBlockChangeSender {
/**
* Replaces gate frame blocks with glowstone for a short period of time.
* Uses the data stored in 'highlightDuration' inside the config file
* for determining when to de-highlight the frames.
*
* @param player The player for whom the frame should be highlighted.
* Must not be null!
*
* @param gates The gates to highlighting
*/
public static void temporaryHighlightGatesFrames(final Player player, final Set<Gate> gates) {
assert(player != null);
assert(gates != null);
for (Gate g : gates) {
Set<Block> frameBlocks = g.getGateFrameBlocks();
for (Block b : frameBlocks) {
player.sendBlockChange(b.getLocation(), Material.GLOWSTONE, (byte) 0);
}
}
scheduleDelighting(player, gates);
}
public class GateBlockChangeSender
{
/** /**
* Sends gate blocks to player at a given location. Will send the updates either immediately or * Sends gate blocks to player at a given location. Will send the updates either immediately or
* immediately and after a short delay. * immediately and after a short delay.
*
* @param player A player to send block changes to. Must not be null! * @param player A player to send block changes to. Must not be null!
* @param location The location to look for gates nearby. Must not be null! * @param location The location to look for gates nearby. Must not be null!
* @param sendDelayed Set to 'true' if the block changes shall be send a second time after a one * @param sendDelayed Set to 'true' if the block changes shall be send a second time after a one
* second delay. * second delay.
*/ */
public static void updateGateBlocks(final Player player, final Location location, boolean sendDelayed) public static void updateGateBlocks(final Player player, final Location location, boolean sendDelayed) {
{ assert(player != null);
if (player == null) { assert(location != null);
throw new IllegalArgumentException("'player' must not be 'null'!");
}
if (location == null) {
throw new IllegalArgumentException("'location' must not be 'null'!");
}
Set<Gate> gatesNearby = Plugin.getPlugin().getGatesManager().getNearbyGates(location.getChunk()); Set<Gate> gatesNearby = Plugin.getPlugin().getGatesManager().getNearbyGates(location.getChunk());
@ -55,102 +76,98 @@ public class GateBlockChangeSender
} }
for (Gate g : gatesNearby) { for (Gate g : gatesNearby) {
if (!g.isOpen()) {
if (!g.isOpen() || g.isHidden()) {
continue; continue;
} }
sendGateBlockChanges(g, true, player);
for (Location l : g.getGateBlockLocations()) {
if (l.getBlock().getType() == Material.AIR) {
player.sendBlockChange(l, Material.PORTAL, (byte)0);
}
}
} }
if (sendDelayed) { if (sendDelayed) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Plugin.getPlugin(), new Runnable() Bukkit.getScheduler().scheduleSyncDelayedTask(Plugin.getPlugin(), new Runnable() {
{
@Override @Override
public void run() public void run() {
{
updateGateBlocks(player, location, false); updateGateBlocks(player, location, false);
} }
}, 20L); }, 20L);
} }
} }
public static void updateGateBlocks(final Player player, final Location location) {
/**
* This method calls: updateGateBlocks(player, location, false);
*/
public static void updateGateBlocks(final Player player, final Location location)
{
updateGateBlocks(player, location, false); updateGateBlocks(player, location, false);
} }
/**
* This method calls: updateGateBlocks(player, player.getLocation(), false);
*/
public static void updateGateBlocks(final Player player)
{
if (player == null) {
throw new IllegalArgumentException("'player' must not be 'null'!");
}
updateGateBlocks(player, player.getLocation(), false); public static void updateGateBlocks(final Gate gate) {
}
public static void updateGateBlocks(final Gate gate)
{
updateGateBlocks(gate, false); updateGateBlocks(gate, false);
} }
/** /**
* Sends block changes to players near a given gate. * Sends block changes to players near a given gate.
* @param gate Must not be 'null'! *
* @param gate Must not be 'null'!
* @param remove Set to true if all visible gate blocks shall be removed. * @param remove Set to true if all visible gate blocks shall be removed.
*/ */
public static void updateGateBlocks(final Gate gate, boolean remove) public static void updateGateBlocks(final Gate gate, boolean remove) {
{ assert(gate != null);
if (gate == null) {
throw new IllegalArgumentException("'gate must not be 'null'!");
}
Location gateLocation = gate.getLocation(); Location gateLocation = gate.getLocation();
if (gate.getGateBlockLocations().isEmpty()) { if (gate.getGateBlockLocations().isEmpty()) {
return; return;
} }
ArrayList<Player> playersNearby = new ArrayList<Player>(); ArrayList<Player> playersNearby = new ArrayList<>();
int searchRadius = Plugin.getPlugin().getConfig().getInt(confPlayerGateBlockUpdateRadiusKey);
int searchRadius = Plugin.getPlugin().getConfig().getInt(Plugin.confPlayerGateBlockUpdateRadiusKey);
for (Player p : Plugin.getPlugin().getServer().getOnlinePlayers()) { for (Player p : Plugin.getPlugin().getServer().getOnlinePlayers()) {
if (p.getWorld() == gateLocation.getWorld() && p.getLocation().distance(gateLocation) < searchRadius) { if (p.getWorld() == gateLocation.getWorld() && p.getLocation().distance(gateLocation) < searchRadius) {
playersNearby.add(p); playersNearby.add(p);
} }
} }
boolean isVisible = gate.isOpen() && !remove;
for (Player p : playersNearby) {
sendGateBlockChanges(gate, isVisible, p);
}
}
private static void scheduleDelighting(final Player player, final Set<Gate> gates) {
Plugin plugin = Plugin.getPlugin();
long highlightDuration = 20 * plugin.getConfig().getLong(confHighlightDurationKey);
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
dehighlightGatesFrames(player, gates);
}
}, highlightDuration);
}
private static void dehighlightGatesFrames(final Player player, final Set<Gate> gates) {
for (Gate g : gates) {
Set<Block> frameBlocks = g.getGateFrameBlocks();
for (Block b : frameBlocks) {
player.sendBlockChange(b.getLocation(), b.getType(), (byte) 0);
}
}
}
private static void sendGateBlockChanges(final Gate gate, boolean isVisible, final Player p) {
byte data;
Material material; Material material;
if (gate.isOpen() && !gate.isHidden() && !remove) { if (isVisible) {
material = Material.PORTAL; GateMaterial gm = gate.getMaterial();
} data = gm.getData(gate.getDirection());
else { material = gm.getMaterial();
} else {
data = 0b0;
material = Material.AIR; material = Material.AIR;
} }
for (Player p : playersNearby) { for (Location l : gate.getGateBlockLocations()) {
if (l.getBlock().getType() == Material.AIR) {
for (Location l : gate.getGateBlockLocations()) { p.sendBlockChange(l, material, data);
if (l.getBlock().getType() == Material.AIR) { // on server-side a gate is always made out of AIR
p.sendBlockChange(l, material, (byte)0);
}
} }
} }
} }

View File

@ -20,46 +20,46 @@ import org.bukkit.ChatColor;
import java.util.List; import java.util.List;
public class TextUtil public class TextUtil {
{
public static String titleize(String str) public static String titleSize(String str) {
{ String center = ".[ " + ChatColor.YELLOW + str + ChatColor.GOLD + " ].";
String line = ChatColor.GOLD + repeat("_", 60);
String center = ".[ " + ChatColor.YELLOW + str + ChatColor.GOLD + " ]."; if (center.length() >= 60) {
int pivot = line.length() / 2; return ChatColor.GOLD + center;
int eatLeft = center.length() / 2; } else {
int eatRight = center.length() - eatLeft; String line = ChatColor.GOLD + repeat("_", 60);
return line.substring(0, pivot - eatLeft) + center + line.substring(pivot + eatRight); int pivot = line.length() / 2;
} int eatLeft = center.length() / 2;
int eatRight = center.length() - eatLeft;
public static String repeat(String s, int times) return line.substring(0, pivot - eatLeft) + center + line.substring(pivot + eatRight);
{ }
if (times <= 0) }
return "";
return s + repeat(s, times-1); private static String repeat(String s, int times) {
} if (times <= 0)
return "";
/** return s + repeat(s, times - 1);
* Joins all elements of list into a single string, separating the original strings with glue. }
*/
public static String implode(List<String> list, String glue) /**
{ * Joins all elements of list into a single string, separating the original strings with glue.
if (list.size() == 0) { */
return ""; public static String implode(List<String> list, String glue) {
} if (list.size() == 0) {
return "";
String ret = list.get(0); }
for (int i=1; i<list.size(); i++) { String ret = list.get(0);
ret += glue + list.get(i);
} for (int i = 1; i < list.size(); i++) {
ret += glue + list.get(i);
return ret; }
}
return ret;
}
} }