Compare commits

..

No commits in common. "development" and "version2.2.0" have entirely different histories.

54 changed files with 2768 additions and 2713 deletions

1
.gitignore vendored
View File

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

View File

@ -0,0 +1,12 @@
#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):
CURRENT MAINTAINERS
CURRENT MAINTAINER
Tobias Ottenweller <mail@ottenweller.net>
Paul Schulze <info@paul-schulze.de>
FORMER CONTRIBUTORS (alphabetical order)
FORMER CONTRIBUTOR (alphabetical order)
Jacob Brunson <jacob@dimensionsmachine.com>
locutus <bladedpenguin@gmail.com>

View File

@ -1,5 +1,10 @@
# 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 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_.
@ -8,12 +13,10 @@ Now it is time for _you_ to try out this wonderful plugin. Simply install, creat
The key features of this are:
* Dynmap integration
* Gates with and without frames
* Gates consisting of portal blocks and gates made of air (so called hidden gates)
* Gates with destinations in different worlds
* 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!
@ -54,9 +57,8 @@ Have a look at the [_Commands_](http://dev.bukkit.org/bukkit-plugins/craftinc-ga
## Installing ##
1. Download the latest release _[here](http://dev.bukkit.org/bukkit-plugins/craftinc-gates/files/)_
2. Delete any old versions of _Craft Inc. Gates_ (only the .jar files) including the extra dynmap-plugin of this plugin.
3. Extract the content of the zip file into the plugins folder of your Bukkit server.
4. Start or reload the server.
2. Extract the content of the zip file into the plugins folder of your Bukkit server.
3. Start or reload the server.
## Craft Inc. ##
Check out our __[Craft Inc. Minecraft Server](http://www.craftinc.de)__. Everyone is welcome!
@ -73,8 +75,15 @@ allows players to build a replicator to replicate blocks and other items. (still
coming soon!
## Roadmap ##
* Per player permissions for using and managing gates.
* Horizontal gates.
* __Version 2.3__
* Info-Tools for gates. (Get the name of a gate you standing next to.)
* 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 ##
Please use our [_issue tracker_](https://github.com/craftinc/craftinc-gates/issues?state=open) on GitHub.
@ -82,4 +91,3 @@ Please use our [_issue tracker_](https://github.com/craftinc/craftinc-gates/issu
## 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).
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,18 +1,3 @@
## 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 ##
* Improved gate commands and shortcuts (have a look at the bukkit-dev page for more information).
* Improved overall performance.

View File

@ -1,21 +1,12 @@
* __/gate allowRiding, ar [id]__
Update a gate so players can travel through it while riding.
* __/gate close, c [id]__
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]__
Removes the gate from the game.
* __/gate exit, e [id]__
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]__
Prints help pages.
@ -23,7 +14,7 @@ Prints help pages.
Makes a gate NOT consist of gate blocks while open.
* __/gate info, i [id]__
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.
Prints details about a certain gate.
* __/gate list, ls [page]__
Prints all available gates.
@ -31,9 +22,6 @@ Prints all available gates.
* __/gate location, lo [id]__
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]__
Creates a gate at your current location.

View File

@ -41,17 +41,11 @@ be displayed.
* __gateTeleportNoPermissionMessage__
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_
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_
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__
A boolean (_true_ or _false_) determining wether the _no permission message_ will
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.

View File

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

90
pom.xml
View File

@ -5,27 +5,13 @@
<groupId>de.craftinc</groupId>
<artifactId>CraftIncGates</artifactId>
<name>Craft Inc. Gates</name>
<url>http://dev.bukkit.org/bukkit-plugins/craftinc-gates/</url>
<packaging>jar</packaging>
<version>2.4.1</version>
<version>2.2.0</version>
<properties>
<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>
<!-- 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>
<finalName>${project.name} ${project.version}</finalName>
<sourceDirectory>src</sourceDirectory>
@ -57,7 +43,7 @@
<executions>
<execution>
<id>Run Test Bukkit Server</id>
<phase>install</phase>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
@ -67,83 +53,41 @@
</execution>
</executions>
</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>
</build>
<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>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Vault-->
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>Vault</artifactId>
<version>1.6.6</version>
<version>1.5.2-R1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!--Metrics-->
<dependency>
<groupId>org.mcstats.bukkit</groupId>
<artifactId>metrics</artifactId>
<version>R8-SNAPSHOT</version>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.5.2-R1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>Vault</artifactId>
<version>1.2.26-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<id>bukkit-repo</id>
<url>http://repo.bukkit.org/content/groups/public</url>
</repository>
<repository>
<id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
<url>http://ci.herocraftonline.com/plugin/repository/everything</url>
</repository>
<repository>
<id>Plugin Metrics</id>
<url>http://repo.mcstats.org/content/repositories/public</url>
</repository>
</repositories>
</project>

View File

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

View File

@ -0,0 +1,350 @@
/* 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

@ -0,0 +1,513 @@
/* 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,16 +16,12 @@
*/
package de.craftinc.gates;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import de.craftinc.gates.controllers.GatesManager;
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 org.bukkit.ChatColor;
@ -37,77 +33,96 @@ import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import de.craftinc.gates.commands.*;
import org.mcstats.Metrics;
public class Plugin extends JavaPlugin {
public class Plugin extends JavaPlugin
{
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";
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;
private String baseCommand;
protected List<BaseCommand> commands = new ArrayList<>();
protected String baseCommand;
protected List<BaseCommand> commands = new ArrayList<BaseCommand>();
protected GatesManager gatesManager = new GatesManager();
private GatesManager gatesManager = new GatesManager();
protected PlayerMoveListener moveListener = new PlayerMoveListener();
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();
private PermissionController permissionController = new PermissionController();
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();
public Plugin() {
public Plugin()
{
instance = this;
moveListener = new PlayerMoveListener(this);
vehicleListener = new VehicleMoveListener(this);
}
public static Plugin getPlugin() {
public static Plugin getPlugin()
{
return instance;
}
public GatesManager getGatesManager() {
public GatesManager getGatesManager()
{
return gatesManager;
}
@Override
public void onLoad() {
public void onLoad()
{
ConfigurationSerialization.registerClass(Gate.class);
}
private void setupPermissions() {
protected void setupPermissions()
{
if (getServer().getPluginManager().getPlugin("Vault") == null) {
log("Not using setup permission provider provided by Vault.");
return;
}
RegisteredServiceProvider<Permission> rsp = getServer().getServicesManager().getRegistration(Permission.class);
if (rsp != null) {
if (rsp != null)
{
log("Using permission provider provided by Vault.");
permissionController.setPermission(rsp.getProvider());
} else {
permission = rsp.getProvider();
}
else
{
log("Not using setup permission provider provided by Vault.");
}
}
@Override
public void onDisable() {
public void onDisable()
{
// Save gates
gatesManager.saveGatesToDisk();
log("Disabled");
}
@Override
public void onEnable() {
// Setup Metrics
try {
Metrics metrics = new Metrics(this);
metrics.start();
} catch (IOException e) {
log("Failed to start metrics!");
}
@Override
public void onEnable()
{
// Setup configuration
this.saveDefaultConfig();
@ -120,14 +135,14 @@ public class Plugin extends JavaPlugin {
commands.add(new CommandRemove());
commands.add(new CommandLocation());
commands.add(new CommandExit());
commands.add(new CommandTriggerOpen());
commands.add(new CommandOpen());
commands.add(new CommandRename());
commands.add(new CommandClose());
commands.add(new CommandList());
commands.add(new CommandInfo());
commands.add(new CommandNearby());
commands.add(new CommandTriggerVehicles());
commands.add(new CommandMaterial());
commands.add(new CommandTeleport());
commands.add(new CommandHide());
commands.add(new CommandUnhide());
// Register events
this.registerEventListeners();
@ -137,17 +152,16 @@ public class Plugin extends JavaPlugin {
if (success) {
log("Enabled");
} else {
}
else {
PluginManager pm = this.getServer().getPluginManager();
pm.disablePlugin(this);
}
}
public PermissionController getPermissionController() {
return permissionController;
}
private void registerEventListeners() {
protected void registerEventListeners()
{
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvents(this.moveListener, this);
@ -155,18 +169,19 @@ public class Plugin extends JavaPlugin {
pm.registerEvents(this.respawnListener, this);
pm.registerEvents(this.worldChangeListener, this);
pm.registerEvents(this.joinListener, this);
pm.registerEvents(this.vehicleListener, this);
if (getConfig().getBoolean(ConfigurationUtil.confCheckForBrokenGateFramesKey)) {
if (getConfig().getBoolean(confCheckForBrokenGateFramesKey)) {
pm.registerEvents(this.blockBreakListener, this);
}
}
// -------------------------------------------- //
// Commands
// -------------------------------------------- //
public String getBaseCommand() {
public String getBaseCommand()
{
if (this.baseCommand != null)
return this.baseCommand;
@ -177,15 +192,20 @@ public class Plugin extends JavaPlugin {
return this.baseCommand;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
List<String> parameters = new ArrayList<>(Arrays.asList(args));
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;
}
private void handleCommand(CommandSender sender, List<String> parameters) {
if (parameters.size() == 0) {
public void handleCommand(CommandSender sender, List<String> parameters)
{
if (parameters.size() == 0)
{
this.commands.get(0).execute(sender, parameters);
return;
}
@ -193,9 +213,11 @@ public class Plugin extends JavaPlugin {
String commandName = parameters.get(0).toLowerCase();
parameters.remove(0);
for (BaseCommand command : this.commands) {
if (command.getAliases().contains(commandName)) {
command.execute(sender, parameters);
for (BaseCommand fcommand : this.commands)
{
if (fcommand.getAliases().contains(commandName))
{
fcommand.execute(sender, parameters);
return;
}
}
@ -204,14 +226,23 @@ public class Plugin extends JavaPlugin {
ChatColor.GREEN + " Try " + "/" + getBaseCommand() + " help");
}
/*
* Logging
*/
public static void log(String msg) {
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 static void log(Level level, String msg)
{
Logger.getLogger("Minecraft").log(level, "["+instance.getDescription().getFullName()+"] "+msg);
}
public static Permission getPermission() {
return permission;
}
}

View File

@ -19,49 +19,41 @@ package de.craftinc.gates.commands;
import java.util.ArrayList;
import java.util.List;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.ConfigurationUtil;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.controllers.GatesManager;
import de.craftinc.gates.Gate;
import de.craftinc.gates.GatesManager;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil;
public abstract class BaseCommand {
PermissionController permissionController;
GatesManager gatesManager;
public abstract class BaseCommand
{
protected List<String> aliases = new ArrayList<String>();
protected List<String> requiredParameters = new ArrayList<String>();
protected List<String> optionalParameters = new ArrayList<String>();
List<String> aliases = new ArrayList<>();
List<String> requiredParameters = new ArrayList<>();
List<String> optionalParameters = new ArrayList<>();
protected String helpDescription = "no description";
String helpDescription = "no description";
protected List<String> parameters;
protected CommandSender sender;
protected Player player;
protected Gate gate;
List<String> parameters;
CommandSender sender;
Player player;
Gate gate;
protected boolean senderMustBePlayer = true;
protected boolean hasGateParam = true;
boolean senderMustBePlayer = true;
boolean hasGateParam = true;
protected String requiredPermission;
protected boolean needsPermissionAtCurrentLocation;
String requiredPermission;
boolean needsPermissionAtCurrentLocation;
protected boolean shouldPersistToDisk;
boolean shouldPersistToDisk;
public List<String> getAliases() {
return aliases;
}
public BaseCommand() {
gatesManager = Plugin.getPlugin().getGatesManager();
permissionController = Plugin.getPlugin().getPermissionController();
}
public void execute(CommandSender sender, List<String> parameters) {
this.sender = sender;
@ -71,82 +63,35 @@ public abstract class BaseCommand {
return;
}
if (sender instanceof Player) {
if (this.senderMustBePlayer) {
this.player = (Player)sender;
}
this.perform();
if (this.shouldPersistToDisk && getSaveOnChanges()) {
gatesManager.saveGatesToDisk();
if (this.shouldPersistToDisk && Plugin.getPlugin().getConfig().getBoolean(Plugin.confSaveOnChangesKey)) {
Plugin.getPlugin().getGatesManager().saveGatesToDisk();
}
}
abstract protected void perform();
void sendMessage(String message) {
protected void sendMessage(String message) {
sender.sendMessage(message);
}
void sendMessage(List<String> messages) {
for (String message : messages) {
protected void sendMessage(List<String> messages) {
for(String message : messages) {
this.sendMessage(message);
}
}
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() {
protected boolean validateCall()
{
boolean allParametersThere = parameters.size() >= requiredParameters.size();
boolean senderIsPlayer = this.sender instanceof Player;
boolean hasGateParameter = false;
@ -159,25 +104,22 @@ public abstract class BaseCommand {
boolean valid;
if (this.senderMustBePlayer && !senderIsPlayer) {
sendMessage(ChatColor.RED + "This command can only be used by in-game players.");
sendMessage(ChatColor.RED + "This command can only be used by ingame players.");
valid = false;
} else {
}
else {
if (!allParametersThere) {
sendMessage(ChatColor.RED + "Some parameters are missing! " +
ChatColor.AQUA + "Usage: " +
getUsageTemplate(false)
);
sendMessage(ChatColor.RED + "Some parameters are missing! " + ChatColor.AQUA + "Usage: " + this.getUsageTemplate(true));
valid = false;
} else if ((!senderHasPermission && this.hasGateParam) ||
}
else if ((!senderHasPermission && this.hasGateParam) ||
(!senderHasPermission) ||
(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;
} else {
}
else {
valid = true;
}
}
@ -185,8 +127,125 @@ public abstract class BaseCommand {
return valid;
}
private boolean getSaveOnChanges() {
FileConfiguration config = Plugin.getPlugin().getConfig();
return config.getBoolean(ConfigurationUtil.confSaveOnChangesKey);
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)) {
// sender is no player - there is no information about the senders locations
return Plugin.getPermission().has(this.sender, this.requiredPermission);
}
Player p = (Player) this.sender;
boolean hasPermission = false;
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,21 +21,27 @@ import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
abstract class BaseLocationCommand extends BaseCommand {
Location getValidPlayerLocation() {
public abstract class BaseLocationCommand extends BaseCommand
{
protected Location getValidPlayerLocation()
{
// The player might stand in a half block or a sign or whatever
// Therefore we load some extra locations and blocks
Location location = player.getLocation().clone();
Block playerBlock = location.getBlock();
Block playerBlock = player.getLocation().getBlock();
Block upBlock = playerBlock.getRelative(BlockFace.UP);
if (playerBlock.getType() == Material.AIR) {
return location;
} else if (upBlock.getType() == Material.AIR) {
return location.add(0, 1, 0);
} else {
return player.getLocation();
}
else if (upBlock.getType() == Material.AIR) {
return new Location(player.getLocation().getWorld(),
player.getLocation().getX(),
player.getLocation().getY() + 1,
player.getLocation().getZ(),
player.getLocation().getYaw(),
player.getLocation().getPitch());
}
return null;
}
}
}

View File

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

View File

@ -16,53 +16,94 @@
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CommandHelp extends BaseCommand {
public class CommandHelp extends BaseCommand
{
public static List<List<String>> helpPages;
private static List<String> help;
static
{
// sort the usage strings
List<String> allUsageStrings = new ArrayList<String>();
public CommandHelp() {
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 = PermissionController.permissionInfo;
requiredPermission = Plugin.permissionInfo;
hasGateParam = false;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = false;
senderMustBePlayer = false;
}
public void perform() {
sendMessage(TextUtil.titleSize("Craft Inc. Gates Help"));
sendMessage(getHelp());
public void perform()
{
int page;
if (parameters.size() > 0) {
try {
page = Integer.parseInt(parameters.get(0));
}
catch (NumberFormatException e) {
// wasn't an integer
page = 1;
}
}
else {
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;
}
return help;
sendMessage(helpPages.get(page));
}
}

View File

@ -0,0 +1,59 @@
/* 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,98 +16,62 @@
*/
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 de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil;
import org.bukkit.entity.Player;
import java.util.HashSet;
public class CommandInfo extends BaseCommand {
public CommandInfo() {
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;
requiredParameters.add("id");
helpDescription = "Print detailed information about a certain gate.";
requiredPermission = Plugin.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;
}
public void perform()
{
sendMessage(TextUtil.titleize("Information about: '" + ChatColor.WHITE + gate.getId() + ChatColor.YELLOW + "'"));
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";
String openHiddenMessage = ChatColor.DARK_AQUA + "This gate is";
if (gate.isOpen())
openMessage += ChatColor.AQUA + " open";
openHiddenMessage += ChatColor.AQUA + " open";
else
openMessage += ChatColor.AQUA + " closed";
openHiddenMessage += ChatColor.AQUA + " closed";
openMessage += ".\n";
if (gate.isHidden())
openHiddenMessage += ChatColor.DARK_AQUA +" and" + ChatColor.AQUA + " hidden";
sendMessage(openMessage);
openHiddenMessage += ".\n";
sendMessage(openHiddenMessage);
if (gate.getLocation() != null)
sendMessage(ChatColor.DARK_AQUA + "location: " + ChatColor.AQUA + "( " + (int) gate.getLocation().getX() +
" | " + (int) gate.getLocation().getY() + " | " + (int) gate.getLocation().getZ() + " ) in " +
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 + "exit: " + ChatColor.AQUA + "( " + (int) gate.getExit().getX() + " | "
+ (int) gate.getExit().getY() + " | " + (int) gate.getExit().getZ() + " ) in " +
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");
if (gate.getAllowsVehicles())
sendMessage(ChatColor.DARK_AQUA + "You can ride through this gate.");
sendMessage(ChatColor.DARK_AQUA + "This gate is made of "
+ ChatColor.AQUA + gate.getMaterial() + ChatColor.DARK_AQUA + ".");
if (this.sender instanceof Player) {
HashSet<Gate> set = new HashSet<>();
set.add(this.gate);
GateBlockChangeSender.temporaryHighlightGatesFrames((Player)this.sender, set);
}
}
}

View File

@ -21,23 +21,27 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.Gate;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.util.TextUtil;
public class CommandList extends BaseCommand {
private static final int linesPerPage = 15;
/* this is actually not true. the font used by Minecraft is not
monospaced. but there seems to be no (easy) way to calculate
public class CommandList extends BaseCommand
{
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.
*/
private static final int charactersPerLine = 52;
public CommandList() {
public CommandList()
{
aliases.add("list");
aliases.add("ls");
@ -47,48 +51,32 @@ public class CommandList extends BaseCommand {
helpDescription = "lists all availible gates.";
requiredPermission = PermissionController.permissionInfo;
requiredPermission = Plugin.permissionInfo;
shouldPersistToDisk = false;
senderMustBePlayer = false;
}
public void perform() {
int page = this.getPageParameter();
List<String> allPages = this.pagedGateIds();
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)");
return;
}
if (page > allPages.size() || page < 1) {
sendMessage(ChatColor.RED + "The requested page is not available");
return;
}
String message = TextUtil.titleSize("List of all gates (" + page + "/" + allPages.size() + ")") + "\n";
message += allPages.get(page - 1);
sendMessage(message);
}
private static List<String> linesOfGateIds(List<String> gates) {
List<String> lines = new ArrayList<>();
protected static List<String> linesOfGateIds(List<String> gates)
{
List<String> lines = new ArrayList<String>();
int index = 0;
List<String> gateIdsForCurrentLine = new ArrayList<>();
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
if (gateIdLength > charactersPerLine && numCharactersInCurrentLine == 0) { // special case: very long gate id
gateIdsForCurrentLine = new ArrayList<>();
// 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?
@ -98,21 +86,28 @@ public class CommandList extends BaseCommand {
lines.add(gateId.substring(0, cutPos));
gateId = gateId.substring(cutPos, gateId.length());
}
gateIdsForCurrentLine.add(gateId);
numCharactersInCurrentLine += gateId.length();
index++;
} else if ((numCharactersInCurrentLine + gateIdLength) <= charactersPerLine) { // gate fits into current line
}
// gate fits into current line
else if ((numCharactersInCurrentLine + gateIdLength) <= charactersPerLine) {
gateIdsForCurrentLine.add(gateId);
numCharactersInCurrentLine += gateIdLength;
index++;
} else { // the current gate does not fit on the
}
// the current gate does not fit on the
else {
lines.add(TextUtil.implode(gateIdsForCurrentLine, ", ") + ", ");
gateIdsForCurrentLine = new ArrayList<>();
gateIdsForCurrentLine = new ArrayList<String>();
numCharactersInCurrentLine = 0;
}
}
@ -121,44 +116,72 @@ public class CommandList extends BaseCommand {
return lines;
}
private static String intToTitleString(int i, boolean addPreviousPageNote, boolean addNextPageNote) {
protected static String intToTitleString(int i, boolean addPreviousPageNote, boolean addNextPageNote)
{
String retVal = ChatColor.DARK_AQUA + "";
if (i < 26) {
retVal += (char) (i + 65);
} else if (i == 26) {
if ( i < 26 ) {
retVal += (char)(i+65);
}
else if ( i == 26 ) {
retVal += "0-9";
} else {
}
else {
retVal += "!@#$";
}
if (addPreviousPageNote && addNextPageNote) {
retVal += " (more on previous and next page)";
} else if (addPreviousPageNote) {
}
else if (addPreviousPageNote) {
retVal += " (more on previous page)";
} else if (addNextPageNote) {
}
else if (addNextPageNote) {
retVal += " (more on next page)";
}
return retVal + "\n";
}
/**
* Method for getting a collection of gates the player is allowed to see.
*/
private Collection<Gate> getAllGates() {
Collection<Gate> gates = gatesManager.allGates();
protected Collection<Gate> getAllGates()
{
Collection<Gate> gates = Plugin.getPlugin().getGatesManager().allGates();
if (this.sender instanceof Player && Plugin.getPermission() != null) {
Player p = (Player)this.sender;
// create a copy since we cannot iterate over a collection while modifying it!
Collection<Gate> gatesCopy = new ArrayList<>(gates);
Collection<Gate> gatesCopy = new ArrayList<Gate>(gates);
for (Gate gate : gatesCopy) {
if (!this.permissionController.hasPermission(this.sender, gate, this.requiredPermission)) {
if (gate.getLocation() != null) {
boolean permissionAtGateLocation = Plugin.getPermission().has(gate.getLocation().getWorld(), p.getName(), this.requiredPermission);
if (!permissionAtGateLocation) {
gates.remove(gate);
continue;
}
}
if (gate.getExit() != null) {
boolean permissionAtGateExit = Plugin.getPermission().has(gate.getExit().getWorld(), p.getName(), this.requiredPermission);
if (!permissionAtGateExit) {
gates.remove(gate);
}
}
}
}
return gates;
}
/**
* Sorts all gates by there first character.
* Puts gates in corresponding Lists: (all returned lists will be sorted alphabetically)
@ -166,11 +189,12 @@ public class CommandList extends BaseCommand {
* list 26: 0-9
* list 27: other
*/
private static List<List<String>> gatesSortedByName(Collection<Gate> allGates) {
protected static List<List<String>> gatesSortedByName(Collection<Gate> allGates)
{
// create the lists
List<List<String>> ids = new ArrayList<>();
List<List<String>> ids = new ArrayList<List<String>>();
for (int i = 0; i < 28; i++) {
for (int i=0; i<28; i++) {
ids.add(new ArrayList<String>());
}
@ -181,11 +205,14 @@ public class CommandList extends BaseCommand {
if (first > 96 && first < 123) { // convert lower case chars
first -= 97;
} else if (first > 64 && first < 91) { // convert upper case chars
}
else if (first > 64 && first < 91) { // convert upper case chars
first -= 65;
} else if (first > 47 && first < 58) { // convert numbers
}
else if (first > 47 && first < 58) { // convert numbers
first = 26;
} else { // everything else
}
else { // everything else
first = 27;
}
@ -193,20 +220,22 @@ public class CommandList extends BaseCommand {
}
// sort everything
for (int i = 0; i < 28; i++) {
for (int i=0; i<28; i++) {
Collections.sort(ids.get(i));
}
return ids;
}
/**
* Returns a list of strings.
* 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.
*/
private List<String> pagedGateIds() {
protected List<String> pagedGateIds()
{
Collection<Gate> gates = this.getAllGates();
if (gates.size() == 0) {
@ -214,15 +243,15 @@ public class CommandList extends BaseCommand {
}
List<List<String>> gatesSortedByName = gatesSortedByName(gates);
List<String> allPages = new ArrayList<>();
List<String> allPages = new ArrayList<String>();
int linesLeftOnPage = linesPerPage - 1;
String currentPageString = "";
for (int i = 0; i < gatesSortedByName.size(); i++) {
for (int i=0; i<gatesSortedByName.size(); i++) {
List<String> currentGates = gatesSortedByName.get(i);
if (currentGates.isEmpty()) {
if(currentGates.isEmpty()) {
continue;
}
@ -232,7 +261,7 @@ public class CommandList extends BaseCommand {
while (!currentGatesAsLines.isEmpty()) {
if (linesLeftOnPage < 2) {
currentPageString = currentPageString.substring(0, currentPageString.length() - 2); // remove newlines add the end of the page
currentPageString = currentPageString.substring(0, currentPageString.length()-2); // remove newlines add the end of the page
allPages.add(currentPageString);
currentPageString = "";
@ -247,8 +276,9 @@ public class CommandList extends BaseCommand {
if (linesNecessaryForCurrentGates < linesLeftOnPage) {
linesToFill = linesNecessaryForCurrentGates;
moreGatesOnNextPage = false;
} else {
linesToFill = linesLeftOnPage - 1;
}
else {
linesToFill = linesLeftOnPage -1;
moreGatesOnNextPage = true;
}
@ -258,12 +288,12 @@ public class CommandList extends BaseCommand {
linesLeftOnPage--;
// add gate lines
for (int j = 0; j < linesToFill; j++) {
for (int j=0; j<linesToFill; j++) {
currentPageString += currentGatesAsLines.get(j) + "\n";
}
// remove lines added
for (int j = 0; j < linesToFill; j++) {
for (int j=0; j<linesToFill; j++) {
currentGatesAsLines.remove(0);
}
@ -275,7 +305,7 @@ public class CommandList extends BaseCommand {
// add the last page
if (!currentPageString.isEmpty()) {
currentPageString = currentPageString.substring(0, currentPageString.length() - 2); // remove newlines add the end of the page
currentPageString = currentPageString.substring(0, currentPageString.length()-2); // remove newlines add the end of the page
allPages.add(currentPageString);
}
@ -283,14 +313,39 @@ public class CommandList extends BaseCommand {
}
private int getPageParameter() {
protected int getPageParameter()
{
int page = 1;
try {
page = new Integer(parameters.get(0));
} catch (Exception ignored) {
}
catch (Exception ignored) { }
return page;
}
public void perform()
{
int page = this.getPageParameter();
List<String> allPages = this.pagedGateIds();
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)");
return;
}
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);
}
}

View File

@ -16,34 +16,43 @@
*/
package de.craftinc.gates.commands;
import java.util.Set;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import de.craftinc.gates.Plugin;
import org.bukkit.block.Block;
public class CommandLocation extends BaseLocationCommand {
public CommandLocation() {
public class CommandLocation extends BaseLocationCommand
{
public CommandLocation()
{
aliases.add("location");
aliases.add("lo");
requiredParameters.add("id");
helpDescription = "Set the entrance of the gate to your current location.";
requiredPermission = PermissionController.permissionManage;
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = true;
shouldPersistToDisk = true;
senderMustBePlayer = true;
}
public void perform() {
public void perform()
{
Location playerLocation = getValidPlayerLocation();
if (playerLocation == null) {
if (playerLocation == null)
{
sendMessage("There is not enough room for a gate to open here");
return;
}
@ -52,19 +61,25 @@ public class CommandLocation extends BaseLocationCommand {
Set<Location> oldGateBlockLocations = gate.getGateBlockLocations();
Set<Block> oldFrameBlocks = gate.getGateFrameBlocks();
try {
try
{
if (gate.isOpen()) {
GateBlockChangeSender.updateGateBlocks(gate, true);
}
gate.setLocation(playerLocation);
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(new CommandTriggerOpen().getUsageTemplate(true));
} finally {
gatesManager.handleGateLocationChange(gate, oldLocation, oldGateBlockLocations, oldFrameBlocks);
sendMessage(new CommandOpen().getUsageTemplate(true, true));
}
finally {
Plugin.getPlugin().getGatesManager().handleGateLocationChange(gate, oldLocation, oldGateBlockLocations, oldFrameBlocks);
GateBlockChangeSender.updateGateBlocks(gate);
}
}
}

View File

@ -1,45 +0,0 @@
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

@ -1,41 +0,0 @@
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,32 +16,41 @@
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.Gate;
import de.craftinc.gates.GatesManager;
import de.craftinc.gates.Plugin;
public class CommandNew extends BaseLocationCommand {
public CommandNew() {
public class CommandNew extends BaseLocationCommand
{
public CommandNew()
{
aliases.add("new");
aliases.add("create");
aliases.add("n");
requiredParameters.add("id");
senderMustBePlayer = true;
hasGateParam = false;
helpDescription = "Create a gate at your current location.";
requiredPermission = PermissionController.permissionManage;
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = true;
shouldPersistToDisk = true;
senderMustBePlayer = true;
}
public void perform() {
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!");
@ -51,19 +60,24 @@ public class CommandNew extends BaseLocationCommand {
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 {
catch (Exception ignored) {}
}
else
{
sendMessage(ChatColor.RED + "Your location is invalid!" + ChatColor.AQUA + "Go somewhere else and execute:");
sendMessage(new CommandLocation().getUsageTemplate(true));
sendMessage(new CommandLocation().getUsageTemplate(true, true));
}
gatesManager.handleNewGate(gate);
}
}

View File

@ -0,0 +1,70 @@
/* 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,13 +16,16 @@
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.ChatColor;
public class CommandRemove extends BaseCommand {
import de.craftinc.gates.Plugin;
public CommandRemove() {
public class CommandRemove extends BaseCommand
{
public CommandRemove()
{
aliases.add("delete");
aliases.add("del");
aliases.add("remove");
@ -32,7 +35,7 @@ public class CommandRemove extends BaseCommand {
senderMustBePlayer = false;
helpDescription = "Removes the gate from the game.";
requiredPermission = PermissionController.permissionManage;
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
@ -40,8 +43,10 @@ public class CommandRemove extends BaseCommand {
senderMustBePlayer = false;
}
public void perform() {
gatesManager.handleDeletion(gate);
public void perform()
{
Plugin.getPlugin().getGatesManager().handleDeletion(gate);
GateBlockChangeSender.updateGateBlocks(gate, true);
sendMessage(ChatColor.GREEN + "Gate with id '" + gate.getId() + "' was deleted.");
}

View File

@ -16,31 +16,44 @@
*/
package de.craftinc.gates.commands;
import de.craftinc.gates.controllers.PermissionController;
import org.bukkit.ChatColor;
public class CommandRename extends BaseCommand {
import de.craftinc.gates.GatesManager;
import de.craftinc.gates.Plugin;
public CommandRename() {
public class CommandRename extends BaseCommand
{
public CommandRename()
{
aliases.add("rename");
aliases.add("rn");
hasGateParam = true;
senderMustBePlayer = false;
requiredParameters.add("current name");
requiredParameters.add("new name");
helpDescription = "Changes the id of a gate.";
requiredPermission = PermissionController.permissionManage;
requiredPermission = Plugin.permissionManage;
needsPermissionAtCurrentLocation = false;
shouldPersistToDisk = true;
senderMustBePlayer = false;
}
public void perform() {
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 {
}
else {
String oldId = gate.getId();
gate.setId(newId);
@ -49,4 +62,5 @@ public class CommandRename extends BaseCommand {
sendMessage(ChatColor.GREEN + "Gate " + gate.getId() + " is now known as " + newId + ".");
}
}
}

View File

@ -1,23 +0,0 @@
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

@ -1,54 +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.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

@ -1,47 +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.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

@ -0,0 +1,58 @@
/* 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

@ -1,477 +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.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

@ -1,58 +0,0 @@
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

@ -1,126 +0,0 @@
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,29 +16,31 @@
*/
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.util.GateBlockChangeSender;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
public class BlockBreakListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(BlockBreakEvent event) {
public class BlockBreakListener implements Listener
{
@EventHandler(priority = EventPriority.NORMAL)
public void onBlockBreak(BlockBreakEvent event)
{
if (event.isCancelled()) {
return;
}
Gate gate = Plugin.getPlugin().getGatesManager().getGateAtFrameLocation(event.getBlock().getLocation());
if (gate != null && gate.getMaterial().getMaterial() != Material.AIR) {
if (gate != null && !gate.isHidden()) {
try {
gate.setOpen(false);
} catch (Exception ignored) {}
}
catch (Exception ignored) { }
GateBlockChangeSender.updateGateBlocks(gate);
}

View File

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

View File

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

View File

@ -16,23 +16,30 @@
*/
package de.craftinc.gates.listeners;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.controllers.TeleportController;
import java.util.Calendar;
import java.util.HashMap;
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.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
public class PlayerMoveListener implements Listener {
private TeleportController teleportController;
import de.craftinc.gates.Gate;
import de.craftinc.gates.GatesManager;
import de.craftinc.gates.Plugin;
public PlayerMoveListener(Plugin plugin) {
this.teleportController = new TeleportController(plugin);
}
public class PlayerMoveListener implements Listener
{
protected HashMap<String, Long> lastNoPermissionMessages = new HashMap<String, Long>();
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerMove(PlayerMoveEvent event) {
public void onPlayerMove(PlayerMoveEvent event)
{
if (event.isCancelled()) {
return;
}
@ -41,6 +48,89 @@ public class PlayerMoveListener implements Listener {
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getTo());
}
teleportController.teleport(event.getPlayer(), event.getTo());
GatesManager gateManager = Plugin.getPlugin().getGatesManager();
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,15 +16,19 @@
*/
package de.craftinc.gates.listeners;
import de.craftinc.gates.util.GateBlockChangeSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerRespawnEvent;
public class PlayerRespawnListener implements Listener {
public class PlayerRespawnListener implements Listener
{
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerRespawn(PlayerRespawnEvent event) {
public void onPlayerRespawn(PlayerRespawnEvent event)
{
GateBlockChangeSender.updateGateBlocks(event.getPlayer(), event.getRespawnLocation(), true);
}
}

View File

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

View File

@ -1,27 +0,0 @@
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

@ -1,298 +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.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

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

View File

@ -1,162 +0,0 @@
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

@ -0,0 +1,100 @@
/* 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;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.Gate;
import de.craftinc.gates.Plugin;
import org.bukkit.Location;
@ -27,14 +27,28 @@ import java.util.List;
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) {
public static boolean performMigration(int storageVersion, int currentVersion, List<Gate> gates) {
if (storageVersion != currentVersion) {
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;
for (Gate g : gates) {
for (Location l : g.getGateBlockLocations()) {
Block b = l.getBlock();
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;
}
}
}

View File

@ -1,30 +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.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,11 +28,13 @@ import org.bukkit.block.BlockFace;
import de.craftinc.gates.Plugin;
public class FloodUtil {
private static final Set<BlockFace> exp1 = new HashSet<>();
private static final Set<BlockFace> exp2 = new HashSet<>();
public class FloodUtil
{
protected static final Set<BlockFace> exp1 = new HashSet<BlockFace>();
protected static final Set<BlockFace> exp2 = new HashSet<BlockFace>();
static {
static
{
exp1.add(BlockFace.UP);
exp1.add(BlockFace.DOWN);
exp1.add(BlockFace.EAST);
@ -44,15 +46,16 @@ public class FloodUtil {
exp2.add(BlockFace.SOUTH);
}
/**
* Returns the all frame blocks of an gate.
*
* @param blocks All blocks inside the gate.
* @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()) {
return new HashSet<>();
return new HashSet<Block>();
}
// try to find gate's direction (north-south or east-west)
@ -78,7 +81,8 @@ public class FloodUtil {
if (gateFrameSearchFaces != null) {
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.
// If air is found (frame broken or wrong direction) return the other direction
@ -96,8 +100,10 @@ public class FloodUtil {
}
private static Set<Block> _getFrame(final Set<Block> blocks, final Set<BlockFace> searchDirections) {
Set<Block> frameBlocks = new HashSet<>();
protected static Set<Block> _getFrame(final Set<Block> blocks, final Set<BlockFace> searchDirections)
{
Set<Block> frameBlocks = new HashSet<Block>();
for (Block b : blocks) {
@ -116,16 +122,16 @@ public class FloodUtil {
/**
* Returns the all frame blocks of an gate.
*
* @param locations All locations inside the gate.
* @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) {
throw new IllegalArgumentException("'locations' must not be 'null'");
}
Set<Block> blocks = new HashSet<>();
Set<Block> blocks = new HashSet<Block>();
for (Location l : locations) {
blocks.add(l.getBlock());
@ -136,12 +142,13 @@ public class FloodUtil {
// 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) {
throw new IllegalArgumentException("'block' must not be 'null'");
}
int frameBlockSearchLimit = Plugin.getPlugin().getConfig().getInt(ConfigurationUtil.confMaxGateBlocksKey);
int frameBlockSearchLimit = Plugin.getPlugin().getConfig().getInt(Plugin.confMaxGateBlocksKey);
Set<Block> blocks1 = getAirFloodBlocks(block, new HashSet<Block>(), exp1, frameBlockSearchLimit);
Set<Block> blocks2 = getAirFloodBlocks(block, new HashSet<Block>(), exp2, frameBlockSearchLimit);
@ -166,10 +173,11 @@ public class FloodUtil {
}
private static Set<Block> getAirFloodBlocks(final Block startBlock,
protected static Set<Block> getAirFloodBlocks(final Block startBlock,
Set<Block> foundBlocks,
final Set<BlockFace> expandFaces,
int limit) {
int limit)
{
if (foundBlocks == null) {
return null;
}
@ -184,8 +192,10 @@ public class FloodUtil {
}
if (startBlock.getType() == Material.AIR) {
// ... We found a block :D ...
foundBlocks.add(startBlock);
// ... And flood away !
for (BlockFace face : expandFaces) {
Block potentialBlock = startBlock.getRelative(face);
foundBlocks = getAirFloodBlocks(potentialBlock, foundBlocks, expandFaces, limit);

View File

@ -16,58 +16,37 @@
*/
package de.craftinc.gates.util;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.models.Gate;
import de.craftinc.gates.models.GateMaterial;
import de.craftinc.gates.Plugin;
import de.craftinc.gates.Gate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import java.util.ArrayList;
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
* immediately and after a short delay.
*
* @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 sendDelayed Set to 'true' if the block changes shall be send a second time after a one
* second delay.
*/
public static void updateGateBlocks(final Player player, final Location location, boolean sendDelayed) {
assert(player != null);
assert(location != null);
public static void updateGateBlocks(final Player player, final Location location, boolean sendDelayed)
{
if (player == 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());
@ -76,98 +55,102 @@ public class GateBlockChangeSender {
}
for (Gate g : gatesNearby) {
if (!g.isOpen()) {
if (!g.isOpen() || g.isHidden()) {
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) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Plugin.getPlugin(), new Runnable() {
Bukkit.getScheduler().scheduleSyncDelayedTask(Plugin.getPlugin(), new Runnable()
{
@Override
public void run() {
public void run()
{
updateGateBlocks(player, location, false);
}
}, 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);
}
/**
* 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'!");
}
public static void updateGateBlocks(final Gate gate) {
updateGateBlocks(player, player.getLocation(), false);
}
public static void updateGateBlocks(final Gate gate)
{
updateGateBlocks(gate, false);
}
/**
* Sends block changes to players near a given gate.
*
* @param gate Must not be 'null'!
* @param remove Set to true if all visible gate blocks shall be removed.
*/
public static void updateGateBlocks(final Gate gate, boolean remove) {
assert(gate != null);
public static void updateGateBlocks(final Gate gate, boolean remove)
{
if (gate == null) {
throw new IllegalArgumentException("'gate must not be 'null'!");
}
Location gateLocation = gate.getLocation();
if (gate.getGateBlockLocations().isEmpty()) {
return;
}
ArrayList<Player> playersNearby = new ArrayList<>();
int searchRadius = Plugin.getPlugin().getConfig().getInt(confPlayerGateBlockUpdateRadiusKey);
ArrayList<Player> playersNearby = new ArrayList<Player>();
int searchRadius = Plugin.getPlugin().getConfig().getInt(Plugin.confPlayerGateBlockUpdateRadiusKey);
for (Player p : Plugin.getPlugin().getServer().getOnlinePlayers()) {
if (p.getWorld() == gateLocation.getWorld() && p.getLocation().distance(gateLocation) < searchRadius) {
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;
if (isVisible) {
GateMaterial gm = gate.getMaterial();
data = gm.getData(gate.getDirection());
material = gm.getMaterial();
} else {
data = 0b0;
if (gate.isOpen() && !gate.isHidden() && !remove) {
material = Material.PORTAL;
}
else {
material = Material.AIR;
}
for (Player p : playersNearby) {
for (Location l : gate.getGateBlockLocations()) {
if (l.getBlock().getType() == Material.AIR) {
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

@ -14,24 +14,27 @@
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;
package de.craftinc.gates.util;
import org.bukkit.Chunk;
import org.bukkit.World;
public class SimpleChunk {
public class SimpleChunk
{
private int x;
private int z;
private String world;
public SimpleChunk(Chunk c) {
public SimpleChunk(Chunk c)
{
this.x = c.getX();
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.z = z;
this.world = w.getName();
@ -39,9 +42,10 @@ public class SimpleChunk {
@Override
public boolean equals(Object o) {
public boolean equals(Object o)
{
if (o instanceof SimpleChunk) {
SimpleChunk otherLocation = (SimpleChunk) o;
SimpleChunk otherLocation = (SimpleChunk)o;
if (otherLocation.x == this.x
&& otherLocation.z == this.z
@ -56,7 +60,8 @@ public class SimpleChunk {
@Override
public int hashCode() {
public int hashCode()
{
int hash = 11;
hash = 29 * hash + x;
hash = 37 * hash + z;
@ -67,7 +72,8 @@ public class SimpleChunk {
@Override
public String toString() {
public String toString()
{
return this.getClass().toString() + " (x=" + this.x + " z=" + this.z + " world='" + this.world + "')";
}
}

View File

@ -14,17 +14,20 @@
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;
package de.craftinc.gates.util;
import org.bukkit.Location;
public class SimpleLocation {
public class SimpleLocation
{
private String world;
private int x;
private int y;
private int z;
public SimpleLocation(Location l) {
public SimpleLocation(Location l)
{
this.world = l.getWorld().getName();
// Using Block coordinates makes it possible to compare block locations with player locations.
@ -34,7 +37,9 @@ public class SimpleLocation {
this.z = l.getBlockZ();
}
public SimpleLocation(Location l, boolean isHeadPosition) {
public SimpleLocation(Location l, boolean isHeadPosition)
{
this.world = l.getWorld().getName();
// Using Block coordinates makes it possible to compare block locations with player locations.
@ -48,15 +53,20 @@ public class SimpleLocation {
}
}
@Override
public String toString() {
public String toString()
{
return super.toString() + " x: " + x + " y: " + y + " z: " + z + " world: " + world;
}
@Override
public boolean equals(final Object o) {
public boolean equals(final Object o)
{
if (o instanceof SimpleLocation) {
SimpleLocation otherLocation = (SimpleLocation) o;
SimpleLocation otherLocation = (SimpleLocation)o;
if (otherLocation.x == this.x
&& otherLocation.y == this.y
@ -70,8 +80,10 @@ public class SimpleLocation {
return false;
}
@Override
public int hashCode() {
public int hashCode()
{
int hash = 13;
hash = 37 * hash + x;
hash = 31 * hash + y;

View File

@ -20,46 +20,46 @@ import org.bukkit.ChatColor;
import java.util.List;
public class TextUtil {
public static String titleSize(String str) {
String center = ".[ " + ChatColor.YELLOW + str + ChatColor.GOLD + " ].";
if (center.length() >= 60) {
return ChatColor.GOLD + center;
} else {
public class TextUtil
{
public static String titleize(String str)
{
String line = ChatColor.GOLD + repeat("_", 60);
String center = ".[ " + ChatColor.YELLOW + str + ChatColor.GOLD + " ].";
int pivot = line.length() / 2;
int eatLeft = center.length() / 2;
int eatRight = center.length() - eatLeft;
return line.substring(0, pivot - eatLeft) + center + line.substring(pivot + eatRight);
}
}
private static String repeat(String s, int times) {
public static String repeat(String s, int times)
{
if (times <= 0)
return "";
return s + repeat(s, times - 1);
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) {
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++) {
for (int i=1; i<list.size(); i++) {
ret += glue + list.get(i);
}
return ret;
}
}