Compare commits

...

49 Commits

Author SHA1 Message Date
af9142bb05 Adds missing known legacy config migrations
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2023-03-24 20:02:05 +01:00
116e816a18 Bumps Spigot version to 1.19.3
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2022-12-10 22:40:03 +01:00
e4539c3623 Changes version to 0.9.4.3-SNAPSHOT
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2022-11-26 17:00:04 +01:00
9ac3c11345 Adds missing distribution management
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-11-26 15:34:34 +01:00
13cdccfc1d Improves Jenkinsfile 2022-11-26 15:15:45 +01:00
31b3423246 Adds the knarcraft git repository
All checks were successful
EpicKnarvik97/Stargate/pipeline/head This commit looks good
2022-11-26 04:05:03 +01:00
a35c07dc9c Updates the JDK used for Jenkins
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-11-22 16:41:55 +01:00
5aed252181 Updates dependencies
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-11-14 00:45:31 +00:00
ef97da9177 Removes KnarLib.setPlugin call
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-11-07 22:27:53 +01:00
a26cc30092 Uses placeholder for plugin version 2022-11-07 10:07:16 +01:00
4fda4c3905 Makes sure to initialize KnarLib properly 2022-11-07 10:01:34 +01:00
2b23e6fc56 Uses KnarLib where possible 2022-11-07 09:57:32 +01:00
c09063c49e Updates README and version to 0.9.4.2
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-10-09 10:46:49 +02:00
b5e2565626 Fixes use of depreciated setWoodType and getWoodType 2022-10-09 10:44:30 +02:00
11d3dc7a92 Increases hitbox of bungee portals using END_PORTAL to fix server change not triggering
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-06-25 12:11:37 +02:00
1c87d803ff Adds a delayed teleport to really force the player respawn for end_portal Stargate 2022-06-25 11:53:52 +02:00
2076fda4d1 Fixes end portals completely hijacking BungeeCord teleportation 2022-06-25 10:54:19 +02:00
524130c4e0 Avoids some potential NullPointerExceptions related to dynmap integration
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-06-24 03:33:49 +02:00
ce5f3ef52f Avoids a NullPointerException if dynmap is present, but isn't loaded properly 2022-06-24 03:23:59 +02:00
cae34d395b Displays bungee markers properly
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-06-18 16:16:36 +02:00
643a48392b Adds Dynmap integration
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
This adds Dynmap integration for displaying Stargates in Dynmap
API version is changed back to 1.18 as 1.19 is still kind of new
Version is now 0.9.4.1
2022-06-18 16:05:05 +02:00
92c3eadf8f Updates Stargate for Spigot 1.19
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-06-17 12:40:15 +02:00
92f452df00 Adds LGPL version to the README
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-03-11 17:16:26 +01:00
6eb7649e0d Clarifies license to prevent any disputes 2022-03-11 17:10:10 +01:00
5c2cbaae58 Merge branch 'master' into dev
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
# Conflicts:
#	README.md
#	pom.xml
#	src/main/resources/plugin.yml
2022-02-17 20:17:11 +01:00
0c69dc8991 Adds the Japanese language file provided by spigot user furplag (0.9.3.7) 2022-02-17 20:08:24 +01:00
68bed24137 Merge branch 'master' of https://git.knarcraft.net/EpicKnarvik97/Stargate
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
 Conflicts:
	README.md
	pom.xml
	src/main/resources/plugin.yml
2022-02-15 18:27:25 +01:00
5c1f9036c2 Merge branch 'dev' of https://git.knarcraft.net/EpicKnarvik97/Stargate into dev
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
 Conflicts:
	README.md
	pom.xml
	src/main/resources/plugin.yml
2022-02-15 18:24:38 +01:00
8488c5abdb Fixes some after-merge problems 2022-02-15 18:21:42 +01:00
e3189e9ab2 Merge branch 'master' into dev
# Conflicts:
#	README.md
#	pom.xml
#	src/main/resources/plugin.yml
2022-02-15 18:16:53 +01:00
8c334ff5f0 Adds simplified chinese, courtesy of YKDZ 2022-02-15 18:15:22 +01:00
4dfce3d325 Updates README and version
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-02-09 18:37:04 +01:00
00462799b9 Fixes the default wait for player after teleport delay 2022-02-09 18:28:47 +01:00
9e78e32db4 Fixes some spacing 2022-02-09 17:20:28 +01:00
28bb6f2109 Improves the generation of the list of available chat colors 2022-02-09 17:19:51 +01:00
61b05bcce9 Improves some code 2022-02-09 16:47:37 +01:00
5f4a90aabb Gives all passengers the same exit velocity as the root vehicle 2022-02-09 16:23:45 +01:00
a481ccf017 Adds some debug messages and makes sure to listen to the vehicle teleport event result 2022-02-09 05:54:57 +01:00
28d84450fb Makes boats keep their boat type when teleported using the CraftBook fix
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-02-08 19:00:44 +01:00
99bceb9165 Updates some test dependencies 2022-02-08 18:44:44 +01:00
a521454020 Updates README and version to 0.9.3.4 2022-02-08 18:43:04 +01:00
6c32de59a8 Makes the delay to prevent client errors configurable 2022-02-08 18:31:26 +01:00
497551d889 Makes the CraftBook remove on eject fix optional 2022-02-08 18:10:02 +01:00
8643a44df6 Moves some code to TeleportHelper 2022-02-08 16:24:47 +01:00
e7b711efcf Makes sure to stop polling the block change thread once it's empty instead of continuing doing nothing 2022-02-07 22:51:09 +01:00
56d59f0d2a Makes sure to check player passengers from the root entity
Some checks failed
EpicKnarvik97/Stargate/pipeline/head There was a failure building this commit
2022-01-29 00:30:26 +01:00
248caee620 Fixes some minor formatting issues 2022-01-28 23:23:33 +01:00
7f08763624 Changes a lot of teleportation code to be able to teleport entities with passengers
Moves some teleportation code to the TeleportHelper class
Changes some teleportation method names
Tries to reduce some code duplication between teleporters
Recursively teleports entities to make sure the teleported entity will arrive in the same shape it entered as
Makes player checks for teleported vehicles account for any number of players riding any entity in the stack
2022-01-28 23:23:09 +01:00
95293204d5 Adds a new StargateTeleportEvent to combine some duplicated code 2022-01-28 22:58:02 +01:00
47 changed files with 1197 additions and 808 deletions

19
HEADER Normal file
View File

@ -0,0 +1,19 @@
Stargate - A portal plugin for Bukkit
Copyright (C) 2011 Shaun (sturmeh)
Copyright (C) 2011 Dinnerbone
Copyright (C) 2011-2013 Steven "Drakia" Scott <Contact@TheDgtl.net>
Copyright (C) 2015-2020 Michael Smith (PseudoKnight)
Copyright (C) 2021-2022 Kristian Knarvik (EpicKnarvik97)
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. If not, see <http://www.gnu.org/licenses/>.

10
Jenkinsfile vendored
View File

@ -1,7 +1,7 @@
pipeline { pipeline {
agent any agent any
tools { tools {
jdk 'JDK16' jdk 'JDK17'
} }
stages { stages {
stage('Build') { stage('Build') {
@ -16,10 +16,16 @@ pipeline {
sh 'mvn test' sh 'mvn test'
} }
} }
stage('Verify') {
steps {
echo 'Verifying...'
sh 'mvn verify -Dmaven.test.skip=true'
}
}
stage('Deploy') { stage('Deploy') {
steps { steps {
echo 'Deploying...' echo 'Deploying...'
sh 'mvn verify -Dmaven.test.skip=true' sh 'mvn deploy -Dmaven.install.skip=true -Dmaven.test.skip=true'
archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
} }
} }

View File

@ -7,7 +7,7 @@ can share a network or be split into clusters; they can be hidden on a network o
- **Vault economy support** -- can add costs for create, destroy and use. - **Vault economy support** -- can add costs for create, destroy and use.
- **Ability to create custom gate configurations**. Four different default gate configurations are available. - **Ability to create custom gate configurations**. Four different default gate configurations are available.
- **Message customization** - **Message customization**
- **Multiple built-in languages** (de, en, es, fr, hu, it, nb-no, nl, nn-no, pt-br, ru) - **Multiple built-in languages** (de, en, es, fr, hu, it, ja, nb-no, nl, nn-no, pt-br, ru, zh_cn)
- **Teleport across worlds or servers** (BungeeCord supported) - **Teleport across worlds or servers** (BungeeCord supported)
- **Vehicle teleportation** -- teleport minecarts, boats, horses, pigs and striders - **Vehicle teleportation** -- teleport minecarts, boats, horses, pigs and striders
- **Leashed teleportation** -- teleport any creature in a leash with the player - **Leashed teleportation** -- teleport any creature in a leash with the player
@ -26,6 +26,11 @@ This was originally TheDgtl's Bukkit port of the Stargate plugin for hMod by Din
of [PseudoKnight's fork](https://github.com/PseudoKnight/Stargate-Bukkit). This fork's main purpose is to create a clean of [PseudoKnight's fork](https://github.com/PseudoKnight/Stargate-Bukkit). This fork's main purpose is to create a clean
version of Stargate compliant with Spigot 1.17, even if it means changing the entire project's previous structure. version of Stargate compliant with Spigot 1.17, even if it means changing the entire project's previous structure.
## License
Stargate is licensed under the GNU Lesser General Public License Version 3.0. This includes every source and resource
file. See the HEADER file for a more detailed license description.
## Migration ## Migration
This plugin should be compatible with configurations from the Stargate plugin all the way back. The nethergate.gate This plugin should be compatible with configurations from the Stargate plugin all the way back. The nethergate.gate
@ -298,7 +303,7 @@ while the per-gate costs re defined in the .gate files. To define a certain cost
# Configuration # Configuration
``` ```
language - The language to use (Included languages: en, de, es, fr, hu, it, nb-no, nl, nn-no, pt-br, ru) language - The language to use (Included languages: en, de, es, fr, hu, it, ja, nb-no, nl, nn-no, pt-br, ru, zh_cn)
adminUpdateAlert - Whether to alert admins about an available update when joining the server adminUpdateAlert - Whether to alert admins about an available update when joining the server
folders: folders:
portalFolder - The folder your portal databases are saved in portalFolder - The folder your portal databases are saved in
@ -324,6 +329,7 @@ gates:
handleCreatureTransportation - Whether or not to handle players that transport creatures by sending vehicles (minecarts, boats) through gates. handleCreatureTransportation - Whether or not to handle players that transport creatures by sending vehicles (minecarts, boats) through gates.
handleNonPlayerVehicles - Whether or not to handle vehicles with a passenger which is not a player going through gates (pigs, horses, villagers, creepers, etc.). handleCreatureTransportation must be enabled. handleNonPlayerVehicles - Whether or not to handle vehicles with a passenger which is not a player going through gates (pigs, horses, villagers, creepers, etc.). handleCreatureTransportation must be enabled.
handleLeashedCreatures - Whether or not to handle creatures leashed by a player going through gates. Set to false to disallow leashed creatures going through gates. handleLeashedCreatures - Whether or not to handle creatures leashed by a player going through gates. Set to false to disallow leashed creatures going through gates.
enableCraftBookRemoveOnEjectFix - Whether to enable a fix that causes loss of NBT data, but allows vehicle teleportation to work when CraftBook's remove minecart/boat on eject setting is enabled
economy: economy:
useEconomy - Whether or not to enable Economy using Vault (must have the Vault plugin) useEconomy - Whether or not to enable Economy using Vault (must have the Vault plugin)
createCost - The cost to create a stargate createCost - The cost to create a stargate
@ -336,11 +342,13 @@ economy:
debugging: debugging:
debug - Whether to show massive debug output debug - Whether to show massive debug output
permissionDebug - Whether to show massive permission debug output permissionDebug - Whether to show massive permission debug output
advanced:
waitForPlayerAfterTeleportDelay - The amount of ticks to wait before adding a player as passenger of a vehicle. On slow servers, a value of 6 is required to avoid client glitches after teleporting on a vehicle.
``` ```
# Message Customization # Message Customization
It is possible to customize all the messages Stargate displays, including the [Stargate] prefix. You can find the It is possible to customize all the messages Stargate displays, including the \[Stargate] prefix. You can find the
strings in plugins/Stargate/lang/chosenLanguage.txt. strings in plugins/Stargate/lang/chosenLanguage.txt.
If a string is removed, or left blank, it will default to the default english string. There are some special cases If a string is removed, or left blank, it will default to the default english string. There are some special cases
@ -397,6 +405,45 @@ portalInfoServer=Server: %server%
# Changes # Changes
#### \[Version 0.9.4.2] EpicKnarvik97 fork
- Avoids a NullPointerException if Dynmap is present, but isn't properly loaded.
- Avoids some potential NullPointerExceptions related to Dynmap integration
- Fixes end portals hijacking BungeeCord teleportation
- Fixes a problem where a player might not be properly teleported from an end portal Stargate in the end to the
over-world.
#### \[Version 0.9.4.1] EpicKnarvik97 fork
- Reverts to Spigot API 1.18
- Adds Dynmap integration
#### \[Version 0.9.4.0] EpicKnarvik97 fork
- Updates Stargate to 1.19
#### \[Version 0.9.3.7] EpicKnarvik97 fork
- Adds the Japanese language file provided by spigot user furplag
#### \[Version 0.9.3.6] EpicKnarvik97 fork
- Adds the simplified Chinese language file provided by spigot user YKDZ
#### \[Version 0.9.3.5] EpicKnarvik97 fork
- Fixes the wait for player delay being too low by default
- Performs some minor code optimizations and restructuring
#### \[Version 0.9.3.4] EpicKnarvik97 fork
- Includes passengers of passengers when teleporting entities
- Fixes a bug which caused Stargate to use more CPU for no reason
- Teleports boats/minecarts like other vehicles unless *enableCraftBookRemoveOnEjectFix* is enabled
- Adds the *waitForPlayerAfterTeleportDelay* config option which allows changing the delay between vehicle teleportation
and the player being teleported to the vehicle
- Makes boats keep their wood type even when re-created
#### \[Version 0.9.3.3] EpicKnarvik97 fork #### \[Version 0.9.3.3] EpicKnarvik97 fork
- Prevents Zombified Piglins from randomly spawning at Stargates - Prevents Zombified Piglins from randomly spawning at Stargates

98
pom.xml
View File

@ -4,7 +4,7 @@
<groupId>net.knarcraft</groupId> <groupId>net.knarcraft</groupId>
<artifactId>Stargate</artifactId> <artifactId>Stargate</artifactId>
<version>0.9.3.3</version> <version>0.9.4.3-SNAPSHOT</version>
<licenses> <licenses>
<license> <license>
@ -15,70 +15,140 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source> <java.version>16</java.version>
<maven.compiler.target>17</maven.compiler.target>
</properties> </properties>
<repositories> <repositories>
<repository>
<id>knarcraft-repo</id>
<url>https://git.knarcraft.net/api/packages/EpicKnarvik97/maven</url>
</repository>
<repository> <repository>
<id>spigot-repo</id> <id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url> <url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository> </repository>
<repository> <repository>
<id>vault-repo</id> <id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url> <url>https://nexus.hc.to/content/repositories/pub_releases</url>
</repository>
<repository>
<id>dynmap</id>
<url>https://repo.mikeprimm.com/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository> </repository>
</repositories> </repositories>
<distributionManagement>
<repository>
<id>knarcraft-repo</id>
<url>https://git.knarcraft.net/api/packages/EpicKnarvik97/maven</url>
</repository>
<snapshotRepository>
<id>knarcraft-repo</id>
<url>https://git.knarcraft.net/api/packages/EpicKnarvik97/maven</url>
</snapshotRepository>
</distributionManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.18.1-R0.1-SNAPSHOT</version> <version>1.19.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.milkbowl.vault</groupId> <groupId>net.milkbowl.vault</groupId>
<artifactId>VaultAPI</artifactId> <artifactId>VaultAPI</artifactId>
<version>1.7</version> <version>1.7</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>
<version>5.8.0-M1</version> <version>5.9.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.seeseemelk</groupId> <groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit-v1.18</artifactId> <artifactId>MockBukkit-v1.18</artifactId>
<version>1.14.0</version> <version>2.85.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jetbrains</groupId> <groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId> <artifactId>annotations</artifactId>
<version>19.0.0</version> <version>23.0.0</version>
<scope>compile</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13.1</version> <version>4.13.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>us.dynmap</groupId>
<artifactId>dynmap-api</artifactId>
<version>3.1-beta-2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.knarcraft</groupId>
<artifactId>knarlib</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version> <version>3.8.1</version>
<configuration> <configuration>
<source>17</source> <source>${java.version}</source>
<target>17</target> <target>${java.version}</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>net.knarcraft:knarlib</artifact>
<includes>
<include>net/knarcraft/knarlib/**</include>
</includes>
</filter>
<filter>
<excludes>
<exclude>*.MF</exclude>
<exclude>*.yml</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build> </build>
</project> </project>

View File

@ -1,5 +1,6 @@
package net.knarcraft.stargate; package net.knarcraft.stargate;
import net.knarcraft.knarlib.util.UpdateChecker;
import net.knarcraft.stargate.command.CommandStarGate; import net.knarcraft.stargate.command.CommandStarGate;
import net.knarcraft.stargate.command.StarGateTabCompleter; import net.knarcraft.stargate.command.StarGateTabCompleter;
import net.knarcraft.stargate.config.EconomyConfig; import net.knarcraft.stargate.config.EconomyConfig;
@ -22,7 +23,6 @@ import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.thread.BlockChangeThread; import net.knarcraft.stargate.thread.BlockChangeThread;
import net.knarcraft.stargate.thread.ChunkUnloadThread; import net.knarcraft.stargate.thread.ChunkUnloadThread;
import net.knarcraft.stargate.thread.StarGateThread; import net.knarcraft.stargate.thread.StarGateThread;
import net.knarcraft.stargate.utility.UpdateChecker;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@ -39,24 +39,44 @@ import java.util.Queue;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/*
Stargate - A portal plugin for Bukkit
Copyright (C) 2011 Shaun (sturmeh)
Copyright (C) 2011 Dinnerbone
Copyright (C) 2011-2013 Steven "Drakia" Scott <Contact@TheDgtl.net>
Copyright (C) 2015-2020 Michael Smith (PseudoKnight)
Copyright (C) 2021-2022 Kristian Knarvik (EpicKnarvik97)
The following license notice applies to all source and resource files in the Stargate project:
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. If not, see <http://www.gnu.org/licenses/>.
*/
/** /**
* The main class of the Stargate plugin * The main class of the Stargate plugin
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class Stargate extends JavaPlugin { public class Stargate extends JavaPlugin {
//Used for changing gate open/closed material.
private static final Queue<BlockChangeRequest> blockChangeRequestQueue = new LinkedList<>(); private static final Queue<BlockChangeRequest> blockChangeRequestQueue = new LinkedList<>();
private static final Queue<ChunkUnloadRequest> chunkUnloadQueue = new PriorityQueue<>(); private static final Queue<ChunkUnloadRequest> chunkUnloadQueue = new PriorityQueue<>();
private static Logger logger; private static Logger logger;
private static Stargate stargate; private static Stargate stargate;
private static String pluginVersion; private static String pluginVersion;
private static PluginManager pluginManager; private static PluginManager pluginManager;
private static StargateConfig stargateConfig; private static StargateConfig stargateConfig;
private static String updateAvailable = null; private static String updateAvailable = null;
/** /**
@ -279,24 +299,6 @@ public class Stargate extends JavaPlugin {
return stargateConfig.getLanguageLoader().getBackupString(name); return stargateConfig.getLanguageLoader().getBackupString(name);
} }
/**
* Replaces a list of variables in a string in the order they are given
*
* @param input <p>The input containing the variables</p>
* @param search <p>The variables to replace</p>
* @param values <p>The replacement values</p>
* @return <p>The input string with the search values replaced with the given values</p>
*/
public static String replaceVars(String input, String[] search, String[] values) {
if (search.length != values.length) {
throw new IllegalArgumentException("The number of search values and replace values do not match.");
}
for (int i = 0; i < search.length; i++) {
input = replaceVars(input, search[i], values[i]);
}
return input;
}
/** /**
* Replaces a variable in a string * Replaces a variable in a string
* *
@ -363,7 +365,8 @@ public class Stargate extends JavaPlugin {
this.registerCommands(); this.registerCommands();
//Check for any available updates //Check for any available updates
UpdateChecker.checkForUpdate(); UpdateChecker.checkForUpdate(this, "https://api.spigotmc.org/legacy/update.php?resource=97784",
Stargate::getPluginVersion, Stargate::setUpdateAvailable);
} }
/** /**
@ -430,4 +433,5 @@ public class Stargate extends JavaPlugin {
public static StargateConfig getStargateConfig() { public static StargateConfig getStargateConfig() {
return stargateConfig; return stargateConfig;
} }
} }

View File

@ -23,8 +23,9 @@ public class CommandAbout implements CommandExecutor {
commandSender.sendMessage(textColor + "Go to " + highlightColor + commandSender.sendMessage(textColor + "Go to " + highlightColor +
"https://git.knarcraft.net/EpicKnarvik97/Stargate " + textColor + "for the official repository"); "https://git.knarcraft.net/EpicKnarvik97/Stargate " + textColor + "for the official repository");
String author = Stargate.getStargateConfig().getLanguageLoader().getString("author"); String author = Stargate.getStargateConfig().getLanguageLoader().getString("author");
if (!author.isEmpty()) if (!author.isEmpty()) {
commandSender.sendMessage(textColor + "Language created by " + highlightColor + author); commandSender.sendMessage(textColor + "Language created by " + highlightColor + author);
}
return true; return true;
} }

View File

@ -3,12 +3,12 @@ package net.knarcraft.stargate.command;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.ConfigOption; import net.knarcraft.stargate.config.ConfigOption;
import net.knarcraft.stargate.config.ConfigTag; import net.knarcraft.stargate.config.ConfigTag;
import net.knarcraft.stargate.config.DynmapManager;
import net.knarcraft.stargate.config.OptionDataType; import net.knarcraft.stargate.config.OptionDataType;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.portal.PortalSignDrawer; import net.knarcraft.stargate.portal.PortalSignDrawer;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -378,6 +378,10 @@ public class CommandConfig implements CommandExecutor {
//Load or unload Vault and Economy as necessary //Load or unload Vault and Economy as necessary
Stargate.getStargateConfig().reloadEconomy(); Stargate.getStargateConfig().reloadEconomy();
} }
if (ConfigTag.requiresDynmapReload(configOption)) {
//Regenerate all Dynmap markers
DynmapManager.addAllPortalMarkers();
}
} }
} }
@ -416,7 +420,7 @@ public class CommandConfig implements CommandExecutor {
Object defaultValue = option.getDefaultValue(); Object defaultValue = option.getDefaultValue();
String stringValue = String.valueOf(defaultValue); String stringValue = String.valueOf(defaultValue);
if (option.getDataType() == OptionDataType.STRING_LIST) { if (option.getDataType() == OptionDataType.STRING_LIST) {
stringValue = "[" + StringUtils.join((String[]) defaultValue, ",") + "]"; stringValue = "[" + String.join(",", (String[]) defaultValue) + "]";
} }
return ChatColor.GOLD + option.getName() + ChatColor.WHITE + " - " + ChatColor.GREEN + option.getDescription() + return ChatColor.GOLD + option.getName() + ChatColor.WHITE + " - " + ChatColor.GREEN + option.getDescription() +
ChatColor.DARK_GRAY + " (Default: " + ChatColor.GRAY + stringValue + ChatColor.DARK_GRAY + ")"; ChatColor.DARK_GRAY + " (Default: " + ChatColor.GRAY + stringValue + ChatColor.DARK_GRAY + ")";

View File

@ -2,12 +2,13 @@ package net.knarcraft.stargate.command;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/** /**
* This command represents any command which starts with stargate * This command represents any command which starts with stargate
* *
@ -25,7 +26,7 @@ public class CommandStarGate implements CommandExecutor {
} else if (args[0].equalsIgnoreCase("reload")) { } else if (args[0].equalsIgnoreCase("reload")) {
return new CommandReload().onCommand(commandSender, command, s, args); return new CommandReload().onCommand(commandSender, command, s, args);
} else if (args[0].equalsIgnoreCase("config")) { } else if (args[0].equalsIgnoreCase("config")) {
String[] subArgs = (String[]) ArrayUtils.remove(args, 0); String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
return new CommandConfig().onCommand(commandSender, command, s, subArgs); return new CommandConfig().onCommand(commandSender, command, s, subArgs);
} }
return false; return false;
@ -35,4 +36,5 @@ public class CommandStarGate implements CommandExecutor {
return true; return true;
} }
} }
} }

View File

@ -14,6 +14,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingStartsWith;
/** /**
* This is the completer for stargates config sub-command (/sg config) * This is the completer for stargates config sub-command (/sg config)
*/ */
@ -48,27 +50,10 @@ public class ConfigTabCompleter implements TabCompleter {
for (ConfigOption option : ConfigOption.values()) { for (ConfigOption option : ConfigOption.values()) {
configOptionNames.add(option.getName()); configOptionNames.add(option.getName());
} }
return filterMatching(configOptionNames, args[0]); return filterMatchingStartsWith(configOptionNames, args[0]);
} }
} }
/**
* Find completable strings which match the text typed by the command's sender
*
* @param values <p>The values to filter</p>
* @param typedText <p>The text the player has started typing</p>
* @return <p>The given string values which start with the player's typed text</p>
*/
private List<String> filterMatching(List<String> values, String typedText) {
List<String> configValues = new ArrayList<>();
for (String value : values) {
if (value.toLowerCase().startsWith(typedText.toLowerCase())) {
configValues.add(value);
}
}
return configValues;
}
/** /**
* Get possible values for the selected option * Get possible values for the selected option
* *
@ -80,7 +65,7 @@ public class ConfigTabCompleter implements TabCompleter {
switch (selectedOption) { switch (selectedOption) {
case LANGUAGE: case LANGUAGE:
//Return available languages //Return available languages
return filterMatching(languages, typedText); return filterMatchingStartsWith(languages, typedText);
case GATE_FOLDER: case GATE_FOLDER:
case PORTAL_FOLDER: case PORTAL_FOLDER:
case DEFAULT_GATE_NETWORK: case DEFAULT_GATE_NETWORK:
@ -94,12 +79,12 @@ public class ConfigTabCompleter implements TabCompleter {
case HIGHLIGHT_SIGN_COLOR: case HIGHLIGHT_SIGN_COLOR:
case FREE_GATES_COLOR: case FREE_GATES_COLOR:
//Return all colors //Return all colors
return filterMatching(chatColors, typedText); return filterMatchingStartsWith(chatColors, typedText);
} }
//If the config value is a boolean, show the two boolean values //If the config value is a boolean, show the two boolean values
if (selectedOption.getDataType() == OptionDataType.BOOLEAN) { if (selectedOption.getDataType() == OptionDataType.BOOLEAN) {
return filterMatching(booleans, typedText); return filterMatchingStartsWith(booleans, typedText);
} }
//If the config value is an integer, display some valid numbers //If the config value is an integer, display some valid numbers
@ -145,11 +130,11 @@ public class ConfigTabCompleter implements TabCompleter {
*/ */
private List<String> getPerSignColorCompletion(String[] args) { private List<String> getPerSignColorCompletion(String[] args) {
if (args.length < 3) { if (args.length < 3) {
return filterMatching(signTypes, args[1]); return filterMatchingStartsWith(signTypes, args[1]);
} else if (args.length < 4) { } else if (args.length < 4) {
return filterMatching(extendedColors, args[2]); return filterMatchingStartsWith(extendedColors, args[2]);
} else if (args.length < 5) { } else if (args.length < 5) {
return filterMatching(extendedColors, args[3]); return filterMatchingStartsWith(extendedColors, args[3]);
} }
return new ArrayList<>(); return new ArrayList<>();
} }
@ -217,22 +202,10 @@ public class ConfigTabCompleter implements TabCompleter {
*/ */
private List<ChatColor> getChatColors() { private List<ChatColor> getChatColors() {
List<ChatColor> chatColors = new ArrayList<>(); List<ChatColor> chatColors = new ArrayList<>();
chatColors.add(ChatColor.WHITE); char[] colors = new char[]{'a', 'b', 'c', 'd', 'e', 'f', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
chatColors.add(ChatColor.BLUE); for (char color : colors) {
chatColors.add(ChatColor.DARK_BLUE); chatColors.add(ChatColor.getByChar(color));
chatColors.add(ChatColor.DARK_PURPLE); }
chatColors.add(ChatColor.LIGHT_PURPLE);
chatColors.add(ChatColor.GOLD);
chatColors.add(ChatColor.GREEN);
chatColors.add(ChatColor.BLACK);
chatColors.add(ChatColor.DARK_GREEN);
chatColors.add(ChatColor.DARK_RED);
chatColors.add(ChatColor.RED);
chatColors.add(ChatColor.AQUA);
chatColors.add(ChatColor.DARK_AQUA);
chatColors.add(ChatColor.DARK_GRAY);
chatColors.add(ChatColor.GRAY);
chatColors.add(ChatColor.YELLOW);
chatColors.add(ChatColor.of("#ed76d9")); chatColors.add(ChatColor.of("#ed76d9"));
chatColors.add(ChatColor.of("#ffecb7")); chatColors.add(ChatColor.of("#ffecb7"));
return chatColors; return chatColors;
@ -249,11 +222,13 @@ public class ConfigTabCompleter implements TabCompleter {
languages.add("fr"); languages.add("fr");
languages.add("hu"); languages.add("hu");
languages.add("it"); languages.add("it");
languages.add("ja");
languages.add("nb-no"); languages.add("nb-no");
languages.add("nl"); languages.add("nl");
languages.add("nn-no"); languages.add("nn-no");
languages.add("pt-br"); languages.add("pt-br");
languages.add("ru"); languages.add("ru");
languages.add("zh_cn");
//TODO: Generate this list dynamically by listing the language files in the jar and adding the user's custom //TODO: Generate this list dynamically by listing the language files in the jar and adding the user's custom
// language files // language files
} }

View File

@ -1,6 +1,5 @@
package net.knarcraft.stargate.command; package net.knarcraft.stargate.command;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter; import org.bukkit.command.TabCompleter;
@ -9,6 +8,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -29,7 +29,7 @@ public class StarGateTabCompleter implements TabCompleter {
} }
return matchingCommands; return matchingCommands;
} else if (args.length > 1 && args[0].equalsIgnoreCase("config")) { } else if (args.length > 1 && args[0].equalsIgnoreCase("config")) {
String[] subArgs = (String[]) ArrayUtils.remove(args, 0); String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
return new ConfigTabCompleter().onTabComplete(commandSender, command, s, subArgs); return new ConfigTabCompleter().onTabComplete(commandSender, command, s, subArgs);
} else { } else {
return new ArrayList<>(); return new ArrayList<>();

View File

@ -50,6 +50,9 @@ public enum ConfigOption {
*/ */
HIGHLIGHT_SIGN_COLOR("gates.cosmetic.highlightSignColor", "The text color used for highlighting stargate signs", "WHITE"), HIGHLIGHT_SIGN_COLOR("gates.cosmetic.highlightSignColor", "The text color used for highlighting stargate signs", "WHITE"),
/**
* The colors to use for each type of sign
*/
PER_SIGN_COLORS("gates.cosmetic.perSignColors", "The per-sign color specification", new String[]{ PER_SIGN_COLORS("gates.cosmetic.perSignColors", "The per-sign color specification", new String[]{
"'ACACIA:default,default'", "'BIRCH:default,default'", "'CRIMSON:inverted,inverted'", "'DARK_OAK:inverted,inverted'", "'ACACIA:default,default'", "'BIRCH:default,default'", "'CRIMSON:inverted,inverted'", "'DARK_OAK:inverted,inverted'",
"'JUNGLE:default,default'", "'OAK:default,default'", "'SPRUCE:inverted,inverted'", "'WARPED:inverted,inverted'"}), "'JUNGLE:default,default'", "'OAK:default,default'", "'SPRUCE:inverted,inverted'", "'WARPED:inverted,inverted'"}),
@ -102,6 +105,20 @@ public enum ConfigOption {
HANDLE_LEASHED_CREATURES("gates.functionality.handleLeashedCreatures", HANDLE_LEASHED_CREATURES("gates.functionality.handleLeashedCreatures",
"Whether to enable players to teleport a creature on a leash", true), "Whether to enable players to teleport a creature on a leash", true),
/**
* Whether to enable a fix that makes teleportation of minecarts/boats work even with craftbook's vehicle removal
*/
ENABLE_CRAFT_BOOK_REMOVE_ON_EJECT_FIX("gates.functionality.enableCraftBookRemoveOnEjectFix",
"Whether to enable a fix that causes loss of NBT data, but allows vehicle teleportation to work " +
"when CraftBook's remove minecart/boat on eject setting is enabled", false),
/**
* The delay between teleporting a vehicle and adding the player as passenger
*/
WAIT_FOR_PLAYER_AFTER_TELEPORT_DELAY("advanced.waitForPlayerAfterTeleportDelay",
"The amount of ticks to wait before adding a player as passenger of a vehicle. On slow servers, " +
"a value of 6 is required to avoid client glitches after teleporting on a vehicle.", 6),
/** /**
* Whether to enable economy support for taking payment from players creating/destroying/using stargates * Whether to enable economy support for taking payment from players creating/destroying/using stargates
*/ */
@ -161,7 +178,18 @@ public enum ConfigOption {
/** /**
* The velocity of players exiting a stargate, relative to the entry velocity * The velocity of players exiting a stargate, relative to the entry velocity
*/ */
EXIT_VELOCITY("gates.exitVelocity", "The velocity of players exiting stargates, relative to the entry velocity", 0.1D); EXIT_VELOCITY("gates.exitVelocity", "The velocity of players exiting stargates, relative to the entry velocity", 0.1D),
/**
* Whether to enable showing Stargates in Dynmap
*/
ENABLE_DYNMAP("dynmap.enableDynmap", "Whether to display Stargates in Dynmap's map", true),
/**
* Whether to hide Dynmap icons by default
*/
DYNMAP_ICONS_DEFAULT_HIDDEN("dynmap.dynmapIconsHiddenByDefault",
"Whether to hide Stargate's Dynmap icons by default, requiring the user to enable them.", true);
private final String configNode; private final String configNode;
private final String description; private final String description;

View File

@ -9,7 +9,8 @@ public enum ConfigTag {
COLOR(new ConfigOption[]{ConfigOption.FREE_GATES_COLOR, ConfigOption.MAIN_SIGN_COLOR, COLOR(new ConfigOption[]{ConfigOption.FREE_GATES_COLOR, ConfigOption.MAIN_SIGN_COLOR,
ConfigOption.HIGHLIGHT_SIGN_COLOR, ConfigOption.PER_SIGN_COLORS}), ConfigOption.HIGHLIGHT_SIGN_COLOR, ConfigOption.PER_SIGN_COLORS}),
FOLDER(new ConfigOption[]{ConfigOption.GATE_FOLDER, ConfigOption.PORTAL_FOLDER}); FOLDER(new ConfigOption[]{ConfigOption.GATE_FOLDER, ConfigOption.PORTAL_FOLDER}),
DYNMAP(new ConfigOption[]{ConfigOption.ENABLE_DYNMAP, ConfigOption.DYNMAP_ICONS_DEFAULT_HIDDEN});
private final ConfigOption[] taggedOptions; private final ConfigOption[] taggedOptions;
@ -52,6 +53,16 @@ public enum ConfigTag {
return FOLDER.isTagged(option); return FOLDER.isTagged(option);
} }
/**
* Checks whether a given config option requires a re-load of all Dynmap markers
*
* @param configOption <p>The config option to check</p>
* @return <p>True if changing the config option requires a reload of all dynmap markers</p>
*/
public static boolean requiresDynmapReload(ConfigOption configOption) {
return DYNMAP.isTagged(configOption);
}
/** /**
* Checks whether a given config option requires a portal reload to take effect * Checks whether a given config option requires a portal reload to take effect
* *

View File

@ -0,0 +1,134 @@
package net.knarcraft.stargate.config;
import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalRegistry;
import org.bukkit.Location;
import org.bukkit.World;
import org.dynmap.DynmapAPI;
import org.dynmap.markers.GenericMarker;
import org.dynmap.markers.Marker;
import org.dynmap.markers.MarkerIcon;
import org.dynmap.markers.MarkerSet;
/**
* A manager for dealing with everything Dynmap
*/
public final class DynmapManager {
private static MarkerSet markerSet;
private static MarkerIcon portalIcon;
private DynmapManager() {
}
/**
* Initializes the dynmap manager
*
* @param dynmapAPI <p>A reference</p>
*/
public static void initialize(DynmapAPI dynmapAPI) {
if (dynmapAPI == null || dynmapAPI.getMarkerAPI() == null) {
markerSet = null;
portalIcon = null;
} else {
markerSet = dynmapAPI.getMarkerAPI().createMarkerSet("stargate", "Stargate", null, false);
if (markerSet != null) {
markerSet.setHideByDefault(Stargate.getStargateConfig().hideDynmapIcons());
}
portalIcon = dynmapAPI.getMarkerAPI().getMarkerIcon("portal");
}
}
/**
* Adds all portal markers for all current portals
*/
public static void addAllPortalMarkers() {
if (markerSet == null || Stargate.getStargateConfig().isDynmapDisabled()) {
//Remove any existing markers if dynmap has been disabled after startup
if (markerSet != null) {
markerSet.getMarkers().forEach(GenericMarker::deleteMarker);
}
return;
}
markerSet.setHideByDefault(Stargate.getStargateConfig().hideDynmapIcons());
//Remove all existing markers for a clean start
markerSet.getMarkers().forEach(GenericMarker::deleteMarker);
for (Portal portal : PortalRegistry.getAllPortals()) {
addPortalMarker(portal);
}
}
/**
* Adds a portal marker for the given portal
*
* @param portal <p>The portal to add a marker for</p>
*/
public static void addPortalMarker(Portal portal) {
if (markerSet == null || Stargate.getStargateConfig().isDynmapDisabled()) {
return;
}
World world = portal.getWorld();
if (portal.getOptions().isHidden() || world == null) {
return;
}
Location location = portal.getBlockAt(portal.getGate().getLayout().getExit());
Marker marker = markerSet.createMarker(getPortalMarkerId(portal), portal.getName(), world.getName(),
location.getX(), location.getY(), location.getZ(), portalIcon, false);
if (marker == null) {
Stargate.logWarning(String.format(
"""
Unable to create marker for portal
Portal marker id: %s
Portal name: %s
Portal world: %s
Portal location: %s,%s,%s""",
getPortalMarkerId(portal), portal.getName(), world.getName(), location.getX(), location.getY(),
location.getZ()));
return;
}
String networkPrompt;
if (portal.getOptions().isBungee()) {
networkPrompt = "Server";
} else {
networkPrompt = "Network";
}
String markerDescription = String.format("<b>Name:</b> %s<br /><b>%s:</b> %s<br /><b>Destination:</b> " +
"%s<br /><b>Owner:</b> %s<br />", portal.getName(), networkPrompt, portal.getNetwork(),
portal.getDestinationName(), portal.getOwner().getName());
marker.setDescription(markerDescription);
marker.setLabel(portal.getName(), true);
if (portalIcon != null) {
marker.setMarkerIcon(portalIcon);
}
}
/**
* Removes the portal marker for the given portal
*
* @param portal <p>The portal to remove the marker for</p>
*/
public static void removePortalMarker(Portal portal) {
if (markerSet == null || Stargate.getStargateConfig().isDynmapDisabled()) {
return;
}
Marker marker = markerSet.findMarker(getPortalMarkerId(portal));
if (marker != null) {
marker.deleteMarker();
}
}
/**
* Gets the id used for the given portal's marker
*
* @param portal <p>The portal to get a marker id for</p>
* @return <p></p>
*/
private static String getPortalMarkerId(Portal portal) {
return portal.getNetwork() + "-:-" + portal.getName();
}
}

View File

@ -1,7 +1,8 @@
package net.knarcraft.stargate.config; package net.knarcraft.stargate.config;
import net.knarcraft.knarlib.property.ColorConversion;
import net.knarcraft.knarlib.util.FileHelper;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.utility.FileHelper;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -136,7 +137,8 @@ public final class LanguageLoader {
String> currentLanguageValues) throws IOException { String> currentLanguageValues) throws IOException {
//Get language values //Get language values
BufferedReader bufferedReader = FileHelper.getBufferedReaderFromInputStream(inputStream); BufferedReader bufferedReader = FileHelper.getBufferedReaderFromInputStream(inputStream);
Map<String, String> internalLanguageValues = FileHelper.readKeyValuePairs(bufferedReader); Map<String, String> internalLanguageValues = FileHelper.readKeyValuePairs(bufferedReader, "=",
ColorConversion.NORMAL);
//If currentLanguageValues is null; the chosen language has not been used before //If currentLanguageValues is null; the chosen language has not been used before
if (currentLanguageValues == null) { if (currentLanguageValues == null) {
@ -221,7 +223,7 @@ public final class LanguageLoader {
} else { } else {
bufferedReader = FileHelper.getBufferedReaderFromInputStream(inputStream); bufferedReader = FileHelper.getBufferedReaderFromInputStream(inputStream);
} }
strings = FileHelper.readKeyValuePairs(bufferedReader); strings = FileHelper.readKeyValuePairs(bufferedReader, "=", ColorConversion.NORMAL);
} catch (Exception e) { } catch (Exception e) {
if (Stargate.getStargateConfig().isDebuggingEnabled()) { if (Stargate.getStargateConfig().isDebuggingEnabled()) {
Stargate.getConsoleLogger().info("[Stargate] Unable to load language " + lang); Stargate.getConsoleLogger().info("[Stargate] Unable to load language " + lang);

View File

@ -1,5 +1,7 @@
package net.knarcraft.stargate.config; package net.knarcraft.stargate.config;
import net.knarcraft.knarlib.property.ColorConversion;
import net.knarcraft.knarlib.util.FileHelper;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.BlockChangeRequest; import net.knarcraft.stargate.container.BlockChangeRequest;
import net.knarcraft.stargate.listener.BungeeCordListener; import net.knarcraft.stargate.listener.BungeeCordListener;
@ -8,13 +10,13 @@ import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.PortalRegistry; import net.knarcraft.stargate.portal.PortalRegistry;
import net.knarcraft.stargate.portal.property.gate.GateHandler; import net.knarcraft.stargate.portal.property.gate.GateHandler;
import net.knarcraft.stargate.thread.BlockChangeThread; import net.knarcraft.stargate.thread.BlockChangeThread;
import net.knarcraft.stargate.utility.FileHelper;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.messaging.Messenger; import org.bukkit.plugin.messaging.Messenger;
import org.dynmap.DynmapAPI;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -101,6 +103,11 @@ public final class StargateConfig {
//Set up vault economy if vault has been loaded //Set up vault economy if vault has been loaded
setupVaultEconomy(); setupVaultEconomy();
DynmapAPI dynmapAPI = (DynmapAPI) Bukkit.getPluginManager().getPlugin("dynmap");
if (dynmapAPI != null) {
DynmapManager.initialize(dynmapAPI);
DynmapManager.addAllPortalMarkers();
}
} }
/** /**
@ -152,6 +159,24 @@ public final class StargateConfig {
return (boolean) configOptions.get(ConfigOption.PERMISSION_DEBUG); return (boolean) configOptions.get(ConfigOption.PERMISSION_DEBUG);
} }
/**
* Gets whether Dynmap integration is disabled
*
* @return <p>Whether Dynmap integration is disabled</p>
*/
public boolean isDynmapDisabled() {
return !((boolean) configOptions.get(ConfigOption.ENABLE_DYNMAP));
}
/**
* Gets whether Dynmap icons should be hidden by default
*
* @return <p>Whether Dynmap icons should be hidden by default</p>
*/
public boolean hideDynmapIcons() {
return (boolean) configOptions.get(ConfigOption.DYNMAP_ICONS_DEFAULT_HIDDEN);
}
/** /**
* Gets the object containing economy config values * Gets the object containing economy config values
* *
@ -189,6 +214,9 @@ public final class StargateConfig {
startStopBungeeListener(stargateGateConfig.enableBungee()); startStopBungeeListener(stargateGateConfig.enableBungee());
} }
//Reload portal markers
DynmapManager.addAllPortalMarkers();
messageSender.sendErrorMessage(sender, languageLoader.getString("reloaded")); messageSender.sendErrorMessage(sender, languageLoader.getString("reloaded"));
} }
@ -421,7 +449,8 @@ public final class StargateConfig {
Map<String, String> migrationFields; Map<String, String> migrationFields;
try { try {
migrationFields = FileHelper.readKeyValuePairs(FileHelper.getBufferedReaderFromInputStream( migrationFields = FileHelper.readKeyValuePairs(FileHelper.getBufferedReaderFromInputStream(
FileHelper.getInputStreamForInternalFile("/config-migrations.txt"))); FileHelper.getInputStreamForInternalFile("/config-migrations.txt")), "=",
ColorConversion.NORMAL);
} catch (IOException e) { } catch (IOException e) {
Stargate.debug("Stargate::migrateConfig", "Unable to load config migration file"); Stargate.debug("Stargate::migrateConfig", "Unable to load config migration file");
e.printStackTrace(); e.printStackTrace();
@ -520,4 +549,5 @@ public final class StargateConfig {
public LanguageLoader getLanguageLoader() { public LanguageLoader getLanguageLoader() {
return languageLoader; return languageLoader;
} }
} }

View File

@ -1,8 +1,8 @@
package net.knarcraft.stargate.config; package net.knarcraft.stargate.config;
import net.knarcraft.knarlib.util.ColorHelper;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.PortalSignDrawer; import net.knarcraft.stargate.portal.PortalSignDrawer;
import net.knarcraft.stargate.utility.ColorHelper;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.Material; import org.bukkit.Material;
@ -16,6 +16,7 @@ import java.util.Map;
* The Stargate gate config keeps track of all global config values related to gates * The Stargate gate config keeps track of all global config values related to gates
*/ */
public final class StargateGateConfig { public final class StargateGateConfig {
private static final int activeTime = 10; private static final int activeTime = 10;
private static final int openTime = 10; private static final int openTime = 10;
private final Map<ConfigOption, Object> configOptions; private final Map<ConfigOption, Object> configOptions;
@ -125,6 +126,29 @@ public final class StargateGateConfig {
return (boolean) configOptions.get(ConfigOption.HANDLE_LEASHED_CREATURES); return (boolean) configOptions.get(ConfigOption.HANDLE_LEASHED_CREATURES);
} }
/**
* Gets whether the CraftBook vehicle removal fix is enabled
*
* <p>If enabled, minecarts and boats should be re-created instead of teleported.</p>
*
* @return <p>True if the CraftBook vehicle removal fix is enabled</p>
*/
public boolean enableCraftBookRemoveOnEjectFix() {
return (boolean) configOptions.get(ConfigOption.ENABLE_CRAFT_BOOK_REMOVE_ON_EJECT_FIX);
}
/**
* Gets the delay to use before adding a player as passenger of a teleported vehicle
*
* @return <p>The delay to use before adding a player as passenger of a teleported vehicle</p>
*/
public int waitForPlayerAfterTeleportDelay() {
if ((int) configOptions.get(ConfigOption.WAIT_FOR_PLAYER_AFTER_TELEPORT_DELAY) < 2) {
configOptions.put(ConfigOption.WAIT_FOR_PLAYER_AFTER_TELEPORT_DELAY, 6);
}
return (int) configOptions.get(ConfigOption.WAIT_FOR_PLAYER_AFTER_TELEPORT_DELAY);
}
/** /**
* Gets whether the list of destinations within a network should be sorted * Gets whether the list of destinations within a network should be sorted
* *
@ -262,8 +286,8 @@ public final class StargateGateConfig {
if (colors[colorIndex].equalsIgnoreCase("inverted")) { if (colors[colorIndex].equalsIgnoreCase("inverted")) {
//Convert from ChatColor to awt.Color to Bukkit.Color then invert and convert to ChatColor //Convert from ChatColor to awt.Color to Bukkit.Color then invert and convert to ChatColor
java.awt.Color color = defaultColors[colorIndex].getColor(); java.awt.Color color = defaultColors[colorIndex].getColor();
parsedColor = ColorHelper.fromColor(ColorHelper.invert(Color.fromRGB(color.getRed(), parsedColor = ColorHelper.fromColor(ColorHelper.invert(Color.fromRGB(color.getRed(), color.getGreen(),
color.getGreen(), color.getBlue()))); color.getBlue())));
} else { } else {
try { try {
parsedColor = ChatColor.of(colors[colorIndex]); parsedColor = ChatColor.of(colors[colorIndex]);
@ -300,4 +324,5 @@ public final class StargateGateConfig {
PortalSignDrawer.setHighlightColor(ChatColor.WHITE); PortalSignDrawer.setHighlightColor(ChatColor.WHITE);
} }
} }
} }

View File

@ -58,16 +58,11 @@ public class RelativeBlockVector {
* @return <p>A new relative block vector with the property altered</p> * @return <p>A new relative block vector with the property altered</p>
*/ */
public RelativeBlockVector addToVector(Property propertyToAddTo, int valueToAdd) { public RelativeBlockVector addToVector(Property propertyToAddTo, int valueToAdd) {
switch (propertyToAddTo) { return switch (propertyToAddTo) {
case RIGHT: case RIGHT -> new RelativeBlockVector(this.right + valueToAdd, this.down, this.out);
return new RelativeBlockVector(this.right + valueToAdd, this.down, this.out); case DOWN -> new RelativeBlockVector(this.right, this.down + valueToAdd, this.out);
case DOWN: case OUT -> new RelativeBlockVector(this.right, this.down, this.out + valueToAdd);
return new RelativeBlockVector(this.right, this.down + valueToAdd, this.out); };
case OUT:
return new RelativeBlockVector(this.right, this.down, this.out + valueToAdd);
default:
throw new IllegalArgumentException("Invalid relative block vector property given");
}
} }
/** /**

View File

@ -1,6 +1,6 @@
package net.knarcraft.stargate.container; package net.knarcraft.stargate.container;
import net.knarcraft.stargate.utility.ColorHelper; import net.knarcraft.knarlib.util.ColorHelper;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;

View File

@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
* <p>This event can be used to overwrite the location the entity is teleported to.</p> * <p>This event can be used to overwrite the location the entity is teleported to.</p>
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class StargateEntityPortalEvent extends StargateEvent { public class StargateEntityPortalEvent extends StargateEvent implements StargateTeleportEvent {
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
final Entity travellingEntity; final Entity travellingEntity;
@ -58,6 +58,7 @@ public class StargateEntityPortalEvent extends StargateEvent {
* *
* @return <p>Location of the exit point</p> * @return <p>Location of the exit point</p>
*/ */
@Override
public Location getExit() { public Location getExit() {
return exit; return exit;
} }

View File

@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
* <p>This event can be used to overwrite the location the player is teleported to.</p> * <p>This event can be used to overwrite the location the player is teleported to.</p>
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class StargatePlayerPortalEvent extends StargatePlayerEvent { public class StargatePlayerPortalEvent extends StargatePlayerEvent implements StargateTeleportEvent {
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
private final Portal destination; private final Portal destination;
@ -47,6 +47,7 @@ public class StargatePlayerPortalEvent extends StargatePlayerEvent {
* *
* @return <p>Location of the exit point</p> * @return <p>Location of the exit point</p>
*/ */
@Override
public Location getExit() { public Location getExit() {
return exit; return exit;
} }

View File

@ -0,0 +1,18 @@
package net.knarcraft.stargate.event;
import org.bukkit.Location;
import org.bukkit.event.Cancellable;
/**
* A generic teleportation event
*/
public interface StargateTeleportEvent extends Cancellable {
/**
* Return the location of the players exit point
*
* @return <p>Location of the exit point</p>
*/
Location getExit();
}

View File

@ -1,5 +1,6 @@
package net.knarcraft.stargate.listener; package net.knarcraft.stargate.listener;
import net.knarcraft.knarlib.util.UpdateChecker;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.MessageSender; import net.knarcraft.stargate.config.MessageSender;
import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.BlockLocation;
@ -7,16 +8,16 @@ import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalActivator; import net.knarcraft.stargate.portal.PortalActivator;
import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter;
import net.knarcraft.stargate.portal.teleporter.Teleporter;
import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter; import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter;
import net.knarcraft.stargate.utility.BungeeHelper; import net.knarcraft.stargate.utility.BungeeHelper;
import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.MaterialHelper;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import net.knarcraft.stargate.utility.TeleportHelper;
import net.knarcraft.stargate.utility.UUIDMigrationHelper; import net.knarcraft.stargate.utility.UUIDMigrationHelper;
import net.knarcraft.stargate.utility.UpdateChecker;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.type.WallSign; import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.AbstractHorse;
@ -33,6 +34,7 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -103,6 +105,11 @@ public class PlayerEventListener implements Listener {
return; return;
} }
Portal entrancePortal = PortalHandler.getByEntrance(toLocation); Portal entrancePortal = PortalHandler.getByEntrance(toLocation);
//Check an additional block away in case the portal is a bungee portal using END_PORTAL
if (entrancePortal == null) {
entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation);
}
Portal destination = entrancePortal.getPortalActivator().getDestination(player); Portal destination = entrancePortal.getPortalActivator().getDestination(player);
Entity playerVehicle = player.getVehicle(); Entity playerVehicle = player.getVehicle();
@ -131,10 +138,11 @@ public class PlayerEventListener implements Listener {
horse.setOwner(player); horse.setOwner(player);
} }
//Teleport the player's vehicle //Teleport the player's vehicle
new VehicleTeleporter(destination, (Vehicle) playerVehicle).teleport(entrancePortal); player.setVelocity(new Vector());
new VehicleTeleporter(destination, (Vehicle) playerVehicle).teleportEntity(entrancePortal);
} else { } else {
//Just teleport the player like normal //Just teleport the player like normal
new PlayerTeleporter(destination, player).teleport(entrancePortal, event); new PlayerTeleporter(destination, player).teleportPlayer(entrancePortal, event);
} }
if (!entrancePortal.getOptions().isSilent()) { if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendSuccessMessage(player, Stargate.getString("teleportMsg")); Stargate.getMessageSender().sendSuccessMessage(player, Stargate.getString("teleportMsg"));
@ -161,7 +169,12 @@ public class PlayerEventListener implements Listener {
//Check if the player moved from a portal //Check if the player moved from a portal
Portal entrancePortal = PortalHandler.getByEntrance(toLocation); Portal entrancePortal = PortalHandler.getByEntrance(toLocation);
if (entrancePortal == null) { if (entrancePortal == null) {
return false; //Check an additional block away for BungeeCord portals using END_PORTAL as its material
entrancePortal = PortalHandler.getByAdjacentEntrance(toLocation);
if (entrancePortal == null || !entrancePortal.getOptions().isBungee() ||
entrancePortal.getGate().getPortalOpenBlock() != Material.END_PORTAL) {
return false;
}
} }
Portal destination = entrancePortal.getPortalActivator().getDestination(player); Portal destination = entrancePortal.getPortalActivator().getDestination(player);
@ -185,7 +198,7 @@ public class PlayerEventListener implements Listener {
} }
//Make sure to check if the player has any leashed creatures, even though leashed teleportation is disabled //Make sure to check if the player has any leashed creatures, even though leashed teleportation is disabled
return Teleporter.noLeashedCreaturesPreventTeleportation(player); return TeleportHelper.noLeashedCreaturesPreventTeleportation(player);
} }
/** /**
@ -228,11 +241,14 @@ public class PlayerEventListener implements Listener {
EquipmentSlot hand = event.getHand(); EquipmentSlot hand = event.getHand();
if (hand != null && (PermissionHelper.hasPermission(player, "stargate.admin.dye") || if (hand != null && (PermissionHelper.hasPermission(player, "stargate.admin.dye") ||
portal.isOwner(player))) { portal.isOwner(player))) {
String itemName = player.getInventory().getItem(hand).getType().toString(); ItemStack item = player.getInventory().getItem(hand);
if (itemName.endsWith("DYE") || itemName.endsWith("INK_SAC")) { if (item != null) {
event.setUseInteractedBlock(Event.Result.ALLOW); String itemName = item.getType().toString();
Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), portal::drawSign, 1); if (itemName.endsWith("DYE") || itemName.endsWith("INK_SAC")) {
return; event.setUseInteractedBlock(Event.Result.ALLOW);
Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), portal::drawSign, 1);
return;
}
} }
} }
@ -323,7 +339,7 @@ public class PlayerEventListener implements Listener {
} else { } else {
//Display information about the portal if it has no sign //Display information about the portal if it has no sign
ItemStack heldItem = player.getInventory().getItem(hand); ItemStack heldItem = player.getInventory().getItem(hand);
if (heldItem.getType().isAir() || !heldItem.getType().isBlock()) { if (heldItem != null && (heldItem.getType().isAir() || !heldItem.getType().isBlock())) {
displayPortalInfo(block, player); displayPortalInfo(block, player);
} }
} }

View File

@ -49,4 +49,5 @@ public class PluginEventListener implements Listener {
Stargate.logInfo("Vault plugin lost."); Stargate.logInfo("Vault plugin lost.");
} }
} }
} }

View File

@ -6,6 +6,7 @@ import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter; import net.knarcraft.stargate.portal.teleporter.PlayerTeleporter;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.PermissionHelper;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
@ -67,14 +68,23 @@ public class PortalEventListener implements Listener {
return; return;
} }
Stargate.debug("PortalEventListener::onEntityPortalEnter",
"Found player " + player + " entering END_PORTAL " + portal);
//Remove any old player teleportations in case weird things happen //Remove any old player teleportations in case weird things happen
playersFromTheEnd.removeIf((teleportation -> teleportation.getPlayer() == player)); playersFromTheEnd.removeIf((teleportation -> teleportation.getPlayer() == player));
//Decide if the anything stops the player from teleporting //Decide if the anything stops the player from teleporting
if (PermissionHelper.playerCannotTeleport(portal, portal.getPortalActivator().getDestination(), player, null)) { if (PermissionHelper.playerCannotTeleport(portal, portal.getPortalActivator().getDestination(), player, null) ||
portal.getOptions().isBungee()) {
//Teleport the player back to the portal they came in, just in case //Teleport the player back to the portal they came in, just in case
playersFromTheEnd.add(new FromTheEndTeleportation(player, portal)); playersFromTheEnd.add(new FromTheEndTeleportation(player, portal));
Stargate.debug("PortalEventListener::onEntityPortalEnter",
"Sending player back to the entrance");
} else {
playersFromTheEnd.add(new FromTheEndTeleportation(player, portal.getPortalActivator().getDestination()));
Stargate.debug("PortalEventListener::onEntityPortalEnter",
"Sending player to destination");
} }
playersFromTheEnd.add(new FromTheEndTeleportation(player, portal.getPortalActivator().getDestination()));
} }
} }
@ -95,10 +105,18 @@ public class PortalEventListener implements Listener {
Portal exitPortal = teleportation.getExit(); Portal exitPortal = teleportation.getExit();
//Overwrite respawn location to respawn in front of the portal //Overwrite respawn location to respawn in front of the portal
event.setRespawnLocation(new PlayerTeleporter(exitPortal, respawningPlayer).getExit(respawningPlayer, PlayerTeleporter teleporter = new PlayerTeleporter(exitPortal, respawningPlayer);
respawningPlayer.getLocation())); Location respawnLocation = teleporter.getExit();
event.setRespawnLocation(respawnLocation);
//Try and force the player if for some reason the changing of respawn location isn't properly handled
Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () ->
respawningPlayer.teleport(respawnLocation), 1);
//Properly close the portal to prevent it from staying in a locked state until it times out //Properly close the portal to prevent it from staying in a locked state until it times out
exitPortal.getPortalOpener().closePortal(false); exitPortal.getPortalOpener().closePortal(false);
Stargate.debug("PortalEventListener::onRespawn", "Overwriting respawn for " + respawningPlayer +
" to " + respawnLocation.getWorld() + ":" + respawnLocation);
} }
} }

View File

@ -3,11 +3,10 @@ package net.knarcraft.stargate.listener;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalHandler;
import net.knarcraft.stargate.portal.teleporter.Teleporter;
import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter; import net.knarcraft.stargate.portal.teleporter.VehicleTeleporter;
import net.knarcraft.stargate.utility.EconomyHelper; import net.knarcraft.stargate.utility.EconomyHelper;
import net.knarcraft.stargate.utility.EntityHelper; import net.knarcraft.stargate.utility.EntityHelper;
import net.knarcraft.stargate.utility.PermissionHelper; import net.knarcraft.stargate.utility.TeleportHelper;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle; import org.bukkit.entity.Vehicle;
@ -62,11 +61,11 @@ public class VehicleEventListener implements Listener {
private static void teleportVehicle(List<Entity> passengers, Portal entrancePortal, Vehicle vehicle) { private static void teleportVehicle(List<Entity> passengers, Portal entrancePortal, Vehicle vehicle) {
String route = "VehicleEventListener::teleportVehicle"; String route = "VehicleEventListener::teleportVehicle";
if (!passengers.isEmpty() && passengers.get(0) instanceof Player) { if (!passengers.isEmpty() && TeleportHelper.containsPlayer(passengers)) {
Stargate.debug(route, "Found passenger vehicle"); Stargate.debug(route, "Found passenger vehicle");
teleportPlayerAndVehicle(entrancePortal, vehicle, passengers); teleportPlayerAndVehicle(entrancePortal, vehicle);
} else { } else {
Stargate.debug(route, "Found empty vehicle"); Stargate.debug(route, "Found vehicle without players");
Portal destinationPortal = entrancePortal.getPortalActivator().getDestination(); Portal destinationPortal = entrancePortal.getPortalActivator().getDestination();
if (destinationPortal == null) { if (destinationPortal == null) {
Stargate.debug(route, "Unable to find portal destination"); Stargate.debug(route, "Unable to find portal destination");
@ -74,7 +73,7 @@ public class VehicleEventListener implements Listener {
} }
Stargate.debug("vehicleTeleport", destinationPortal.getWorld() + " " + Stargate.debug("vehicleTeleport", destinationPortal.getWorld() + " " +
destinationPortal.getSignLocation()); destinationPortal.getSignLocation());
new VehicleTeleporter(destinationPortal, vehicle).teleport(entrancePortal); new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal);
} }
} }
@ -83,98 +82,66 @@ public class VehicleEventListener implements Listener {
* *
* @param entrancePortal <p>The portal the minecart entered</p> * @param entrancePortal <p>The portal the minecart entered</p>
* @param vehicle <p>The vehicle to teleport</p> * @param vehicle <p>The vehicle to teleport</p>
* @param passengers <p>Any entities sitting in the minecart</p>
*/ */
private static void teleportPlayerAndVehicle(Portal entrancePortal, Vehicle vehicle, List<Entity> passengers) { private static void teleportPlayerAndVehicle(Portal entrancePortal, Vehicle vehicle) {
Player player = (Player) passengers.get(0); Entity rootEntity = vehicle;
//On the assumption that a non-player cannot sit in the driver's seat and since some portals can only be open while (rootEntity.getVehicle() != null) {
// to one player at a time, we only need to check if the portal is open to the driver. rootEntity = rootEntity.getVehicle();
if (!entrancePortal.getPortalOpener().isOpenFor(player)) { }
if (!entrancePortal.getOptions().isSilent()) { List<Player> players = TeleportHelper.getPlayers(rootEntity.getPassengers());
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg")); Portal destinationPortal = null;
for (Player player : players) {
//The entrance portal must be open for one player for the teleportation to happen
if (!entrancePortal.getPortalOpener().isOpenFor(player)) {
continue;
} }
return;
}
//If no destination exists, the teleportation cannot happen //Check if any of the players has selected the destination
Portal destinationPortal = entrancePortal.getPortalActivator().getDestination(player); Portal possibleDestinationPortal = entrancePortal.getPortalActivator().getDestination(player);
if (destinationPortal == null) { if (possibleDestinationPortal != null) {
return; destinationPortal = possibleDestinationPortal;
}
//Make sure all player passengers are allowed to, and can afford to, enter the portal
for (Entity entity : passengers) {
if (entity instanceof Player && !playerCanTeleport((Player) entity, entrancePortal, destinationPortal)) {
return;
} }
} }
//To prevent the case where the first passenger pays and then the second passenger is denied, this has to be //Cancel the teleport if no players activated the portal, or if any players are denied access
// run after it has been confirmed that all passengers are able to pay boolean cancelTeleport = false;
int cost = EconomyHelper.getUseCost(player, entrancePortal, destinationPortal); for (Player player : players) {
if (cost > 0) { if (destinationPortal == null) {
if (!takePlayerPayment(passengers, entrancePortal, cost)) { cancelTeleport = true;
return; if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("invalidMsg"));
}
} else if (!TeleportHelper.playerCanTeleport(player, entrancePortal, destinationPortal)) {
cancelTeleport = true;
}
}
if (cancelTeleport) {
return;
}
//Take payment from all players
for (Player player : players) {
//To prevent the case where the first passenger pays and then the second passenger is denied, this has to be
// run after it has been confirmed that all passengers are able to pay
int cost = EconomyHelper.getUseCost(player, entrancePortal, destinationPortal);
if (cost > 0) {
if (EconomyHelper.cannotPayTeleportFee(entrancePortal, player, cost)) {
return;
}
} }
} }
//Teleport the vehicle and inform the user if the vehicle was teleported //Teleport the vehicle and inform the user if the vehicle was teleported
boolean teleported = new VehicleTeleporter(destinationPortal, vehicle).teleport(entrancePortal); boolean teleported = new VehicleTeleporter(destinationPortal, vehicle).teleportEntity(entrancePortal);
if (teleported) { if (teleported) {
if (!entrancePortal.getOptions().isSilent()) { if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendSuccessMessage(player, Stargate.getString("teleportMsg")); for (Player player : players) {
Stargate.getMessageSender().sendSuccessMessage(player, Stargate.getString("teleportMsg"));
}
} }
entrancePortal.getPortalOpener().closePortal(false); entrancePortal.getPortalOpener().closePortal(false);
} }
} }
/**
* Takes payment from all player passengers
*
* @param passengers <p>All passengers in the teleporting vehicle</p>
* @param entrancePortal <p>The portal the vehicle is entering from</p>
* @param cost <p>The cost each player has to pay</p>
* @return <p>True if all player passengers paid successfully</p>
*/
private static boolean takePlayerPayment(List<Entity> passengers, Portal entrancePortal, int cost) {
for (Entity entity : passengers) {
//If the passenger is a player, make it pay
if (entity instanceof Player && EconomyHelper.cannotPayTeleportFee(entrancePortal, (Player) entity, cost)) {
return false;
}
}
return true;
}
/**
* Checks whether the given player is allowed to and can afford to teleport
*
* @param player <p>The player trying to teleport</p>
* @param entrancePortal <p>The portal the player is entering</p>
* @param destinationPortal <p>The portal the player is to exit from</p>
* @return <p>True if the player is allowed to teleport and is able to pay necessary fees</p>
*/
private static boolean playerCanTeleport(Player player, Portal entrancePortal, Portal destinationPortal) {
//Make sure the user can access the portal
if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destinationPortal)) {
if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg"));
}
entrancePortal.getPortalOpener().closePortal(false);
return false;
}
//Check if the player is able to afford the teleport fee
int cost = EconomyHelper.getUseCost(player, entrancePortal, destinationPortal);
boolean canAffordFee = cost <= 0 || Stargate.getEconomyConfig().canAffordFee(player, cost);
if (!canAffordFee) {
if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("ecoInFunds"));
}
return false;
}
return Teleporter.noLeashedCreaturesPreventTeleportation(player);
}
} }

View File

@ -46,4 +46,5 @@ public class WorldEventListener implements Listener {
PortalRegistry.clearPortals(world); PortalRegistry.clearPortals(world);
} }
} }
} }

View File

@ -345,4 +345,5 @@ public class Portal {
return cleanNetwork.equalsIgnoreCase(other.cleanNetwork); return cleanNetwork.equalsIgnoreCase(other.cleanNetwork);
} }
} }
} }

View File

@ -448,4 +448,5 @@ public class PortalHandler {
} }
return input.replaceAll("[|:#]", "").trim(); return input.replaceAll("[|:#]", "").trim();
} }
} }

View File

@ -1,6 +1,7 @@
package net.knarcraft.stargate.portal; package net.knarcraft.stargate.portal;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.DynmapManager;
import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.utility.PortalFileHelper; import net.knarcraft.stargate.utility.PortalFileHelper;
import org.bukkit.World; import org.bukkit.World;
@ -224,6 +225,7 @@ public class PortalRegistry {
PortalFileHelper.saveAllPortals(portal.getWorld()); PortalFileHelper.saveAllPortals(portal.getWorld());
portal.setRegistered(false); portal.setRegistered(false);
DynmapManager.removePortalMarker(portal);
} }
/** /**
@ -289,6 +291,7 @@ public class PortalRegistry {
allPortals.add(portal); allPortals.add(portal);
portal.setRegistered(true); portal.setRegistered(true);
DynmapManager.addPortalMarker(portal);
} }
} }

View File

@ -1,5 +1,7 @@
package net.knarcraft.stargate.portal; package net.knarcraft.stargate.portal;
import net.knarcraft.knarlib.property.ColorConversion;
import net.knarcraft.knarlib.util.ColorHelper;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.SignData; import net.knarcraft.stargate.container.SignData;
import net.knarcraft.stargate.portal.property.PortalLocation; import net.knarcraft.stargate.portal.property.PortalLocation;
@ -12,8 +14,6 @@ import org.bukkit.block.Sign;
import java.util.Map; import java.util.Map;
import static net.knarcraft.stargate.utility.ColorHelper.translateAllColorCodes;
/** /**
* The portal sign drawer draws the sing of a given portal * The portal sign drawer draws the sing of a given portal
*/ */
@ -393,4 +393,14 @@ public class PortalSignDrawer {
} }
} }
/**
* Translates all normal and RGB color codes in the given input
*
* @param input <p>The input to translate color codes for</p>
* @return <p>The input with color codes converted translated from & to §</p>
*/
private String translateAllColorCodes(String input) {
return ColorHelper.translateColorCodes(input, ColorConversion.RGB);
}
} }

View File

@ -1,9 +1,7 @@
package net.knarcraft.stargate.portal.teleporter; package net.knarcraft.stargate.portal.teleporter;
import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.event.StargateEntityPortalEvent; import net.knarcraft.stargate.event.StargateEntityPortalEvent;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import org.bukkit.Location;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
/** /**
@ -16,10 +14,10 @@ public class EntityTeleporter extends Teleporter {
/** /**
* Instantiates a new portal teleporter * Instantiates a new portal teleporter
* *
* @param portal <p>The portal which is the target of the teleportation</p> * @param targetPortal <p>The portal which is the target of the teleportation</p>
*/ */
public EntityTeleporter(Portal portal, Entity teleportingEntity) { public EntityTeleporter(Portal targetPortal, Entity teleportingEntity) {
super(portal); super(targetPortal, teleportingEntity);
this.teleportingEntity = teleportingEntity; this.teleportingEntity = teleportingEntity;
} }
@ -29,44 +27,8 @@ public class EntityTeleporter extends Teleporter {
* @param origin <p>The portal the entity is teleporting from</p> * @param origin <p>The portal the entity is teleporting from</p>
* @return <p>True if the entity was teleported. False otherwise</p> * @return <p>True if the entity was teleported. False otherwise</p>
*/ */
public boolean teleport(Portal origin) { public boolean teleportEntity(Portal origin) {
Location traveller = teleportingEntity.getLocation(); return teleport(origin, new StargateEntityPortalEvent(teleportingEntity, origin, portal, exit));
Location exit = getExit(teleportingEntity, traveller);
//Rotate the entity to face out from the portal
adjustRotation(exit);
//Call the StargateEntityPortalEvent to allow plugins to change destination
if (!origin.equals(portal)) {
exit = triggerEntityPortalEvent(origin, exit);
if (exit == null) {
return false;
}
}
//Load chunks to make sure not to teleport to the void
loadChunks();
teleportingEntity.teleport(exit);
return true;
} }
/**
* Triggers the entity portal event to allow plugins to change the exit location
*
* @param origin <p>The origin portal teleported from</p>
* @param exit <p>The exit location to teleport the entity to</p>
* @return <p>The location the entity should be teleported to, or null if the event was cancelled</p>
*/
protected Location triggerEntityPortalEvent(Portal origin, Location exit) {
StargateEntityPortalEvent stargateEntityPortalEvent = new StargateEntityPortalEvent(teleportingEntity, origin,
portal, exit);
Stargate.getInstance().getServer().getPluginManager().callEvent(stargateEntityPortalEvent);
//Teleport is cancelled. Teleport the entity back to where it came from just for sanity's sake
if (stargateEntityPortalEvent.isCancelled()) {
new EntityTeleporter(origin, teleportingEntity).teleport(origin);
return null;
}
return stargateEntityPortalEvent.getExit();
}
} }

View File

@ -4,12 +4,15 @@ import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.event.StargatePlayerPortalEvent; import net.knarcraft.stargate.event.StargatePlayerPortalEvent;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.utility.DirectionHelper; import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.TeleportHelper;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.List;
/** /**
* The portal teleporter takes care of the actual portal teleportation for any players * The portal teleporter takes care of the actual portal teleportation for any players
*/ */
@ -20,11 +23,11 @@ public class PlayerTeleporter extends Teleporter {
/** /**
* Instantiates a new player teleporter * Instantiates a new player teleporter
* *
* @param portal <p>The portal which is the target of the teleportation</p> * @param targetPortal <p>The portal which is the target of the teleportation</p>
* @param player <p>The teleporting player</p> * @param player <p>The teleporting player</p>
*/ */
public PlayerTeleporter(Portal portal, Player player) { public PlayerTeleporter(Portal targetPortal, Player player) {
super(portal); super(targetPortal, player);
this.player = player; this.player = player;
} }
@ -34,27 +37,31 @@ public class PlayerTeleporter extends Teleporter {
* @param origin <p>The portal the player teleports from</p> * @param origin <p>The portal the player teleports from</p>
* @param event <p>The player move event triggering the event</p> * @param event <p>The player move event triggering the event</p>
*/ */
public void teleport(Portal origin, PlayerMoveEvent event) { public void teleportPlayer(Portal origin, PlayerMoveEvent event) {
double velocity = player.getVelocity().length(); double velocity = player.getVelocity().length();
Location traveller = player.getLocation(); List<Entity> passengers = player.getPassengers();
Location exit = getExit(player, traveller);
//Rotate the player to face out from the portal
adjustRotation(exit);
//Call the StargatePlayerPortalEvent to allow plugins to change destination //Call the StargatePlayerPortalEvent to allow plugins to change destination
if (!origin.equals(portal)) { if (!origin.equals(portal)) {
exit = triggerPlayerPortalEvent(origin, exit, event); exit = triggerPortalEvent(origin, new StargatePlayerPortalEvent(player, origin, portal, exit));
if (exit == null) { if (exit == null) {
return; return;
} }
} }
//Calculate the exit velocity of the player
Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw());
Vector newVelocity = newVelocityDirection.multiply(velocity * Stargate.getGateConfig().getExitVelocity());
//Load chunks to make sure not to teleport to the void //Load chunks to make sure not to teleport to the void
loadChunks(); loadChunks();
//Teleport any creatures leashed by the player in a 15-block range //Teleport any creatures leashed by the player in a 15-block range
teleportLeashedCreatures(player, origin); TeleportHelper.teleportLeashedCreatures(player, origin, portal);
if (player.eject()) {
TeleportHelper.handleEntityPassengers(passengers, player, origin, portal, exit.getDirection(), newVelocity);
}
//If no event is passed in, assume it's a teleport, and act as such //If no event is passed in, assume it's a teleport, and act as such
if (event == null) { if (event == null) {
@ -65,30 +72,7 @@ public class PlayerTeleporter extends Teleporter {
} }
//Set the velocity of the teleported player after the teleportation is finished //Set the velocity of the teleported player after the teleportation is finished
Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> { Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> player.setVelocity(newVelocity), 1);
Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw());
Vector newVelocity = newVelocityDirection.multiply(velocity * Stargate.getGateConfig().getExitVelocity());
player.setVelocity(newVelocity);
}, 1);
}
/**
* Triggers the player portal event to allow plugins to change the exit location
*
* @param origin <p>The origin portal teleported from</p>
* @param exit <p>The exit location to teleport the player to</p>
* @param event <p>The player move event which triggered the teleportation</p>
* @return <p>The location the player should be teleported to, or null if the event was cancelled</p>
*/
private Location triggerPlayerPortalEvent(Portal origin, Location exit, PlayerMoveEvent event) {
StargatePlayerPortalEvent stargatePlayerPortalEvent = new StargatePlayerPortalEvent(player, origin, portal, exit);
Stargate.getInstance().getServer().getPluginManager().callEvent(stargatePlayerPortalEvent);
//Teleport is cancelled. Teleport the player back to where it came from
if (stargatePlayerPortalEvent.isCancelled()) {
new PlayerTeleporter(origin, player).teleport(origin, event);
return null;
}
return stargatePlayerPortalEvent.getExit();
} }
} }

View File

@ -4,9 +4,11 @@ import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.BlockLocation;
import net.knarcraft.stargate.container.ChunkUnloadRequest; import net.knarcraft.stargate.container.ChunkUnloadRequest;
import net.knarcraft.stargate.container.RelativeBlockVector; import net.knarcraft.stargate.container.RelativeBlockVector;
import net.knarcraft.stargate.event.StargateTeleportEvent;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.utility.DirectionHelper; import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.EntityHelper; import net.knarcraft.stargate.utility.EntityHelper;
import net.knarcraft.stargate.utility.TeleportHelper;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -14,10 +16,10 @@ import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Slab; import org.bukkit.block.data.type.Slab;
import org.bukkit.entity.AbstractHorse; import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.event.Event;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.Vector;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -31,28 +33,96 @@ public abstract class Teleporter {
* The portal the entity is teleporting to * The portal the entity is teleporting to
*/ */
protected final Portal portal; protected final Portal portal;
/** /**
* The scheduler to use for delaying tasks * The scheduler to use for delaying tasks
*/ */
protected final BukkitScheduler scheduler; protected final BukkitScheduler scheduler;
/**
* The exit location any entities will be teleported to
*/
protected Location exit;
/**
* The entity being teleported by this teleporter
*/
protected final Entity teleportedEntity;
/** /**
* Instantiates a new portal teleporter * Instantiates a new portal teleporter
* *
* @param portal <p>The portal which is the target of the teleportation</p> * @param portal <p>The portal which is the target of the teleportation</p>
* @param teleportedEntity <p>The entity teleported by this teleporter</p>
*/ */
public Teleporter(Portal portal) { public Teleporter(Portal portal, Entity teleportedEntity) {
this.portal = portal; this.portal = portal;
this.scheduler = Stargate.getInstance().getServer().getScheduler(); this.scheduler = Stargate.getInstance().getServer().getScheduler();
this.teleportedEntity = teleportedEntity;
this.exit = getExit(teleportedEntity);
} }
/**
* Teleports an entity
*
* @param origin <p>The portal the entity teleported from</p>
* @param stargateTeleportEvent <p>The event to call to make sure the teleportation is valid</p>
* @return <p>True if the teleportation was successfully performed</p>
*/
public boolean teleport(Portal origin, StargateTeleportEvent stargateTeleportEvent) {
List<Entity> passengers = teleportedEntity.getPassengers();
//Call the StargateEntityPortalEvent to allow plugins to change destination
if (!origin.equals(portal)) {
exit = triggerPortalEvent(origin, stargateTeleportEvent);
if (exit == null) {
return false;
}
}
//Load chunks to make sure not to teleport to the void
loadChunks();
if (teleportedEntity.eject()) {
TeleportHelper.handleEntityPassengers(passengers, teleportedEntity, origin, portal, exit.getDirection(),
new Vector());
}
teleportedEntity.teleport(exit);
return true;
}
/**
* Gets the exit location of this teleporter
*
* @return <p>The exit location of this teleporter</p>
*/
public Location getExit() {
return exit.clone();
}
/**
* Triggers the entity portal event to allow plugins to change the exit location
*
* @param origin <p>The origin portal teleported from</p>
* @param stargateTeleportEvent <p>The exit location to teleport the entity to</p>
* @return <p>The location the entity should be teleported to, or null if the event was cancelled</p>
*/
protected Location triggerPortalEvent(Portal origin, StargateTeleportEvent stargateTeleportEvent) {
Stargate.getInstance().getServer().getPluginManager().callEvent((Event) stargateTeleportEvent);
//Teleport is cancelled. Teleport the entity back to where it came from just for sanity's sake
if (stargateTeleportEvent.isCancelled()) {
new EntityTeleporter(origin, teleportedEntity).teleportEntity(origin);
return null;
}
return stargateTeleportEvent.getExit();
}
/** /**
* Adjusts the rotation of the exit to make the teleporting entity face directly out from the portal * Adjusts the rotation of the exit to make the teleporting entity face directly out from the portal
* *
* @param exit <p>The location the entity will exit from</p> * @param exit <p>The location the entity will exit from</p>
*/ */
protected void adjustRotation(Location exit) { protected void adjustExitLocationRotation(Location exit) {
int adjust = 0; int adjust = 0;
if (portal.getOptions().isBackwards()) { if (portal.getOptions().isBackwards()) {
adjust = 180; adjust = 180;
@ -63,39 +133,14 @@ public abstract class Teleporter {
} }
/** /**
* Gets the exit location for a given entity and current location * Loads the chunks outside the portal's entrance
*
* @param entity <p>The entity to teleport (used to determine distance from portal to avoid suffocation)</p>
* @param traveller <p>The location of the entity travelling</p>
* @return <p>The location the entity should be teleported to.</p>
*/ */
public Location getExit(Entity entity, Location traveller) { protected void loadChunks() {
Location exitLocation = null; for (Chunk chunk : getChunksToLoad()) {
RelativeBlockVector relativeExit = portal.getGate().getLayout().getExit(); chunk.addPluginChunkTicket(Stargate.getInstance());
if (relativeExit != null) { //Allow the chunk to unload after 10 seconds
BlockLocation exit = portal.getBlockAt(relativeExit); Stargate.addChunkUnloadRequest(new ChunkUnloadRequest(chunk, 10000L));
//Move one block out to prevent exiting inside the portal
float portalYaw = portal.getYaw();
if (portal.getOptions().isBackwards()) {
portalYaw += 180;
}
exitLocation = exit.getRelativeLocation(0D, 0D, 1, portalYaw);
if (entity != null) {
double entitySize = EntityHelper.getEntityMaxSize(entity);
//Prevent exit suffocation for players riding horses or similar
if (entitySize > 1) {
exitLocation = preventExitSuffocation(relativeExit, exitLocation, entity);
}
}
} else {
Stargate.logWarning(String.format("Missing destination point in .gate file %s",
portal.getGate().getFilename()));
} }
//Adjust pitch and height
return adjustExitLocation(traveller, exitLocation);
} }
/** /**
@ -185,41 +230,62 @@ public abstract class Teleporter {
* slab check is necessary to prevent the player from clipping through the slab and spawning beneath it. The water * slab check is necessary to prevent the player from clipping through the slab and spawning beneath it. The water
* check is necessary when teleporting boats to prevent it from becoming a submarine.</p> * check is necessary when teleporting boats to prevent it from becoming a submarine.</p>
* *
* @param traveller <p>The location of the travelling entity</p> * @param entity <p>The travelling entity</p>
* @param exitLocation <p>The exit location generated</p> * @param exitLocation <p>The exit location generated</p>
* @return <p>The location the travelling entity should be teleported to</p> * @return <p>The location the travelling entity should be teleported to</p>
*/ */
private Location adjustExitLocation(Location traveller, Location exitLocation) { private Location adjustExitLocationHeight(Entity entity, Location exitLocation) {
if (exitLocation != null) { if (exitLocation != null) {
BlockData blockData = exitLocation.getBlock().getBlockData(); BlockData blockData = exitLocation.getBlock().getBlockData();
if ((blockData instanceof Bisected bisected && bisected.getHalf() == Bisected.Half.BOTTOM) || if ((blockData instanceof Bisected bisected && bisected.getHalf() == Bisected.Half.BOTTOM) ||
(blockData instanceof Slab slab && slab.getType() == Slab.Type.BOTTOM)) { (blockData instanceof Slab slab && slab.getType() == Slab.Type.BOTTOM) ||
//Prevent traveller from spawning inside a slab blockData.getMaterial() == Material.WATER) {
Stargate.debug("adjustExitLocation", "Added a block to get above a slab"); //Prevent traveller from spawning inside a slab, or a boat from spawning inside water
exitLocation.add(0, 1, 0); Stargate.debug("adjustExitLocation", "Added a block to get above a slab or a block of water");
} else if (blockData.getMaterial() == Material.WATER) {
//If there's water outside, go one up to allow for boat teleportation
Stargate.debug("adjustExitLocation", "Added a block to get above a block of water");
exitLocation.add(0, 1, 0); exitLocation.add(0, 1, 0);
} }
exitLocation.setPitch(traveller.getPitch());
return exitLocation; return exitLocation;
} else { } else {
Stargate.logWarning("Unable to generate exit location"); Stargate.logWarning("Unable to generate exit location");
return traveller; return entity.getLocation();
} }
} }
/** /**
* Loads the chunks outside the portal's entrance * Gets the exit location for a given entity and current location
*
* @param entity <p>The entity to teleport (used to determine distance from portal to avoid suffocation)</p>
* @return <p>The location the entity should be teleported to.</p>
*/ */
protected void loadChunks() { private Location getExit(Entity entity) {
for (Chunk chunk : getChunksToLoad()) { Location exitLocation = null;
chunk.addPluginChunkTicket(Stargate.getInstance()); RelativeBlockVector relativeExit = portal.getGate().getLayout().getExit();
//Allow the chunk to unload after 10 seconds if (relativeExit != null) {
Stargate.addChunkUnloadRequest(new ChunkUnloadRequest(chunk, 10000L)); BlockLocation exit = portal.getBlockAt(relativeExit);
//Move one block out to prevent exiting inside the portal
float portalYaw = portal.getYaw();
if (portal.getOptions().isBackwards()) {
portalYaw += 180;
}
exitLocation = exit.getRelativeLocation(0D, 0D, 1, portalYaw);
if (entity != null) {
double entitySize = EntityHelper.getEntityMaxSize(entity);
//Prevent exit suffocation for players riding horses or similar
if (entitySize > 1) {
exitLocation = preventExitSuffocation(relativeExit, exitLocation, entity);
}
}
} else {
Stargate.logWarning(String.format("Missing destination point in .gate file %s",
portal.getGate().getFilename()));
} }
//Adjust height and rotation
Location adjusted = adjustExitLocationHeight(entity, exitLocation);
adjustExitLocationRotation(adjusted);
return adjusted;
} }
/** /**
@ -250,76 +316,4 @@ public abstract class Teleporter {
return chunksToLoad; return chunksToLoad;
} }
/**
* Checks whether a player has leashed creatures that block the teleportation
*
* @param player <p>The player trying to teleport</p>
* @return <p>False if the player has leashed any creatures that cannot go through the portal</p>
*/
public static boolean noLeashedCreaturesPreventTeleportation(Player player) {
//Find any nearby leashed entities to teleport with the player
List<Creature> nearbyCreatures = getLeashedCreatures(player);
//Disallow creatures with passengers to prevent smuggling
for (Creature creature : nearbyCreatures) {
if (!creature.getPassengers().isEmpty()) {
return false;
}
}
//If it's enabled, there is no problem
if (Stargate.getGateConfig().handleLeashedCreatures()) {
return true;
} else {
return nearbyCreatures.isEmpty();
}
}
/**
* Teleports any creatures leashed by the player
*
* <p>Will return false if the teleportation should be aborted because the player has leashed creatures that
* aren't allowed to be teleported with the player.</p>
*
* @param player <p>The player which is teleported</p>
* @param origin <p>The portal the player is teleporting from</p>
*/
protected void teleportLeashedCreatures(Player player, Portal origin) {
//If this feature is disabled, just return
if (!Stargate.getGateConfig().handleLeashedCreatures()) {
return;
}
//Find any nearby leashed entities to teleport with the player
List<Creature> nearbyEntities = getLeashedCreatures(player);
//Teleport all creatures leashed by the player to the portal the player is to exit from
for (Creature creature : nearbyEntities) {
creature.setLeashHolder(null);
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> {
new EntityTeleporter(portal, creature).teleport(origin);
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> creature.setLeashHolder(player), 6);
}, 2);
}
}
/**
* Gets all creatures leashed by a player within the given range
*
* @param player <p>The player to check</p>
* @return <p>A list of all creatures the player is holding in a leash (lead)</p>
*/
protected static List<Creature> getLeashedCreatures(Player player) {
List<Creature> leashedCreatures = new ArrayList<>();
//Find any nearby leashed entities to teleport with the player
List<Entity> nearbyEntities = player.getNearbyEntities(15, 15, 15);
//Teleport all creatures leashed by the player to the portal the player is to exit from
for (Entity entity : nearbyEntities) {
if (entity instanceof Creature creature && creature.isLeashed() && creature.getLeashHolder() == player) {
leashedCreatures.add(creature);
}
}
return leashedCreatures;
}
} }

View File

@ -2,14 +2,17 @@ package net.knarcraft.stargate.portal.teleporter;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.StargateGateConfig; import net.knarcraft.stargate.config.StargateGateConfig;
import net.knarcraft.stargate.event.StargateEntityPortalEvent;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.utility.DirectionHelper; import net.knarcraft.stargate.utility.DirectionHelper;
import net.knarcraft.stargate.utility.TeleportHelper;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle; import org.bukkit.entity.Vehicle;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.List; import java.util.List;
@ -24,11 +27,11 @@ public class VehicleTeleporter extends EntityTeleporter {
/** /**
* Instantiates a new vehicle teleporter * Instantiates a new vehicle teleporter
* *
* @param portal <p>The portal which is the target of the teleportation</p> * @param targetPortal <p>The targetPortal which is the target of the teleportation</p>
* @param teleportingVehicle <p>The teleporting vehicle</p> * @param teleportingVehicle <p>The teleporting vehicle</p>
*/ */
public VehicleTeleporter(Portal portal, Vehicle teleportingVehicle) { public VehicleTeleporter(Portal targetPortal, Vehicle teleportingVehicle) {
super(portal, teleportingVehicle); super(targetPortal, teleportingVehicle);
this.teleportingVehicle = teleportingVehicle; this.teleportingVehicle = teleportingVehicle;
} }
@ -42,28 +45,22 @@ public class VehicleTeleporter extends EntityTeleporter {
* @return <p>True if the vehicle was teleported. False otherwise</p> * @return <p>True if the vehicle was teleported. False otherwise</p>
*/ */
@Override @Override
public boolean teleport(Portal origin) { public boolean teleportEntity(Portal origin) {
Location traveller = teleportingVehicle.getLocation(); Stargate.debug("VehicleTeleporter::teleport", "Preparing to teleport: " + teleportingVehicle);
Location exit = getExit(teleportingVehicle, traveller);
double velocity = teleportingVehicle.getVelocity().length(); double velocity = teleportingVehicle.getVelocity().length();
//Stop and teleport //Stop the vehicle before teleporting
teleportingVehicle.setVelocity(new Vector()); teleportingVehicle.setVelocity(new Vector());
//Get new velocity //Get new velocity
Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw()); Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw());
Vector newVelocity = newVelocityDirection.multiply(velocity); Vector newVelocity = newVelocityDirection.multiply(velocity);
//Make sure the vehicle points out from the portal
adjustRotation(exit);
//Call the StargateEntityPortalEvent to allow plugins to change destination //Call the StargateEntityPortalEvent to allow plugins to change destination
if (!origin.equals(portal)) { exit = triggerPortalEvent(origin, new StargateEntityPortalEvent(teleportingVehicle, origin, portal, exit));
exit = triggerEntityPortalEvent(origin, exit); if (exit == null) {
if (exit == null) { return false;
return false;
}
} }
//Teleport the vehicle //Teleport the vehicle
@ -89,12 +86,13 @@ public class VehicleTeleporter extends EntityTeleporter {
return false; return false;
} }
if (!(teleportingVehicle instanceof LivingEntity)) { if (!(teleportingVehicle instanceof LivingEntity) &&
Stargate.getGateConfig().enableCraftBookRemoveOnEjectFix()) {
//Teleport a normal vehicle with passengers (minecart or boat) //Teleport a normal vehicle with passengers (minecart or boat)
putPassengersInNewVehicle(passengers, exit, newVelocity, origin); putPassengersInNewVehicle(passengers, exit, newVelocity, origin);
} else { } else {
//Teleport a living vehicle with passengers (pig, horse, donkey, strider) //Teleport a living vehicle with passengers (pig, horse, donkey, strider)
teleportLivingVehicle(exit, passengers, origin); teleportVehicle(passengers, exit, newVelocity, origin);
} }
} else { } else {
//Check if teleportation of empty vehicles is enabled //Check if teleportation of empty vehicles is enabled
@ -118,54 +116,35 @@ public class VehicleTeleporter extends EntityTeleporter {
private boolean vehiclePassengersAllowed(List<Entity> passengers) { private boolean vehiclePassengersAllowed(List<Entity> passengers) {
StargateGateConfig config = Stargate.getGateConfig(); StargateGateConfig config = Stargate.getGateConfig();
//Don't teleport if the vehicle contains a creature and creature transportation is disabled //Don't teleport if the vehicle contains a creature and creature transportation is disabled
if (containsNonPlayer(passengers) && !config.handleCreatureTransportation()) { if (TeleportHelper.containsNonPlayer(passengers) && !config.handleCreatureTransportation()) {
return false; return false;
} }
//Don't teleport if the player does not contain a player and non-player vehicles is disabled //Don't teleport if the player does not contain a player and non-player vehicles is disabled
return containsPlayer(passengers) || config.handleNonPlayerVehicles(); return TeleportHelper.containsPlayer(passengers) || config.handleNonPlayerVehicles();
}
/**
* Checks whether a list of entities contains any non-players
*
* @param entities <p>The list of entities to check</p>
* @return <p>True if at least one entity is not a player</p>
*/
private boolean containsNonPlayer(List<Entity> entities) {
for (Entity entity : entities) {
if (!(entity instanceof Player)) {
return true;
}
}
return false;
}
/**
* Checks whether a list of entities contains at least one player
*
* @param entities <p>The list of entities to check</p>
* @return <p>True if at least one player is present among the passengers</p>
*/
private boolean containsPlayer(List<Entity> entities) {
for (Entity entity : entities) {
if (entity instanceof Player) {
return true;
}
}
return false;
} }
/** /**
* Teleport a vehicle which is not a minecart or a boat * Teleport a vehicle which is not a minecart or a boat
* *
* @param exit <p>The location the vehicle will exit</p> * @param passengers <p>The passengers of the vehicle</p>
* @param passengers <p>The passengers of the vehicle</p> * @param exit <p>The location the vehicle will exit</p>
* @param origin <p>The portal the vehicle teleported from</p> * @param newVelocity <p>The new velocity of the teleported vehicle</p>
* @param origin <p>The portal the vehicle teleported from</p>
*/ */
private void teleportLivingVehicle(Location exit, List<Entity> passengers, Portal origin) { private void teleportVehicle(List<Entity> passengers, Location exit, Vector newVelocity, Portal origin) {
teleportingVehicle.eject(); if (teleportingVehicle.eject()) {
teleportingVehicle.teleport(exit); TeleportHelper.handleEntityPassengers(passengers, teleportingVehicle, origin, portal, exit.getDirection(),
handleVehiclePassengers(passengers, teleportingVehicle, 2, origin, exit.getDirection()); newVelocity);
}
Stargate.debug("VehicleTeleporter::teleportVehicle", "Teleporting " + teleportingVehicle +
" to final location " + exit + " with direction " + exit.getDirection());
teleportingVehicle.teleport(exit, PlayerTeleportEvent.TeleportCause.PLUGIN);
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(),
() -> {
Stargate.debug("VehicleTeleporter::teleportVehicle", "Setting velocity " + newVelocity +
" for vehicle " + teleportingVehicle);
teleportingVehicle.setVelocity(newVelocity);
}, 1);
} }
/** /**
@ -189,54 +168,16 @@ public class VehicleTeleporter extends EntityTeleporter {
} }
//Spawn a new vehicle //Spawn a new vehicle
Vehicle newVehicle = vehicleWorld.spawn(exit, teleportingVehicle.getClass()); Vehicle newVehicle = vehicleWorld.spawn(exit, teleportingVehicle.getClass());
if (teleportingVehicle instanceof Boat boat) {
((Boat) newVehicle).setBoatType(boat.getBoatType());
}
//Remove the old vehicle //Remove the old vehicle
teleportingVehicle.eject(); if (teleportingVehicle.eject()) {
TeleportHelper.handleEntityPassengers(passengers, newVehicle, origin, portal, exit.getDirection(),
newVelocity);
}
teleportingVehicle.remove(); teleportingVehicle.remove();
//Set rotation, add passengers and restore velocity
newVehicle.setRotation(exit.getYaw(), exit.getPitch());
handleVehiclePassengers(passengers, newVehicle, 1, origin, exit.getDirection());
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> newVehicle.setVelocity(newVelocity), 1); scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> newVehicle.setVelocity(newVelocity), 1);
} }
/**
* Ejects, teleports and adds all passengers to the target vehicle
*
* @param passengers <p>The passengers to handle</p>
* @param vehicle <p>The vehicle the passengers should be put into</p>
* @param delay <p>The amount of milliseconds to wait before adding the vehicle passengers</p>
* @param origin <p>The portal the vehicle teleported from</p>
* @param exitRotation <p>The rotation of any passengers exiting the stargate</p>
*/
private void handleVehiclePassengers(List<Entity> passengers, Vehicle vehicle, long delay, Portal origin, Vector exitRotation) {
for (Entity passenger : passengers) {
passenger.eject();
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> {
if (passenger instanceof Player player) {
//Teleport any creatures leashed by the player in a 15-block range
teleportLeashedCreatures(player, origin);
}
teleportAndAddPassenger(vehicle, passenger, exitRotation);
}, delay);
}
}
/**
* Teleports and adds a passenger to a vehicle
*
* <p>Teleportation of living vehicles is really buggy if you wait between the teleportation and passenger adding,
* but there needs to be a delay between teleporting the vehicle and teleporting and adding the passenger.</p>
*
* @param targetVehicle <p>The vehicle to add the passenger to</p>
* @param passenger <p>The passenger to teleport and add</p>
* @param exitDirection <p>The direction of any passengers exiting the stargate</p>
*/
private void teleportAndAddPassenger(Vehicle targetVehicle, Entity passenger, Vector exitDirection) {
if (!passenger.teleport(targetVehicle.getLocation().clone().setDirection(exitDirection))) {
Stargate.debug("handleVehiclePassengers", "Failed to teleport passenger");
}
if (!targetVehicle.addPassenger(passenger)) {
Stargate.debug("handleVehiclePassengers", "Failed to add passenger");
}
}
} }

View File

@ -21,18 +21,22 @@ public class BlockChangeThread implements Runnable {
long sTime = System.nanoTime(); long sTime = System.nanoTime();
//Repeat for at most 0.025 seconds //Repeat for at most 0.025 seconds
while (System.nanoTime() - sTime < 25000000) { while (System.nanoTime() - sTime < 25000000) {
pollQueue(); if (pollQueue()) {
break;
}
} }
} }
/** /**
* Polls the block change request queue for any waiting requests * Polls the block change request queue for any waiting requests
*
* @return <p>True if the queue is empty and it's safe to quit</p>
*/ */
public static void pollQueue() { public static boolean pollQueue() {
//Abort if there's no work to be done //Abort if there's no work to be done
BlockChangeRequest blockChangeRequest = Stargate.getBlockChangeRequestQueue().poll(); BlockChangeRequest blockChangeRequest = Stargate.getBlockChangeRequestQueue().poll();
if (blockChangeRequest == null) { if (blockChangeRequest == null) {
return; return true;
} }
//Change the material of the pulled block //Change the material of the pulled block
@ -46,6 +50,7 @@ public class BlockChangeThread implements Runnable {
//If orientation is relevant, adjust the block's orientation //If orientation is relevant, adjust the block's orientation
orientBlock(block, blockChangeRequest.getAxis()); orientBlock(block, blockChangeRequest.getAxis());
} }
return false;
} }
/** /**

View File

@ -190,7 +190,7 @@ public final class BungeeHelper {
} }
//Teleport the player back to this gate, for sanity's sake //Teleport the player back to this gate, for sanity's sake
new PlayerTeleporter(entrancePortal, player).teleport(entrancePortal, event); new PlayerTeleporter(entrancePortal, player).teleportPlayer(entrancePortal, event);
//Send the SGBungee packet first, it will be queued by BC if required //Send the SGBungee packet first, it will be queued by BC if required
if (!BungeeHelper.sendTeleportationMessage(player, entrancePortal)) { if (!BungeeHelper.sendTeleportationMessage(player, entrancePortal)) {

View File

@ -1,47 +0,0 @@
package net.knarcraft.stargate.utility;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Color;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ColorHelper {
/**
* Inverts the given color
*
* @param color <p>The color to invert</p>
* @return <p>The inverted color</p>
*/
public static Color invert(Color color) {
return color.setRed(255 - color.getRed()).setGreen(255 - color.getGreen()).setBlue(255 - color.getBlue());
}
/**
* Gets the chat color corresponding to the given color
*
* @param color <p>The color to convert into a chat color</p>
* @return <p>The resulting chat color</p>
*/
public static ChatColor fromColor(Color color) {
return ChatColor.of(String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue()));
}
/**
* Translates all found color codes to formatting in a string
*
* @param message <p>The string to search for color codes</p>
* @return <p>The message with color codes translated</p>
*/
public static String translateAllColorCodes(String message) {
message = ChatColor.translateAlternateColorCodes('&', message);
Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
Matcher matcher = pattern.matcher(message);
while (matcher.find()) {
message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
}
return message;
}
}

View File

@ -1,5 +1,6 @@
package net.knarcraft.stargate.utility; package net.knarcraft.stargate.utility;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.config.EconomyConfig; import net.knarcraft.stargate.config.EconomyConfig;
import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.Portal;
@ -78,7 +79,7 @@ public final class EconomyHelper {
*/ */
public static void sendObtainMessage(String portalName, Player portalOwner, int earnings) { public static void sendObtainMessage(String portalName, Player portalOwner, int earnings) {
String obtainedMsg = Stargate.getString("ecoObtain"); String obtainedMsg = Stargate.getString("ecoObtain");
obtainedMsg = replaceVars(obtainedMsg, portalName, earnings); obtainedMsg = replacePlaceholders(obtainedMsg, portalName, earnings);
Stargate.getMessageSender().sendSuccessMessage(portalOwner, obtainedMsg); Stargate.getMessageSender().sendSuccessMessage(portalOwner, obtainedMsg);
} }
@ -91,7 +92,7 @@ public final class EconomyHelper {
*/ */
public static void sendDeductMessage(String portalName, Player player, int cost) { public static void sendDeductMessage(String portalName, Player player, int cost) {
String deductMsg = Stargate.getString("ecoDeduct"); String deductMsg = Stargate.getString("ecoDeduct");
deductMsg = replaceVars(deductMsg, portalName, cost); deductMsg = replacePlaceholders(deductMsg, portalName, cost);
Stargate.getMessageSender().sendSuccessMessage(player, deductMsg); Stargate.getMessageSender().sendSuccessMessage(player, deductMsg);
} }
@ -104,7 +105,7 @@ public final class EconomyHelper {
*/ */
public static void sendInsufficientFundsMessage(String portalName, Player player, int cost) { public static void sendInsufficientFundsMessage(String portalName, Player player, int cost) {
String inFundMsg = Stargate.getString("ecoInFunds"); String inFundMsg = Stargate.getString("ecoInFunds");
inFundMsg = replaceVars(inFundMsg, portalName, cost); inFundMsg = replacePlaceholders(inFundMsg, portalName, cost);
Stargate.getMessageSender().sendErrorMessage(player, inFundMsg); Stargate.getMessageSender().sendErrorMessage(player, inFundMsg);
} }
@ -117,7 +118,7 @@ public final class EconomyHelper {
*/ */
public static void sendRefundMessage(String portalName, Player player, int cost) { public static void sendRefundMessage(String portalName, Player player, int cost) {
String refundMsg = Stargate.getString("ecoRefund"); String refundMsg = Stargate.getString("ecoRefund");
refundMsg = replaceVars(refundMsg, portalName, -cost); refundMsg = replacePlaceholders(refundMsg, portalName, -cost);
Stargate.getMessageSender().sendSuccessMessage(player, refundMsg); Stargate.getMessageSender().sendSuccessMessage(player, refundMsg);
} }
@ -239,8 +240,8 @@ public final class EconomyHelper {
* @param cost <p>The cost for a given interaction</p> * @param cost <p>The cost for a given interaction</p>
* @return <p>The same string with cost and portal variables replaced</p> * @return <p>The same string with cost and portal variables replaced</p>
*/ */
private static String replaceVars(String message, String portalName, int cost) { private static String replacePlaceholders(String message, String portalName, int cost) {
return Stargate.replaceVars(message, new String[]{"%cost%", "%portal%"}, return StringFormatter.replacePlaceholders(message, new String[]{"%cost%", "%portal%"},
new String[]{Stargate.getEconomyConfig().format(cost), portalName}); new String[]{Stargate.getEconomyConfig().format(cost), portalName});
} }

View File

@ -1,127 +0,0 @@
package net.knarcraft.stargate.utility;
import net.md_5.bungee.api.ChatColor;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* Helper class for reading files
*/
public final class FileHelper {
private FileHelper() {
}
/**
* Gets an input stream from a string pointing to an internal file
*
* <p>This is used for getting an input stream for reading a file contained within the compiled .jar file. The file
* should be in the resources directory, and the file path should start with a forward slash ("/") character.</p>
*
* @param file <p>The file to read</p>
* @return <p>An input stream for the file</p>
*/
public static InputStream getInputStreamForInternalFile(String file) {
return FileHelper.class.getResourceAsStream(file);
}
/**
* Gets a buffered reader from a string pointing to a file
*
* @param file <p>The file to read</p>
* @return <p>A buffered reader reading the file</p>
* @throws FileNotFoundException <p>If the given file does not exist</p>
*/
public static BufferedReader getBufferedReaderFromString(String file) throws FileNotFoundException {
FileInputStream fileInputStream = new FileInputStream(file);
return getBufferedReaderFromInputStream(fileInputStream);
}
/**
* Gets a buffered reader given an input stream
*
* @param inputStream <p>The input stream to read</p>
* @return <p>A buffered reader reading the input stream</p>
*/
public static BufferedReader getBufferedReaderFromInputStream(InputStream inputStream) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
return new BufferedReader(inputStreamReader);
}
/**
* Gets a buffered writer from a string pointing to a file
*
* @param file <p>The file to write to</p>
* @return <p>A buffered writer writing to the file</p>
* @throws FileNotFoundException <p>If the file does not exist</p>
*/
public static BufferedWriter getBufferedWriterFromString(String file) throws FileNotFoundException {
FileOutputStream fileOutputStream = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
return new BufferedWriter(outputStreamWriter);
}
/**
* Reads key/value pairs from an input stream
*
* @param bufferedReader <p>The buffered reader to read</p>
* @return <p>A map containing the read pairs</p>
* @throws IOException <p>If unable to read from the stream</p>
*/
public static Map<String, String> readKeyValuePairs(BufferedReader bufferedReader) throws IOException {
Map<String, String> readPairs = new HashMap<>();
String line = bufferedReader.readLine();
boolean firstLine = true;
while (line != null) {
//Strip UTF BOM from the first line
if (firstLine) {
line = removeUTF8BOM(line);
firstLine = false;
}
//Split at first "="
int equalSignIndex = line.indexOf('=');
if (equalSignIndex == -1) {
line = bufferedReader.readLine();
continue;
}
//Read the line
String key = line.substring(0, equalSignIndex);
String value = ChatColor.translateAlternateColorCodes('&', line.substring(equalSignIndex + 1));
readPairs.put(key, value);
line = bufferedReader.readLine();
}
bufferedReader.close();
return readPairs;
}
/**
* Removes the UTF-8 Byte Order Mark if present
*
* @param string <p>The string to remove the BOM from</p>
* @return <p>A string guaranteed without a BOM</p>
*/
private static String removeUTF8BOM(String string) {
String UTF8_BOM = "\uFEFF";
if (string.startsWith(UTF8_BOM)) {
string = string.substring(1);
}
return string;
}
}

View File

@ -387,7 +387,7 @@ public final class PermissionHelper {
if (!entrancePortal.getOptions().isSilent()) { if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg")); Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg"));
} }
new PlayerTeleporter(entrancePortal, player).teleport(entrancePortal, event); new PlayerTeleporter(entrancePortal, player).teleportPlayer(entrancePortal, event);
return true; return true;
} }
@ -401,7 +401,7 @@ public final class PermissionHelper {
if (!entrancePortal.getOptions().isSilent()) { if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg")); Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg"));
} }
new PlayerTeleporter(entrancePortal, player).teleport(entrancePortal, event); new PlayerTeleporter(entrancePortal, player).teleportPlayer(entrancePortal, event);
entrancePortal.getPortalOpener().closePortal(false); entrancePortal.getPortalOpener().closePortal(false);
return true; return true;
} }

View File

@ -0,0 +1,247 @@
package net.knarcraft.stargate.utility;
import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.portal.Portal;
import net.knarcraft.stargate.portal.teleporter.EntityTeleporter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
/**
* A helper class with methods for various teleportation tasks
*
* <p>The teleport helper mainly helps with passengers and leashed creatures</p>
*/
public final class TeleportHelper {
private TeleportHelper() {
}
/**
* Checks whether a player has leashed creatures that block the teleportation
*
* @param player <p>The player trying to teleport</p>
* @return <p>False if the player has leashed any creatures that cannot go through the portal</p>
*/
public static boolean noLeashedCreaturesPreventTeleportation(Player player) {
//Find any nearby leashed entities to teleport with the player
List<Creature> nearbyCreatures = getLeashedCreatures(player);
//Disallow creatures with passengers to prevent smuggling
for (Creature creature : nearbyCreatures) {
if (!creature.getPassengers().isEmpty()) {
return false;
}
}
//TODO: Improve this to account for any players sitting on any of the lead creatures
//If it's enabled, there is no problem
if (Stargate.getGateConfig().handleLeashedCreatures()) {
return true;
} else {
return nearbyCreatures.isEmpty();
}
}
/**
* Gets all creatures leashed by a player within the given range
*
* @param player <p>The player to check</p>
* @return <p>A list of all creatures the player is holding in a leash (lead)</p>
*/
public static List<Creature> getLeashedCreatures(Player player) {
List<Creature> leashedCreatures = new ArrayList<>();
//Find any nearby leashed entities to teleport with the player
List<Entity> nearbyEntities = player.getNearbyEntities(15, 15, 15);
//Teleport all creatures leashed by the player to the portal the player is to exit from
for (Entity entity : nearbyEntities) {
if (entity instanceof Creature creature && creature.isLeashed() && creature.getLeashHolder() == player) {
leashedCreatures.add(creature);
}
}
return leashedCreatures;
}
/**
* Teleports and adds a passenger to an entity
*
* <p>Teleportation of living vehicles is really buggy if you wait between the teleportation and passenger adding,
* but there needs to be a delay between teleporting the vehicle and teleporting and adding the passenger.</p>
*
* @param targetVehicle <p>The entity to add the passenger to</p>
* @param passenger <p>The passenger to teleport and add</p>
* @param exitDirection <p>The direction of any passengers exiting the stargate</p>
* @param newVelocity <p>The new velocity of the teleported passenger</p>
*/
public static void teleportAndAddPassenger(Entity targetVehicle, Entity passenger, Vector exitDirection,
Vector newVelocity) {
Location passengerExit = targetVehicle.getLocation().clone().setDirection(exitDirection);
if (!passenger.teleport(passengerExit)) {
Stargate.debug("TeleportHelper::handleVehiclePassengers", "Failed to teleport passenger" +
passenger);
} else {
Stargate.debug("TeleportHelper::handleVehiclePassengers", "Teleported " + passenger +
" to " + passengerExit);
}
if (!targetVehicle.addPassenger(passenger)) {
Stargate.debug("TeleportHelper::handleVehiclePassengers", "Failed to add passenger" +
passenger);
} else {
Stargate.debug("TeleportHelper::handleVehiclePassengers", "Added passenger " + passenger +
" to " + targetVehicle);
}
Stargate.debug("VehicleTeleporter::teleportVehicle", "Setting velocity " + newVelocity +
" for passenger " + passenger);
passenger.setVelocity(newVelocity);
}
/**
* Ejects, teleports and adds all passengers to the target entity
*
* @param passengers <p>The passengers to handle</p>
* @param entity <p>The entity the passengers should be put into</p
* @param origin <p>The portal the entity teleported from</p>
* @param target <p>The portal the entity is teleporting to</p>
* @param exitRotation <p>The rotation of any passengers exiting the stargate</p>
* @param newVelocity <p>The new velocity of the teleported passengers</p>
*/
public static void handleEntityPassengers(List<Entity> passengers, Entity entity, Portal origin, Portal target,
Vector exitRotation, Vector newVelocity) {
for (Entity passenger : passengers) {
List<Entity> passengerPassengers = passenger.getPassengers();
if (!passengerPassengers.isEmpty()) {
Stargate.debug("Teleporter::handleEntityPassengers", "Found the entities: " +
passengerPassengers + " as passengers of " + entity);
}
if (passenger.eject()) {
//Teleport any passengers of the passenger
handleEntityPassengers(passengerPassengers, passenger, origin, target, exitRotation, newVelocity);
}
Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> {
if (passenger instanceof Player player) {
//Teleport any creatures leashed by the player in a 15-block range
teleportLeashedCreatures(player, origin, target);
}
teleportAndAddPassenger(entity, passenger, exitRotation, newVelocity);
}, passenger instanceof Player ? Stargate.getGateConfig().waitForPlayerAfterTeleportDelay() : 0);
}
}
/**
* Teleports any creatures leashed by the player
*
* <p>Will return false if the teleportation should be aborted because the player has leashed creatures that
* aren't allowed to be teleported with the player.</p>
*
* @param player <p>The player which is teleported</p>
* @param origin <p>The portal the player is teleporting from</p>
* @param target <p>The portal the player is teleporting to</p>
*/
public static void teleportLeashedCreatures(Player player, Portal origin, Portal target) {
//If this feature is disabled, just return
if (!Stargate.getGateConfig().handleLeashedCreatures()) {
return;
}
BukkitScheduler scheduler = Bukkit.getScheduler();
//Find any nearby leashed entities to teleport with the player
List<Creature> nearbyEntities = TeleportHelper.getLeashedCreatures(player);
//Teleport all creatures leashed by the player to the portal the player is to exit from
for (Creature creature : nearbyEntities) {
creature.setLeashHolder(null);
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> {
new EntityTeleporter(target, creature).teleportEntity(origin);
scheduler.scheduleSyncDelayedTask(Stargate.getInstance(), () -> creature.setLeashHolder(player),
Stargate.getGateConfig().waitForPlayerAfterTeleportDelay());
}, 2);
}
}
/**
* Checks whether a list of entities or any of their passengers contains any non-players
*
* @param entities <p>The list of entities to check</p>
* @return <p>True if at least one entity is not a player</p>
*/
public static boolean containsNonPlayer(List<Entity> entities) {
for (Entity entity : entities) {
if (!(entity instanceof Player) || containsNonPlayer(entity.getPassengers())) {
return true;
}
}
return false;
}
/**
* Checks whether a list of entities of their passengers contains at least one player
*
* @param entities <p>The list of entities to check</p>
* @return <p>True if at least one player is present among the passengers</p>
*/
public static boolean containsPlayer(List<Entity> entities) {
for (Entity entity : entities) {
if (entity instanceof Player || containsPlayer(entity.getPassengers())) {
return true;
}
}
return false;
}
/**
* Gets all players recursively from a list of entities
*
* @param entities <p>The entities to check for players</p>
* @return <p>The found players</p>
*/
public static List<Player> getPlayers(List<Entity> entities) {
List<Player> players = new ArrayList<>(5);
for (Entity entity : entities) {
if (entity instanceof Player) {
players.add((Player) entity);
}
players.addAll(getPlayers(entity.getPassengers()));
}
return players;
}
/**
* Checks whether the given player is allowed to and can afford to teleport
*
* @param player <p>The player trying to teleport</p>
* @param entrancePortal <p>The portal the player is entering</p>
* @param destinationPortal <p>The portal the player is to exit from</p>
* @return <p>True if the player is allowed to teleport and is able to pay necessary fees</p>
*/
public static boolean playerCanTeleport(Player player, Portal entrancePortal, Portal destinationPortal) {
//Make sure the user can access the portal
if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destinationPortal)) {
if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("denyMsg"));
}
entrancePortal.getPortalOpener().closePortal(false);
return false;
}
//Check if the player is able to afford the teleport fee
int cost = EconomyHelper.getUseCost(player, entrancePortal, destinationPortal);
boolean canAffordFee = cost <= 0 || Stargate.getEconomyConfig().canAffordFee(player, cost);
if (!canAffordFee) {
if (!entrancePortal.getOptions().isSilent()) {
Stargate.getMessageSender().sendErrorMessage(player, Stargate.getString("ecoInFunds"));
}
return false;
}
return TeleportHelper.noLeashedCreaturesPreventTeleportation(player);
}
}

View File

@ -1,87 +0,0 @@
package net.knarcraft.stargate.utility;
import net.knarcraft.stargate.Stargate;
import org.bukkit.scheduler.BukkitScheduler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.logging.Level;
/**
* The update checker is responsible for looking for new updates
*/
public final class UpdateChecker {
private final static String APIResourceURL = "https://api.spigotmc.org/legacy/update.php?resource=97784";
private final static String updateNotice = "A new update is available: %s (You are still on %s)";
private UpdateChecker() {
}
/**
* Checks if there's a new update available, and alerts the user if necessary
*/
public static void checkForUpdate() {
BukkitScheduler scheduler = Stargate.getInstance().getServer().getScheduler();
scheduler.runTaskAsynchronously(Stargate.getInstance(), UpdateChecker::queryAPI);
}
/**
* Queries the spigot API to check for a newer version, and informs the user
*/
private static void queryAPI() {
try {
InputStream inputStream = new URL(APIResourceURL).openStream();
BufferedReader reader = FileHelper.getBufferedReaderFromInputStream(inputStream);
//There should only be one line of output
String newVersion = reader.readLine();
reader.close();
String oldVersion = Stargate.getPluginVersion();
//If there is a newer version, notify the user
if (isVersionHigher(oldVersion, newVersion)) {
Stargate.getConsoleLogger().log(Level.INFO, Stargate.getBackupString("prefix") +
getUpdateAvailableString(newVersion, oldVersion));
Stargate.setUpdateAvailable(newVersion);
}
} catch (IOException e) {
Stargate.debug("UpdateChecker", "Unable to get newest version.");
}
}
/**
* Gets the string to display to a user to alert about a new update
*
* @param newVersion <p>The new available plugin version</p>
* @param oldVersion <p>The old (current) plugin version</p>
* @return <p>The string to display</p>
*/
public static String getUpdateAvailableString(String newVersion, String oldVersion) {
return String.format(updateNotice, newVersion, oldVersion);
}
/**
* Decides whether one version number is higher than another
*
* @param oldVersion <p>The old version to check</p>
* @param newVersion <p>The new version to check</p>
* @return <p>True if the new version is higher than the old one</p>
*/
public static boolean isVersionHigher(String oldVersion, String newVersion) {
String[] oldVersionParts = oldVersion.split("\\.");
String[] newVersionParts = newVersion.split("\\.");
int versionLength = Math.max(oldVersionParts.length, newVersionParts.length);
for (int i = 0; i < versionLength; i++) {
int oldVersionNumber = oldVersionParts.length > i ? Integer.parseInt(oldVersionParts[i]) : 0;
int newVersionNumber = newVersionParts.length > i ? Integer.parseInt(newVersionParts[i]) : 0;
if (newVersionNumber != oldVersionNumber) {
return newVersionNumber > oldVersionNumber;
}
}
return false;
}
}

View File

@ -1,4 +1,8 @@
lang=language lang=language
defaultNetwork=defaultGateNetwork
use-mysql=
ignoreEntrance=
portal-save-location=folders.portalFolder
portal-folder=folders.portalFolder portal-folder=folders.portalFolder
gate-folder=folders.gateFolder gate-folder=folders.gateFolder
default-gate-network=gates.defaultGateNetwork default-gate-network=gates.defaultGateNetwork
@ -18,11 +22,28 @@ debug=debugging.debug
permdebug=debugging.permissionDebug permdebug=debugging.permissionDebug
useiconomy=economy.useEconomy useiconomy=economy.useEconomy
useeconomy=economy.useEconomy useeconomy=economy.useEconomy
cost-to-use=economy.useCost
cost-to-create=economy.createCost
createcost=economy.createCost createcost=economy.createCost
destroycost=economy.destroyCost destroycost=economy.destroyCost
usecost=economy.useCost usecost=economy.useCost
toowner=economy.toOwner toowner=economy.toOwner
cost-destination=economy.chargeFreeDestination
chargefreedestination=economy.chargeFreeDestination chargefreedestination=economy.chargeFreeDestination
freegatesgreen=economy.freeGatesGreen freegatesgreen=economy.freeGatesGreen
CheckUpdates= CheckUpdates=
economy.freeGatesGreen=economy.freeGatesColored economy.freeGatesGreen=economy.freeGatesColored
teleportMessage=
registerMessage=
destroyzMessage=
noownersMessage=
unselectMessage=
collisinMessage=
cantAffordToUse=
cantAffordToNew=
portal-open=
portal-closed=
cost-type=
cost-to-activate=
taxaccount=taxAccount
usevault=

View File

@ -1,7 +1,7 @@
# stargate Configuration File # stargate Configuration File
# Main stargate config # Main stargate config
# language - The language file to load for messages # language - The language file to load for messages (de,en,es,fr,hu,it,ja,nb-no,nl,nn-no,pt-br,ru,zh_cn)
language: en language: en
# adminUpdateAlert - Whether to alert admins about new plugin updates # adminUpdateAlert - Whether to alert admins about new plugin updates
adminUpdateAlert: true adminUpdateAlert: true
@ -40,7 +40,8 @@ gates:
destroyedByExplosion: false destroyedByExplosion: false
# verifyPortals - Whether all the non-sign blocks are checked to match the gate layout when a stargate is loaded. # verifyPortals - Whether all the non-sign blocks are checked to match the gate layout when a stargate is loaded.
verifyPortals: false verifyPortals: false
# protectEntrance - Whether to protect gate entrance material (More resource intensive. Only enable if using destroyable open/closed material) # protectEntrance - Whether to protect gate entrance material (More resource intensive. Only enable if using
# destroyable open/closed material)
protectEntrance: false protectEntrance: false
functionality: functionality:
enableBungee: false enableBungee: false
@ -48,16 +49,21 @@ gates:
handleVehicles: true handleVehicles: true
# handleEmptyVehicles - Whether to allow empty vehicles through gates (chest/hopper/tnt/furnace minecarts included) # handleEmptyVehicles - Whether to allow empty vehicles through gates (chest/hopper/tnt/furnace minecarts included)
handleEmptyVehicles: true handleEmptyVehicles: true
# handleCreatureTransportation - Whether to allow players to transport creatures by sending vehicles (minecarts, boats) through gates # handleCreatureTransportation - Whether to allow players to transport creatures by sending vehicles (minecarts,
# boats) through gates
handleCreatureTransportation: true handleCreatureTransportation: true
# handleNonPlayerVehicles - Whether to allow vehicles with a passenger which is not a player through gates. handleCreatureTransportation must be enabled # handleNonPlayerVehicles - Whether to allow vehicles with a passenger which is not a player through gates.
# handleCreatureTransportation must be enabled
handleNonPlayerVehicles: true handleNonPlayerVehicles: true
# handleLeashedCreatures - Whether to allow creatures lead by a player to teleport with the player # handleLeashedCreatures - Whether to allow creatures lead by a player to teleport with the player
handleLeashedCreatures: true handleLeashedCreatures: true
# enableCraftBookRemoveOnEjectFix - Whether to enable a fix that causes loss of NBT data, but allows vehicle
# teleportation to work when CraftBook's remove minecart/boat on eject setting is enabled
enableCraftBookRemoveOnEjectFix: false
# I------------I-------------I # # ######################## #
# stargate economy options # # stargate economy options #
# I------------I-------------I # # ######################## #
economy: economy:
# useEconomy - Whether to use an economy plugin # useEconomy - Whether to use an economy plugin
useEconomy: false useEconomy: false
@ -76,11 +82,26 @@ economy:
# freeGatesColor - The color to use for marking free gates # freeGatesColor - The color to use for marking free gates
freeGatesColor: DARK_GREEN freeGatesColor: DARK_GREEN
# I-------I-------I # # ############# #
# Debug options # # Debug options #
# I-------I-------I # # ############# #
debugging: debugging:
# debug - Debug -- Only enable if you have issues, massive console output # debug - Debug -- Only enable if you have issues, massive console output
debug: false debug: false
# permissionDebug - This will output any and all Permissions checks to console, used for permissions debugging (Requires debug: true) # permissionDebug - This will output any and all Permissions checks to console, used for permissions debugging
permissionDebug: false # (Requires debug: true)
permissionDebug: false
advanced:
# waitForPlayerAfterTeleportDelay - The amount of ticks to wait before adding a player as passenger of a vehicle.
# On slow servers, a value of 6 is required to avoid client glitches after teleporting on a vehicle.
waitForPlayerAfterTeleportDelay: 6
# ############## #
# Dynmap options #
# ############## #
dynmap:
# enableDynmap - Whether to display Stargates in Dynmap's map
enableDynmap: true
# dynmapIconsHiddenByDefault - Whether to hide the set of Stargate icons by default, requiring users to
# manually enable them with a checkbox.
dynmapIconsHiddenByDefault: true

View File

@ -0,0 +1,44 @@
author=furplag
prefix=[Stargate]
teleportMsg=テレポート
destroyMsg=ゲートが破壊されました
invalidMsg=無効な行き先
blockMsg=ブロックされた行き先
destEmpty=行き先リストが空です
denyMsg=アクセスが拒否されました
reloaded= Stargate をリロードしました
ecoDeduct=cost の値引き
ecoRefund=cost の返金
ecoObtain= Stargate portal から cost を得ました
ecoInFunds=資金の不足
ecoLoadError= Vault が読み込まれましたが、Economy プラグインをフックできませんでした
vaultLoadError=Economy は有効になっていますが、Vault をロードできないため Economy は無効化されました
vaultLoaded= Vault vversion が見つかりました
createMsg=ゲートが作成されました
createNetDeny=対象のネットワークにアクセスできません
createGateDeny=対象のゲートレイアウトにアクセスできません
createPersonal=パーソナルネットワーク上にゲートを作成する
createNameLength=ゲート名が短すぎるか長すぎます
createExists=すでに存在するゲート名です
createFull=対象のネットワークはいっぱいです
createWorldDeny=あなたはその世界にアクセスできません
createConflict=ゲートが既存のゲートと競合しています
signRightClick=右クリック
signToUse=ゲートを使用する
signRandom=ランダム
signDisconnected=切断
signInvalidGate=無効なゲート
bungeeDisabled=BungeeCord サポートは無効になっています
bungeeDeny=BungeeCord ゲートを作成する権限がありません
bungeeEmpty=BungeeCord ゲートには、行き先とネットワークの両方が必要です
bungeeSign=テレポート先:
portalInfoTitle=[STARGATE INFO]
portalInfoName=ゲート名: name
portalInfoDestination=行き先: destination
portalInfoNetwork=ネットワーク: network
portalInfoServer=サーバー: server

View File

@ -0,0 +1,39 @@
author=YKDZ
signRightClick=右键
ecoLoadError=Vault 已加载, 但未检测到合适的经济插件
createConflict=星门与现有星门冲突
invalidMsg=无效的目的地
prefix=[星门]
ecoObtain=从星门 %portal% 收取了 %cost%
vaultLoaded=检测到 Vault v%version%
reloaded=星门插件已重载
bungeeDeny=你没有创建跨服星门的权限.
signToUse=以使用星门
signInvalidGate=未知星门
bungeeEmpty=跨服星门需要提供目的地和网络.
createMsg=星门已创建
bungeeDisabled=跨服功能已被禁用.
blockMsg=目的地被阻挡
ecoInFunds=余额不足
createNameLength=名称过短或过长.
vaultLoadError=未检测到Vault. 经济模块已禁用
denyMsg=访问被拒
ecoDeduct=花费 %cost%
signDisconnected=已取消链接
createNetDeny=你没有这个星门网络的许可
bungeeSign=传送到
portalInfoName=名称: %name%
destroyMsg=星门已被破坏
portalInfoTitle=[星门信息]
createExists=与已有星门重名
teleportMsg=已传送
createGateDeny=你没有使用这个星门结构的权限
signRandom=随机
portalInfoServer=服务器: %server%
createWorldDeny=你没有链接这个世界的权限
portalInfoDestination=目的地: %destination%
portalInfoNetwork=星门网络: %network%
destEmpty=目的地列表为空
createPersonal=在私人网络中创建星门
ecoRefund=退款 %cost%
createFull=此星门网络已满

View File

@ -1,12 +1,12 @@
name: Stargate name: Stargate
main: net.knarcraft.stargate.Stargate main: net.knarcraft.stargate.Stargate
version: 0.9.3.3 version: '${project.version}'
description: Stargate mod for Bukkit Revived description: Stargate mod for Bukkit Revived
author: EpicKnarvik97 author: EpicKnarvik97
authors: [ Drakia, PseudoKnight, EpicKnarvik97 ] authors: [ Drakia, PseudoKnight, EpicKnarvik97 ]
website: https://git.knarcraft.net/EpicKnarvik97/Stargate website: https://git.knarcraft.net/EpicKnarvik97/Stargate
api-version: 1.18 api-version: 1.18
softdepend: [ Vault ] softdepend: [ Vault, dynmap ]
commands: commands:
stargate: stargate:
aliases: aliases: