Compare commits

...
Author SHA1 Message Date
main() caf4f1b566 Bukkit perms are broken.
Or at least they don't work the way they (in my opinion) should. Take a
look at HierarchyPermission.java for a detailed explanation.
2013-04-13 02:26:19 +02:00
main() 4a66a2f5bb If the debug level is >= 1: stacktrace 2013-03-18 18:02:55 +01:00
main() a8040abd52 "Not MV's fault"-Message for getChunkGenerator()
If a plugin, for whatever weird reason, gets loaded and enabled correctly,
but just getDefaultWorldGenerator() throws, people might think it's MV's
fault. Not anymore.
2013-03-18 17:27:03 +01:00
Jeremy Wood 72a14719ac Now using apache commons for file operations. Hopefully we will get more success with deleting and copying stuff. May fix Inventories test failures. 2013-03-11 15:35:05 -04:00
main() 2b827a1fae Style fixes. 2013-03-02 13:13:24 +01:00
main() e45520c43b Update checkstyle. 2013-03-02 13:13:09 +01:00
main() 0fb33d12d6 Now mocking plugin.getLogger() in the tests.
Fixes the test issues with AllPay.
2013-03-02 12:31:31 +01:00
main() ebe44ed99e Fixed the GenericBank imports 2013-03-02 12:24:05 +01:00
Jeremy Wood 23ba7fe73b Updated to AllPay 13. 2013-02-26 09:49:38 -05:00
Jeremy Wood 4efa97ee0e Removing deprecated getMVConfiguration() method because I suspect it could be related to some issues. 2013-02-20 13:56:24 -05:00
Jeremy Wood 8bfe3a5473 Don't try to set search radius when portal travel agent is null. Fixes #1072. 2013-02-04 15:15:52 -05:00
Jeremy Wood 07a38e3e58 Should fix issue where gamemode/flight change on /reload of server due to permission issues. 2013-01-02 13:20:52 -05:00
Jeremy Wood 360c63fad9 Updated to AllPay 11 2013-01-02 11:44:38 -05:00
Jeremy Wood 2a5edc4f91 Added argument check to setBlockSafety. 2012-12-27 16:02:46 -05:00
main() fa9191dd8f The message now CLEARLY states that it's not Multiverse's fault. 2012-12-22 15:26:20 +01:00
main() 4043d5abcb Getting the generator is now wrapped in a try block.
The Bukkit API calls a plugin method. If that method throws exceptions, they fall through right into our face and then Bukkit blames us. Not good.
Thanks andrewkm for mentioning this.
2012-12-22 00:53:03 +01:00
Jeremy Wood eff56f74da Changed the default portal search radius back to match vanilla's 128 instead of 16. 2012-12-21 10:14:45 -05:00
Jeremy Wood d97a9bccde Now building against Vault 1.2.20 which is hosted on our own repo now. 2012-12-13 08:50:32 -05:00
Jeremy Wood 55741b524d Added bats to animals for the time being. Fixes #996 2012-12-10 23:27:55 -05:00
Jeremy Wood 186d3f15a4 Woo, Travis.ci! 2012-12-10 12:04:26 -08:00
Jeremy Wood 841f6f05df Added "/mv gamerule" and "/mv gamerules" for setting and listing game rules per world. Fixes #987. 2012-12-03 15:05:58 -05:00
Jeremy Wood ebc2a516bb Added world property 'allowFlight' to disable flying per world. Does not have an override permission yet. Adds #440. 2012-12-03 11:59:01 -05:00
Jeremy Wood 9e029ad6ae Maps can now be made for non default worlds! Fixes #972 2012-11-30 13:08:15 -05:00
main() b2135a8f42 Added world seed to the info command.
Fixes #627.
2012-11-28 14:39:07 +01:00
Jeremy Wood 8cbffd1cee Now building against Bukkit 1.4.5-R0.2 2012-11-27 15:59:24 -05:00
Jeremy Wood ff22077adf New worlds now use the correct scale. Fixes #979. 2012-11-27 14:09:33 -05:00
Jeremy Wood 60c0a1ab92 Fixed world spawns not keeping pitch + yaw. Fixes #976 2012-11-23 12:30:11 -05:00
Jeremy Wood 58eeecbcb8 Fixed issue where Multiverse always checks block safety to fix world spawns on startup/reload. 2012-11-23 11:49:14 -05:00
Jeremy Wood 876456b932 Fixed up some migration issues caused by WorldProperties refactor. Fixes #968. 2012-11-19 14:05:07 -05:00
Jeremy Wood 18db50ca56 MVWorld now throws IllegalStateException when it cannot obtain a world reference. This should help pinpoint the source of sometimes cryptic exceptions elsewhere. 2012-11-15 13:49:11 -05:00
Jeremy Wood cce1ccc967 Now caches the world properties before unloading the world in order to prevent NPE on unload then load. Really fixes #947. 2012-11-15 09:30:19 -05:00
Jeremy Wood e5537dd8f1 "mv regen" now respects world type! 2012-11-14 20:55:12 -05:00
Jeremy Wood 0c7ba2ae67 Fixed tests for entity purger changes. 2012-11-14 15:52:21 -05:00
Jeremy Wood bbfc672582 Improved world purger debug. 2012-11-14 15:19:09 -05:00
Jeremy Wood a65dc4966b Now removes projectiles shot by the entities removed by the purger. Should fix #958. 2012-11-14 15:11:55 -05:00
Jeremy Wood 4780f87278 Now uses world UUID to retrieve world reference. 2012-11-14 14:24:10 -05:00
Jeremy Wood b11d911e4a Newly created END worlds will now use a scale of 16. This will result in people ending up invariably closer to the end island when teleporting in while using MV-NetherPortals. 2012-11-14 13:58:08 -05:00
Jeremy Wood 155aad8bf2 Multiverse now uses it's own portal search radius by default (16 blocks instead of bukkit's 128). 2 new configuration options added to adjust this behaviour. 2012-11-14 13:52:37 -05:00
Jeremy Wood 6e1d4ef961 Block safety debugging moved to finest level. 2012-11-14 12:52:33 -05:00
Jeremy Wood cfa5a04e3a Fixes #960 2012-11-14 09:08:04 -05:00
Jeremy Wood 7d1c47c2fc Shifted world properties to its own class WorldProperties so we can now only initialize an MVWorld if there is a 'more solid' world reference. Let's hope this works! Should fix #947 2012-11-13 17:30:35 -05:00
Jeremy Wood 957c55955d Now using SerializationConfig 1.7 2012-11-13 13:39:22 -05:00
main() 0226ab9609 Style again. 2012-11-06 17:52:29 +01:00
Jeremy Wood b888561d98 Added package-private method for setting MVWorld plugin and name. Fixes #923. 2012-11-05 13:08:37 -05:00
Jeremy Wood f210851294 Changed how we deal with CB world reference. Partially fixes #923. 2012-11-05 13:02:03 -05:00
main() 73e394d5ec Style. 2012-11-05 16:40:06 +01:00
Jeremy Wood 63f8811b67 Fixed #942. 2012-11-05 09:05:11 -05:00
Jeremy Wood d01ce71343 Fixed #935. 2012-10-31 08:31:07 -04:00
Jeremy Wood fe00aae7e3 Fixes #934 - Vault dependency issue. 2012-10-30 08:45:05 -04:00
Jeremy Wood d4347d0cff Fixed incorrect log level. 2012-10-25 15:48:28 -03:00
Jeremy Wood b033d59b8a Optimized some log messages and change some Level.INFO messages to Level.CONFIG for the new silent start mode. Fixes #697. 2012-10-25 14:36:44 -04:00
Jeremy Wood aedbfd7bab Added command "mv silent [on|off]" for enabling silent startup mode. 2012-10-25 14:35:22 -04:00
Jeremy Wood b93822502e Reverted debug command. 2012-10-25 14:02:01 -04:00
Jeremy Wood f053f0546b Now using Logging 1.0.9! 2012-10-25 13:56:57 -04:00
Jeremy Wood af3b3d0fab Added ability to set debug level to -1 to disable common startup messages. 2012-10-25 10:43:57 -04:00
Jeremy Wood b1fa677330 Now using Logging 1.0.8 2012-10-25 10:35:27 -04:00
main() 9691a0f978 Merge pull request #931 from ammaraskar/limit
Add player limit per world. Closes #727.
2012-10-25 02:11:29 -07:00
Ammar Askar 0b1a387003 Add player limit per world. Addresses #727 2012-10-25 14:02:27 +05:00
Jeremy Wood 4ce503f55e Cow using EnumSet for maximum performance!!!! 2012-10-23 14:26:09 -04:00
main() 74947a7efd Fixed all other style warnings 2012-10-23 16:58:16 +02:00
main() 85cd71cb8a Fixed high priority style warnings 2012-10-23 16:49:08 +02:00
Jeremy Wood 3ad7d86f74 Deprecated DebugLog. 2012-10-22 17:40:39 -04:00
Jeremy Wood ac9194ec87 Now building with SerializationConfig 1.6c, finally fixes weird config exception messages. 2012-10-22 17:35:06 -04:00
main() 96e8208f3d Merge branch 'ammaraskar_folder' 2012-10-22 19:08:15 +02:00
Ammar Askar 895360ce8b Only delete world folder contents on mv regen, fixes #767 2012-10-22 19:06:19 +02:00
main() 59e34ef353 Merge pull request #925 from ammaraskar/entities
Add golems to animals fixes #891
2012-10-22 08:39:44 -07:00
Ammar Askar 11e556c099 Add golems to animals fixes #891 2012-10-22 20:34:01 +05:00
main() a9579a6594 Merge pull request #922 from ammaraskar/spawn
Added configurable animal and monster ticks per spawn setting. Fixes #519
2012-10-22 04:12:42 -07:00
Ammar Askar 5a1fe2a9e5 Added configurable animal and monster ticks per spawn setting. Fixes #519 2012-10-22 13:20:09 +05:00
Eric Stokes 1c5c792cf3 A broadcast is not needed if we're not doing anything 2012-10-21 18:57:54 -06:00
Eric Stokes dbe9494dbf Fixed Bed Spawns
This fixes #652 and fixes #916
This also fixes some other issues with NullPointerExceptions when trying to teleport to a bed if it was invalid.
2012-10-21 18:49:48 -06:00
Jeremy Wood b116effa2b Using HashSet instead of ArrayList for better contains() efficiency. 2012-10-21 17:55:41 -04:00
Jeremy Wood d361ceb45b Increased efficiency/safety of recent /mv who changes. 2012-10-21 17:49:51 -04:00
Eric Stokes 35709f5389 Tell user when creating a duplicate world
Fixes #921
2012-10-21 14:49:56 -06:00
Eric Stokes b45a4cf20a Fix NPCs Showing up in mv who
This fixes #501. FINALLY!

If anyone wants NPCs back, open a ticket, and I'll add a flag, but this is now the default behavior.
2012-10-21 14:22:12 -06:00
Eric Stokes 009ceeeede Fixed #918, Update to RB
Also added a test for #918, I probably need one more (to test that generators DO work) but I just tested that ingame this time.
2012-10-21 13:38:36 -06:00
Jeremy Wood 19fb9df5cf Added online player count / max players to /mv who header 2012-10-21 00:39:13 -04:00
Jeremy Wood 0829df01aa Readded the accidently removed shading of AllPay! 2012-10-20 20:55:56 -04:00
Jeremy Wood 78ac068a3f Fixed world's not charging correctly. Fixes #893. Fixes #777. Possibly fixes #723. That's a 3fer, good buddy. 2012-10-20 20:49:15 -04:00
Jeremy Wood 57da3df860 Added in Vault as the prefered method for checking economy stuff. Will defer to AllPay for item based world costs. 2012-10-20 20:43:58 -04:00
Jeremy Wood 74241e3d9c Updated protocol to 18 for Vault. 2012-10-20 20:12:42 -04:00
Jeremy Wood 6a4921d7d1 MVWorld.toString() now outputs JSON data. 2012-10-20 12:44:50 -04:00
Jeremy Wood 271e5f339e Version command now outputs world information instead of juts count. 2012-10-20 12:44:29 -04:00
Eric Stokes ec89db1bed Update MCSTATS to 1.2-SNAPSHOT
1.0-SNAPSHOT is gone from the repo :(
2012-10-19 23:35:48 -06:00
Jeremy Wood 7346cbe48c Actually enables debug logging when enabled via command. 2012-10-19 15:11:02 -04:00
Jeremy Wood ac3049f3ab Now properly enables debug logging on startup if debug logging should be enabled. 2012-10-19 15:10:36 -04:00
Jeremy Wood e82db95bbc Now using Logging 1.0.6! 2012-10-19 15:10:02 -04:00
Jeremy Wood 0d0f167396 Stopped trying to replace the old DebugLog. 2012-10-18 21:39:43 -04:00
Jeremy Wood b35a0325b8 Now using Logging 1.0.4 2012-10-18 21:19:33 -04:00
Jeremy Wood 3572d3fbe7 Now using Logging 1.0.3! 2012-10-18 15:17:52 -04:00
Jeremy Wood 7304269866 Upgraded to testificated Logging 1.0.2! 2012-10-18 14:46:25 -04:00
Jeremy Wood d7535b0551 replaced logging with com.dumptruckman.minecraft:Logging lib. 2012-10-17 14:23:00 -04:00
main() 0437a4bd92 Why is/was this "Multiverse-Adventure"... 2012-10-17 14:26:40 +02:00
main() d881908ecc Made entity listener use the world purger's logic
This should fix #872 and most other spawning issues.
2012-09-20 20:01:55 +02:00
Jeremy Wood 3715bc8bc5 Should now detect Async chat availability for even better backwards compatibility. 2012-09-05 20:53:59 -04:00
main() a9f00a46f5 Fixed #859
The WhoCommand was handling invisible players incorrectly
2012-08-26 14:47:01 +02:00
Jeremy Wood d9a7275682 Stop checking for null worlds. 2012-08-21 15:06:55 -04:00
Jeremy Wood 80f6a0159c Now using ConcurrentHashMap instead of ReentrantLock for caching player world. 2012-08-21 15:06:33 -04:00
Jeremy Wood f2e1053b88 Now using ConcurrentHashMap instead of locks for worlds Map. 2012-08-21 14:54:49 -04:00
Jeremy Wood e975968637 MVWorld properties now volatile instead of using thread lock. 2012-08-21 14:25:11 -04:00
Jeremy Wood a778d353c4 Config now volatile instead of using thread lock. 2012-08-21 14:19:05 -04:00
Jeremy Wood d40e67b47d Config properties now volatile instead of using thread lock. 2012-08-21 14:17:24 -04:00
Jeremy Wood 9196973d1c Fixed NPE in world loading.. Thanks Grimlock257 for spotting this. 2012-08-21 13:20:13 -04:00
Jeremy Wood 242d20884c Now building against Bukkit 1.3.1-R2.1-SNAPSHOT 2012-08-21 09:16:28 -04:00
main() b909af873d Should fix #847
(NPE in the GeneratorPlotter for worlds with a null generator)
2012-08-20 10:22:39 +02:00
main() e6f7ba5ac9 Fixed the tests 2012-08-18 15:17:17 +02:00
main() 4ecb28b3bb Less duplicate code ... I think. 2012-08-18 15:13:09 +02:00
main() d0ea4168bc Style! 2012-08-18 14:54:18 +02:00
main() fd9464ced1 More anchor permissions (as suggested in #831) 2012-08-18 14:45:15 +02:00
Jeremy Wood 49eb93af2e Once again prints debug mode output to the console 2012-08-15 11:33:16 -04:00
Jeremy Wood 9274570fa4 Added config option for setting whether or not to use async chat. (Default true (uses async)) 2012-08-15 09:27:52 -04:00
Jeremy Wood 319a701a16 Modifying world values now persists again! (When the hell did this break???) 2012-08-14 15:00:08 -04:00
Jeremy Wood 807c8d0f2c Debug setting saves to config now. 2012-08-13 13:52:25 -04:00
Jeremy Wood 29d97274fe Stopped being dumb and denying bukkit of it's precious invisible constraints for ConfigurationSerializable. Fixes #827. 2012-08-13 13:51:42 -04:00
Jeremy Wood eb1dc502cd Now using ReentrantLock instead of synchronized blocks. Should help debug lag issue. 2012-08-11 23:21:58 -04:00
Jeremy Wood 622fb19c4a Using logging instead of System.out... 2012-08-09 09:18:06 -04:00
Jeremy Wood 5705b5b6a0 Added missing import... 2012-08-09 09:15:07 -04:00
main() 1d1a2213c1 Merge branch 'metrics' 2012-08-09 13:43:07 +02:00
Jeremy Wood 4dd3df26a5 Now building against Bukkit-1.3.1-R1.0 2012-08-08 10:56:22 -04:00
main() 39293482d2 Removed duplicate maven source plugin 2012-08-06 18:44:42 +02:00
main() 9813e5f531 MBot's ?internalerror is useful but this is better 2012-08-06 18:41:02 +02:00
main() 48adbec011 dat style
CheckStyle is merciless!
2012-08-06 15:34:01 +02:00
main() a9a5d7467a Fixed world regeneration 2012-08-06 15:17:14 +02:00
main() b8a0891c4c Fixed again... 2012-08-06 12:06:50 +02:00
main() 53567d4646 Hopefully fixed the tests 2012-08-06 11:54:54 +02:00
main() 3395f3d7c7 We shouldn't try to load deleted worlds 2012-08-06 11:29:54 +02:00
Jeremy Wood e197091bb2 Added better support for large biomes. 2012-08-05 15:40:58 -04:00
Jeremy Wood ede0395d39 Mapping the known world of players for Async chat event. 2012-08-05 14:58:24 -04:00
Jeremy Wood 17963964c7 Minor test update. 2012-08-05 14:53:41 -04:00
Jeremy Wood bb0e2e4a2d Tests now using AsyncPlayerChatEvent. 2012-08-05 00:28:00 -04:00
Jeremy Wood ce4e608cf4 MultiverseCoreConfiguration.setDefaults() now protected as it should be. 2012-08-05 00:27:33 -04:00
Jeremy Wood 944f961ee5 Removed synchronization from setDefaults() due to how SerializationConfig operates. 2012-08-05 00:26:55 -04:00
Jeremy Wood 5335e73707 Now using AsyncPlayerChatEvent... let's hope for the best! 2012-08-05 00:11:39 -04:00
Jeremy Wood d05e2b500f Synchronized world properties required by Async chat event. 2012-08-05 00:11:13 -04:00
Jeremy Wood b2f3b74062 Synchronized all access to worlds map in WorldManager. 2012-08-05 00:00:46 -04:00
Jeremy Wood 16e42f6469 Finalized some object in MultiverseCore to help with thread-safe migration. 2012-08-04 23:51:43 -04:00
Jeremy Wood a31dc83635 Synchronized getting/setting of mv config object. 2012-08-04 23:50:01 -04:00
Jeremy Wood 7b99130bfa Synchronized config values to be used in new Async chat event. 2012-08-04 23:43:09 -04:00
Matt H f57468126a Added '/mv clone' command to clone a world. 2012-08-04 14:29:13 -06:00
Jeremy Wood d17fee6b7c Now building against Bukkit 1.3.1-R0.1-SNAPSHOT. 2012-08-03 13:29:55 -04:00
Jeremy Wood 1a943e42a9 Added maven source and javadoc plugins. 2012-08-03 13:28:32 -04:00
Jeremy Wood 2b80ca80ae Bumped protocol from 16 to 17. 2012-07-25 22:10:06 -04:00
Jeremy Wood 24e26bb7d7 Added buscript Javascript library. 2012-07-25 22:09:28 -04:00
Jeremy Wood 6133cf6bdf Bumped protocol from 15 to 16 2012-07-19 21:10:51 -04:00
Jeremy Wood 085c7a1ccc Migrated Multiverse-Adventure's copyFolder() into core. 2012-07-19 21:08:39 -04:00
main() dd0b2137d6 Changes... 2012-07-12 17:34:25 +02:00
main() 8a4ba2a66c Metrics! 2012-07-12 17:24:23 +02:00
75 changed files with 3569 additions and 1137 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
language: java
jdk:
- oraclejdk6
notifications:
email: false
-1
View File
@@ -104,7 +104,6 @@
</module>
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="DoubleCheckedLocking"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="HiddenField">
+125 -13
View File
@@ -20,6 +20,16 @@
<id>Bukkit Official</id>
<url>http://repo.bukkit.org/content/repositories/public</url>
</repository>
<!-- Required for Metrics -->
<repository>
<id>mcstats</id>
<url>http://repo.mcstats.org/content/repositories/snapshots</url>
</repository>
<!-- Required for Vault -->
<!--repository>
<id>herocraft</id>
<url>http://ci.herocraftonline.com/plugin/repository/everything/</url>
</repository-->
</repositories>
<pluginRepositories>
@@ -101,12 +111,6 @@
</archive>
</configuration>
</plugin>
<!-- Maven Source Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@@ -130,12 +134,39 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.8</version>
<version>2.10</version>
<configuration>
<enableRulesSummary>true</enableRulesSummary>
<configLocation>${project.basedir}/config/mv_checks.xml</configLocation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>javadoc-jar</id>
<phase>verify</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@@ -150,8 +181,11 @@
<artifactSet>
<includes>
<include>me.main__.util:SerializationConfig</include>
<include>com.fernferret.allpay:AllPay</include>
<include>com.pneumaticraft.commandhandler:CommandHandler</include>
<include>com.dumptruckman.minecraft:buscript</include>
<include>org.mcstats:metrics</include>
<include>com.dumptruckman.minecraft:Logging</include>
<include>com.fernferret.allpay:AllPay</include>
</includes>
</artifactSet>
<relocations>
@@ -167,20 +201,64 @@
<pattern>com.pneumaticraft.commandhandler</pattern>
<shadedPattern>com.pneumaticraft.commandhandler.multiverse</shadedPattern>
</relocation>
<relocation>
<pattern>buscript</pattern>
<shadedPattern>buscript.multiverse</shadedPattern>
</relocation>
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>org.mcstats.multiverse</shadedPattern>
</relocation>
<relocation>
<pattern>com.dumptruckman.minecraft.util.Logging</pattern>
<shadedPattern>com.onarandombox.MultiverseCore.utils.CoreLogging</shadedPattern>
</relocation>
<relocation>
<pattern>com.dumptruckman.minecraft.util.DebugLog</pattern>
<shadedPattern>com.onarandombox.MultiverseCore.utils.DebugFileLogger</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
<execution>
<id>apache-commons-io</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>org.apache.commons:commons-io</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.apache.commons</pattern>
<shadedPattern>org.apache.commons.multiverse</shadedPattern>
</relocation>
</relocations>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- Bukkit Dependency -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.2.5-R1.0</version>
<version>1.4.5-R0.2</version>
<!-- If you want the lates, use this -->
<!-- <version>LATEST</version> -->
<type>jar</type>
@@ -198,20 +276,27 @@
<dependency>
<groupId>me.main__.util</groupId>
<artifactId>SerializationConfig</artifactId>
<version>1.6b</version>
<version>1.7</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- End of SerializationConfig Dependency -->
<!-- Start of AllPay Dependency -->
<!-- Start of Economy Dependency -->
<dependency>
<groupId>com.fernferret.allpay</groupId>
<artifactId>AllPay</artifactId>
<version>10</version>
<version>13</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- End of AllPay Dependency -->
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>Vault</artifactId>
<version>1.2.20</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- End of Economy Dependency -->
<!-- Start of CommandHandler Dependency -->
<dependency>
<groupId>com.pneumaticraft.commandhandler</groupId>
@@ -221,6 +306,33 @@
<scope>compile</scope>
</dependency>
<!-- End of CommandHandler Dependency -->
<!-- Start of Buscript Dependency -->
<dependency>
<groupId>com.dumptruckman.minecraft</groupId>
<artifactId>buscript</artifactId>
<version>1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- End of Buscript Dependency -->
<!-- Start of Metrics Dependency -->
<dependency>
<groupId>org.mcstats</groupId>
<artifactId>metrics</artifactId>
<version>1.2-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- End of Metrics Dependency -->
<!-- Start of Logging Dependency -->
<dependency>
<groupId>com.dumptruckman.minecraft</groupId>
<artifactId>Logging</artifactId>
<version>1.0.9</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- End of Logging Dependency -->
<!-- Start of Test Dependencies -->
<dependency>
<groupId>junit</groupId>
File diff suppressed because it is too large. Load diff
@@ -7,8 +7,11 @@
package com.onarandombox.MultiverseCore;
import buscript.Buscript;
import com.dumptruckman.minecraft.util.Logging;
import com.fernferret.allpay.AllPay;
import com.fernferret.allpay.GenericBank;
import com.fernferret.allpay.commons.GenericBank;
import com.onarandombox.MultiverseCore.MVWorld.NullLocation;
import com.onarandombox.MultiverseCore.api.BlockSafety;
import com.onarandombox.MultiverseCore.api.Core;
import com.onarandombox.MultiverseCore.api.LocationManipulation;
@@ -20,6 +23,7 @@ import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.commands.AnchorCommand;
import com.onarandombox.MultiverseCore.commands.CheckCommand;
import com.onarandombox.MultiverseCore.commands.CloneCommand;
import com.onarandombox.MultiverseCore.commands.ConfigCommand;
import com.onarandombox.MultiverseCore.commands.ConfirmCommand;
import com.onarandombox.MultiverseCore.commands.CoordCommand;
@@ -27,6 +31,8 @@ import com.onarandombox.MultiverseCore.commands.CreateCommand;
import com.onarandombox.MultiverseCore.commands.DebugCommand;
import com.onarandombox.MultiverseCore.commands.DeleteCommand;
import com.onarandombox.MultiverseCore.commands.EnvironmentCommand;
import com.onarandombox.MultiverseCore.commands.GameruleCommand;
import com.onarandombox.MultiverseCore.commands.GamerulesCommand;
import com.onarandombox.MultiverseCore.commands.GeneratorCommand;
import com.onarandombox.MultiverseCore.commands.HelpCommand;
import com.onarandombox.MultiverseCore.commands.ImportCommand;
@@ -42,7 +48,9 @@ import com.onarandombox.MultiverseCore.commands.PurgeCommand;
import com.onarandombox.MultiverseCore.commands.RegenCommand;
import com.onarandombox.MultiverseCore.commands.ReloadCommand;
import com.onarandombox.MultiverseCore.commands.RemoveCommand;
import com.onarandombox.MultiverseCore.commands.ScriptCommand;
import com.onarandombox.MultiverseCore.commands.SetSpawnCommand;
import com.onarandombox.MultiverseCore.commands.SilentCommand;
import com.onarandombox.MultiverseCore.commands.SpawnCommand;
import com.onarandombox.MultiverseCore.commands.TeleportCommand;
import com.onarandombox.MultiverseCore.commands.UnloadCommand;
@@ -56,25 +64,33 @@ import com.onarandombox.MultiverseCore.destination.ExactDestination;
import com.onarandombox.MultiverseCore.destination.PlayerDestination;
import com.onarandombox.MultiverseCore.destination.WorldDestination;
import com.onarandombox.MultiverseCore.event.MVVersionEvent;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import com.onarandombox.MultiverseCore.listeners.MVAsyncPlayerChatListener;
import com.onarandombox.MultiverseCore.listeners.MVChatListener;
import com.onarandombox.MultiverseCore.listeners.MVEntityListener;
import com.onarandombox.MultiverseCore.listeners.MVMapListener;
import com.onarandombox.MultiverseCore.listeners.MVPlayerChatListener;
import com.onarandombox.MultiverseCore.listeners.MVPlayerListener;
import com.onarandombox.MultiverseCore.listeners.MVPluginListener;
import com.onarandombox.MultiverseCore.listeners.MVPortalListener;
import com.onarandombox.MultiverseCore.listeners.MVWeatherListener;
import com.onarandombox.MultiverseCore.utils.AnchorManager;
import com.onarandombox.MultiverseCore.utils.DebugLog;
import com.onarandombox.MultiverseCore.utils.MVMessaging;
import com.onarandombox.MultiverseCore.utils.MVPermissions;
import com.onarandombox.MultiverseCore.utils.MVPlayerSession;
import com.onarandombox.MultiverseCore.utils.SimpleBlockSafety;
import com.onarandombox.MultiverseCore.utils.SimpleLocationManipulation;
import com.onarandombox.MultiverseCore.utils.SimpleSafeTTeleporter;
import com.onarandombox.MultiverseCore.utils.UnsafeCallWrapper;
import com.onarandombox.MultiverseCore.utils.VaultHandler;
import com.onarandombox.MultiverseCore.utils.WorldManager;
import com.pneumaticraft.commandhandler.CommandHandler;
import me.main__.util.SerializationConfig.NoSuchPropertyException;
import me.main__.util.SerializationConfig.SerializationConfig;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World.Environment;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.Configuration;
@@ -84,6 +100,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.mcstats.Metrics;
import java.io.File;
import java.io.IOException;
@@ -91,25 +108,25 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The implementation of the Multiverse-{@link Core}.
*/
public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
private static final int PROTOCOL = 15;
private static final int PROTOCOL = 18;
// TODO: Investigate if this one is really needed to be static.
// Doubt it. -- FernFerret
private static Map<String, String> teleportQueue = new HashMap<String, String>();
private AnchorManager anchorManager = new AnchorManager(this);
// TODO please let's make this non-static
private MultiverseCoreConfiguration config;
private volatile MultiverseCoreConfiguration config;
/**
* This method is used to find out who is teleporting a player.
@@ -132,7 +149,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
* @param teleportee The name of the player that was teleported.
*/
public static void addPlayerToTeleportQueue(String teleporter, String teleportee) {
staticLog(Level.FINEST, "Adding mapping '" + teleporter + "' => '" + teleportee + "' to teleport queue");
Logging.finest("Adding mapping '%s' => '%s' to teleport queue", teleporter, teleportee);
teleportQueue.put(teleportee, teleporter);
}
@@ -168,10 +185,6 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
return MultiverseCore.PROTOCOL;
}
// Useless stuff to keep us going.
private static final Logger LOGGER = Logger.getLogger("Minecraft");
private static DebugLog debugLog;
// Setup our Map for our Commands using the CommandHandler.
private CommandHandler commandHandler;
@@ -183,19 +196,22 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Configurations
private FileConfiguration multiverseConfig = null;
private MVWorldManager worldManager = new WorldManager(this);
private final MVWorldManager worldManager = new WorldManager(this);
// Setup the block/player/entity listener.
private MVPlayerListener playerListener = new MVPlayerListener(this);
private MVEntityListener entityListener = new MVEntityListener(this);
private MVPluginListener pluginListener = new MVPluginListener(this);
private MVWeatherListener weatherListener = new MVWeatherListener(this);
private MVPortalListener portalListener = new MVPortalListener(this);
private final MVPlayerListener playerListener = new MVPlayerListener(this);
private final MVEntityListener entityListener = new MVEntityListener(this);
private final MVPluginListener pluginListener = new MVPluginListener(this);
private final MVWeatherListener weatherListener = new MVWeatherListener(this);
private final MVPortalListener portalListener = new MVPortalListener(this);
private MVChatListener chatListener;
// HashMap to contain information relating to the Players.
private HashMap<String, MVPlayerSession> playerSessions;
private VaultHandler vaultHandler;
private GenericBank bank = null;
private AllPay banker;
private Buscript buscript;
private int pluginCount;
private DestinationFactory destFactory;
//private SpoutInterface spoutInterface = null;
@@ -203,6 +219,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
private BlockSafety blockSafety;
private LocationManipulation locationManipulation;
private SafeTTeleporter safeTTeleporter;
private UnsafeCallWrapper unsafeCallWrapper;
private File serverFolder = new File(System.getProperty("user.dir"));
@@ -211,39 +228,36 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Register our config
SerializationConfig.registerAll(MultiverseCoreConfiguration.class);
// Register our world
SerializationConfig.registerAll(MVWorld.class);
SerializationConfig.registerAll(WorldProperties.class);
// Create our DataFolder
getDataFolder().mkdirs();
// Setup our Debug Log
debugLog = new DebugLog("Multiverse-Core", getDataFolder() + File.separator + "debug.log");
debugLog.setStandardLogger(LOGGER);
SerializationConfig.initLogging(debugLog);
Logging.init(this);
SerializationConfig.initLogging(Logging.getLogger());
// Setup our BlockSafety
this.blockSafety = new SimpleBlockSafety(this);
// Setup our LocationManipulation
this.locationManipulation = new SimpleLocationManipulation();
// Setup our SafeTTeleporter
this.safeTTeleporter = new SimpleSafeTTeleporter(this);
this.unsafeCallWrapper = new UnsafeCallWrapper(this);
}
/**
* {@inheritDoc}
* @deprecated This is deprecated.
* @deprecated Now using Vault.
*/
@Override
@Deprecated
public FileConfiguration getMVConfiguration() {
return this.multiverseConfig;
}
/**
* {@inheritDoc}
*/
@Override
public GenericBank getBank() {
return this.bank;
}
@Override
public VaultHandler getVaultHandler() {
return vaultHandler;
}
/**
* {@inheritDoc}
*/
@@ -251,8 +265,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
public void onEnable() {
this.messaging = new MVMessaging();
this.banker = new AllPay(this, LOG_TAG + " ");
// Output a little snippet to show it's enabled.
this.log(Level.INFO, "- Version " + this.getDescription().getVersion() + " (API v" + PROTOCOL + ") Enabled - By " + getAuthors());
this.vaultHandler = new VaultHandler(this);
// Load the defaultWorldGenerators
this.worldManager.getDefaultWorldGenerators();
@@ -281,6 +294,8 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Setup & Load our Configuration files.
loadConfigs();
if (this.multiverseConfig != null) {
Logging.setDebugLevel(getMVConfig().getGlobalDebug());
Logging.setShowingConfig(!getMVConfig().getSilentStart());
this.worldManager.loadDefaultWorlds();
this.worldManager.loadWorlds(true);
} else {
@@ -289,13 +304,25 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
this.anchorManager.loadAnchors();
// Now set the firstspawnworld (after the worlds are loaded):
this.worldManager.setFirstSpawnWorld(config.getFirstSpawnWorld());
this.worldManager.setFirstSpawnWorld(getMVConfig().getFirstSpawnWorld());
try {
config.setFirstSpawnWorld(this.worldManager.getFirstSpawnWorld().getName());
getMVConfig().setFirstSpawnWorld(this.worldManager.getFirstSpawnWorld().getName());
} catch (NullPointerException e) {
// A test that had no worlds loaded was being run. This should never happen in production
}
this.saveMVConfig();
// Register async or sync player chat according to config
try {
Class.forName("org.bukkit.event.player.AsyncPlayerChatEvent");
} catch (ClassNotFoundException e) {
getMVConfig().setUseAsyncChat(false);
}
if (getMVConfig().getUseAsyncChat()) {
this.chatListener = new MVAsyncPlayerChatListener(this, this.playerListener);
} else {
this.chatListener = new MVPlayerChatListener(this, this.playerListener);
}
getServer().getPluginManager().registerEvents(this.chatListener, this);
/*
// Check to see if spout was already loaded (most likely):
if (this.getServer().getPluginManager().getPlugin("Spout") != null) {
@@ -303,6 +330,112 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
this.log(Level.INFO, "Spout integration enabled.");
}
*/
this.initializeBuscript();
this.setupMetrics();
// Output a little snippet to show it's enabled.
Logging.config("Version %s (API v%s) Enabled - By %s", this.getDescription().getVersion(), PROTOCOL, getAuthors());
}
/**
* Initializes the buscript javascript library.
*/
private void initializeBuscript() {
buscript = new Buscript(this);
// Add global variable "multiverse" to javascript environment
buscript.getGlobalScope().put("multiverse", buscript.getGlobalScope(), this);
}
/**
* Plotter for Environment-Values.
*/
private static final class EnvironmentPlotter extends Metrics.Plotter {
private MultiverseCore core;
private final Environment env;
public EnvironmentPlotter(MultiverseCore core, Environment env) {
super(envToString(env));
this.core = core;
this.env = env;
}
private static String envToString(Environment env) {
return new StringBuilder().append(env.name().toUpperCase().charAt(0))
.append(env.name().toLowerCase().substring(1)).toString();
}
@Override
public int getValue() {
int count = 0;
for (MultiverseWorld w : core.getMVWorldManager().getMVWorlds())
if (w.getEnvironment() == env)
count++;
core.log(Level.FINE, String.format("Tracking %d worlds of type %s", count, env));
return count;
}
}
/**
* Plotter for Generator-Values.
*/
private static final class GeneratorPlotter extends Metrics.Plotter {
private MultiverseCore core;
private final String gen;
public GeneratorPlotter(MultiverseCore core, String gen) {
super(gen);
this.core = core;
this.gen = gen;
}
@Override
public int getValue() {
int count = 0;
for (MultiverseWorld w : core.getMVWorldManager().getMVWorlds())
if (gen.equals(w.getGenerator()))
count++;
core.log(Level.FINE, String.format("Tracking %d worlds of type %s", count, gen));
return count;
}
}
private void setupMetrics() {
try {
Metrics m = new Metrics(this);
Metrics.Graph envGraph = m.createGraph("worlds_by_env");
for (Environment env : Environment.values())
envGraph.addPlotter(new EnvironmentPlotter(this, env));
m.addCustomData(new Metrics.Plotter("Loaded worlds") {
@Override
public int getValue() {
return getMVWorldManager().getMVWorlds().size();
}
});
m.addCustomData(new Metrics.Plotter("Total number of worlds") {
@Override
public int getValue() {
return getMVWorldManager().getMVWorlds().size()
+ getMVWorldManager().getUnloadedWorlds().size();
}
});
Set<String> gens = new HashSet<String>();
for (MultiverseWorld w : this.getMVWorldManager().getMVWorlds())
gens.add(w.getGenerator());
gens.remove(null);
gens.remove("null");
Metrics.Graph genGraph = m.createGraph("custom_gens");
for (String gen : gens)
genGraph.addPlotter(new GeneratorPlotter(this, gen));
m.start();
log(Level.FINE, "Metrics have run!");
} catch (IOException e) {
log(Level.WARNING, "There was an issue while enabling metrics: " + e.getMessage());
}
}
private void initializeDestinationFactory() {
@@ -326,7 +459,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
pm.registerEvents(this.pluginListener, this);
pm.registerEvents(this.weatherListener, this);
pm.registerEvents(this.portalListener, this);
pm.registerEvents(new MVMapListener(this), this);
}
/**
@@ -344,15 +477,14 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
MultiverseCoreConfiguration wantedConfig = null;
try {
wantedConfig = (MultiverseCoreConfiguration) multiverseConfig.get("multiverse-configuration");
} catch (Exception e) {
// We're just thinking "no risk no fun" and therefore have to catch and forget this exception
} catch (Exception ignore) {
} finally {
config = ((wantedConfig == null) ? new MultiverseCoreConfiguration() : wantedConfig);
}
this.migrateWorldConfig();
this.worldManager.loadWorldConfig(new File(getDataFolder(), "worlds.yml"));
this.messaging.setCooldown(config.getMessageCooldown());
this.messaging.setCooldown(getMVConfig().getMessageCooldown());
// Remove old values.
this.multiverseConfig.set("enforcegamemodes", null);
@@ -370,47 +502,47 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
*/
private void migrate22Values() {
if (this.multiverseConfig.isSet("worldnameprefix")) {
this.log(Level.INFO, "Migrating 'worldnameprefix'...");
this.config.setPrefixChat(this.multiverseConfig.getBoolean("worldnameprefix"));
Logging.config("Migrating 'worldnameprefix'...");
this.getMVConfig().setPrefixChat(this.multiverseConfig.getBoolean("worldnameprefix"));
this.multiverseConfig.set("worldnameprefix", null);
}
if (this.multiverseConfig.isSet("firstspawnworld")) {
this.log(Level.INFO, "Migrating 'firstspawnworld'...");
this.config.setFirstSpawnWorld(this.multiverseConfig.getString("firstspawnworld"));
Logging.config("Migrating 'firstspawnworld'...");
this.getMVConfig().setFirstSpawnWorld(this.multiverseConfig.getString("firstspawnworld"));
this.multiverseConfig.set("firstspawnworld", null);
}
if (this.multiverseConfig.isSet("enforceaccess")) {
this.log(Level.INFO, "Migrating 'enforceaccess'...");
this.config.setEnforceAccess(this.multiverseConfig.getBoolean("enforceaccess"));
Logging.config("Migrating 'enforceaccess'...");
this.getMVConfig().setEnforceAccess(this.multiverseConfig.getBoolean("enforceaccess"));
this.multiverseConfig.set("enforceaccess", null);
}
if (this.multiverseConfig.isSet("displaypermerrors")) {
this.log(Level.INFO, "Migrating 'displaypermerrors'...");
this.config.setDisplayPermErrors(this.multiverseConfig.getBoolean("displaypermerrors"));
Logging.config("Migrating 'displaypermerrors'...");
this.getMVConfig().setDisplayPermErrors(this.multiverseConfig.getBoolean("displaypermerrors"));
this.multiverseConfig.set("displaypermerrors", null);
}
if (this.multiverseConfig.isSet("teleportintercept")) {
this.log(Level.INFO, "Migrating 'teleportintercept'...");
this.config.setTeleportIntercept(this.multiverseConfig.getBoolean("teleportintercept"));
Logging.config("Migrating 'teleportintercept'...");
this.getMVConfig().setTeleportIntercept(this.multiverseConfig.getBoolean("teleportintercept"));
this.multiverseConfig.set("teleportintercept", null);
}
if (this.multiverseConfig.isSet("firstspawnoverride")) {
this.log(Level.INFO, "Migrating 'firstspawnoverride'...");
this.config.setFirstSpawnOverride(this.multiverseConfig.getBoolean("firstspawnoverride"));
Logging.config("Migrating 'firstspawnoverride'...");
this.getMVConfig().setFirstSpawnOverride(this.multiverseConfig.getBoolean("firstspawnoverride"));
this.multiverseConfig.set("firstspawnoverride", null);
}
if (this.multiverseConfig.isSet("messagecooldown")) {
this.log(Level.INFO, "Migrating 'messagecooldown'...");
this.config.setMessageCooldown(this.multiverseConfig.getInt("messagecooldown"));
Logging.config("Migrating 'messagecooldown'...");
this.getMVConfig().setMessageCooldown(this.multiverseConfig.getInt("messagecooldown"));
this.multiverseConfig.set("messagecooldown", null);
}
if (this.multiverseConfig.isSet("debug")) {
this.log(Level.INFO, "Migrating 'debug'...");
this.config.setGlobalDebug(this.multiverseConfig.getInt("debug"));
Logging.config("Migrating 'debug'...");
this.getMVConfig().setGlobalDebug(this.multiverseConfig.getInt("debug"));
this.multiverseConfig.set("debug", null);
}
if (this.multiverseConfig.isSet("version")) {
this.log(Level.INFO, "Migrating 'version'...");
Logging.config("Migrating 'version'...");
this.multiverseConfig.set("version", null);
}
}
@@ -418,11 +550,11 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
/**
* Migrate the worlds.yml to SerializationConfig.
*/
private void migrateWorldConfig() {
private void migrateWorldConfig() { // SUPPRESS CHECKSTYLE: MethodLength
FileConfiguration wconf = YamlConfiguration
.loadConfiguration(new File(getDataFolder(), "worlds.yml"));
if (!wconf.isConfigurationSection("worlds")) {// empty config
if (!wconf.isConfigurationSection("worlds")) { // empty config
this.log(Level.FINE, "No worlds to migrate!");
return;
}
@@ -432,13 +564,13 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
boolean wasChanged = false;
Map<String, Object> newValues = new LinkedHashMap<String, Object>(values.size());
for (Map.Entry<String, Object> entry : values.entrySet()) {
if (entry.getValue() instanceof MVWorld) {
if (entry.getValue() instanceof WorldProperties) {
// fine
newValues.put(entry.getKey(), entry.getValue());
} else if (entry.getValue() instanceof ConfigurationSection) {
this.log(Level.FINE, "Migrating: " + entry.getKey());
// we have to migrate this
MVWorld world = new MVWorld(Collections.EMPTY_MAP);
WorldProperties world = new WorldProperties(Collections.EMPTY_MAP);
ConfigurationSection section = (ConfigurationSection) entry.getValue();
// migrate animals and monsters
@@ -508,10 +640,9 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// migrate gamemode
if (section.isString("gamemode")) {
try {
world.setPropertyValue("gamemode", section.getString("gamemode"));
} catch (PropertyDoesNotExistException e) {
throw new RuntimeException("Who forgot to update the migrator?", e);
final GameMode gameMode = GameMode.valueOf(section.getString("gamemode").toUpperCase());
if (gameMode != null) {
world.setGameMode(gameMode);
}
}
@@ -533,8 +664,8 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// migrate portalform
if (section.isString("portalform")) {
try {
world.setPropertyValue("portalform", section.getString("portalform"));
} catch (PropertyDoesNotExistException e) {
world.setProperty("portalform", section.getString("portalform"), true);
} catch (NoSuchPropertyException e) {
throw new RuntimeException("Who forgot to update the migrator?", e);
}
}
@@ -542,8 +673,8 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// migrate environment
if (section.isString("environment")) {
try {
world.setPropertyValue("environment", section.getString("environment"));
} catch (PropertyDoesNotExistException e) {
world.setProperty("environment", section.getString("environment"), true);
} catch (NoSuchPropertyException e) {
throw new RuntimeException("Who forgot to update the migrator?", e);
}
}
@@ -581,7 +712,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// migrate spawn
if (section.isConfigurationSection("spawn")) {
ConfigurationSection spawnSect = section.getConfigurationSection("spawn");
Location spawnLoc = world.getSpawnLocation();
Location spawnLoc = new NullLocation();
if (spawnSect.isDouble("yaw"))
spawnLoc.setYaw((float) spawnSect.getDouble("yaw"));
if (spawnSect.isDouble("pitch"))
@@ -596,6 +727,19 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
world.setSpawnLocation(spawnLoc);
}
// migrate difficulty
if (section.isString("difficulty")) {
final Difficulty difficulty = Difficulty.valueOf(section.getString("difficulty").toUpperCase());
if (difficulty != null) {
world.setDifficulty(difficulty);
}
}
// migrate keepspawninmemory
if (section.isBoolean("keepspawninmemory")) {
world.setKeepSpawnInMemory(section.getBoolean("keepspawninmemory"));
}
newValues.put(entry.getKey(), world);
wasChanged = true;
} else {
@@ -643,6 +787,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
this.commandHandler.registerCommand(new ListCommand(this));
this.commandHandler.registerCommand(new InfoCommand(this));
this.commandHandler.registerCommand(new CreateCommand(this));
this.commandHandler.registerCommand(new CloneCommand(this));
this.commandHandler.registerCommand(new ImportCommand(this));
this.commandHandler.registerCommand(new ReloadCommand(this));
this.commandHandler.registerCommand(new SetSpawnCommand(this));
@@ -669,8 +814,12 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Misc Commands
this.commandHandler.registerCommand(new EnvironmentCommand(this));
this.commandHandler.registerCommand(new DebugCommand(this));
this.commandHandler.registerCommand(new SilentCommand(this));
this.commandHandler.registerCommand(new GeneratorCommand(this));
this.commandHandler.registerCommand(new CheckCommand(this));
this.commandHandler.registerCommand(new ScriptCommand(this));
this.commandHandler.registerCommand(new GameruleCommand(this));
this.commandHandler.registerCommand(new GamerulesCommand(this));
}
/**
@@ -679,10 +828,9 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
@Override
public void onDisable() {
this.saveMVConfigs();
debugLog.close();
this.banker = null;
this.bank = null;
log(Level.INFO, "- Disabled");
Logging.shutdown();
}
/**
@@ -693,7 +841,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
if (this.playerSessions.containsKey(player.getName())) {
return this.playerSessions.get(player.getName());
} else {
this.playerSessions.put(player.getName(), new MVPlayerSession(player, config));
this.playerSessions.put(player.getName(), new MVPlayerSession(player, getMVConfig()));
return this.playerSessions.get(player.getName());
}
}
@@ -728,7 +876,17 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
}
ArrayList<String> allArgs = new ArrayList<String>(Arrays.asList(args));
allArgs.add(0, command.getName());
return this.commandHandler.locateAndRunCommand(sender, allArgs, config.getDisplayPermErrors());
try {
return this.commandHandler.locateAndRunCommand(sender, allArgs, getMVConfig().getDisplayPermErrors());
} catch (Exception e) {
e.printStackTrace();
sender.sendMessage(ChatColor.RED + "An internal error occurred when attempting to perform this command.");
if (sender.isOp())
sender.sendMessage(ChatColor.RED + "Details were printed to the server console and logs, please add that to your bug report.");
else
sender.sendMessage(ChatColor.RED + "Try again and contact the server owner or an admin if this problem persists.");
return true;
}
}
/**
@@ -736,7 +894,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
*/
@Override
public void log(Level level, String msg) {
staticLog(level, msg);
Logging.log(level, msg);
}
/**
@@ -744,30 +902,28 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
*
* @param level The Log-{@link Level}.
* @param msg The message to log.
*
* @deprecated Replaced by {@link Logging}. Please refrain from using this from a third party plugin as the
* messages will appear to originate from Multiverse-Core.
*/
@Deprecated
public static void staticLog(Level level, String msg) {
if (level == Level.FINE && MultiverseCoreConfiguration.getInstance().getGlobalDebug() >= 1) {
staticDebugLog(Level.INFO, msg);
} else if (level == Level.FINER && MultiverseCoreConfiguration.getInstance().getGlobalDebug() >= 2) {
staticDebugLog(Level.INFO, msg);
} else if (level == Level.FINEST && MultiverseCoreConfiguration.getInstance().getGlobalDebug() >= 3) {
staticDebugLog(Level.INFO, msg);
} else if (level != Level.FINE && level != Level.FINER && level != Level.FINEST) {
String message = LOG_TAG + " " + msg;
LOGGER.log(level, message);
debugLog.log(level, message);
}
Logging.log(level, msg);
}
/**
* Print messages to the Debug Log, if the servers in Debug Mode then we also wan't to print the messages to the
* Print messages to the Debug Log, if the servers in Debug Mode then we also want to print the messages to the
* standard Server Console.
*
* @param level The Log-{@link Level}
* @param msg The message
*
* @deprecated Replaced by {@link Logging}. Please refrain from using this from a third party plugin as the
* messages will appear to originate from Multiverse-Core.
*/
@Deprecated
public static void staticDebugLog(Level level, String msg) {
debugLog.log(level, msg);
Logging.log(level, msg);
}
/**
@@ -861,16 +1017,20 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
/**
* {@inheritDoc}
* @deprecated Now using Vault.
*/
@Override
@Deprecated
public AllPay getBanker() {
return this.banker;
}
/**
* {@inheritDoc}
* @deprecated Now using Vault.
*/
@Override
@Deprecated
public void setBank(GenericBank bank) {
this.bank = bank;
}
@@ -952,6 +1112,15 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
return this.playerListener;
}
/**
* Gets the {@link MVChatListener}.
*
* @return The {@link MVChatListener}.
*/
public MVChatListener getChatListener() {
return this.chatListener;
}
/**
* Gets the {@link MVEntityListener}.
*
@@ -977,7 +1146,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
*/
public boolean saveMVConfig() {
try {
this.multiverseConfig.set("multiverse-configuration", config);
this.multiverseConfig.set("multiverse-configuration", getMVConfig());
this.multiverseConfig.save(new File(getDataFolder(), "config.yml"));
return true;
} catch (IOException e) {
@@ -1014,38 +1183,27 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
return this.worldManager.deleteWorld(name);
}
/**
* NOT deprecated for the time as queued commands use this.
* However, this is not in the API and other plugins should therefore not use it.
*
* @param oldName World to copy
* @param newName World to create
* @param generator The Custom generator plugin to use.
* @return True if success, false if fail.
*/
public Boolean cloneWorld(String oldName, String newName, String generator) {
return this.worldManager.cloneWorld(oldName, newName, generator);
}
/**
* {@inheritDoc}
* @deprecated This is deprecated!
*/
@Override
@Deprecated
public Boolean regenWorld(String name, Boolean useNewSeed, Boolean randomSeed, String seed) {
MultiverseWorld world = this.worldManager.getMVWorld(name);
if (world == null) {
return false;
}
List<Player> ps = world.getCBWorld().getPlayers();
if (useNewSeed) {
// Set the worldseed.
if (randomSeed) {
Random random = new Random();
Long newseed = random.nextLong();
seed = newseed.toString();
}
((WorldManager) this.worldManager).getConfigWorlds().set("worlds." + name + ".seed", seed);
}
if (this.worldManager.deleteWorld(name, false)) {
this.worldManager.loadWorlds(false);
SafeTTeleporter teleporter = this.getSafeTTeleporter();
Location newSpawn = this.getServer().getWorld(name).getSpawnLocation();
// Send all players that were in the old world, BACK to it!
for (Player p : ps) {
teleporter.safelyTeleport(null, p, newSpawn, true);
}
return true;
}
return false;
return this.worldManager.regenWorld(name, useNewSeed, randomSeed, seed);
}
/**
@@ -1069,6 +1227,9 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
*/
@Override
public void setBlockSafety(BlockSafety bs) {
if (bs == null) {
throw new NullPointerException("block safety may not be null.");
}
this.blockSafety = bs;
}
@@ -1122,4 +1283,13 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
public static MultiverseCoreConfiguration getStaticConfig() {
return MultiverseCoreConfiguration.getInstance();
}
@Override
public Buscript getScriptAPI() {
return buscript;
}
public UnsafeCallWrapper getUnsafeCallWrapper() {
return this.unsafeCallWrapper;
}
}
@@ -1,11 +1,10 @@
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseCoreConfig;
import me.main__.util.SerializationConfig.NoSuchPropertyException;
import me.main__.util.SerializationConfig.Property;
import me.main__.util.SerializationConfig.SerializationConfig;
import com.dumptruckman.minecraft.util.*;
import com.onarandombox.MultiverseCore.api.*;
import me.main__.util.SerializationConfig.*;
import java.util.Map;
import java.util.*;
/**
* Our configuration.
@@ -39,25 +38,33 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
}
@Property
private boolean enforceaccess;
private volatile boolean enforceaccess;
@Property
private boolean prefixchat;
private volatile boolean prefixchat;
@Property
private boolean teleportintercept;
private volatile boolean useasyncchat;
@Property
private boolean firstspawnoverride;
private volatile boolean teleportintercept;
@Property
private boolean displaypermerrors;
private volatile boolean firstspawnoverride;
@Property
private int globaldebug;
private volatile boolean displaypermerrors;
@Property
private int messagecooldown;
private volatile int globaldebug;
@Property
private double version;
private volatile boolean silentstart;
@Property
private String firstspawnworld;
private volatile int messagecooldown;
@Property
private int teleportcooldown;
private volatile double version;
@Property
private volatile String firstspawnworld;
@Property
private volatile int teleportcooldown;
@Property
private volatile boolean defaultportalsearch;
@Property
private volatile int portalsearchradius;
public MultiverseCoreConfiguration() {
super();
@@ -73,9 +80,10 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
* {@inheritDoc}
*/
@Override
public void setDefaults() {
protected void setDefaults() {
// BEGIN CHECKSTYLE-SUPPRESSION: MagicNumberCheck
enforceaccess = false;
useasyncchat = true;
prefixchat = true;
teleportintercept = true;
firstspawnoverride = true;
@@ -84,6 +92,9 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
messagecooldown = 5000;
teleportcooldown = 1000;
this.version = 2.9;
silentstart = false;
defaultportalsearch = false;
portalsearchradius = 128;
// END CHECKSTYLE-SUPPRESSION: MagicNumberCheck
}
@@ -195,6 +206,7 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
@Override
public void setGlobalDebug(int globalDebug) {
this.globaldebug = globalDebug;
Logging.setDebugLevel(globalDebug);
}
/**
@@ -260,4 +272,45 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
public void setTeleportCooldown(int teleportCooldown) {
this.teleportcooldown = teleportCooldown;
}
@Override
public void setUseAsyncChat(boolean useAsyncChat) {
this.useasyncchat = useAsyncChat;
}
@Override
public boolean getUseAsyncChat() {
return this.useasyncchat;
}
@Override
public void setSilentStart(boolean silentStart) {
Logging.setShowingConfig(!silentStart);
this.silentstart = silentStart;
}
@Override
public boolean getSilentStart() {
return silentstart;
}
@Override
public void setUseDefaultPortalSearch(boolean useDefaultPortalSearch) {
defaultportalsearch = useDefaultPortalSearch;
}
@Override
public boolean isUsingDefaultPortalSearch() {
return defaultportalsearch;
}
@Override
public void setPortalSearchRadius(int searchRadius) {
this.portalsearchradius = searchRadius;
}
@Override
public int getPortalSearchRadius() {
return portalsearchradius;
}
}
@@ -0,0 +1,638 @@
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.MVWorld.NullLocation;
import com.onarandombox.MultiverseCore.configuration.EntryFee;
import com.onarandombox.MultiverseCore.configuration.SpawnLocation;
import com.onarandombox.MultiverseCore.configuration.SpawnSettings;
import com.onarandombox.MultiverseCore.configuration.WorldPropertyValidator;
import com.onarandombox.MultiverseCore.enums.AllowedPortalType;
import com.onarandombox.MultiverseCore.enums.EnglishChatColor;
import com.onarandombox.MultiverseCore.enums.EnglishChatStyle;
import me.main__.util.SerializationConfig.IllegalPropertyValueException;
import me.main__.util.SerializationConfig.Property;
import me.main__.util.SerializationConfig.SerializationConfig;
import me.main__.util.SerializationConfig.Serializor;
import me.main__.util.SerializationConfig.Validator;
import me.main__.util.SerializationConfig.VirtualProperty;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World.Environment;
import org.bukkit.configuration.serialization.SerializableAs;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* This is a property class, I think we don't need that much javadoc.
* BEGIN CHECKSTYLE-SUPPRESSION: Javadoc
*/
@SerializableAs("MVWorld")
public class WorldProperties extends SerializationConfig {
private static final Map<String, String> PROPERTY_ALIASES;
static {
PROPERTY_ALIASES = new HashMap<String, String>();
PROPERTY_ALIASES.put("curr", "currency");
PROPERTY_ALIASES.put("scaling", "scale");
PROPERTY_ALIASES.put("aliascolor", "color");
PROPERTY_ALIASES.put("heal", "autoHeal");
PROPERTY_ALIASES.put("storm", "allowWeather");
PROPERTY_ALIASES.put("weather", "allowWeather");
PROPERTY_ALIASES.put("spawnmemory", "keepSpawnInMemory");
PROPERTY_ALIASES.put("memory", "keepSpawnInMemory");
PROPERTY_ALIASES.put("mode", "gameMode");
PROPERTY_ALIASES.put("diff", "difficulty");
PROPERTY_ALIASES.put("spawnlocation", "spawn");
PROPERTY_ALIASES.put("limit", "playerLimit");
PROPERTY_ALIASES.put("animals", "spawning.animals.spawn");
PROPERTY_ALIASES.put("monsters", "spawning.monsters.spawn");
PROPERTY_ALIASES.put("animalsrate", "spawning.animals.spawnrate");
PROPERTY_ALIASES.put("monstersrate", "spawning.monsters.spawnrate");
PROPERTY_ALIASES.put("flight", "allowFlight");
PROPERTY_ALIASES.put("fly", "allowFlight");
PROPERTY_ALIASES.put("allowfly", "allowFlight");
}
public WorldProperties(Map<String, Object> values) {
super(values);
}
public WorldProperties() {
super();
}
public WorldProperties(final boolean fixSpawn, final Environment environment) {
super();
if (!fixSpawn) {
this.adjustSpawn = false;
}
setScaling(getDefaultScale(environment));
}
void setMVWorld(MVWorld world) {
registerObjectUsing(world);
registerGlobalValidator(new WorldPropertyValidator());
}
/**
* Serializor for the color-property.
*/
private static final class EnumPropertySerializor<T extends Enum<T>> implements Serializor<T, String> {
@Override
public String serialize(T from) {
return from.toString();
}
@Override
public T deserialize(String serialized, Class<T> wanted) throws IllegalPropertyValueException {
try {
return Enum.valueOf(wanted, serialized.toUpperCase());
} catch (IllegalArgumentException e) {
throw new IllegalPropertyValueException(e);
}
}
}
/**
* Serializor for the difficulty-property.
*/
private static final class DifficultyPropertySerializor implements Serializor<Difficulty, String> {
@Override
public String serialize(Difficulty from) {
return from.toString();
}
@Override
public Difficulty deserialize(String serialized, Class<Difficulty> wanted) throws IllegalPropertyValueException {
try {
return Difficulty.getByValue(Integer.parseInt(serialized));
} catch (Exception e) {
}
try {
return Difficulty.valueOf(serialized.toUpperCase());
} catch (Exception e) {
}
throw new IllegalPropertyValueException();
}
}
/**
* Serializor for the gameMode-property.
*/
private static final class GameModePropertySerializor implements Serializor<GameMode, String> {
@Override
public String serialize(GameMode from) {
return from.toString();
}
@Override
public GameMode deserialize(String serialized, Class<GameMode> wanted) throws IllegalPropertyValueException {
try {
return GameMode.getByValue(Integer.parseInt(serialized));
} catch (NumberFormatException nfe) {
}
try {
return GameMode.valueOf(serialized.toUpperCase());
} catch (Exception e) {
}
throw new IllegalPropertyValueException();
}
}
/**
* Serializor for the time-property.
*/
private static final class TimePropertySerializor implements Serializor<Long, String> {
// BEGIN CHECKSTYLE-SUPPRESSION: MagicNumberCheck
private static final String TIME_REGEX = "(\\d\\d?):?(\\d\\d)(a|p)?m?";
private static final Map<String, String> TIME_ALIASES;
static {
Map<String, String> staticTimes = new HashMap<String, String>();
staticTimes.put("morning", "8:00");
staticTimes.put("day", "12:00");
staticTimes.put("noon", "12:00");
staticTimes.put("midnight", "0:00");
staticTimes.put("night", "20:00");
// now set TIME_ALIASES to a "frozen" map
TIME_ALIASES = Collections.unmodifiableMap(staticTimes);
}
@Override
public String serialize(Long from) {
// I'm tired, so they get time in 24 hour for now.
// Someone else can add 12 hr format if they want :P
int hours = (int) ((from / 1000 + 8) % 24);
int minutes = (int) (60 * (from % 1000) / 1000);
return String.format("%d:%02d", hours, minutes);
}
@Override
public Long deserialize(String serialized, Class<Long> wanted) throws IllegalPropertyValueException {
if (TIME_ALIASES.containsKey(serialized.toLowerCase())) {
serialized = TIME_ALIASES.get(serialized.toLowerCase());
}
// Regex that extracts a time in the following formats:
// 11:11pm, 11:11, 23:11, 1111, 1111p, and the aliases at the top of this file.
Pattern pattern = Pattern.compile(TIME_REGEX, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(serialized);
matcher.find();
int hour = 0;
double minute = 0;
int count = matcher.groupCount();
if (count >= 2) {
hour = Integer.parseInt(matcher.group(1));
minute = Integer.parseInt(matcher.group(2));
}
// If there were 4 matches (all, hour, min, am/pm)
if (count == 4) {
// We want 24 hour time for calcs, but if they
// added a p[m], turn it into a 24 hr one.
if (matcher.group(3).equals("p")) {
hour += 12;
}
}
// Translate 24th hour to 0th hour.
if (hour == 24) {
hour = 0;
}
// Clamp the hour
if (hour > 23 || hour < 0) {
throw new IllegalPropertyValueException("Illegal hour!");
}
// Clamp the minute
if (minute > 59 || minute < 0) {
throw new IllegalPropertyValueException("Illegal minute!");
}
// 60 seconds in a minute, time needs to be in hrs * 1000, per
// the bukkit docs.
double totaltime = (hour + (minute / 60.0)) * 1000;
// Somehow there's an 8 hour offset...
totaltime -= 8000;
if (totaltime < 0) {
totaltime = 24000 + totaltime;
}
return (long) totaltime;
}
// END CHECKSTYLE-SUPPRESSION: MagicNumberCheck
}
// --------------------------------------------------------------
// Begin properties
@Property(description = "Sorry, 'hidden' must either be: true or false.")
private volatile boolean hidden;
@Property(description = "Alias must be a valid string.")
private volatile String alias;
@Property(serializor = EnumPropertySerializor.class, description = "Sorry, 'color' must be a valid color-name.")
private volatile EnglishChatColor color;
@Property(serializor = EnumPropertySerializor.class, description = "Sorry, 'style' must be a valid style-name.")
private volatile EnglishChatStyle style;
@Property(description = "Sorry, 'pvp' must either be: true or false.", virtualType = Boolean.class, persistVirtual = true)
volatile VirtualProperty<Boolean> pvp; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(description = "Scale must be a positive double value. ex: 2.3")
private volatile double scale;
@Property(description = "You must set this to the NAME not alias of a world.")
private volatile String respawnWorld;
@Property(description = "Sorry, this must either be: true or false.")
private volatile boolean allowWeather;
@Property(serializor = DifficultyPropertySerializor.class, virtualType = Difficulty.class, persistVirtual = true,
description = "Difficulty must be set as one of the following: peaceful easy normal hard")
volatile VirtualProperty<Difficulty> difficulty; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(description = "Sorry, 'animals' must either be: true or false.")
private volatile SpawnSettings spawning;
@Property
private volatile EntryFee entryfee;
@Property(description = "Sorry, 'hunger' must either be: true or false.")
private volatile boolean hunger;
@Property(description = "Sorry, 'autoheal' must either be: true or false.")
private volatile boolean autoHeal;
@Property(description = "Sorry, 'adjustspawn' must either be: true or false.")
private volatile boolean adjustSpawn;
@Property(serializor = EnumPropertySerializor.class, description = "Allow portal forming must be NONE, ALL, NETHER or END.")
private volatile AllowedPortalType portalForm;
@Property(serializor = GameModePropertySerializor.class, description = "GameMode must be set as one of the following: survival creative")
private volatile GameMode gameMode;
@Property(description = "Sorry, this must either be: true or false.", virtualType = Boolean.class, persistVirtual = true)
volatile VirtualProperty<Boolean> keepSpawnInMemory; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
volatile SpawnLocation spawnLocation; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(virtualType = Location.class,
description = "There is no help available for this variable. Go bug Rigby90 about it.")
volatile VirtualProperty<Location> spawn; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property(description = "Set this to false ONLY if you don't want this world to load itself on server restart.")
private volatile boolean autoLoad;
@Property(description = "If a player dies in this world, shoudld they go to their bed?")
private volatile boolean bedRespawn;
@Property
private volatile List<String> worldBlacklist;
@Property(serializor = TimePropertySerializor.class, virtualType = Long.class,
description = "Set the time to whatever you want! (Will NOT freeze time)")
volatile VirtualProperty<Long> time; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
volatile Environment environment; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
volatile long seed; // SUPPRESS CHECKSTYLE: VisibilityModifier
@Property
private volatile String generator;
@Property
private volatile int playerLimit;
@Property
private volatile boolean allowFlight;
// End of properties
// --------------------------------------------------------------
void setValidator(String fieldName, Validator validator) {
registerValidator(fieldName, validator); //To change body of overridden methods use File | Settings | File Templates.
}
/**
* {@inheritDoc}
*/
@Override
public void copyValues(SerializationConfig other) {
super.copyValues(other);
}
/**
* This prepares the MVWorld for unloading.
*/
public void cacheVirtualProperties() {
try {
this.buildVPropChanges();
} catch (IllegalStateException e) {
// do nothing
}
}
/**
* {@inheritDoc}
*/
@Override
protected void setDefaults() {
this.hidden = false;
this.alias = new String();
this.color = EnglishChatColor.WHITE;
this.style = EnglishChatStyle.NORMAL;
this.scale = 1D;
this.respawnWorld = new String();
this.allowWeather = true;
this.spawning = new SpawnSettings();
this.entryfee = new EntryFee();
this.hunger = true;
this.autoHeal = true;
this.adjustSpawn = true;
this.portalForm = AllowedPortalType.ALL;
this.gameMode = GameMode.SURVIVAL;
this.spawnLocation = new NullLocation();
this.autoLoad = true;
this.bedRespawn = true;
this.worldBlacklist = new ArrayList<String>();
this.generator = null;
this.playerLimit = -1;
this.allowFlight = true;
}
private static double getDefaultScale(Environment environment) {
if (environment == Environment.NETHER) {
return 8.0; // SUPPRESS CHECKSTYLE: MagicNumberCheck
} else if (environment == Environment.THE_END) {
return 16.0; // SUPPRESS CHECKSTYLE: MagicNumberCheck
}
return 1.0;
}
/**
* getAliases().
* @return The alias-map.
* @see SerializationConfig
*/
protected static Map<String, String> getAliases() {
return PROPERTY_ALIASES;
}
void flushChanges() {
this.flushPendingVPropChanges();
}
String getAlias() {
return this.alias;
}
public void setAlias(String alias) {
this.setPropertyValueUnchecked("alias", alias);
}
public Environment getEnvironment() {
return this.environment;
}
public void setEnvironment(Environment environment) {
this.setPropertyValueUnchecked("environment", environment);
}
public long getSeed() {
return this.seed;
}
public void setSeed(long seed) {
this.setPropertyValueUnchecked("seed", seed);
}
public String getGenerator() {
return this.generator;
}
public void setGenerator(String generator) {
this.setPropertyValueUnchecked("generator", generator);
}
public int getPlayerLimit() {
return this.playerLimit;
}
public void setPlayerLimit(int limit) {
this.setPropertyValueUnchecked("playerLimit", limit);
}
public boolean canAnimalsSpawn() {
return this.spawning.getAnimalSettings().doSpawn();
}
public void setAllowAnimalSpawn(boolean animals) {
this.setPropertyValueUnchecked("spawning.animals.spawn", animals);
}
public List<String> getAnimalList() {
// These don't fire events at the moment. Should they?
return this.spawning.getAnimalSettings().getExceptions();
}
public boolean canMonstersSpawn() {
return this.spawning.getMonsterSettings().doSpawn();
}
public void setAllowMonsterSpawn(boolean monsters) {
this.setPropertyValueUnchecked("spawning.monsters.spawn", monsters);
}
public int getAnimalSpawnRate() {
return this.spawning.getAnimalSettings().getSpawnRate();
}
public int getMonsterSpawnRate() {
return this.spawning.getMonsterSettings().getSpawnRate();
}
public List<String> getMonsterList() {
// These don't fire events at the moment. Should they?
return this.spawning.getMonsterSettings().getExceptions();
}
public boolean isPVPEnabled() {
return this.pvp.get();
}
public void setPVPMode(boolean pvp) {
this.setPropertyValueUnchecked("pvp", pvp);
}
public boolean isHidden() {
return this.hidden;
}
public void setHidden(boolean hidden) {
this.setPropertyValueUnchecked("hidden", hidden);
}
public List<String> getWorldBlacklist() {
return this.worldBlacklist;
}
public double getScaling() {
return this.scale;
}
public boolean setScaling(double scaling) {
return this.setPropertyValueUnchecked("scale", scaling);
}
public boolean setColor(String aliasColor) {
return this.setPropertyUnchecked("color", aliasColor);
}
public boolean setColor(EnglishChatColor color) {
return this.setPropertyValueUnchecked("color", color);
}
public EnglishChatColor getColor() {
return this.color;
}
public String getRespawnToWorld() {
return this.respawnWorld;
}
public boolean setRespawnToWorld(String respawnToWorld) {
return this.setPropertyValueUnchecked("respawnWorld", respawnToWorld);
}
public int getCurrency() {
return this.entryfee.getCurrency();
}
public void setCurrency(int currency) {
this.setPropertyValueUnchecked("entryfee.currency", currency);
}
public double getPrice() {
return this.entryfee.getAmount();
}
public void setPrice(double price) {
this.setPropertyValueUnchecked("entryfee.amount", price);
}
public boolean setGameMode(String mode) {
return this.setPropertyUnchecked("gameMode", mode);
}
public boolean setGameMode(GameMode mode) {
return this.setPropertyValueUnchecked("gameMode", mode);
}
public GameMode getGameMode() {
return this.gameMode;
}
public void setEnableWeather(boolean weather) {
this.setPropertyValueUnchecked("allowWeather", weather);
}
public boolean isWeatherEnabled() {
return this.allowWeather;
}
public boolean isKeepingSpawnInMemory() {
return this.keepSpawnInMemory.get();
}
public void setKeepSpawnInMemory(boolean value) {
this.setPropertyValueUnchecked("keepSpawnInMemory", value);
}
public boolean getHunger() {
return this.hunger;
}
public void setHunger(boolean hunger) {
this.setPropertyValueUnchecked("hunger", hunger);
}
public Location getSpawnLocation() {
return this.spawn.get();
}
public void setSpawnLocation(Location l) {
this.setPropertyValueUnchecked("spawn", l);
}
public Difficulty getDifficulty() {
return this.difficulty.get();
}
@Deprecated // SUPPRESS CHECKSTYLE: Deprecated
public boolean setDifficulty(String difficulty) {
return this.setPropertyUnchecked("difficulty", difficulty);
}
public boolean setDifficulty(Difficulty difficulty) {
return this.setPropertyValueUnchecked("difficulty", difficulty);
}
public boolean getAutoHeal() {
return this.autoHeal;
}
public void setAutoHeal(boolean heal) {
this.setPropertyValueUnchecked("autoHeal", heal);
}
public void setAdjustSpawn(boolean adjust) {
this.setPropertyValueUnchecked("adjustSpawn", adjust);
}
public boolean getAdjustSpawn() {
return this.adjustSpawn;
}
public void setAutoLoad(boolean load) {
this.setPropertyValueUnchecked("autoLoad", load);
}
public boolean getAutoLoad() {
return this.autoLoad;
}
public void setBedRespawn(boolean respawn) {
this.setPropertyValueUnchecked("bedRespawn", respawn);
}
public boolean getBedRespawn() {
return this.bedRespawn;
}
public String getAllPropertyNames() {
ChatColor myColor = ChatColor.AQUA;
StringBuilder result = new StringBuilder();
Map<String, Object> serialized = this.serialize();
for (String key : serialized.keySet()) {
result.append(myColor).append(key).append(' ');
myColor = (myColor == ChatColor.AQUA) ? ChatColor.GOLD : ChatColor.AQUA;
}
return result.toString();
}
public String getTime() {
return this.getPropertyUnchecked("time");
}
public boolean setTime(String timeAsString) {
return this.setPropertyUnchecked("time", timeAsString);
}
public AllowedPortalType getAllowedPortals() {
return portalForm;
}
public void allowPortalMaking(AllowedPortalType portalType) {
this.setPropertyValueUnchecked("portalForm", portalType);
}
public EnglishChatStyle getStyle() {
return style;
}
public boolean setStyle(String style) {
return this.setPropertyUnchecked("style", style);
}
public boolean getAllowFlight() {
return this.allowFlight;
}
public void setAllowFlight(final boolean allowFlight) {
this.setPropertyValueUnchecked("allowFlight", allowFlight);
}
}
@@ -35,6 +35,13 @@ public interface BlockSafety {
*/
boolean playerCanSpawnHereSafely(Location l);
/**
* Gets a safe bed spawn location OR null if the bed is invalid.
* @param l The location of the bead head (block with the pillow on it).
* @return Safe location around the bed or null if no location was found.
*/
Location getSafeBedSpawn(Location l);
/**
* Gets the location of the top block at the specified {@link Location}.
* @param l Any {@link Location}.
@@ -7,12 +7,18 @@
package com.onarandombox.MultiverseCore.api;
import buscript.Buscript;
import com.fernferret.allpay.AllPay;
import com.fernferret.allpay.GenericBank;
import com.fernferret.allpay.commons.GenericBank;
import com.onarandombox.MultiverseCore.destination.DestinationFactory;
import com.onarandombox.MultiverseCore.utils.*;
import com.onarandombox.MultiverseCore.utils.AnchorManager;
import com.onarandombox.MultiverseCore.utils.MVPermissions;
import com.onarandombox.MultiverseCore.utils.MVPlayerSession;
import com.onarandombox.MultiverseCore.utils.SimpleBlockSafety;
import com.onarandombox.MultiverseCore.utils.SimpleLocationManipulation;
import com.onarandombox.MultiverseCore.utils.SimpleSafeTTeleporter;
import com.onarandombox.MultiverseCore.utils.VaultHandler;
import com.pneumaticraft.commandhandler.CommandHandler;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
/**
@@ -22,22 +28,23 @@ import org.bukkit.entity.Player;
*/
public interface Core {
/**
* Gets the Multiverse config file.
*
* @return The Multiverse config file.
* @deprecated Don't modify the config-file manually!
*/
@Deprecated
FileConfiguration getMVConfiguration();
/**
* Gets the Banking system that Multiverse-Core has hooked into.
*
* @return A {@link GenericBank} that can be used for payments.
* @deprecated Now using vault, see {@link VaultHandler#getEconomy}
*/
@Deprecated
GenericBank getBank();
/**
* Returns the Vault handler used by Multiverse. The returned object will have all methods necessary for
* interfacing with Vault.
*
* @return the Vault handler for Multiverse.
*/
VaultHandler getVaultHandler();
/**
* Reloads the Multiverse Configuration files:
* worlds.yml and config.yml.
@@ -128,21 +135,28 @@ public interface Core {
* @param seed The seed of the world.
*
* @return True if success, false if fail.
*
* @deprecated Use {@link MVWorldManager#regenWorld(String, boolean, boolean, String)} instead.
*/
@Deprecated
Boolean regenWorld(String name, Boolean useNewSeed, Boolean randomSeed, String seed);
/**
* Sets the {@link GenericBank}-Bank AllPay is using.
*
* @param bank The new {@link GenericBank}
* @deprecated Now using vault, see {@link VaultHandler#getEconomy}
*/
@Deprecated
void setBank(GenericBank bank);
/**
* Gets this plugin's {@link AllPay}-Banker.
*
* @return An {@link AllPay}-Banker
* @deprecated Now using vault, see {@link VaultHandler#getEconomy}
*/
@Deprecated
AllPay getBanker();
/**
@@ -222,4 +236,11 @@ public interface Core {
* @return The configuration.
*/
MultiverseCoreConfig getMVConfig();
/**
* Gets the buscript object for Multiverse. This is what handles Javascript processing.
*
* @return The Multiverse buscript object.
*/
Buscript getScriptAPI();
}
@@ -30,14 +30,14 @@ public interface MVPlugin extends LoggablePlugin {
/**
* Gets the reference to MultiverseCore.
*
* @return A valid {@link MultiverseCore}.
* @return A valid {@link com.onarandombox.MultiverseCore}.
*/
MultiverseCore getCore();
/**
* Sets the reference to MultiverseCore.
*
* @param core A valid {@link MultiverseCore}.
* @param core A valid {@link com.onarandombox.MultiverseCore}.
*/
void setCore(MultiverseCore core);
@@ -60,6 +60,16 @@ public interface MVWorldManager {
boolean addWorld(String name, Environment env, String seedString, WorldType type, Boolean generateStructures,
String generator, boolean useSpawnAdjust);
/**
* Make a copy of a world.
*
* @param oldName Name of world to be copied
* @param newName Name of world to be created
* @param generator The Custom generator plugin to use.
* @return True if the world is copied successfully, false if not.
*/
boolean cloneWorld(String oldName, String newName, String generator);
/**
* Remove the world from the Multiverse list, from the
* config and deletes the folder.
@@ -80,6 +90,17 @@ public interface MVWorldManager {
*/
boolean deleteWorld(String name, boolean removeConfig);
/**
*
* @param name The name of the world to remove
* @param removeFromConfig If true(default), we'll remove the entries from the
* config. If false, they'll stay and the world may come back.
* @param deleteWorldFolder If true the world folder will be completely deleted. If false
* only the contents of the world folder will be deleted
* @return True if success, false if failure.
*/
boolean deleteWorld(String name, boolean removeFromConfig, boolean deleteWorldFolder);
/**
* Unload a world from Multiverse.
*
@@ -245,4 +266,16 @@ public interface MVWorldManager {
* @return The {@link MultiverseWorld} new players should spawn in.
*/
MultiverseWorld getFirstSpawnWorld();
/**
* Regenerates a world.
*
* @param name Name of the world to regenerate
* @param useNewSeed If a new seed should be used
* @param randomSeed IF the new seed should be random
* @param seed The seed of the world.
*
* @return True if success, false if fail.
*/
boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed);
}
@@ -133,4 +133,58 @@ public interface MultiverseCoreConfig extends ConfigurationSerializable {
* @return enforceAccess.
*/
boolean getEnforceAccess();
/**
* Sets useasyncchat.
* @param useAsyncChat The new value.
*/
void setUseAsyncChat(boolean useAsyncChat);
/**
* Gets useasyncchat.
* @return useasyncchat.
*/
boolean getUseAsyncChat();
/**
* Sets whether to suppress startup messages.
*
* @param silentStart true to suppress messages.
*/
void setSilentStart(boolean silentStart);
/**
* Whether we are suppressing startup messages.
*
* @return true if we are suppressing startup messages.
*/
boolean getSilentStart();
/**
* Sets whether or not to let Bukkit determine portal search radius on its own or if Multiverse should give input.
*
* @param useDefaultPortalSearch True to let Bukkit determine portal search radius on its own.
*/
void setUseDefaultPortalSearch(boolean useDefaultPortalSearch);
/**
* Gets whether or not Bukkit will be determining portal search radius on its own or if Multiverse should help.
*
* @return True means Bukkit will use its own default values.
*/
boolean isUsingDefaultPortalSearch();
/**
* Sets the radius at which vanilla style portals will be searched for to connect to worlds together.
*
* @param searchRadius The portal search radius.
*/
void setPortalSearchRadius(int searchRadius);
/**
* Gets the radius at which vanilla style portals will be searched for to connect to worlds together.
*
* @return The portal search radius.
*/
int getPortalSearchRadius();
}
@@ -49,7 +49,6 @@ public abstract class MultiversePlugin extends JavaPlugin implements MVPlugin {
}
this.setCore(theCore);
// Turn on Logging
this.getServer().getLogger().info(String.format("%s - Version %s enabled - By %s",
this.getDescription().getName(), this.getDescription().getVersion(), getAuthors()));
getDataFolder().mkdirs();
@@ -59,7 +58,7 @@ public abstract class MultiversePlugin extends JavaPlugin implements MVPlugin {
} catch (IOException e) {
e.printStackTrace();
}
debugLog = new DebugLog("Multiverse-Adventure", getDataFolder() + File.separator + "debug.log");
debugLog = new DebugLog(this.getDescription().getName(), getDataFolder() + File.separator + "debug.log");
debugLog.setTag(String.format("[%s-Debug]", this.getDescription().getName()));
this.onPluginEnable();
@@ -9,7 +9,6 @@ package com.onarandombox.MultiverseCore.api;
import com.onarandombox.MultiverseCore.enums.AllowedPortalType;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
@@ -621,6 +620,22 @@ public interface MultiverseWorld {
*/
void setBedRespawn(boolean autoLoad);
/**
* Sets the player limit for this world after which players without an override
* permission node will not be allowed in. A value of -1 or less signifies no limit
*
* @param limit The new limit
*/
void setPlayerLimit(int limit);
/**
* Gets the player limit for this world after which players without an override
* permission node will not be allowed in. A value of -1 or less signifies no limit
*
* @return The player limit
*/
int getPlayerLimit();
/**
* Same as {@link #getTime()}, but returns a string.
* @return The time as a short string: 12:34pm
@@ -669,4 +684,18 @@ public interface MultiverseWorld {
* @return All property names, with alternating colors.
*/
String getAllPropertyNames();
/**
* Whether or not players are allowed to fly in this world.
*
* @return True if players allowed to fly in this world.
*/
boolean getAllowFlight();
/**
* Sets whether or not players are allowed to fly in this world.
*
* @param allowFlight True to allow flight in this world.
*/
void setAllowFlight(final boolean allowFlight);
}
@@ -3,14 +3,14 @@ package com.onarandombox.MultiverseCore.api;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
/**
* Used to remove animals from worlds that don't belong there.
*/
public interface WorldPurger {
/**
* Synchronizes the given world with it's settings.
* Synchronizes the given worlds with their settings.
*
* @param worlds A list of {@link MultiverseWorld}
*/
@@ -46,4 +46,23 @@ public interface WorldPurger {
void purgeWorld(MultiverseWorld mvworld, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters, CommandSender sender);
/**
* Determines whether the specified creature should be killed.
*
* @param e The creature.
* @param thingsToKill A {@link List} of animals/monsters to be killed.
* @param negateAnimals Whether the monsters in the list should be negated.
* @param negateMonsters Whether the animals in the list should be negated.
* @return {@code true} if the creature should be killed, otherwise {@code false}.
*/
boolean shouldWeKillThisCreature(Entity e, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters);
/**
* Determines whether the specified creature should be killed and automatically reads the params from a world object.
*
* @param w The world.
* @param e The creature.
* @return {@code true} if the creature should be killed, otherwise {@code false}.
*/
boolean shouldWeKillThisCreature(MultiverseWorld w, Entity e);
}
@@ -11,6 +11,7 @@ import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import java.util.ArrayList;
@@ -34,7 +35,11 @@ public class AnchorCommand extends PaginatedCoreCommand<String> {
this.addCommandExample("/mv anchor " + ChatColor.GREEN + "otherthing");
this.addCommandExample("/mv anchor " + ChatColor.GREEN + "awesomething " + ChatColor.RED + "-d");
this.addCommandExample("/mv anchors ");
this.setPermission("multiverse.core.anchor", "Allows management of Anchor Destinations.", PermissionDefault.OP);
this.setPermission("multiverse.core.anchor.list", "Allows a player to list all anchors.", PermissionDefault.OP);
this.addAdditonalPermission(new Permission("multiverse.core.anchor.create",
"Allows a player to create anchors.", PermissionDefault.OP));
this.addAdditonalPermission(new Permission("multiverse.core.anchor.delete",
"Allows a player to delete anchors.", PermissionDefault.OP));
this.setItemsPerPage(8); // SUPPRESS CHECKSTYLE: MagicNumberCheck
}
@@ -49,6 +54,11 @@ public class AnchorCommand extends PaginatedCoreCommand<String> {
}
private void showList(CommandSender sender, List<String> args) {
if (!this.plugin.getMVPerms().hasPermission(sender, "multiverse.core.anchor.list", true)) {
sender.sendMessage(ChatColor.RED + "You don't have the permission to list anchors!");
return;
}
sender.sendMessage(ChatColor.LIGHT_PURPLE + "====[ Multiverse Anchor List ]====");
Player p = null;
if (sender instanceof Player) {
@@ -105,10 +115,14 @@ public class AnchorCommand extends PaginatedCoreCommand<String> {
return;
}
if (args.size() == 2 && args.get(1).equalsIgnoreCase("-d")) {
if (this.plugin.getAnchorManager().deleteAnchor(args.get(0))) {
sender.sendMessage("Anchor '" + args.get(0) + "' was successfully " + ChatColor.RED + "deleted!");
if (!this.plugin.getMVPerms().hasPermission(sender, "multiverse.core.anchor.delete", true)) {
sender.sendMessage(ChatColor.RED + "You don't have the permission to delete anchors!");
} else {
sender.sendMessage("Anchor '" + args.get(0) + "' was " + ChatColor.RED + " NOT " + ChatColor.WHITE + "deleted!");
if (this.plugin.getAnchorManager().deleteAnchor(args.get(0))) {
sender.sendMessage("Anchor '" + args.get(0) + "' was successfully " + ChatColor.RED + "deleted!");
} else {
sender.sendMessage("Anchor '" + args.get(0) + "' was " + ChatColor.RED + " NOT " + ChatColor.WHITE + "deleted!");
}
}
return;
}
@@ -118,13 +132,16 @@ public class AnchorCommand extends PaginatedCoreCommand<String> {
return;
}
Player player = (Player) sender;
if (this.plugin.getAnchorManager().saveAnchorLocation(args.get(0), player.getLocation())) {
sender.sendMessage("Anchor '" + args.get(0) + "' was successfully " + ChatColor.GREEN + "created!");
if (!this.plugin.getMVPerms().hasPermission(sender, "multiverse.core.anchor.create", true)) {
sender.sendMessage(ChatColor.RED + "You don't have the permission to create anchors!");
} else {
sender.sendMessage("Anchor '" + args.get(0) + "' was " + ChatColor.RED + " NOT " + ChatColor.WHITE + "created!");
Player player = (Player) sender;
if (this.plugin.getAnchorManager().saveAnchorLocation(args.get(0), player.getLocation())) {
sender.sendMessage("Anchor '" + args.get(0) + "' was successfully " + ChatColor.GREEN + "created!");
} else {
sender.sendMessage("Anchor '" + args.get(0) + "' was " + ChatColor.RED + " NOT " + ChatColor.WHITE + "created!");
}
}
}
@Override
@@ -0,0 +1,60 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.pneumaticraft.commandhandler.CommandHandler;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.PermissionDefault;
import java.util.ArrayList;
import java.util.List;
/**
* Creates a clone of a world.
*/
public class CloneCommand extends MultiverseCommand {
private MVWorldManager worldManager;
public CloneCommand(MultiverseCore plugin) {
super(plugin);
this.setName("Clone World");
this.setCommandUsage("/mv clone" + ChatColor.GREEN + " {TARGET} {NAME}" + ChatColor.GOLD + " -g [GENERATOR[:ID]]");
this.setArgRange(2, 4); // SUPPRESS CHECKSTYLE: MagicNumberCheck
this.addKey("mvclone");
this.addKey("mvcl");
this.addKey("mv cl");
this.addKey("mv clone");
this.addCommandExample("/mv clone " + ChatColor.GOLD + "world" + ChatColor.GREEN + " world_backup");
this.addCommandExample("/mv clone " + ChatColor.GOLD + "skyblock_pristine" + ChatColor.GREEN + " skyblock");
this.addCommandExample("To clone a world that uses a generator:");
this.addCommandExample("/mv clone " + ChatColor.GOLD + "CleanRoom"
+ ChatColor.GREEN + " CleanRoomCopy" + ChatColor.DARK_AQUA + " -g CleanRoomGenerator");
this.setPermission("multiverse.core.clone", "Clones a world.", PermissionDefault.OP);
this.worldManager = this.plugin.getMVWorldManager();
}
@Override
public void runCommand(CommandSender sender, List<String> args) {
Class<?>[] paramTypes = {String.class, String.class, String.class};
List<Object> objectArgs = new ArrayList<Object>();
objectArgs.add(args.get(0));
objectArgs.add(args.get(1));
objectArgs.add(CommandHandler.getFlag("-g", args));
if (!this.worldManager.isMVWorld(args.get(0))) {
// If no world was found, we can't clone.
sender.sendMessage("Sorry, Multiverse doesn't know about world " + args.get(0) + ", so we can't clone it!");
sender.sendMessage("Check the " + ChatColor.GREEN + "/mv list" + ChatColor.WHITE + " command to verify it is listed.");
return;
}
this.plugin.getCommandHandler().queueCommand(sender, "mvclone", "cloneWorld", objectArgs,
paramTypes, ChatColor.GREEN + "World Cloned!", ChatColor.RED + "World could NOT be cloned!");
}
}
@@ -18,6 +18,8 @@ import org.bukkit.command.CommandSender;
import org.bukkit.permissions.PermissionDefault;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -65,7 +67,13 @@ public class CreateCommand extends MultiverseCommand {
}
}
if (worldFile.exists() || this.worldManager.isMVWorld(worldName)) {
if (this.worldManager.isMVWorld(worldName)) {
sender.sendMessage(ChatColor.RED + "Multiverse cannot create " + ChatColor.GOLD + ChatColor.UNDERLINE
+ "another" + ChatColor.RESET + ChatColor.RED + " world named " + worldName);
return;
}
if (worldFile.exists()) {
sender.sendMessage(ChatColor.RED + "A Folder/World already exists with this name!");
sender.sendMessage(ChatColor.RED + "If you are confident it is a world you can import with /mvimport");
return;
@@ -88,7 +96,19 @@ public class CreateCommand extends MultiverseCommand {
EnvironmentCommand.showWorldTypes(sender);
return;
}
// Determine if the generator is valid. #918
if (generator != null) {
List<String> genarray = new ArrayList<String>(Arrays.asList(generator.split(":")));
if (genarray.size() < 2) {
// If there was only one arg specified, pad with another empty one.
genarray.add("");
}
if (this.worldManager.getChunkGenerator(genarray.get(0), genarray.get(1), "test") == null) {
// We have an invalid generator.
sender.sendMessage("Invalid generator! '" + generator + "'. " + ChatColor.RED + "Aborting world creation.");
return;
}
}
Command.broadcastCommandMessage(sender, "Starting creation of world '" + worldName + "'...");
if (this.worldManager.addWorld(worldName, environment, seed, type, allowStructures, generator, useSpawnAdjust)) {
@@ -23,7 +23,7 @@ public class DebugCommand extends MultiverseCommand {
public DebugCommand(MultiverseCore plugin) {
super(plugin);
this.setName("Turn Debug on/off?");
this.setCommandUsage("/mv debug" + ChatColor.GOLD + " [1|2|3|off]");
this.setCommandUsage("/mv debug" + ChatColor.GOLD + " [1|2|3|off|silent]");
this.setArgRange(0, 1);
this.addKey("mv debug");
this.addKey("mv d");
@@ -48,17 +48,18 @@ public class DebugCommand extends MultiverseCommand {
sender.sendMessage(ChatColor.RED + "Error" + ChatColor.WHITE
+ " setting debug level. Please use a number 0-3 " + ChatColor.AQUA + "(3 being many many messages!)");
}
}
plugin.saveMVConfigs();
}
this.displayDebugMode(sender);
}
private void displayDebugMode(CommandSender sender) {
if (plugin.getMVConfig().getGlobalDebug() == 0) {
final int debugLevel = plugin.getMVConfig().getGlobalDebug();
if (debugLevel == 0) {
sender.sendMessage("Multiverse Debug mode is " + ChatColor.RED + "OFF");
} else {
sender.sendMessage("Multiverse Debug mode is " + ChatColor.GREEN + plugin.getMVConfig().getGlobalDebug());
sender.sendMessage("Multiverse Debug mode is " + ChatColor.GREEN + debugLevel);
this.plugin.log(Level.FINE, "Multiverse Debug ENABLED");
}
}
@@ -53,8 +53,8 @@ public class EnvironmentCommand extends MultiverseCommand {
*/
public static void showWorldTypes(CommandSender sender) {
sender.sendMessage(ChatColor.YELLOW + "Valid World Types are:");
sender.sendMessage(String.format("%sNORMAL%s, %sFLAT %sor %sVERSION_1_1",
ChatColor.GREEN, ChatColor.WHITE, ChatColor.AQUA, ChatColor.WHITE, ChatColor.GOLD));
sender.sendMessage(String.format("%sNORMAL%s, %sFLAT, %sLARGEBIOMES %sor %sVERSION_1_1",
ChatColor.GREEN, ChatColor.WHITE, ChatColor.AQUA, ChatColor.RED, ChatColor.WHITE, ChatColor.GOLD));
}
@Override
@@ -75,6 +75,9 @@ public class EnvironmentCommand extends MultiverseCommand {
type = "NORMAL";
if (type.equalsIgnoreCase("flat"))
type = "FLAT";
if (type.equalsIgnoreCase("largebiomes")) {
type = "LARGE_BIOMES";
}
try {
// Now that we've converted a potentially unfriendly value
// to a friendly one, get it from the ENUM!
@@ -0,0 +1,75 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import java.util.List;
/**
* Allows management of Anchor Destinations.
*/
public class GameruleCommand extends MultiverseCommand {
public GameruleCommand(MultiverseCore plugin) {
super(plugin);
this.setName("Set a Minecraft Game Rule for a World.");
this.setCommandUsage("/mv gamerule " + ChatColor.GREEN + "{RULE} {VALUE}" + ChatColor.GOLD + " [WORLD]");
this.setArgRange(2, 3);
this.addKey("mv gamerule");
this.addKey("mv rule");
this.addKey("mvgamerule");
this.addKey("mvrule");
this.addCommandExample("/mv gamerule " + ChatColor.GREEN + "doMobLoot false");
this.addCommandExample("/mvrule " + ChatColor.GREEN + "keepInventory true " + ChatColor.RED + "world_nether");
this.setPermission("multiverse.core.gamerule.set", "Allows a player to set a gamerule.", PermissionDefault.OP);
}
@Override
public void runCommand(CommandSender sender, List<String> args) {
// We NEED a world from the command line
final Player p;
if (sender instanceof Player) {
p = (Player) sender;
} else {
p = null;
}
if (args.size() == 2 && p == null) {
sender.sendMessage("From the command line, WORLD is required.");
sender.sendMessage(this.getCommandDesc());
sender.sendMessage(this.getCommandUsage());
sender.sendMessage("Nothing changed.");
return;
}
final String gameRule = args.get(0);
final String value = args.get(1);
final World world;
if (args.size() == 2) {
world = p.getWorld();
} else {
world = Bukkit.getWorld(args.get(2));
}
if (world.setGameRuleValue(gameRule, value)) {
sender.sendMessage(ChatColor.GREEN + "Success!" + ChatColor.WHITE + " Gamerule " + ChatColor.AQUA + gameRule
+ ChatColor.WHITE + " was set to " + ChatColor.GREEN + value);
} else {
sender.sendMessage(ChatColor.RED + "Failure!" + ChatColor.WHITE + " Gamerule " + ChatColor.AQUA + gameRule
+ ChatColor.WHITE + " cannot be set to " + ChatColor.RED + value);
}
}
}
@@ -0,0 +1,76 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import java.util.List;
/**
* Allows management of Anchor Destinations.
*/
public class GamerulesCommand extends MultiverseCommand {
public GamerulesCommand(MultiverseCore plugin) {
super(plugin);
this.setName("List the Minecraft Game Rules for a World.");
this.setCommandUsage("/mv gamerules" + ChatColor.GOLD + " [WORLD]");
this.setArgRange(0, 1);
this.addKey("mv gamerules");
this.addKey("mv rules");
this.addKey("mvgamerules");
this.addKey("mvrules");
this.addCommandExample("/mv gamerules");
this.addCommandExample("/mvrules " + ChatColor.RED + "world_nether");
this.setPermission("multiverse.core.gamerule.list", "Allows a player to list gamerules.", PermissionDefault.OP);
}
@Override
public void runCommand(CommandSender sender, List<String> args) {
// We NEED a world from the command line
final Player p;
if (sender instanceof Player) {
p = (Player) sender;
} else {
p = null;
}
if (args.size() == 0 && p == null) {
sender.sendMessage("From the command line, WORLD is required.");
sender.sendMessage(this.getCommandDesc());
sender.sendMessage(this.getCommandUsage());
sender.sendMessage("Nothing changed.");
return;
}
final World world;
if (args.size() == 0) {
world = p.getWorld();
} else {
world = Bukkit.getWorld(args.get(0));
}
final StringBuilder gameRules = new StringBuilder();
for (final String gameRule : world.getGameRules()) {
if (gameRules.length() != 0) {
gameRules.append(ChatColor.WHITE).append(", ");
}
gameRules.append(ChatColor.AQUA).append(gameRule).append(ChatColor.WHITE).append(": ");
gameRules.append(ChatColor.GREEN).append(world.getGameRuleValue(gameRule));
}
sender.sendMessage("=== Gamerules for " + ChatColor.AQUA + world.getName() + ChatColor.WHITE + " ===");
sender.sendMessage(gameRules.toString());
}
}
@@ -7,6 +7,7 @@
package com.onarandombox.MultiverseCore.commands;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -15,7 +16,6 @@ import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
/**
* Returns a list of loaded generator plugins.
@@ -37,7 +37,7 @@ public class GeneratorCommand extends MultiverseCommand {
@Override
public void runCommand(CommandSender sender, List<String> args) {
this.plugin.log(Level.INFO, "PLEASE IGNORE the 'Plugin X does not contain any generators' message below!");
Logging.info("PLEASE IGNORE the 'Plugin X does not contain any generators' message below!");
Plugin[] plugins = this.plugin.getServer().getPluginManager().getPlugins();
List<String> generators = new ArrayList<String>();
for (Plugin p : plugins) {
@@ -122,10 +122,16 @@ public class InfoCommand extends MultiverseCommand {
//message.add(new FancyMessage("Game Mode: ", StringUtils.capitalize(world.getGameMode().toString()), colors));
Location spawn = world.getSpawnLocation();
message.add(new FancyMessage("Spawn Location: ", plugin.getLocationManipulation().strCoords(spawn), colors));
message.add(new FancyMessage("World Scale: ", world.getScaling() + "", colors));
message.add(new FancyMessage("World Scale: ", String.valueOf(world.getScaling()), colors));
message.add(new FancyMessage("World Seed: ", String.valueOf(world.getSeed()), colors));
if (world.getPrice() > 0) {
message.add(new FancyMessage("Price to enter this world: ",
this.plugin.getBank().getFormattedAmount(p, world.getPrice(), world.getCurrency()), colors));
final String formattedAmount;
if (world.getCurrency() <= 0 && plugin.getVaultHandler().getEconomy() != null) {
formattedAmount = plugin.getVaultHandler().getEconomy().format(world.getPrice());
} else {
formattedAmount = this.plugin.getBank().getFormattedAmount(p, world.getPrice(), world.getCurrency());
}
message.add(new FancyMessage("Price to enter this world: ", formattedAmount, colors));
} else {
message.add(new FancyMessage("Price to enter this world: ", ChatColor.GREEN + "FREE!", colors));
}
@@ -85,6 +85,9 @@ public class ModifyAddCommand extends MultiverseCommand {
if (world.addToVariable(property, value)) {
sender.sendMessage(ChatColor.GREEN + "Success! " + ChatColor.AQUA
+ value + ChatColor.WHITE + " was " + ChatColor.GREEN + "added to " + ChatColor.GREEN + property);
if (!plugin.saveWorldConfig()) {
sender.sendMessage(ChatColor.RED + "There was an issue saving worlds.yml! Your changes will only be temporary!");
}
} else {
sender.sendMessage(value + " could not be added to " + property);
}
@@ -80,6 +80,9 @@ public class ModifyClearCommand extends MultiverseCommand {
sender.sendMessage(property + " was cleared. It contains 0 values now.");
sender.sendMessage(ChatColor.GREEN + "Success! " + ChatColor.AQUA + property + ChatColor.WHITE + " was "
+ ChatColor.GREEN + "CLEARED" + ChatColor.WHITE + ". It contains " + ChatColor.LIGHT_PURPLE + "0" + ChatColor.WHITE + " values now.");
if (!plugin.saveWorldConfig()) {
sender.sendMessage(ChatColor.RED + "There was an issue saving worlds.yml! Your changes will only be temporary!");
}
} else {
sender.sendMessage(ChatColor.RED + "Error: " + ChatColor.GOLD + property
+ ChatColor.WHITE + " was " + ChatColor.GOLD + "NOT" + ChatColor.WHITE + " cleared.");
@@ -85,6 +85,9 @@ public class ModifyRemoveCommand extends MultiverseCommand {
if (world.removeFromVariable(property, value)) {
sender.sendMessage(ChatColor.GREEN + "Success! " + ChatColor.AQUA + value + ChatColor.WHITE
+ " was " + ChatColor.RED + "removed from " + ChatColor.GREEN + property);
if (!plugin.saveWorldConfig()) {
sender.sendMessage(ChatColor.RED + "There was an issue saving worlds.yml! Your changes will only be temporary!");
}
} else {
sender.sendMessage(ChatColor.RED + "There was an error removing " + ChatColor.GRAY
+ value + ChatColor.WHITE + " from " + ChatColor.GOLD + property);
@@ -111,6 +111,9 @@ public class ModifySetCommand extends MultiverseCommand {
if (world.setPropertyValue(property, value)) {
sender.sendMessage(ChatColor.GREEN + "Success!" + ChatColor.WHITE + " Property " + ChatColor.AQUA + property
+ ChatColor.WHITE + " was set to " + ChatColor.GREEN + value);
if (!plugin.saveWorldConfig()) {
sender.sendMessage(ChatColor.RED + "There was an issue saving worlds.yml! Your changes will only be temporary!");
}
} else {
sender.sendMessage(ChatColor.RED + world.getPropertyHelp(property));
}
@@ -0,0 +1,54 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import java.io.File;
import java.util.List;
/**
* States who is in what world.
*/
public class ScriptCommand extends MultiverseCommand {
public ScriptCommand(MultiverseCore plugin) {
super(plugin);
this.setName("Runs a script.");
this.setCommandUsage("/mv script" + ChatColor.GOLD + " {script} [target]");
this.setArgRange(1, 2);
this.addKey("mv script");
this.addKey("mvscript");
this.addCommandExample(String.format("/mv script %sscript.txt", ChatColor.GOLD));
this.addCommandExample(String.format("/mv script %stest.txt %ssomeplayer", ChatColor.GOLD, ChatColor.GREEN));
this.setPermission("multiverse.core.script", "Runs a script.", PermissionDefault.OP);
}
@Override
public void runCommand(CommandSender sender, List<String> args) {
File file = new File(plugin.getScriptAPI().getScriptFolder(), args.get(0));
if (!file.exists()) {
sender.sendMessage("That script file does not exist in the Multiverse-Core scripts directory!");
return;
}
Player player = null;
if (sender instanceof Player) {
player = (Player) sender;
}
String target = null;
if (args.size() == 2) {
target = args.get(1);
}
plugin.getScriptAPI().executeScript(file, target, player);
sender.sendMessage(String.format("Script '%s%s%s' finished!", ChatColor.GOLD, file.getName(), ChatColor.WHITE));
}
}
@@ -64,6 +64,9 @@ public class SetSpawnCommand extends MultiverseCommand {
foundWorld.setAdjustSpawn(false);
}
sender.sendMessage("Spawn was set to: " + plugin.getLocationManipulation().strCoords(p.getLocation()));
if (!plugin.saveWorldConfig()) {
sender.sendMessage(ChatColor.RED + "There was an issue saving worlds.yml! Your changes will only be temporary!");
}
} else {
w.setSpawnLocation(l.getBlockX(), l.getBlockY(), l.getBlockZ());
sender.sendMessage("Multiverse does not know about this world, only X,Y and Z set. Please import it to set the spawn fully (Pitch/Yaws).");
@@ -0,0 +1,52 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.PermissionDefault;
import java.util.List;
/**
* Enables debug-information.
*/
public class SilentCommand extends MultiverseCommand {
public SilentCommand(MultiverseCore plugin) {
super(plugin);
this.setName("Turn silent mode on/off?");
this.setCommandUsage("/mv silent" + ChatColor.GOLD + " [true|false|on|off]");
this.setArgRange(0, 1);
this.addKey("mv silent");
this.addKey("mvsilent");
this.addCommandExample("/mv silent " + ChatColor.GOLD + "true");
this.setPermission("multiverse.core.silent", "Reduces the amount of startup messages.", PermissionDefault.OP);
}
@Override
public void runCommand(CommandSender sender, List<String> args) {
if (args.size() == 1) {
if (args.get(0).equalsIgnoreCase("on")) {
args.set(0, "true");
}
plugin.getMVConfig().setSilentStart(Boolean.valueOf(args.get(0)));
plugin.saveMVConfigs();
}
this.displaySilentMode(sender);
}
private void displaySilentMode(CommandSender sender) {
if (plugin.getMVConfig().getSilentStart()) {
sender.sendMessage("Multiverse Silent Start mode is " + ChatColor.GREEN + "ON");
} else {
sender.sendMessage("Multiverse Silent Start mode is " + ChatColor.RED + "OFF");
}
}
}
@@ -7,6 +7,7 @@
package com.onarandombox.MultiverseCore.commands;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.event.MVVersionEvent;
import com.onarandombox.MultiverseCore.utils.webpaste.BitlyURLShortener;
@@ -15,14 +16,12 @@ import com.onarandombox.MultiverseCore.utils.webpaste.PasteService;
import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceFactory;
import com.onarandombox.MultiverseCore.utils.webpaste.PasteServiceType;
import com.onarandombox.MultiverseCore.utils.webpaste.URLShortener;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import java.util.List;
import java.util.logging.Level;
/**
* Dumps version info to the console.
@@ -52,9 +51,15 @@ public class VersionCommand extends MultiverseCommand {
StringBuilder buffer = new StringBuilder();
buffer.append("[Multiverse-Core] Multiverse-Core Version: ").append(this.plugin.getDescription().getVersion()).append('\n');
buffer.append("[Multiverse-Core] Bukkit Version: ").append(this.plugin.getServer().getVersion()).append('\n');
buffer.append("[Multiverse-Core] Loaded Worlds: ").append(this.plugin.getMVWorldManager().getMVWorlds().size()).append('\n');
buffer.append("[Multiverse-Core] Loaded Worlds: ").append(this.plugin.getMVWorldManager().getMVWorlds()).append('\n');
buffer.append("[Multiverse-Core] Multiverse Plugins Loaded: ").append(this.plugin.getPluginCount()).append('\n');
buffer.append("[Multiverse-Core] Economy being used: ").append(this.plugin.getBank().getEconUsed()).append('\n');
final boolean usingVault = plugin.getVaultHandler().getEconomy() != null;
buffer.append("[Multiverse-Core] Using Vault: ").append(usingVault).append('\n');
if (usingVault) {
buffer.append("[Multiverse-Core] Economy being used: ").append(plugin.getVaultHandler().getEconomy().getName()).append('\n');
} else {
buffer.append("[Multiverse-Core] Economy being used: ").append(this.plugin.getBank().getEconUsed()).append('\n');
}
buffer.append("[Multiverse-Core] Permissions Plugin: ").append(this.plugin.getMVPerms().getType()).append('\n');
buffer.append("[Multiverse-Core] Dumping Config Values: (version ")
.append(this.plugin.getMVConfig().getVersion()).append(")").append('\n');
@@ -76,7 +81,7 @@ public class VersionCommand extends MultiverseCommand {
final String data = versionEvent.getVersionInfo();
String[] lines = data.split("\n");
for (String line : lines) {
this.plugin.log(Level.INFO, line);
Logging.info(line);
}
this.plugin.getServer().getScheduler().scheduleAsyncDelayedTask(this.plugin, new Runnable() {
@@ -93,7 +98,7 @@ public class VersionCommand extends MultiverseCommand {
}
sender.sendMessage("Version info dumped here: " + ChatColor.GREEN + pasteUrl);
plugin.log(Level.INFO, "Version info dumped here: " + pasteUrl);
Logging.info("Version info dumped here: %s", pasteUrl);
}
}
});
@@ -15,6 +15,8 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
@@ -50,6 +52,14 @@ public class WhoCommand extends MultiverseCommand {
showAll = false;
}
final Player[] onlinePlayers = plugin.getServer().getOnlinePlayers();
final Collection<Player> visiblePlayers = new HashSet<Player>(onlinePlayers.length);
for (final Player player : onlinePlayers) {
if (p == null || p.canSee(player)) {
visiblePlayers.add(player);
}
}
if (args.size() == 1) {
if (args.get(0).equalsIgnoreCase("--all") || args.get(0).equalsIgnoreCase("-a")) {
showAll = true;
@@ -68,18 +78,19 @@ public class WhoCommand extends MultiverseCommand {
sender.sendMessage(String.format("%s--- Players in %s%s ---", ChatColor.AQUA,
world.getColoredWorldString(), ChatColor.AQUA));
sender.sendMessage(buildPlayerString(world, p));
sender.sendMessage(this.buildPlayerString(world, p, visiblePlayers));
return;
}
}
// multiworld mode
sender.sendMessage(ChatColor.AQUA + "--- Worlds and their players ---");
sender.sendMessage(ChatColor.AQUA + "--- Worlds and their players --- "
+ visiblePlayers.size() + "/" + plugin.getServer().getMaxPlayers());
boolean shownOne = false;
for (MultiverseWorld world : this.worldManager.getMVWorlds()) {
if (this.plugin.getMVPerms().canEnterWorld(p, world)) { // only show world if the player can access it
if (showAll || !world.getCBWorld().getPlayers().isEmpty()) { // either show all or show if the world is not empty
sender.sendMessage(String.format("%s%s - %s", world.getColoredWorldString(), ChatColor.WHITE, buildPlayerString(world, p)));
sender.sendMessage(String.format("%s%s - %s", world.getColoredWorldString(), ChatColor.WHITE, buildPlayerString(world, p, visiblePlayers)));
shownOne = true;
}
}
@@ -90,18 +101,18 @@ public class WhoCommand extends MultiverseCommand {
return;
}
private static String buildPlayerString(MultiverseWorld world, Player viewer) {
private static String buildPlayerString(MultiverseWorld world, Player viewer, final Collection<Player> visiblePlayers) {
// Retrieve the players in this world
List<Player> players = world.getCBWorld().getPlayers();
if (players.size() == 0) {
return "No players found.";
} else {
StringBuilder playerBuilder = new StringBuilder();
for (Player player : players) {
if ((viewer == null) || viewer.canSee(player))
playerBuilder.append(player.getDisplayName()).append(", ");
}
String bString = playerBuilder.toString();
return bString.substring(0, bString.length() - 2);
StringBuilder playerBuilder = new StringBuilder();
for (Player player : players) {
// If the viewer is the console or the viewier is allowed to see the player, show them.
// Make sure we're also ONLY showing online players.
// Since we already checked visible players, we'll just make sure who we're about to show is in that.
if (visiblePlayers.contains(player))
playerBuilder.append(player.getDisplayName()).append(", ");
}
String bString = playerBuilder.toString();
return (bString.length() == 0) ? "No players found." : bString.substring(0, bString.length() - 2);
}
}
@@ -17,6 +17,8 @@ public class SubSpawnSettings extends SerializationConfig {
@Property
private boolean spawn;
@Property
private int spawnrate;
@Property
private List<String> exceptions;
public SubSpawnSettings() {
@@ -34,6 +36,7 @@ public class SubSpawnSettings extends SerializationConfig {
public void setDefaults() {
spawn = true;
exceptions = new ArrayList<String>();
spawnrate = -1;
}
/**
@@ -51,9 +54,23 @@ public class SubSpawnSettings extends SerializationConfig {
}
/**
* @return the exceptions
* @return The exceptions
*/
public List<String> getExceptions() {
return exceptions;
}
/**
* @param rate The new spawn rate
*/
public void setSpawnRate(int rate) {
this.spawnrate = rate;
}
/**
* @return The spawn rate
*/
public int getSpawnRate() {
return this.spawnrate;
}
}
@@ -7,7 +7,9 @@
package com.onarandombox.MultiverseCore.destination;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVDestination;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -21,6 +23,7 @@ public class BedDestination implements MVDestination {
private boolean isValid;
private Location knownBedLoc;
private MultiverseCore plugin;
/**
* {@inheritDoc}
@@ -46,7 +49,10 @@ public class BedDestination implements MVDestination {
@Override
public Location getLocation(Entity entity) {
if (entity instanceof Player) {
this.knownBedLoc = ((Player) entity).getBedSpawnLocation();
this.knownBedLoc = this.plugin.getBlockSafety().getSafeBedSpawn(((Player) entity).getBedSpawnLocation());
if (this.knownBedLoc == null) {
((Player) entity).sendMessage("Your bed was " + ChatColor.RED + "invalid or blocked" + ChatColor.RESET + ". Sorry.");
}
return this.knownBedLoc;
}
return null;
@@ -65,7 +71,7 @@ public class BedDestination implements MVDestination {
*/
@Override
public void setDestination(JavaPlugin plugin, String destination) {
// Not needed.
this.plugin = (MultiverseCore) plugin;
}
/**
@@ -0,0 +1,35 @@
package com.onarandombox.MultiverseCore.listeners;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
/**
* A wrapper for the {@link AsyncPlayerChatEvent}.
*/
public class AsyncChatEvent implements ChatEvent {
private final AsyncPlayerChatEvent event;
public AsyncChatEvent(AsyncPlayerChatEvent event) {
this.event = event;
}
@Override
public boolean isCancelled() {
return event.isCancelled();
}
@Override
public String getFormat() {
return event.getFormat();
}
@Override
public void setFormat(String s) {
event.setFormat(s);
}
@Override
public Player getPlayer() {
return event.getPlayer();
}
}
@@ -0,0 +1,29 @@
package com.onarandombox.MultiverseCore.listeners;
import org.bukkit.entity.Player;
/**
* A wrapper for the two chat-events in Bukkit.
*/
public interface ChatEvent {
/**
* @return Whether this event is cancelled.
*/
boolean isCancelled();
/**
* @return The format.
*/
String getFormat();
/**
* Sets the format.
* @param s The new format.
*/
void setFormat(String s);
/**
* @return The player.
*/
Player getPlayer();
}
@@ -0,0 +1,34 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import java.util.logging.Level;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import com.onarandombox.MultiverseCore.MultiverseCore;
/**
* Multiverse's {@link org.bukkit.event.Listener} for players.
*/
public class MVAsyncPlayerChatListener extends MVChatListener {
public MVAsyncPlayerChatListener(MultiverseCore plugin, MVPlayerListener playerListener) {
super(plugin, playerListener);
plugin.log(Level.FINE, "Created AsyncPlayerChatEvent listener.");
}
/**
* This method is called when a player wants to chat.
* @param event The Event that was fired.
*/
@EventHandler
public void playerChat(AsyncPlayerChatEvent event) {
this.playerChat(new AsyncChatEvent(event));
}
}
@@ -0,0 +1,52 @@
package com.onarandombox.MultiverseCore.listeners;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import org.bukkit.event.Listener;
/**
* Multiverse's {@link org.bukkit.event.Listener} for players.
*/
public abstract class MVChatListener implements Listener {
private final MultiverseCore plugin;
private final MVWorldManager worldManager;
private final MVPlayerListener playerListener;
public MVChatListener(MultiverseCore plugin, MVPlayerListener playerListener) {
this.plugin = plugin;
this.worldManager = plugin.getMVWorldManager();
this.playerListener = playerListener;
}
/**
* This handles a {@link ChatEvent}.
* @param event The {@link ChatEvent}.
*/
public void playerChat(ChatEvent event) {
if (event.isCancelled()) {
return;
}
// Check whether the Server is set to prefix the chat with the World name.
// If not we do nothing, if so we need to check if the World has an Alias.
if (plugin.getMVConfig().getPrefixChat()) {
String world = playerListener.getPlayerWorld().get(event.getPlayer().getName());
if (world == null) {
world = event.getPlayer().getWorld().getName();
playerListener.getPlayerWorld().put(event.getPlayer().getName(), world);
}
String prefix = "";
// If we're not a MV world, don't do anything
if (!this.worldManager.isMVWorld(world)) {
return;
}
MultiverseWorld mvworld = this.worldManager.getMVWorld(world);
if (mvworld.isHidden()) {
return;
}
prefix = mvworld.getColoredWorldString();
String format = event.getFormat();
event.setFormat("[" + prefix + "]" + format);
}
}
}
@@ -11,13 +11,8 @@ import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import org.bukkit.World;
import org.bukkit.entity.Animals;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Ghast;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Squid;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
@@ -26,14 +21,12 @@ import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import java.util.List;
import java.util.logging.Level;
/**
* Multiverse's Entity {@link Listener}.
*/
public class MVEntityListener implements Listener {
private MultiverseCore plugin;
private MVWorldManager worldManager;
@@ -87,7 +80,8 @@ public class MVEntityListener implements Listener {
public void creatureSpawn(CreatureSpawnEvent event) {
// Check to see if the Creature is spawned by a plugin, we don't want to prevent this behaviour.
// TODO: Allow the egg thing to be a config param. Doubt this will be per world; seems silly.
if (event.getSpawnReason() == SpawnReason.CUSTOM || event.getSpawnReason() == SpawnReason.SPAWNER_EGG) {
if (event.getSpawnReason() == SpawnReason.CUSTOM || event.getSpawnReason() == SpawnReason.SPAWNER_EGG
|| event.getSpawnReason() == SpawnReason.BREEDING) {
return;
}
@@ -100,8 +94,6 @@ public class MVEntityListener implements Listener {
return;
EntityType type = event.getEntityType();
MultiverseWorld mvworld = this.worldManager.getMVWorld(world.getName());
/**
* Handle people with non-standard animals: ie a patched craftbukkit.
*/
@@ -110,43 +102,8 @@ public class MVEntityListener implements Listener {
return;
}
/**
* Animal Handling
*/
if (!event.isCancelled() && (event.getEntity() instanceof Animals || event.getEntity() instanceof Squid)) {
event.setCancelled(shouldWeKillThisCreature(mvworld.getAnimalList(), mvworld.canAnimalsSpawn(), type.getName().toUpperCase()));
}
/**
* Monster Handling
*/
if (!event.isCancelled() && (event.getEntity() instanceof Monster || event.getEntity() instanceof Ghast || event.getEntity() instanceof Slime)) {
event.setCancelled(shouldWeKillThisCreature(mvworld.getMonsterList(), mvworld.canMonstersSpawn(), type.getName().toUpperCase()));
}
}
private static boolean shouldWeKillThisCreature(List<String> creatureList, boolean allowCreatureSpawning, String creature) {
if (creatureList.isEmpty() && allowCreatureSpawning) {
// 1. There are no exceptions and animals are allowed. Save it.
return false;
} else if (creatureList.isEmpty()) {
// 2. There are no exceptions and animals are NOT allowed. Kill it.
return true;
} else if (creatureList.contains(creature.toUpperCase()) && allowCreatureSpawning) {
// 3. There ARE exceptions and animals ARE allowed. Kill it.
return true;
} else if (!creatureList.contains(creature.toUpperCase()) && allowCreatureSpawning) {
// 4. There ARE exceptions and animals ARE NOT allowed. SAVE it.
return false;
} else if (creatureList.contains(creature.toUpperCase()) && !allowCreatureSpawning) {
// 5. No animals are allowed to be spawned, BUT this one can stay...
return false;
} else if (!creatureList.contains(creature.toUpperCase()) && !allowCreatureSpawning) {
// 6. Animals are NOT allowed to spawn, and this creature is not in the save list... KILL IT
return true;
} else {
// This code should NEVER execute. I just left the verbose conditions in right now.
throw new UnsupportedOperationException();
}
MultiverseWorld mvworld = this.worldManager.getMVWorld(world.getName());
event.setCancelled(this.plugin.getMVWorldManager().getTheWorldPurger().shouldWeKillThisCreature(mvworld, event.getEntity()));
}
}
@@ -0,0 +1,43 @@
package com.onarandombox.MultiverseCore.listeners;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.MapInitializeEvent;
import org.bukkit.map.MapView;
/**
* A listener for bukkit map events.
*/
public class MVMapListener implements Listener {
private final MultiverseCore plugin;
public MVMapListener(final MultiverseCore plugin) {
this.plugin = plugin;
}
/**
* This method is called when a map is initialized.
* @param event The event that was fired.
*/
@EventHandler
public void mapInitialize(final MapInitializeEvent event) {
for (final Player player : Bukkit.getOnlinePlayers()) {
if ((player.getItemInHand().getType() == Material.MAP
|| player.getItemInHand().getType() == Material.EMPTY_MAP)
&& player.getItemInHand().getDurability() == event.getMap().getId()) {
final Location playerLoc = player.getLocation();
final MapView map = event.getMap();
map.setCenterX(playerLoc.getBlockX());
map.setCenterZ(playerLoc.getBlockZ());
map.setWorld(playerLoc.getWorld());
return;
}
}
}
}
@@ -0,0 +1,35 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.listeners;
import java.util.logging.Level;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerChatEvent;
import com.onarandombox.MultiverseCore.MultiverseCore;
/**
* Multiverse's {@link org.bukkit.event.Listener} for players.
*/
@SuppressWarnings("deprecation") // this exists only for downwards compatibility
public class MVPlayerChatListener extends MVChatListener {
public MVPlayerChatListener(MultiverseCore plugin, MVPlayerListener playerListener) {
super(plugin, playerListener);
plugin.log(Level.FINE, "Registered PlayerChatEvent listener.");
}
/**
* This method is called when a player wants to chat.
* @param event The Event that was fired.
*/
@EventHandler
public void playerChat(PlayerChatEvent event) {
this.playerChat(new NormalChatEvent(event));
}
}
@@ -7,11 +7,13 @@
package com.onarandombox.MultiverseCore.listeners;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
import com.onarandombox.MultiverseCore.utils.PermissionTools;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@@ -21,55 +23,37 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
/**
* Multiverse's {@link Listener} for players.
*/
public class MVPlayerListener implements Listener {
private MultiverseCore plugin;
private MVWorldManager worldManager;
private PermissionTools pt;
private final MultiverseCore plugin;
private final MVWorldManager worldManager;
private final PermissionTools pt;
private final Map<String, String> playerWorld = new ConcurrentHashMap<String, String>();
public MVPlayerListener(MultiverseCore plugin) {
this.plugin = plugin;
worldManager = plugin.getMVWorldManager();
pt = new PermissionTools(plugin);
}
/**
* This method is called when a player wants to chat.
* @param event The Event that was fired.
* @return the playerWorld-map
*/
@EventHandler
public void playerChat(PlayerChatEvent event) {
if (event.isCancelled()) {
return;
}
// Check whether the Server is set to prefix the chat with the World name.
// If not we do nothing, if so we need to check if the World has an Alias.
if (plugin.getMVConfig().getPrefixChat()) {
String world = event.getPlayer().getWorld().getName();
String prefix = "";
// If we're not a MV world, don't do anything
if (!this.worldManager.isMVWorld(world)) {
return;
}
MultiverseWorld mvworld = this.worldManager.getMVWorld(world);
if (mvworld.isHidden()) {
return;
}
prefix = mvworld.getColoredWorldString();
String format = event.getFormat();
event.setFormat("[" + prefix + "]" + format);
}
public Map<String, String> getPlayerWorld() {
return playerWorld;
}
/**
@@ -142,7 +126,8 @@ public class MVPlayerListener implements Listener {
}
}
// Handle the Players GameMode setting for the new world.
this.handleGameMode(event.getPlayer(), event.getPlayer().getWorld());
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
playerWorld.put(p.getName(), p.getWorld().getName());
}
/**
@@ -152,7 +137,8 @@ public class MVPlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void playerChangedWorld(PlayerChangedWorldEvent event) {
// Permissions now determine whether or not to handle a gamemode.
this.handleGameMode(event.getPlayer(), event.getPlayer().getWorld());
this.handleGameModeAndFlight(event.getPlayer(), event.getPlayer().getWorld());
playerWorld.put(event.getPlayer().getName(), event.getPlayer().getWorld().getName());
}
/**
@@ -208,6 +194,8 @@ public class MVPlayerListener implements Listener {
+ "' don't have the FUNDS required to enter it.");
return;
}
// Check if player is allowed to enter the world if we're enforcing permissions
if (plugin.getMVConfig().getEnforceAccess()) {
event.setCancelled(!pt.playerCanGoFromTo(fromWorld, toWorld, teleporter, teleportee));
if (event.isCancelled() && teleporter != null) {
@@ -215,13 +203,31 @@ public class MVPlayerListener implements Listener {
+ "' was DENIED ACCESS to '" + toWorld.getAlias()
+ "' because '" + teleporter.getName()
+ "' don't have: multiverse.access." + event.getTo().getWorld().getName());
} else {
this.stateSuccess(teleportee.getName(), toWorld.getAlias());
return;
}
} else {
this.plugin.log(Level.FINE, "Player '" + teleportee.getName()
+ "' was allowed to go to '" + toWorld.getAlias() + "' because enforceaccess is off.");
}
// Does a limit actually exist?
if (toWorld.getPlayerLimit() > -1) {
// Are there equal or more people on the world than the limit?
if (toWorld.getCBWorld().getPlayers().size() >= toWorld.getPlayerLimit()) {
// Ouch the world is full, lets see if the player can bypass that limitation
if (!pt.playerCanBypassPlayerLimit(toWorld, teleporter, teleportee)) {
this.plugin.log(Level.FINE, "Player '" + teleportee.getName()
+ "' was DENIED ACCESS to '" + toWorld.getAlias()
+ "' because the world is full and '" + teleporter.getName()
+ "' doesn't have: mv.bypass.playerlimit." + event.getTo().getWorld().getName());
event.setCancelled(true);
return;
}
}
}
// By this point anything cancelling the event has returned on the method, meaning the teleport is a success \o/
this.stateSuccess(teleportee.getName(), toWorld.getAlias());
}
private void stateSuccess(String playerName, String worldName) {
@@ -294,12 +300,16 @@ public class MVPlayerListener implements Listener {
+ "' was allowed to go to '" + event.getTo().getWorld().getName()
+ "' because enforceaccess is off.");
}
if (!plugin.getMVConfig().isUsingDefaultPortalSearch() && event.getPortalTravelAgent() != null) {
event.getPortalTravelAgent().setSearchRadius(plugin.getMVConfig().getPortalSearchRadius());
}
}
private void sendPlayerToDefaultWorld(final Player player) {
// Remove the player 1 tick after the login. I'm sure there's GOT to be a better way to do this...
this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin,
new Runnable() {
@Override
public void run() {
player.teleport(plugin.getMVWorldManager().getFirstSpawnWorld().getSpawnLocation());
}
@@ -307,13 +317,13 @@ public class MVPlayerListener implements Listener {
}
// FOLLOWING 2 Methods and Private class handle Per Player GameModes.
private void handleGameMode(Player player, World world) {
private void handleGameModeAndFlight(Player player, World world) {
MultiverseWorld mvWorld = this.worldManager.getMVWorld(world.getName());
if (mvWorld != null) {
this.handleGameMode(player, mvWorld);
this.handleGameModeAndFlight(player, mvWorld);
} else {
this.plugin.log(Level.FINER, "Not handling gamemode for world '" + world.getName()
this.plugin.log(Level.FINER, "Not handling gamemode and flight for world '" + world.getName()
+ "' not managed by Multiverse.");
}
}
@@ -323,30 +333,40 @@ public class MVPlayerListener implements Listener {
* @param player The {@link Player}.
* @param world The world the player is in.
*/
public void handleGameMode(final Player player, final MultiverseWorld world) {
public void handleGameModeAndFlight(final Player player, final MultiverseWorld world) {
// We perform this task one tick later to MAKE SURE that the player actually reaches the
// destination world, otherwise we'd be changing the player mode if they havent moved anywhere.
if (!this.pt.playerCanIgnoreGameModeRestriction(world, player)) {
this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin,
this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin,
new Runnable() {
@Override
public void run() {
// Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled.
if (player.getWorld() == world.getCBWorld()) {
MultiverseCore.staticLog(Level.FINE, "Handling gamemode for player: "
+ player.getName() + ", Changing to " + world.getGameMode().toString());
MultiverseCore.staticLog(Level.FINEST, "From World: " + player.getWorld());
MultiverseCore.staticLog(Level.FINEST, "To World: " + world);
player.setGameMode(world.getGameMode());
if (!MVPlayerListener.this.pt.playerCanIgnoreGameModeRestriction(world, player)) {
// Check that the player is in the new world and they haven't been teleported elsewhere or the event cancelled.
if (player.getWorld() == world.getCBWorld()) {
Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString());
Logging.finest("From World: %s", player.getWorld());
Logging.finest("To World: %s", world);
player.setGameMode(world.getGameMode());
// Check if their flight mode should change
// TODO need a override permission for this
if (player.getAllowFlight() && !world.getAllowFlight() && player.getGameMode() != GameMode.CREATIVE) {
player.setAllowFlight(false);
if (player.isFlying()) {
player.setFlying(false);
}
} else if (world.getAllowFlight()) {
if (player.getGameMode() == GameMode.CREATIVE) {
player.setAllowFlight(true);
}
}
} else {
Logging.fine("The gamemode/allowfly was NOT changed for player '%s' because he is now in world '%s' instead of world '%s'",
player.getName(), player.getWorld().getName(), world.getName());
}
} else {
MultiverseCore.staticLog(Level.FINE, "The gamemode was NOT changed for player '"
+ player.getName() + "' because he is now in world '"
+ player.getWorld().getName() + "' instead of world '"
+ world.getName() +"'");
MVPlayerListener.this.plugin.log(Level.FINE, "Player: " + player.getName() + " is IMMUNE to gamemode changes!");
}
}
}, 1L);
} else {
this.plugin.log(Level.FINE, "Player: " + player.getName() + " is IMMUNE to gamemode changes!");
}
}
}
@@ -34,6 +34,10 @@ public class MVPluginListener implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR)
public void pluginEnable(PluginEnableEvent event) {
if (plugin.getVaultHandler().getEconomy() != null) {
// Don't hook 2 economy plugins.
return;
}
// Let AllPay handle all econ plugin loadings, only go for econ plugins we support
if (Arrays.asList(AllPay.getValidEconPlugins()).contains(event.getPlugin().getDescription().getName())) {
this.plugin.setBank(this.plugin.getBanker().loadEconPlugin());
@@ -0,0 +1,37 @@
package com.onarandombox.MultiverseCore.listeners;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChatEvent;
/**
* A wrapper for the {@link PlayerChatEvent}.
* @deprecated This is deprecated like the {@link PlayerChatEvent}.
*/
@Deprecated
public class NormalChatEvent implements ChatEvent {
private final PlayerChatEvent event;
public NormalChatEvent(PlayerChatEvent event) {
this.event = event;
}
@Override
public boolean isCancelled() {
return event.isCancelled();
}
@Override
public String getFormat() {
return event.getFormat();
}
@Override
public void setFormat(String s) {
event.setFormat(s);
}
@Override
public Player getPlayer() {
return event.getPlayer();
}
}
@@ -0,0 +1,52 @@
package com.onarandombox.MultiverseCore.permissions;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissionDefault;
/**
* Provides improved parent-child relationships for permissions. This is the standard implementation of {@link PermissionNode}.
* <p>
* Apparently parents override their children in Bukkit:
* Let {@code permissionA} be a parent permission of {@code permissionB}, setting {@code permissionB} to {@code true}.
* Now a player has {@code permissionA=true} and {@code permissionB=false}. Result: Both are {@code true}.
* Another player has {@code permissionA=false} and {@code permissionB=true}. Result: Both are {@code false}.
* <p>
* This is completely useless for things like MV's world access permissions where you could for example want to deny
* access to all worlds by default, with a few exceptions.
* <p>
* This class takes over all the permission hierarchy checks and provides a way that makes sense. In the
* above examples, the effective permissions would be equal to the permissions that were set.
*/
public class HierarchyPermission implements PermissionNode {
private final PermissionNode parent;
private final Permission permission;
public HierarchyPermission(final PermissionNode parent, final String permission, final String description) {
this.parent = parent;
Permission p = Bukkit.getServer().getPluginManager().getPermission(permission);
if (p == null)
p = new Permission(permission, description, PermissionDefault.FALSE);
else {
p.getChildren().clear();
//p.recalculatePermissibles(); // Not necessary because it's done automatically after setting the default
p.setDefault(PermissionDefault.FALSE);
}
this.permission = p;
}
/**
* Checks whether a given {@link Permissible} has this {@link HierarchyPermission}.
*
* @param permissible The {@link Permissible} that might have the permission.
* @return Whether it has the permission.
*/
public boolean has(Permissible permissible) {
if (permissible.isPermissionSet(permission))
return permissible.hasPermission(permission);
// ask the guy over there
return parent.has(permissible);
}
}
@@ -0,0 +1,38 @@
package com.onarandombox.MultiverseCore.permissions;
import org.bukkit.permissions.Permissible;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a permission node with dynamically created children.
*/
public class PermissionCollection {
private final PermissionNode root;
private final Map<String, PermissionNode> elements;
private final String prefix;
private final String description;
public PermissionCollection(PermissionNode parent, String prefix, String description) {
if (!prefix.endsWith("."))
throw new IllegalArgumentException("The prefix must end with a dot!");
this.root = new HierarchyPermission(parent, prefix + "*", description);
this.elements = new HashMap<String, PermissionNode>();
this.prefix = prefix;
this.description = description;
}
/**
* Checks whether a given {@link Permissible} has a specified element permission.
*
* @param p The {@link Permissible}.
* @param element The element.
* @return Whether the {@link Permissible} has the permission.
*/
public boolean has(Permissible p, String element) {
if (!this.elements.containsKey(element))
this.elements.put(element, new HierarchyPermission(root, prefix + element, description));
return this.elements.get(element).has(p);
}
}
@@ -0,0 +1,30 @@
package com.onarandombox.MultiverseCore.permissions;
import org.bukkit.permissions.Permissible;
/**
* A node in a permissions hierarchy.
*
* @see HierarchyPermission
*/
public interface PermissionNode {
static final class OperatorDefault implements PermissionNode {
@Override
public boolean has(final Permissible permissible) {
return permissible.isOp();
}
}
/**
* This {@link HierarchyPermission} depends on the operator state. Ops have it, non-ops don't.
*/
PermissionNode OP_DEFAULT = new OperatorDefault();
/**
* Checks whether a given {@link Permissible} has this node.
*
* @param permissible The {@link Permissible} that might have the permission.
* @return Whether it has the permission.
*/
boolean has(Permissible permissible);
}
@@ -0,0 +1,21 @@
package com.onarandombox.MultiverseCore.permissions;
/**
* Permission nodes.
*/
public class Permissions {
protected Permissions() {
throw new UnsupportedOperationException();
}
/**
* The {@code multiverse.*} permission.
*/
public static final HierarchyPermission MV_ROOT = new HierarchyPermission(PermissionNode.OP_DEFAULT,
"multiverse.*", "Provides access to all Multiverse features.");
/**
* The {@code multiverse.access.*} family of permissions.
*/
public static final PermissionCollection ACCESS = new PermissionCollection(MV_ROOT, "multiverse.access.", "World access");
}
@@ -0,0 +1,4 @@
/**
* Contains permissions utility classes.
*/
package com.onarandombox.MultiverseCore.permissions;
@@ -7,6 +7,7 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
@@ -16,7 +17,6 @@ import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -50,10 +50,10 @@ public class AnchorManager {
//world:x,y,z:pitch:yaw
Location anchorLocation = plugin.getLocationManipulation().stringToLocation(anchorsSection.getString(key, ""));
if (anchorLocation != null) {
MultiverseCore.staticLog(Level.INFO, "Loading anchor: '" + key + "'...");
Logging.config("Loading anchor: '%s'...", key);
this.anchors.put(key, anchorLocation);
} else {
MultiverseCore.staticLog(Level.WARNING, "The location for anchor '" + key + "' is INVALID.");
Logging.warning("The location for anchor '%s' is INVALID.", key);
}
}
@@ -7,15 +7,13 @@
package com.onarandombox.MultiverseCore.utils;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Vehicle;
import java.util.logging.Level;
/**
* Used to determine block/location-related facts.
*
@@ -75,28 +73,28 @@ public class BlockSafety {
if (this.isSolidBlock(world.getBlockAt(actual).getType())
|| this.isSolidBlock(upOne.getBlock().getType())) {
MultiverseCore.staticLog(Level.FINER, "Error Here (Actual)? ("
+ actual.getBlock().getType() + ")[" + this.isSolidBlock(actual.getBlock().getType()) + "]");
MultiverseCore.staticLog(Level.FINER, "Error Here (upOne)? ("
+ upOne.getBlock().getType() + ")[" + this.isSolidBlock(upOne.getBlock().getType()) + "]");
Logging.finest("Error Here (Actual)? (%s)[%s]", actual.getBlock().getType(),
this.isSolidBlock(actual.getBlock().getType()));
Logging.finest("Error Here (upOne)? (%s)[%s]", upOne.getBlock().getType(),
this.isSolidBlock(upOne.getBlock().getType()));
return false;
}
if (downOne.getBlock().getType() == Material.LAVA || downOne.getBlock().getType() == Material.STATIONARY_LAVA) {
MultiverseCore.staticLog(Level.FINER, "Error Here (downOne)? ("
+ downOne.getBlock().getType() + ")[" + this.isSolidBlock(downOne.getBlock().getType()) + "]");
Logging.finest("Error Here (downOne)? (%s)[%s]", downOne.getBlock().getType(),
this.isSolidBlock(downOne.getBlock().getType()));
return false;
}
if (downOne.getBlock().getType() == Material.FIRE) {
MultiverseCore.staticLog(Level.FINER, "There's fire below! ("
+ actual.getBlock().getType() + ")[" + this.isSolidBlock(actual.getBlock().getType()) + "]");
Logging.finest("There's fire below! (%s)[%s]", actual.getBlock().getType(),
this.isSolidBlock(actual.getBlock().getType()));
return false;
}
if (isBlockAboveAir(actual)) {
MultiverseCore.staticLog(Level.FINER, "Is block above air [" + isBlockAboveAir(actual) + "]");
MultiverseCore.staticLog(Level.FINER, "Has 2 blocks of water below [" + this.hasTwoBlocksofWaterBelow(actual) + "]");
Logging.finest("Is block above air [%s]", isBlockAboveAir(actual));
Logging.finest("Has 2 blocks of water below [%s]", this.hasTwoBlocksofWaterBelow(actual));
return this.hasTwoBlocksofWaterBelow(actual);
}
return true;
@@ -24,7 +24,9 @@ import java.util.logging.Logger;
/**
* The Multiverse debug-logger.
* @deprecated Deprecated in favor of new Logging lib. See {@link com.dumptruckman.minecraft.util.Logging}.
*/
@Deprecated
public class DebugLog extends Logger {
private FileHandler fh;
private Logger standardLog = null;
@@ -79,11 +81,11 @@ public class DebugLog extends Logger {
* @param msg the message.
*/
@Override
public void log(Level level, String msg) {
public void log(final Level level, final String msg) {
if (MultiverseCoreConfiguration.isSet() && MultiverseCoreConfiguration.getInstance().getGlobalDebug() > 0) {
// only redirect to standardLog if it's lower than INFO so we don't log that twice!
if ((level.intValue() < Level.INFO.intValue()) && (standardLog != null)) {
standardLog.log(level, prefix + msg);
standardLog.log(Level.INFO, prefix + msg);
}
super.log(level, prefix + msg);
@@ -7,7 +7,11 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
/**
* File-utilities.
@@ -24,16 +28,47 @@ public class FileUtils {
* @return true if the folder was successfully deleted.
*/
public static boolean deleteFolder(File file) {
if (file.exists()) {
boolean ret = true;
// If the file exists, and it has more than one file in it.
if (file.isDirectory()) {
for (File f : file.listFiles()) {
ret = ret && deleteFolder(f);
}
}
return ret && file.delete();
} else {
try {
org.apache.commons.io.FileUtils.deleteDirectory(file);
return true;
} catch (IOException e) {
Logging.warning(e.getMessage());
return false;
}
}
/**
* Used to delete the contents of a folder, without deleting the folder itself.
*
* @param file The folder whose contents to delete.
* @return true if the contents were successfully deleted
*/
public static boolean deleteFolderContents(File file) {
try {
org.apache.commons.io.FileUtils.cleanDirectory(file);
return true;
} catch (IOException e) {
Logging.warning(e.getMessage());
return false;
}
}
private static final int COPY_BLOCK_SIZE = 1024;
/**
* Helper method to copy the world-folder.
* @param source Source-File
* @param target Target-File
* @param log A logger that logs the operation
*
* @return if it had success
*/
public static boolean copyFolder(File source, File target, Logger log) {
try {
org.apache.commons.io.FileUtils.copyDirectory(source, target);
return true;
} catch (IOException e) {
log.warning(e.getMessage());
return false;
}
}
@@ -11,6 +11,7 @@ import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVDestination;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.permissions.Permissions;
import com.pneumaticraft.commandhandler.PermissionsInterface;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@@ -76,6 +77,10 @@ public class MVPermissions implements PermissionsInterface {
* @return Whether the {@link CommandSender} can travel to the specified {@link Location}.
*/
public boolean canTravelFromLocation(CommandSender sender, Location location) {
// Now The Bed destination can return null now.
if (location == null) {
return false;
}
if (!(sender instanceof Player)) {
return true;
}
@@ -99,18 +104,15 @@ public class MVPermissions implements PermissionsInterface {
this.plugin.log(Level.FINEST, "EnforceAccess is OFF. Player was allowed in " + w.getAlias());
return true;
}
return this.hasPermission(p, "multiverse.access." + w.getName(), false);
return Permissions.ACCESS.has(p, w.getName());
}
private boolean canEnterLocation(Player p, Location l) {
if (l == null) {
if (l == null)
return false;
}
String worldName = l.getWorld().getName();
if (!this.plugin.getMVWorldManager().isMVWorld(worldName)) {
return false;
}
return this.hasPermission(p, "multiverse.access." + worldName, false);
return this.plugin.getMVWorldManager().isMVWorld(worldName) && Permissions.ACCESS.has(p, worldName);
}
/**
@@ -7,7 +7,7 @@
package com.onarandombox.MultiverseCore.utils;
import com.fernferret.allpay.GenericBank;
import com.fernferret.allpay.commons.GenericBank;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import org.bukkit.command.CommandSender;
@@ -143,17 +143,40 @@ public class PermissionTools {
if (this.plugin.getMVPerms().hasPermission(teleporter, toWorld.getExemptPermission().getName(), true)) {
return true;
}
GenericBank bank = plugin.getBank();
String errString = "You need " + bank.getFormattedAmount(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency())
+ " to send " + teleportee + " to " + toWorld.getColoredWorldString();
if (teleportee.equals(teleporter)) {
errString = "You need " + bank.getFormattedAmount(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency())
+ " to enter " + toWorld.getColoredWorldString();
final boolean usingVault;
final String formattedAmount;
if (toWorld.getCurrency() <= 0 && plugin.getVaultHandler().getEconomy() != null) {
usingVault = true;
formattedAmount = plugin.getVaultHandler().getEconomy().format(toWorld.getPrice());
} else {
usingVault = false;
formattedAmount = this.plugin.getBank().getFormattedAmount(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency());
}
if (!bank.hasEnough(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency(), errString)) {
return false;
} else if (pay) {
bank.give(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency());
String errString = "You need " + formattedAmount + " to send " + teleportee + " to " + toWorld.getColoredWorldString();
if (teleportee.equals(teleporter)) {
errString = "You need " + formattedAmount + " to enter " + toWorld.getColoredWorldString();
}
if (usingVault) {
if (!plugin.getVaultHandler().getEconomy().has(teleporterPlayer.getName(), toWorld.getPrice())) {
return false;
} else if (pay) {
if (toWorld.getPrice() < 0D) {
plugin.getVaultHandler().getEconomy().depositPlayer(teleporterPlayer.getName(), toWorld.getPrice() * -1D);
} else {
plugin.getVaultHandler().getEconomy().withdrawPlayer(teleporterPlayer.getName(), toWorld.getPrice());
}
}
} else {
GenericBank bank = plugin.getBank();
if (!bank.hasEnough(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency(), errString)) {
return false;
} else if (pay) {
if (toWorld.getPrice() < 0D) {
bank.give(teleporterPlayer, toWorld.getPrice() * -1D, toWorld.getCurrency());
} else {
bank.take(teleporterPlayer, toWorld.getPrice(), toWorld.getCurrency());
}
}
}
}
return true;
@@ -235,6 +258,32 @@ public class PermissionTools {
return true;
}
/**
* Checks to see if a player can bypass the player limit.
*
* @param toWorld The world travelling to.
* @param teleporter The player that initiated the teleport.
* @param teleportee The player travelling.
* @return True if they can bypass the player limit.
*/
public boolean playerCanBypassPlayerLimit(MultiverseWorld toWorld, CommandSender teleporter, Player teleportee) {
if (teleporter == null) {
teleporter = teleportee;
}
if (!(teleporter instanceof Player)) {
return true;
}
MVPermissions perms = plugin.getMVPerms();
if (perms.hasPermission(teleportee, "mv.bypass.playerlimit." + toWorld.getName(), false)) {
return true;
} else {
teleporter.sendMessage("The world " + toWorld.getColoredWorldString() + " is full");
return false;
}
}
/**
* Checks to see if a player should bypass game mode restrictions.
*
@@ -7,23 +7,38 @@
package com.onarandombox.MultiverseCore.utils;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.BlockSafety;
import com.onarandombox.MultiverseCore.api.Core;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Vehicle;
import org.bukkit.material.Bed;
import java.util.logging.Level;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
/**
* The default-implementation of {@link BlockSafety}.
*/
public class SimpleBlockSafety implements BlockSafety {
private final Core plugin;
private static final Set<BlockFace> AROUND_BLOCK = EnumSet.noneOf(BlockFace.class);
static {
AROUND_BLOCK.add(BlockFace.NORTH);
AROUND_BLOCK.add(BlockFace.NORTH_EAST);
AROUND_BLOCK.add(BlockFace.EAST);
AROUND_BLOCK.add(BlockFace.SOUTH_EAST);
AROUND_BLOCK.add(BlockFace.SOUTH);
AROUND_BLOCK.add(BlockFace.SOUTH_WEST);
AROUND_BLOCK.add(BlockFace.WEST);
AROUND_BLOCK.add(BlockFace.NORTH_WEST);
}
public SimpleBlockSafety(Core plugin) {
this.plugin = plugin;
@@ -67,33 +82,88 @@ public class SimpleBlockSafety implements BlockSafety {
if (isSolidBlock(world.getBlockAt(actual).getType())
|| isSolidBlock(upOne.getBlock().getType())) {
MultiverseCore.staticLog(Level.FINER, "Error Here (Actual)? ("
+ actual.getBlock().getType() + ")[" + isSolidBlock(actual.getBlock().getType()) + "]");
MultiverseCore.staticLog(Level.FINER, "Error Here (upOne)? ("
+ upOne.getBlock().getType() + ")[" + isSolidBlock(upOne.getBlock().getType()) + "]");
Logging.finer("Error Here (Actual)? (%s)[%s]", actual.getBlock().getType(),
isSolidBlock(actual.getBlock().getType()));
Logging.finer("Error Here (upOne)? (%s)[%s]", upOne.getBlock().getType(),
isSolidBlock(upOne.getBlock().getType()));
return false;
}
if (downOne.getBlock().getType() == Material.LAVA || downOne.getBlock().getType() == Material.STATIONARY_LAVA) {
MultiverseCore.staticLog(Level.FINER, "Error Here (downOne)? ("
+ downOne.getBlock().getType() + ")[" + isSolidBlock(downOne.getBlock().getType()) + "]");
Logging.finer("Error Here (downOne)? (%s)[%s]", downOne.getBlock().getType(), isSolidBlock(downOne.getBlock().getType()));
return false;
}
if (downOne.getBlock().getType() == Material.FIRE) {
MultiverseCore.staticLog(Level.FINER, "There's fire below! ("
+ actual.getBlock().getType() + ")[" + isSolidBlock(actual.getBlock().getType()) + "]");
Logging.finer("There's fire below! (%s)[%s]", actual.getBlock().getType(), isSolidBlock(actual.getBlock().getType()));
return false;
}
if (isBlockAboveAir(actual)) {
MultiverseCore.staticLog(Level.FINER, "Is block above air [" + isBlockAboveAir(actual) + "]");
MultiverseCore.staticLog(Level.FINER, "Has 2 blocks of water below [" + this.hasTwoBlocksofWaterBelow(actual) + "]");
Logging.finer("Is block above air [%s]", isBlockAboveAir(actual));
Logging.finer("Has 2 blocks of water below [%s]", this.hasTwoBlocksofWaterBelow(actual));
return this.hasTwoBlocksofWaterBelow(actual);
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public Location getSafeBedSpawn(Location l) {
// The passed location, may be null (if the bed is invalid)
if (l == null) {
return null;
}
final Location trySpawn = this.getSafeSpawnAroundABlock(l);
if (trySpawn != null) {
return trySpawn;
}
Location otherBlock = this.findOtherBedPiece(l);
if (otherBlock == null) {
return null;
}
// Now we have 2 locations, check around each, if the type is bed, skip it.
return this.getSafeSpawnAroundABlock(otherBlock);
}
/**
* Find a safe spawn around a location. (N,S,E,W,NE,NW,SE,SW)
* @param l Location to check around
* @return A safe location, or none if it wasn't found.
*/
private Location getSafeSpawnAroundABlock(Location l) {
Iterator<BlockFace> checkblock = AROUND_BLOCK.iterator();
while (checkblock.hasNext()) {
final BlockFace face = checkblock.next();
if (this.playerCanSpawnHereSafely(l.getBlock().getRelative(face).getLocation())) {
// Don't forget to center the player.
return l.getBlock().getRelative(face).getLocation().add(.5, 0, .5);
}
}
return null;
}
/**
* Find the other bed block.
* @param checkLoc The location to check for the other piece at
* @return The location of the other bed piece, or null if it was a jacked up bed.
*/
private Location findOtherBedPiece(Location checkLoc) {
if (checkLoc.getBlock().getType() != Material.BED_BLOCK) {
return null;
}
// Construct a bed object at this location
final Bed b = new Bed(Material.BED_BLOCK, checkLoc.getBlock().getData());
if (b.isHeadOfBed()) {
return checkLoc.getBlock().getRelative(b.getFacing().getOppositeFace()).getLocation();
}
// We shouldn't ever be looking at the foot, but here's the code for it.
return checkLoc.getBlock().getRelative(b.getFacing()).getLocation();
}
/**
* {@inheritDoc}
*/
@@ -7,23 +7,26 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Ghast;
import org.bukkit.entity.Golem;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Squid;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
/**
* Utility class that removes animals from worlds that don't belong there.
@@ -32,8 +35,16 @@ public class SimpleWorldPurger implements WorldPurger {
private MultiverseCore plugin;
private Class<Entity> ambientClass = null;
public SimpleWorldPurger(MultiverseCore plugin) {
this.plugin = plugin;
try {
Class entityClass = Class.forName("org.bukkit.entity.Ambient");
if (Entity.class.isAssignableFrom(entityClass)) {
ambientClass = entityClass;
}
} catch (ClassNotFoundException ignore) { }
}
/**
@@ -62,6 +73,16 @@ public class SimpleWorldPurger implements WorldPurger {
purgeWorld(world, allMobs, !world.canAnimalsSpawn(), !world.canMonstersSpawn());
}
/**
* {@inheritDoc}
*/
@Override
public boolean shouldWeKillThisCreature(MultiverseWorld world, Entity e) {
ArrayList<String> allMobs = new ArrayList<String>(world.getAnimalList());
allMobs.addAll(world.getMonsterList());
return this.shouldWeKillThisCreature(e, allMobs, !world.canAnimalsSpawn(), !world.canMonstersSpawn());
}
/**
* {@inheritDoc}
*/
@@ -75,61 +96,98 @@ public class SimpleWorldPurger implements WorldPurger {
if (world == null) {
return;
}
int projectilesKilled = 0;
int entitiesKilled = 0;
boolean specifiedAll = thingsToKill.contains("ALL");
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
for (Entity e : world.getEntities()) {
boolean negate = false;
boolean specified = false;
if (e instanceof Squid || e instanceof Animals) {
// it's an animal
if (specifiedAnimals && !negateAnimals) {
this.plugin.log(Level.FINEST, "Removing an entity because I was told to remove all animals: " + e);
e.remove();
entitiesKilled++;
continue;
List<Entity> worldEntities = world.getEntities();
List<LivingEntity> livingEntities = new ArrayList<LivingEntity>(worldEntities.size());
List<Projectile> projectiles = new ArrayList<Projectile>(worldEntities.size());
for (final Entity e : worldEntities) {
if (e instanceof Projectile) {
final Projectile p = (Projectile) e;
if (p.getShooter() != null) {
projectiles.add((Projectile) e);
}
if (specifiedAnimals)
specified = true;
negate = negateAnimals;
} else if (e instanceof Monster || e instanceof Ghast || e instanceof Slime) {
// it's a monster
if (specifiedMonsters && !negateMonsters) {
this.plugin.log(Level.FINEST, "Removing an entity because I was told to remove all monsters: " + e);
e.remove();
entitiesKilled++;
continue;
}
if (specifiedMonsters)
specified = true;
negate = negateMonsters;
} else if (e instanceof LivingEntity) {
livingEntities.add((LivingEntity) e);
}
for (String s : thingsToKill) {
EntityType type = EntityType.fromName(s);
if (type != null && type.equals(e.getType())) {
specified = true;
if (!negate) {
this.plugin.log(Level.FINEST, "Removing an entity because it WAS specified and we are NOT negating: " + e);
e.remove();
entitiesKilled++;
continue;
}
for (final LivingEntity e : livingEntities) {
if (killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters)) {
final Iterator<Projectile> it = projectiles.iterator();
while (it.hasNext()) {
final Projectile p = it.next();
if (p.getShooter().equals(e)) {
p.remove();
it.remove();
projectilesKilled++;
}
break;
}
}
if (!specified && negate) {
this.plugin.log(Level.FINEST, "Removing an entity because it was NOT specified and we ARE negating: " + e);
e.remove();
entitiesKilled++;
continue;
}
}
if (sender != null) {
sender.sendMessage(entitiesKilled + " entities purged from the world '" + world.getName() + "'");
sender.sendMessage(entitiesKilled + " entities purged from the world '" + world.getName() + "' along with " + projectilesKilled + " projectiles that belonged to them.");
}
}
private boolean killDecision(Entity e, List<String> thingsToKill, boolean negateAnimals,
boolean negateMonsters, boolean specifiedAnimals, boolean specifiedMonsters) {
boolean negate = false;
boolean specified = false;
if (e instanceof Golem || e instanceof Squid || e instanceof Animals
|| (ambientClass != null && ambientClass.isInstance(e))) {
// it's an animal
if (specifiedAnimals && !negateAnimals) {
Logging.finest("Removing an entity because I was told to remove all animals in world %s: %s", e.getWorld().getName(), e);
return true;
}
if (specifiedAnimals)
specified = true;
negate = negateAnimals;
} else if (e instanceof Monster || e instanceof Ghast || e instanceof Slime) {
// it's a monster
if (specifiedMonsters && !negateMonsters) {
Logging.finest("Removing an entity because I was told to remove all monsters in world %s: %s", e.getWorld().getName(), e);
return true;
}
if (specifiedMonsters)
specified = true;
negate = negateMonsters;
}
for (String s : thingsToKill) {
EntityType type = EntityType.fromName(s);
if (type != null && type.equals(e.getType())) {
specified = true;
if (!negate) {
Logging.finest("Removing an entity because it WAS specified and we are NOT negating in world %s: %s", e.getWorld().getName(), e);
return true;
}
break;
}
}
if (!specified && negate) {
Logging.finest("Removing an entity because it was NOT specified and we ARE negating in world %s: %s", e.getWorld().getName(), e);
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean shouldWeKillThisCreature(Entity e, List<String> thingsToKill, boolean negateAnimals, boolean negateMonsters) {
boolean specifiedAll = thingsToKill.contains("ALL");
boolean specifiedAnimals = thingsToKill.contains("ANIMALS") || specifiedAll;
boolean specifiedMonsters = thingsToKill.contains("MONSTERS") || specifiedAll;
return this.killDecision(e, thingsToKill, negateAnimals, negateMonsters, specifiedAnimals, specifiedMonsters);
}
/**
* {@inheritDoc}
*/
@@ -0,0 +1,44 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.Core;
import java.util.concurrent.Callable;
/**
* Wraps calls that could result in exceptions that are not Multiverse's fault.
*/
public class UnsafeCallWrapper {
private final Core core;
public UnsafeCallWrapper(Core core) {
this.core = core;
}
/**
* Wraps calls that could result in exceptions that are not Multiverse's fault.
*
* @param callable The potentially unsafe call.
* @param plugin The plugin that's probably the culprit.
* @param action What MV was attempting to do (error message, format string).
* @param formatArgs The formatting arguments for the error message.
* The exception that was thrown will be appended to these objects.
* @param <T> The type of the return value.
* @return The return value or null if the call failed.
*/
public <T> T wrap(Callable<T> callable, String plugin, String action, Object... formatArgs) {
try {
// We're ready to catch you! JUMP!
return callable.call();
} catch (Throwable t) {
Object[] actualFormatArgs = new Object[formatArgs.length + 1];
System.arraycopy(formatArgs, 0, actualFormatArgs, 0, formatArgs.length);
actualFormatArgs[formatArgs.length] = t;
Logging.warning(action, actualFormatArgs);
Logging.warning("This is a bug in %s, NOT a bug in Multiverse!", plugin);
if (core.getMVConfig().getGlobalDebug() >= 1)
t.printStackTrace();
return null;
}
}
}
@@ -7,6 +7,8 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -87,7 +89,7 @@ public class UpdateChecker {
int compare = v1.compareTo(v2);
if (compare > 0) {
log.info("[" + this.name + "]" + " - Update Available (" + version + ")");
Logging.info("[%s] - Update Available (%s)", this.name, version);
}
rd.close();
@@ -0,0 +1,72 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
/**
* A class we use to interface with Vault when it is present.
*/
public class VaultHandler implements Listener {
private Economy economy;
public VaultHandler(final Plugin plugin) {
Bukkit.getPluginManager().registerEvents(new VaultListener(), plugin);
setupVaultEconomy();
}
private boolean setupVaultEconomy() {
if (Bukkit.getPluginManager().getPlugin("Vault") != null) {
final RegisteredServiceProvider<Economy> economyProvider =
Bukkit.getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if (economyProvider != null) {
Logging.fine("Vault economy enabled.");
economy = economyProvider.getProvider();
} else {
Logging.finer("Vault economy not detected.");
economy = null;
}
} else {
Logging.finer("Vault was not found.");
economy = null;
}
return (economy != null);
}
/**
* Listens for Vault plugin events.
*/
private class VaultListener implements Listener {
@EventHandler
private void vaultEnabled(PluginEnableEvent event) {
if (event.getPlugin() != null && event.getPlugin().getName().equals("Vault")) {
setupVaultEconomy();
}
}
@EventHandler
private void vaultDisabled(PluginDisableEvent event) {
if (event.getPlugin() != null && event.getPlugin().getName().equals("Vault")) {
Logging.fine("Vault economy disabled");
setupVaultEconomy();
}
}
}
/**
* Returns the Vault economy system if Vault is present and has an economy system enabled.
*
* @return The vault economy system or null if not configured.
*/
public Economy getEconomy() {
return economy;
}
}
@@ -7,13 +7,17 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MVWorld;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.WorldProperties;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
@@ -35,26 +39,30 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Public facing API to add/remove Multiverse worlds.
*/
public class WorldManager implements MVWorldManager {
private MultiverseCore plugin;
private WorldPurger worldPurger;
private Map<String, MVWorld> worldsFromTheConfig;
private Map<String, MultiverseWorld> worlds;
private final MultiverseCore plugin;
private final WorldPurger worldPurger;
private final Map<String, MultiverseWorld> worlds;
private Map<String, WorldProperties> worldsFromTheConfig;
private FileConfiguration configWorlds = null;
private Map<String, String> defaultGens;
private String firstSpawn;
public WorldManager(MultiverseCore core) {
this.plugin = core;
this.worldsFromTheConfig = new HashMap<String, MVWorld>();
this.worlds = new HashMap<String, MultiverseWorld>();
this.worldsFromTheConfig = new HashMap<String, WorldProperties>();
this.worlds = new ConcurrentHashMap<String, MultiverseWorld>();
this.worldPurger = new SimpleWorldPurger(plugin);
}
@@ -83,6 +91,85 @@ public class WorldManager implements MVWorldManager {
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean cloneWorld(String oldName, String newName, String generator) {
// Make sure we don't already know about the new world.
if (this.isMVWorld(newName)) {
return false;
}
// Make sure the old world is actually a world!
if (this.getUnloadedWorlds().contains(oldName) || !this.isMVWorld(oldName)) {
return false;
}
final File oldWorldFile = new File(this.plugin.getServer().getWorldContainer(), oldName);
final File newWorldFile = new File(this.plugin.getServer().getWorldContainer(), newName);
// Make sure the new world doesn't exist outside of multiverse.
if (newWorldFile.exists()) {
return false;
}
unloadWorld(oldName);
removePlayersFromWorld(oldName);
Logging.config("Copying data for world '%s'", oldName);
try {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
FileUtils.copyFolder(oldWorldFile, newWorldFile, Logger.getLogger("Minecraft"));
}
});
t.start();
try {
t.join();
} catch (InterruptedException e) {
// do nothing
}
File uidFile = new File(newWorldFile, "uid.dat");
uidFile.delete();
} catch (NullPointerException e) {
e.printStackTrace();
return false;
}
Logging.fine("Kind of copied stuff");
WorldCreator worldCreator = new WorldCreator(newName);
Logging.fine("Started to copy settings");
worldCreator.copy(this.getMVWorld(oldName).getCBWorld());
Logging.fine("Copied lots of settings");
boolean useSpawnAdjust = this.getMVWorld(oldName).getAdjustSpawn();
Logging.fine("Copied more settings");
Environment environment = worldCreator.environment();
Logging.fine("Copied most settings");
if (newWorldFile.exists()) {
Logging.fine("Succeeded at copying stuff");
if (this.addWorld(newName, environment, null, null, null, generator, useSpawnAdjust)) {
// getMVWorld() doesn't actually return an MVWorld
Logging.fine("Succeeded at importing stuff");
MVWorld newWorld = (MVWorld) this.getMVWorld(newName);
MVWorld oldWorld = (MVWorld) this.getMVWorld(oldName);
newWorld.copyValues(oldWorld);
try {
// don't keep the alias the same -- that would be useless
newWorld.setPropertyValue("alias", newName);
} catch (PropertyDoesNotExistException e) {
// this should never happen
throw new RuntimeException(e);
}
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
@@ -122,8 +209,10 @@ public class WorldManager implements MVWorldManager {
}
// Important: doLoad() needs the MVWorld-object in worldsFromTheConfig
if (!worldsFromTheConfig.containsKey(name))
worldsFromTheConfig.put(name, new MVWorld(useSpawnAdjust));
if (!worldsFromTheConfig.containsKey(name)) {
WorldProperties props = new WorldProperties(useSpawnAdjust, env);
worldsFromTheConfig.put(name, props);
}
StringBuilder builder = new StringBuilder();
builder.append("Loading World & Settings - '").append(name).append("'");
@@ -135,9 +224,9 @@ public class WorldManager implements MVWorldManager {
if (generator != null) {
builder.append(" & generator: ").append(generator);
}
this.plugin.log(Level.INFO, builder.toString());
Logging.info(builder.toString());
if (!doLoad(c)) {
if (!doLoad(c, true)) {
this.plugin.log(Level.SEVERE, "Failed to Create/Load the world '" + name + "'");
return false;
}
@@ -153,16 +242,21 @@ public class WorldManager implements MVWorldManager {
* {@inheritDoc}
*/
@Override
public ChunkGenerator getChunkGenerator(String generator, String generatorID, String worldName) {
public ChunkGenerator getChunkGenerator(String generator, final String generatorID, final String worldName) {
if (generator == null) {
return null;
}
Plugin myPlugin = this.plugin.getServer().getPluginManager().getPlugin(generator);
final Plugin myPlugin = this.plugin.getServer().getPluginManager().getPlugin(generator);
if (myPlugin == null) {
return null;
} else {
return myPlugin.getDefaultWorldGenerator(worldName, generatorID);
return plugin.getUnsafeCallWrapper().wrap(new Callable<ChunkGenerator>() {
@Override
public ChunkGenerator call() throws Exception {
return myPlugin.getDefaultWorldGenerator(worldName, generatorID);
}
}, myPlugin.getName(), "Failed to get the default chunk generator: %s");
}
}
@@ -176,12 +270,12 @@ public class WorldManager implements MVWorldManager {
}
if (this.worldsFromTheConfig.containsKey(name)) {
this.worldsFromTheConfig.remove(name);
this.plugin.log(Level.INFO, "World '" + name + "' was removed from config.yml");
Logging.info("World '%s' was removed from config.yml", name);
this.saveWorldsConfig();
return true;
} else {
this.plugin.log(Level.INFO, "World '" + name + "' was already removed from config.yml");
Logging.info("World '%s' was already removed from config.yml", name);
}
return false;
}
@@ -223,22 +317,22 @@ public class WorldManager implements MVWorldManager {
@Override
public boolean unloadWorld(String name) {
if (this.worlds.containsKey(name)) {
this.worldsFromTheConfig.get(name).cacheVirtualProperties();
if (this.unloadWorldFromBukkit(name, true)) {
this.worlds.remove(name);
this.plugin.log(Level.INFO, "World '" + name + "' was unloaded from memory.");
this.worldsFromTheConfig.get(name).tearDown();
Logging.info("World '%s' was unloaded from memory.", name);
return true;
} else {
this.plugin.log(Level.WARNING, "World '" + name + "' could not be unloaded. Is it a default world?");
Logging.warning("World '%s' could not be unloaded. Is it a default world?", name);
}
} else if (this.plugin.getServer().getWorld(name) != null) {
this.plugin.log(Level.WARNING, "Hmm Multiverse does not know about this world but it's loaded in memory.");
this.plugin.log(Level.WARNING, "To let Multiverse know about it, use:");
this.plugin.log(Level.WARNING, String.format("/mv import %s %s", name, this.plugin.getServer().getWorld(name).getEnvironment().toString()));
Logging.warning("Hmm Multiverse does not know about this world but it's loaded in memory.");
Logging.warning("To let Multiverse know about it, use:");
Logging.warning("/mv import %s %s", name, this.plugin.getServer().getWorld(name).getEnvironment().toString());
} else if (this.worldsFromTheConfig.containsKey(name)) {
return true; // it's already unloaded
} else {
this.plugin.log(Level.INFO, "Multiverse does not know about " + name + " and it's not loaded by Bukkit.");
Logging.info("Multiverse does not know about '%s' and it's not loaded by Bukkit.", name);
}
return false;
}
@@ -268,26 +362,48 @@ public class WorldManager implements MVWorldManager {
}
private boolean doLoad(String name) {
return doLoad(name, false, null);
}
private boolean doLoad(String name, boolean ignoreExists, WorldType type) {
if (!worldsFromTheConfig.containsKey(name))
throw new IllegalArgumentException("That world doesn't exist!");
MVWorld world = worldsFromTheConfig.get(name);
WorldCreator creator = WorldCreator.name(name);
final WorldProperties world = worldsFromTheConfig.get(name);
final WorldCreator creator = WorldCreator.name(name);
creator.environment(world.getEnvironment()).seed(world.getSeed());
if ((world.getGenerator() != null) && (!world.getGenerator().equals("null")))
creator.generator(world.getGenerator());
if (type != null) {
creator.type(type);
}
return doLoad(creator);
boolean generatorSuccess = true;
if ((world.getGenerator() != null) && (!world.getGenerator().equals("null")))
generatorSuccess = null != plugin.getUnsafeCallWrapper().wrap(new Callable<Object>() {
@Override
public Object call() throws Exception {
creator.generator(world.getGenerator());
return new Object();
}
}, "the generator plugin", "Failed to set the generator for world '%s' to '%s': %s", name, world.getGenerator());
return generatorSuccess && doLoad(creator, ignoreExists);
}
private boolean doLoad(WorldCreator creator) {
private boolean doLoad(WorldCreator creator, boolean ignoreExists) {
String worldName = creator.name();
if (!worldsFromTheConfig.containsKey(worldName))
throw new IllegalArgumentException("That world doesn't exist!");
if (worlds.containsKey(worldName))
throw new IllegalArgumentException("That world is already loaded!");
MVWorld mvworld = worldsFromTheConfig.get(worldName);
if (!ignoreExists && !new File(this.plugin.getServer().getWorldContainer(), worldName).exists()) {
this.plugin.log(Level.WARNING, "WorldManager: Can't load this world because the folder was deleted/moved: " + worldName);
this.plugin.log(Level.WARNING, "Use '/mv remove' to remove it from the config!");
return false;
}
WorldProperties mvworld = worldsFromTheConfig.get(worldName);
World cbworld;
try {
cbworld = creator.createWorld();
@@ -296,9 +412,9 @@ public class WorldManager implements MVWorldManager {
brokenWorld(worldName);
return false;
}
mvworld.init(cbworld, plugin);
this.worldPurger.purgeWorld(mvworld);
this.worlds.put(worldName, mvworld);
MVWorld world = new MVWorld(plugin, cbworld, mvworld);
this.worldPurger.purgeWorld(world);
this.worlds.put(worldName, world);
return true;
}
@@ -306,7 +422,7 @@ public class WorldManager implements MVWorldManager {
* {@inheritDoc}
*/
@Override
public boolean deleteWorld(String name, boolean removeFromConfig) {
public boolean deleteWorld(String name, boolean removeFromConfig, boolean deleteWorldFolder) {
World world = this.plugin.getServer().getWorld(name);
if (world == null) {
// We can only delete loaded worlds
@@ -334,25 +450,33 @@ public class WorldManager implements MVWorldManager {
try {
File worldFile = world.getWorldFolder();
plugin.log(Level.FINER, "deleteWorld(): worldFile: " + worldFile.getAbsolutePath());
boolean deletedWorld = FileUtils.deleteFolder(worldFile);
if (deletedWorld) {
this.plugin.log(Level.INFO, "World " + name + " was DELETED.");
if (deleteWorldFolder ? FileUtils.deleteFolder(worldFile) : FileUtils.deleteFolderContents(worldFile)) {
Logging.info("World '%s' was DELETED.", name);
return true;
} else {
this.plugin.log(Level.SEVERE, "World " + name + " was NOT deleted.");
this.plugin.log(Level.SEVERE, "Are you sure the folder " + name + " exists?");
this.plugin.log(Level.SEVERE, "Please check your file permissions on " + name);
Logging.severe("World '%s' was NOT deleted.", name);
Logging.severe("Are you sure the folder %s exists?", name);
Logging.severe("Please check your file permissions on '%s'", name);
return false;
}
return deletedWorld;
} catch (Throwable e) {
this.plugin.log(Level.SEVERE, "Hrm, something didn't go as planned. Here's an exception for ya.");
this.plugin.log(Level.SEVERE, "You can go politely explain your situation in #multiverse on esper.net");
this.plugin.log(Level.SEVERE, "But from here, it looks like your folder is oddly named.");
this.plugin.log(Level.SEVERE, "This world has been removed from Multiverse-Core so your best bet is to go delete the folder by hand. Sorry.");
this.plugin.log(Level.SEVERE, e.getMessage());
Logging.severe("Hrm, something didn't go as planned. Here's an exception for ya.");
Logging.severe("You can go politely explain your situation in #multiverse on esper.net");
Logging.severe("But from here, it looks like your folder is oddly named.");
Logging.severe("This world has been removed from Multiverse-Core so your best bet is to go delete the folder by hand. Sorry.");
Logging.severe(e.getMessage());
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean deleteWorld(String name, boolean removeFromConfig) {
return this.deleteWorld(name, removeFromConfig, true);
}
/**
* {@inheritDoc}
*/
@@ -403,8 +527,12 @@ public class WorldManager implements MVWorldManager {
*/
@Override
public MultiverseWorld getMVWorld(String name) {
if (this.worlds.containsKey(name)) {
return this.worlds.get(name);
if (name == null) {
return null;
}
MultiverseWorld world = this.worlds.get(name);
if (world != null) {
return world;
}
return this.getMVWorldByAlias(name);
}
@@ -439,7 +567,7 @@ public class WorldManager implements MVWorldManager {
* {@inheritDoc}
*/
@Override
public boolean isMVWorld(String name) {
public boolean isMVWorld(final String name) {
return (this.worlds.containsKey(name) || isMVWorldAlias(name));
}
@@ -457,7 +585,7 @@ public class WorldManager implements MVWorldManager {
* @param alias The alias of the world to check.
* @return True if the world exists, false if not.
*/
private boolean isMVWorldAlias(String alias) {
private boolean isMVWorldAlias(final String alias) {
for (MultiverseWorld w : this.worlds.values()) {
if (w.getAlias().equalsIgnoreCase(alias)) {
return true;
@@ -526,9 +654,10 @@ public class WorldManager implements MVWorldManager {
this.worlds.clear();
}
for (Map.Entry<String, MVWorld> entry : worldsFromTheConfig.entrySet()) {
if (worlds.containsKey(entry.getKey()))
for (Map.Entry<String, WorldProperties> entry : worldsFromTheConfig.entrySet()) {
if (worlds.containsKey(entry.getKey())) {
continue;
}
if (!entry.getValue().getAutoLoad())
continue;
@@ -537,7 +666,7 @@ public class WorldManager implements MVWorldManager {
}
// Simple Output to the Console to show how many Worlds were loaded.
this.plugin.log(Level.INFO, count + " - World(s) loaded.");
Logging.config("%s - World(s) loaded.", count);
this.saveWorldsConfig();
}
@@ -585,26 +714,23 @@ public class WorldManager implements MVWorldManager {
// load world-objects
Stack<String> worldKeys = new Stack<String>();
worldKeys.addAll(this.configWorlds.getConfigurationSection("worlds").getKeys(false));
Map<String, MVWorld> newWorldsFromTheConfig = new HashMap<String, MVWorld>();
Map<String, WorldProperties> newWorldsFromTheConfig = new HashMap<String, WorldProperties>();
while (!worldKeys.isEmpty()) {
String key = worldKeys.pop();
String path = "worlds" + SEPARATOR + key;
Object obj = this.configWorlds.get(path);
if ((obj != null) && (obj instanceof MVWorld)) {
if ((obj != null) && (obj instanceof WorldProperties)) {
String worldName = key.replaceAll(String.valueOf(SEPARATOR), ".");
WorldProperties props = (WorldProperties) obj;
if (this.worldsFromTheConfig.containsKey(worldName)) {
// Object-Recycling :D
MVWorld oldMVWorld = (MVWorld) this.worlds.get(worldName);
oldMVWorld.copyValues((MVWorld) obj);
newWorldsFromTheConfig.put(worldName, oldMVWorld);
} else {
// we have to use a new one
World cbworld = this.plugin.getServer().getWorld(worldName);
MVWorld mvworld = (MVWorld) obj;
if (cbworld != null)
mvworld.init(cbworld, this.plugin);
newWorldsFromTheConfig.put(worldName, mvworld);
// TODO Why is is checking worldsFromTheConfig and then getting from worlds? So confused... (DTM)
MVWorld mvWorld = (MVWorld) this.worlds.get(worldName);
if (mvWorld != null) {
mvWorld.copyValues((WorldProperties) obj);
}
}
newWorldsFromTheConfig.put(worldName, props);
} else if (this.configWorlds.isConfigurationSection(path)) {
ConfigurationSection section = this.configWorlds.getConfigurationSection(path);
Set<String> subkeys = section.getKeys(false);
@@ -626,7 +752,7 @@ public class WorldManager implements MVWorldManager {
try {
this.configWorlds.options().pathSeparator(SEPARATOR);
this.configWorlds.set("worlds", null);
for (Map.Entry<String, ? extends MultiverseWorld> entry : worldsFromTheConfig.entrySet()) {
for (Map.Entry<String, WorldProperties> entry : worldsFromTheConfig.entrySet()) {
this.configWorlds.set("worlds" + SEPARATOR + entry.getKey(), entry.getValue());
}
this.configWorlds.save(new File(this.plugin.getDataFolder(), "worlds.yml"));
@@ -655,6 +781,47 @@ public class WorldManager implements MVWorldManager {
return allNames;
}
/**
* {@inheritDoc}
*/
@Override
public boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed) {
MultiverseWorld world = this.getMVWorld(name);
if (world == null)
return false;
List<Player> ps = world.getCBWorld().getPlayers();
if (useNewSeed) {
long theSeed;
if (randomSeed) {
theSeed = new Random().nextLong();
} else {
try {
theSeed = Long.parseLong(seed);
} catch (NumberFormatException e) {
theSeed = seed.hashCode();
}
}
world.setSeed(theSeed);
}
WorldType type = world.getWorldType();
if (this.deleteWorld(name, false, false)) {
this.doLoad(name, true, type);
SafeTTeleporter teleporter = this.plugin.getSafeTTeleporter();
Location newSpawn = world.getSpawnLocation();
// Send all players that were in the old world, BACK to it!
for (Player p : ps) {
teleporter.safelyTeleport(null, p, newSpawn, true);
}
return true;
}
return false;
}
/**
* Gets the {@link FileConfiguration} that this {@link WorldManager} is using.
* @return The {@link FileConfiguration} that this {@link WorldManager} is using.
+30
View File
@@ -202,3 +202,33 @@ commands:
description: Regenerates a world Multiverse already knows about.
usage: |
/<command> {WORLD}
mvscript:
description: Runs a script from the Multiverse scripts directory.
usage: |
/<command> {script} [target]
mvclone:
description: World clone command
usage: |
/<command> <world> <environment>
/<command> creative grieftastic -- Creates a world called 'grieftastic' exactly identical to the world 'creative'.
mvsilent:
description: Reduces startup messages
usage: |
/<command> [true|false]
mvgamerule:
description: Sets a gamerule.
usage: |
/<command> {RULE} {VALUE} [WORLD]
mvrule:
description: Sets a gamerule.
usage: |
/<command> {RULE} {VALUE} [WORLD]
mvgamerules:
description: Lists the gamerules.
usage: |
/<command> [WORLD]
mvrules:
description: Lists the gamerules.
usage: |
/<command> [WORLD]
@@ -5,17 +5,11 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.api.Core;
import com.onarandombox.MultiverseCore.utils.TestInstanceCreator;
import junit.framework.Assert;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -28,9 +22,12 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.Core;
import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator;
import java.io.File;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MultiverseCore.class, PluginDescriptionFile.class })
@@ -0,0 +1,156 @@
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.listeners.MVEntityListener;
import com.onarandombox.MultiverseCore.utils.TestInstanceCreator;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Sheep;
import org.bukkit.entity.Zombie;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.plugin.PluginDescriptionFile;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MultiverseCore.class, PluginDescriptionFile.class })
public class TestEntitySpawnRules {
TestInstanceCreator creator;
MultiverseCore core;
MVEntityListener listener;
MultiverseWorld mvWorld;
World cbworld;
Sheep sheep;
Zombie zombie;
CreatureSpawnEvent sheepEvent;
CreatureSpawnEvent zombieEvent;
@Before
public void setUp() throws Exception {
creator = new TestInstanceCreator();
assertTrue(creator.setUp());
core = creator.getCore();
listener = core.getEntityListener();
mvWorld = mock(MultiverseWorld.class);
cbworld = mock(World.class);
when(mvWorld.getCBWorld()).thenReturn(cbworld);
MVWorldManager worldman = mock(MVWorldManager.class);
when(worldman.isMVWorld(anyString())).thenReturn(true);
when(worldman.getMVWorld(anyString())).thenReturn(mvWorld);
Field worldmanfield = MVEntityListener.class.getDeclaredField("worldManager");
worldmanfield.setAccessible(true);
worldmanfield.set(listener, worldman);
core.getMVConfig().setGlobalDebug(3);
}
@After
public void tearDown() throws Exception {
creator.tearDown();
}
private static CreatureSpawnEvent mockSpawnEvent(LivingEntity e, SpawnReason reason) {
CreatureSpawnEvent event = mock(CreatureSpawnEvent.class);
when(event.getEntity()).thenReturn(e);
EntityType type = e.getType();
when(event.getEntityType()).thenReturn(type);
when(event.getSpawnReason()).thenReturn(reason);
return event;
}
private void spawnAll(SpawnReason reason) {
sheepEvent = mockSpawnEvent(sheep, reason);
zombieEvent = mockSpawnEvent(zombie, reason);
listener.creatureSpawn(sheepEvent);
listener.creatureSpawn(zombieEvent);
}
private void spawnAllNatural() {
spawnAll(SpawnReason.NATURAL);
}
private void adjustSettings(boolean animalSpawn, boolean monsterSpawn,
List<String> animalExceptions, List<String> monsterExceptions) {
when(this.mvWorld.canAnimalsSpawn()).thenReturn(animalSpawn);
when(this.mvWorld.canMonstersSpawn()).thenReturn(monsterSpawn);
when(this.mvWorld.getAnimalList()).thenReturn(animalExceptions);
when(this.mvWorld.getMonsterList()).thenReturn(monsterExceptions);
}
@Test
public void test() {
// test 1: no spawning at all allowed
adjustSettings(false, false, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
createAnimals();
spawnAllNatural();
verify(sheepEvent).setCancelled(true);
verify(zombieEvent).setCancelled(true);
// test 2: only monsters
adjustSettings(false, true, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
createAnimals();
spawnAllNatural();
verify(sheepEvent).setCancelled(true);
verify(zombieEvent).setCancelled(false);
// test 3: all spawning allowed
adjustSettings(true, true, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
createAnimals();
spawnAllNatural();
verify(sheepEvent).setCancelled(false);
verify(zombieEvent).setCancelled(false);
// test 4: no spawning with zombie exception
adjustSettings(false, false, Collections.EMPTY_LIST, Arrays.asList("ZOMBIE"));
createAnimals();
spawnAllNatural();
verify(sheepEvent).setCancelled(true);
verify(zombieEvent).setCancelled(false);
// test 5: all spawning with sheep exception
adjustSettings(true, true, Arrays.asList("SHEEP"), Collections.EMPTY_LIST);
createAnimals();
spawnAllNatural();
verify(sheepEvent).setCancelled(true);
verify(zombieEvent).setCancelled(false);
// test 6: eggs
adjustSettings(false, false, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
createAnimals();
spawnAll(SpawnReason.SPAWNER_EGG);
verify(sheepEvent, never()).setCancelled(anyBoolean());
verify(zombieEvent, never()).setCancelled(anyBoolean());
}
private void createAnimals() {
sheep = mock(Sheep.class);
when(sheep.getType()).thenReturn(EntityType.SHEEP);
when(sheep.getWorld()).thenReturn(this.cbworld);
zombie = mock(Zombie.class);
when(zombie.getType()).thenReturn(EntityType.ZOMBIE);
when(zombie.getWorld()).thenReturn(this.cbworld);
when(cbworld.getEntities()).thenReturn(Arrays.asList((Entity) sheep, (Entity) zombie));
}
}
@@ -1,8 +1,7 @@
package com.onarandombox.MultiverseCore.test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.utils.TestInstanceCreator;
import org.bukkit.Server;
import org.bukkit.World.Environment;
import org.bukkit.command.Command;
@@ -15,9 +14,9 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@@ -5,19 +5,20 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test;
package com.onarandombox.MultiverseCore;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
import java.io.File;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.configuration.SpawnLocation;
import com.onarandombox.MultiverseCore.listeners.MVAsyncPlayerChatListener;
import com.onarandombox.MultiverseCore.utils.TestInstanceCreator;
import com.onarandombox.MultiverseCore.utils.WorldManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
@@ -27,7 +28,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.weather.ThunderChangeEvent;
@@ -44,17 +45,16 @@ import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.onarandombox.MultiverseCore.MVWorld;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.configuration.SpawnLocation;
import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator;
import com.onarandombox.MultiverseCore.utils.WorldManager;
import java.io.File;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ PluginManager.class, MultiverseCore.class, Permission.class, Bukkit.class,
WeatherChangeEvent.class, ThunderChangeEvent.class, PlayerChatEvent.class,
WeatherChangeEvent.class, ThunderChangeEvent.class, AsyncPlayerChatEvent.class,
PlayerJoinEvent.class, PlayerRespawnEvent.class, EntityRegainHealthEvent.class,
FoodLevelChangeEvent.class, WorldManager.class, PluginDescriptionFile.class })
public class TestWorldProperties {
@@ -68,7 +68,7 @@ public class TestWorldProperties {
private ThunderChangeEvent thunderChangeOffEvent;
private ThunderChangeEvent thunderChangeOnEvent;
private Player mockPlayer;
private PlayerChatEvent playerChatEvent;
private AsyncPlayerChatEvent playerChatEvent;
private Player mockNewPlayer;
private PlayerJoinEvent playerNewJoinEvent;
private PlayerJoinEvent playerJoinEvent;
@@ -167,10 +167,10 @@ public class TestWorldProperties {
// call player chat event
core.getMVConfig().setPrefixChat(true);
core.getPlayerListener().playerChat(playerChatEvent);
((MVAsyncPlayerChatListener) core.getChatListener()).playerChat(playerChatEvent);
verify(playerChatEvent).setFormat("[" + mvWorld.getColoredWorldString() + "]" + "format");
core.getMVConfig().setPrefixChat(false);
core.getPlayerListener().playerChat(playerChatEvent);
((MVAsyncPlayerChatListener) core.getChatListener()).playerChat(playerChatEvent);
verify(playerChatEvent, times(1)).setFormat(anyString()); // only ONE TIME (not the 2nd time!)
// call player join events
@@ -261,15 +261,15 @@ public class TestWorldProperties {
// call player chat event
core.getMVConfig().setPrefixChat(true);
core.getPlayerListener().playerChat(playerChatEvent);
((MVAsyncPlayerChatListener) core.getChatListener()).playerChat(playerChatEvent);
// never because it's hidden!
verify(playerChatEvent, never()).setFormat(
"[" + mvWorld.getColoredWorldString() + "]" + "format");
mvWorld.setHidden(false);
core.getPlayerListener().playerChat(playerChatEvent);
((MVAsyncPlayerChatListener) core.getChatListener()).playerChat(playerChatEvent);
verify(playerChatEvent).setFormat("[" + mvWorld.getColoredWorldString() + "]" + "format");
core.getMVConfig().setPrefixChat(false);
core.getPlayerListener().playerChat(playerChatEvent);
((MVAsyncPlayerChatListener) core.getChatListener()).playerChat(playerChatEvent);
verify(playerChatEvent, times(1)).setFormat(anyString()); // only ONE TIME (not the 2nd time!)
mvWorld.setHidden(true); // reset hidden-state
@@ -298,7 +298,7 @@ public class TestWorldProperties {
assertTrue(core.saveMVConfigs());
// change a value here
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(core.getDataFolder(), "worlds.yml"));
MVWorld worldObj = (MVWorld) config.get("worlds.world");
WorldProperties worldObj = (WorldProperties) config.get("worlds.world");
assertTrue(worldObj.setColor("GREEN"));
config.set("worlds.world", worldObj);
config.save(new File(core.getDataFolder(), "worlds.yml"));
@@ -331,20 +331,22 @@ public class TestWorldProperties {
}
public void createEvents(MultiverseWorld mvWorld) {
final World world = mvWorld.getCBWorld();
//// Weather events
// weather change
weatherChangeOffEvent = new WeatherChangeEvent(mvWorld.getCBWorld(), false);
weatherChangeOnEvent = new WeatherChangeEvent(mvWorld.getCBWorld(), true);
weatherChangeOffEvent = new WeatherChangeEvent(world, false);
weatherChangeOnEvent = new WeatherChangeEvent(world, true);
// thunder change
thunderChangeOffEvent = new ThunderChangeEvent(mvWorld.getCBWorld(), false);
thunderChangeOnEvent = new ThunderChangeEvent(mvWorld.getCBWorld(), true);
thunderChangeOffEvent = new ThunderChangeEvent(world, false);
thunderChangeOnEvent = new ThunderChangeEvent(world, true);
//// Player events
// player chat
mockPlayer = mock(Player.class);
when(mockPlayer.getWorld()).thenReturn(mvWorld.getCBWorld());
when(mockPlayer.getWorld()).thenReturn(world);
when(mockPlayer.hasPlayedBefore()).thenReturn(true);
when(mockPlayer.hasPermission("multiverse.access.world")).thenReturn(true);
playerChatEvent = PowerMockito.mock(PlayerChatEvent.class);
when(mockPlayer.getName()).thenReturn("MultiverseMan");
playerChatEvent = PowerMockito.mock(AsyncPlayerChatEvent.class);
when(playerChatEvent.getPlayer()).thenReturn(mockPlayer);
when(playerChatEvent.getFormat()).thenReturn("format");
// player join
@@ -366,7 +368,7 @@ public class TestWorldProperties {
// entity regain health
entityRegainHealthEvent = PowerMockito.mock(EntityRegainHealthEvent.class);
when(entityRegainHealthEvent.getRegainReason()).thenReturn(RegainReason.REGEN);
when(mockHumanEntity.getLocation()).thenReturn(new Location(mvWorld.getCBWorld(), 0, 0, 0));
when(mockHumanEntity.getLocation()).thenReturn(new Location(world, 0, 0, 0));
when(entityRegainHealthEvent.getEntity()).thenReturn(mockHumanEntity);
// entity food level change event
entityFoodLevelChangeEvent = PowerMockito.mock(FoodLevelChangeEvent.class);
@@ -1,10 +1,8 @@
package com.onarandombox.MultiverseCore.test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.util.Arrays;
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.utils.TestInstanceCreator;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -18,10 +16,10 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.api.WorldPurger;
import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator;
import java.util.Arrays;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MultiverseCore.class, PluginDescriptionFile.class })
@@ -113,10 +111,13 @@ public class TestWorldPurger {
}
private void createAnimals() {
World world = mvWorld.getCBWorld();
sheep = mock(Sheep.class);
when(sheep.getType()).thenReturn(EntityType.SHEEP);
when(sheep.getWorld()).thenReturn(world);
zombie = mock(Zombie.class);
when(zombie.getType()).thenReturn(EntityType.ZOMBIE);
when(zombie.getWorld()).thenReturn(world);
when(cbworld.getEntities()).thenReturn(Arrays.asList((Entity) sheep, (Entity) zombie));
}
}
@@ -5,15 +5,18 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test;
package com.onarandombox.MultiverseCore;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator;
import com.onarandombox.MultiverseCore.test.utils.WorldCreatorMatcher;
import com.onarandombox.MultiverseCore.utils.TestInstanceCreator;
import com.onarandombox.MultiverseCore.utils.WorldCreatorMatcher;
import com.onarandombox.MultiverseCore.utils.WorldManager;
import org.bukkit.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Server;
import org.bukkit.WorldCreator;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.Permission;
@@ -168,6 +171,35 @@ public class TestWorldStuff {
verify(mockServer).createWorld(Matchers.argThat(matcher));
}
@Test
public void testWorldCreateInvalidGenerator() {
// Pull a core instance from the server.
Plugin plugin = mockServer.getPluginManager().getPlugin("Multiverse-Core");
// Make sure Core is not null
assertNotNull(plugin);
// Make sure Core is enabled
assertTrue(plugin.isEnabled());
// Initialize a fake command
Command mockCommand = mock(Command.class);
when(mockCommand.getName()).thenReturn("mv");
// Ensure that there are no worlds imported. This is a fresh setup.
assertEquals(0, creator.getCore().getMVWorldManager().getMVWorlds().size());
// Create the world
String[] normalArgs = new String[]{ "create", "newworld", "normal", "-g", "BogusGen"};
plugin.onCommand(mockCommandSender, mockCommand, "", normalArgs);
// This command should halt, not creating any worlds
assertEquals(0, creator.getCore().getMVWorldManager().getMVWorlds().size());
// Verify
verify(mockCommandSender).sendMessage("Invalid generator! 'BogusGen'. " + ChatColor.RED + "Aborting world creation.");
}
@Test
public void testNullWorld() {
// Pull a core instance from the server.
@@ -1,91 +0,0 @@
package com.onarandombox.MultiverseCore.test;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.test.utils.TestInstanceCreator;
import com.onarandombox.MultiverseCore.utils.WorldManager;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.PluginDescriptionFile;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.internal.verification.VerificationModeFactory;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.lang.reflect.Field;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ MultiverseCore.class, PluginDescriptionFile.class })
public class TestWorldCreation {
private TestInstanceCreator creator;
private MultiverseCore core;
private CommandSender mockCommandSender;
@Before
public void setUp() throws Exception {
this.creator = new TestInstanceCreator();
assertTrue(this.creator.setUp());
this.core = this.creator.getCore();
this.mockCommandSender = this.creator.getCommandSender();
}
@After
public void tearDown() throws Exception {
creator.tearDown();
}
@Test
@Ignore
public void test() {
// Initialize a fake command
Command mockCommand = mock(Command.class);
when(mockCommand.getName()).thenReturn("mv");
// Try to create a world that exists
String[] normalArgs = new String[] { "create", "world", "normal" };
core.onCommand(mockCommandSender, mockCommand, "", normalArgs);
verify(mockCommandSender).sendMessage(ChatColor.RED + "A Folder/World already exists with this name!");
verify(mockCommandSender).sendMessage(ChatColor.RED + "If you are confident it is a world you can import with /mvimport");
// Try to create a world that is new
String[] newArgs = new String[] { "create", "world2", "normal" };
core.onCommand(mockCommandSender, mockCommand, "", newArgs);
verify(mockCommandSender).sendMessage("Starting creation of world 'world2'...");
String[] dottedWorld = new String[] { "create", "fish.world", "normal" };
core.onCommand(mockCommandSender, mockCommand, "", dottedWorld);
verify(mockCommandSender).sendMessage("Starting creation of world 'fish.world'...");
verify(mockCommandSender, VerificationModeFactory.times(2)).sendMessage("Complete!");
// Grab the Config
Field worldConfigField = null;
ConfigurationSection worldsSection = null;
try {
worldConfigField = WorldManager.class.getDeclaredField("configWorlds");
worldConfigField.setAccessible(true);
Configuration rootConfig = (Configuration) worldConfigField.get(this.core.getMVWorldManager());
worldsSection = rootConfig.getConfigurationSection("worlds");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// Verify that the world was added to the configs
// TODO: Expand this.
assertNotNull(worldsSection);
assertEquals(2, worldsSection.getKeys(false).size());
assertTrue(worldsSection.getKeys(false).contains("world2"));
assertTrue(worldsSection.getKeys(false).contains("fish.world"));
}
}
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test.utils;
package com.onarandombox.MultiverseCore.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -5,16 +5,7 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test.utils;
import static org.mockito.Mockito.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
package com.onarandombox.MultiverseCore.utils;
import org.bukkit.Difficulty;
import org.bukkit.Location;
@@ -26,9 +17,20 @@ import org.bukkit.generator.ChunkGenerator;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;
import static org.mockito.Mockito.*;
public class MockWorldFactory {
private static final Map<String, World> createdWorlds = new HashMap<String, World>();
private static final Map<UUID, World> worldUIDS = new HashMap<UUID, World>();
private static final Map<World, Boolean> pvpStates = new WeakHashMap<World, Boolean>();
private static final Map<World, Boolean> keepSpawnInMemoryStates = new WeakHashMap<World, Boolean>();
@@ -39,6 +41,8 @@ public class MockWorldFactory {
private static void registerWorld(World world) {
createdWorlds.put(world.getName(), world);
worldUIDS.put(world.getUID(), world);
new File(TestInstanceCreator.worldsDirectory, world.getName()).mkdir();
}
private static World basics(String world, World.Environment env, WorldType type) {
@@ -131,6 +135,7 @@ public class MockWorldFactory {
return mockBlock;
}
});
when(mockWorld.getUID()).thenReturn(UUID.randomUUID());
return mockWorld;
}
@@ -202,6 +207,10 @@ public class MockWorldFactory {
return createdWorlds.get(name);
}
public static World getWorld(UUID worldUID) {
return worldUIDS.get(worldUID);
}
public static List<World> getWorlds() {
// we have to invert the order!
ArrayList<World> myList = new ArrayList<World>(createdWorlds.values());
@@ -213,6 +222,9 @@ public class MockWorldFactory {
}
public static void clearWorlds() {
for (String name : createdWorlds.keySet())
new File(TestInstanceCreator.worldsDirectory, name).delete();
createdWorlds.clear();
worldUIDS.clear();
}
}
@@ -5,15 +5,14 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test.utils;
package com.onarandombox.MultiverseCore.utils;
import buscript.Buscript;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.listeners.MVEntityListener;
import com.onarandombox.MultiverseCore.listeners.MVPlayerListener;
import com.onarandombox.MultiverseCore.listeners.MVWeatherListener;
import com.onarandombox.MultiverseCore.utils.FileUtils;
import com.onarandombox.MultiverseCore.utils.WorldManager;
import junit.framework.Assert;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -37,6 +36,7 @@ import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -60,6 +60,12 @@ public class TestInstanceCreator {
MockGateway.MOCK_STANDARD_METHODS = false;
core = PowerMockito.spy(new MultiverseCore());
PowerMockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
return null; // don't run metrics in tests
}
}).when(core, "setupMetrics");
// Let's let all MV files go to bin/test
doReturn(pluginDirectory).when(core).getDataFolder();
@@ -70,6 +76,7 @@ public class TestInstanceCreator {
when(pdf.getAuthors()).thenReturn(new ArrayList<String>());
doReturn(pdf).when(core).getDescription();
doReturn(true).when(core).isEnabled();
doReturn(Util.logger).when(core).getLogger();
core.setServerFolder(serverDirectory);
// Add Core to the list of loaded plugins
@@ -80,6 +87,8 @@ public class TestInstanceCreator {
when(mockPluginManager.getPlugins()).thenReturn(plugins);
when(mockPluginManager.getPlugin("Multiverse-Core")).thenReturn(core);
when(mockPluginManager.getPermission(anyString())).thenReturn(null);
// Tell Buscript Vault is not available.
when(mockPluginManager.getPermission("Vault")).thenReturn(null);
// Make some fake folders to fool the fake MV into thinking these worlds exist
File worldNormalFile = new File(core.getServerFolder(), "world");
@@ -113,6 +122,19 @@ public class TestInstanceCreator {
}
});
when(mockServer.getWorld(any(UUID.class))).thenAnswer(new Answer<World>() {
@Override
public World answer(InvocationOnMock invocation) throws Throwable {
UUID arg;
try {
arg = (UUID) invocation.getArguments()[0];
} catch (Exception e) {
return null;
}
return MockWorldFactory.getWorld(arg);
}
});
when(mockServer.getWorlds()).thenAnswer(new Answer<List<World>>() {
@Override
public List<World> answer(InvocationOnMock invocation) throws Throwable {
@@ -178,6 +200,13 @@ public class TestInstanceCreator {
serverfield.setAccessible(true);
serverfield.set(core, mockServer);
// Set buscript
Buscript buscript = PowerMockito.spy(new Buscript(core));
Field buscriptfield = MultiverseCore.class.getDeclaredField("buscript");
buscriptfield.setAccessible(true);
buscriptfield.set(core, buscript);
when(buscript.getPlugin()).thenReturn(core);
// Set worldManager
WorldManager wm = PowerMockito.spy(new WorldManager(core));
Field worldmanagerfield = MultiverseCore.class.getDeclaredField("worldManager");
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test.utils;
package com.onarandombox.MultiverseCore.utils;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
@@ -5,7 +5,7 @@
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.test.utils;
package com.onarandombox.MultiverseCore.utils;
import org.bukkit.WorldCreator;
import org.mockito.ArgumentMatcher;