├── .gitignore
├── docs
└── img
│ ├── Banner.pdn
│ ├── Banner.png
│ └── PhantomWorlds.png
├── src
└── main
│ ├── resources
│ ├── advancedSettings.yml
│ ├── data.yml
│ ├── settings.yml
│ ├── plugin.yml
│ └── messages.yml
│ └── java
│ └── me
│ └── lokka30
│ └── phantomworlds
│ ├── misc
│ ├── UpdateCheckerResult.java
│ ├── WorldLoadResponse.java
│ ├── CompatibilityChecker.java
│ └── Utils.java
│ ├── commandsredux
│ ├── utils
│ │ └── WorldFolder.java
│ ├── sub
│ │ ├── TeleportCommand.java
│ │ ├── SpawnCommand.java
│ │ ├── DebugCommand.java
│ │ ├── InfoCommand.java
│ │ ├── BackupCommand.java
│ │ ├── set
│ │ │ ├── SetWhitelistCommand.java
│ │ │ ├── SetGamemodeCommand.java
│ │ │ ├── SetPortalCommand.java
│ │ │ └── SetEffectsCommand.java
│ │ ├── UnloadCommand.java
│ │ ├── ReloadCommand.java
│ │ ├── DeleteCommand.java
│ │ ├── ImportCommand.java
│ │ ├── CompatibilityCommand.java
│ │ ├── LoadCommand.java
│ │ ├── SetSpawnCommand.java
│ │ ├── ListCommand.java
│ │ └── CreateCommand.java
│ ├── handler
│ │ └── PWInvalidUsageHandler.java
│ ├── params
│ │ ├── SettingParameter.java
│ │ ├── AliasWorldParameter.java
│ │ ├── PotionEffectParameter.java
│ │ ├── PortalParameter.java
│ │ ├── GamemodeParameter.java
│ │ └── WorldFolderParameter.java
│ └── PWCommand.java
│ ├── listeners
│ ├── world
│ │ └── WorldInitListener.java
│ └── player
│ │ ├── PlayerDeathListener.java
│ │ ├── PlayerJoinListener.java
│ │ ├── PlayerTeleportListener.java
│ │ ├── PlayerPortalListener.java
│ │ └── PlayerChangeWorldListener.java
│ ├── scheduler
│ └── BackupScheduler.java
│ ├── managers
│ ├── FileManager.java
│ └── WorldManager.java
│ ├── world
│ └── PhantomWorld.java
│ └── PhantomWorlds.java
├── README.md
├── PW Code Style.xml
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # IntelliJ IDEA
2 | target/
3 | .idea
4 | *.iml
5 |
6 | # macOS
7 | ._.git
8 | .DS_Store
--------------------------------------------------------------------------------
/docs/img/Banner.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArcanePlugins/PhantomWorlds/HEAD/docs/img/Banner.pdn
--------------------------------------------------------------------------------
/docs/img/Banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArcanePlugins/PhantomWorlds/HEAD/docs/img/Banner.png
--------------------------------------------------------------------------------
/docs/img/PhantomWorlds.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArcanePlugins/PhantomWorlds/HEAD/docs/img/PhantomWorlds.png
--------------------------------------------------------------------------------
/src/main/resources/advancedSettings.yml:
--------------------------------------------------------------------------------
1 | # .___ _ . . __ . _
2 | # / \ / ___ , __ _/_ __. , _ , _ / | __. .___ | ___/ ____
3 | # |,_-' |,---. / ` |' `. | .' \ |' `|' `. | | .' \ / \ | / | (
4 | # | |' ` | | | | | | | | | | | /\ / | | | ' | ,' | `--.
5 | # / / | `.__/| / | \__/ `._.' / ' / |,' \,' `._.' / /\__ `___,' \___.'
6 |
7 | # Do not touch anything here unless you know what you are doing.
8 | advanced:
9 | file-version: 1
10 | generated-with: '${project.version}'
--------------------------------------------------------------------------------
/src/main/resources/data.yml:
--------------------------------------------------------------------------------
1 | # .___ _ . . __ . _
2 | # / \ / ___ , __ _/_ __. , _ , _ / | __. .___ | ___/ ____
3 | # |,_-' |,---. / ` |' `. | .' \ |' `|' `. | | .' \ / \ | / | (
4 | # | |' ` | | | | | | | | | | | /\ / | | | ' | ,' | `--.
5 | # / / | `.__/| / | \__/ `._.' / ' / |,' \,' `._.' / /\__ `___,' \___.'
6 |
7 | worlds-to-load:
8 |
9 | # Do not touch anything here unless you know what you are doing.
10 | advanced:
11 | file-version: 2
12 | generated-with: '${project.version}'
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/misc/UpdateCheckerResult.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.misc;
2 |
3 | /**
4 | * @author lokka30
5 | * @since v2.0.0
6 | */
7 | public class UpdateCheckerResult {
8 |
9 | private final boolean outdated;
10 | private final String currentVersion;
11 | private final String latestVersion;
12 |
13 | public UpdateCheckerResult(boolean outdated, String currentVersion, String latestVersion) {
14 | this.outdated = outdated;
15 | this.currentVersion = currentVersion;
16 | this.latestVersion = latestVersion;
17 | }
18 |
19 | public boolean isOutdated() {
20 | return outdated;
21 | }
22 |
23 | public String getCurrentVersion() {
24 | return currentVersion;
25 | }
26 |
27 | public String getLatestVersion() {
28 | return latestVersion;
29 | }
30 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PhantomWorlds
2 |
3 | ## About
4 |
5 | * A [SpigotMC](https://www.spigotmc.org/) plugin which allows administrators to create, manage and
6 | teleport to whatever worlds they wish.
7 |
8 | ## Learn more
9 |
10 | * Click [here](https://www.spigotmc.org/resources/phantomworlds.84099/) to visit the SpigotMC
11 | resource page for PhantomWorlds, where you can learn more and download the resource if you
12 | wish. :)
13 | * Click [here](https://github.com/TheNewEconomy/PhantomWorlds/wiki) to visit the Wiki.
14 |
15 | ## Contributors
16 |
17 | * Please see the [Credits](https://github.com/TheNewEconomy/PhantomWorlds/wiki/Credits) - thank you
18 | very
19 | much to all contributors to the resource! ❤
20 |
21 | ## License
22 |
23 | * Licensed under `GNU AGPL v3.0` (
24 | see [LICENSE.md](https://github.com/TheNewEconomy/PhantomWorlds/blob/master/LICENSE.md)).
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/misc/WorldLoadResponse.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.misc;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | /**
21 | * WorldLoadResponse
22 | *
23 | * @author creatorfromhell
24 | * @since 2.0.5.0
25 | */
26 | public enum WorldLoadResponse {
27 | LOADED,
28 | NOT_FOUND,
29 | ALREADY_LOADED,
30 | INVALID,
31 | CONFIG_SKIPPED
32 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/utils/WorldFolder.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.utils;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | /**
21 | * WorldFolder
22 | *
23 | * @author creatorfromhell
24 | * @since 2.0.5.0
25 | */
26 | public class WorldFolder {
27 |
28 | private final String folder;
29 |
30 | public WorldFolder(String folder) {
31 | this.folder = folder;
32 | }
33 |
34 | public String getFolder() {
35 | return folder;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/resources/settings.yml:
--------------------------------------------------------------------------------
1 | # .___ _ . . __ . _
2 | # / \ / ___ , __ _/_ __. , _ , _ / | __. .___ | ___/ ____
3 | # |,_-' |,---. / ` |' `. | .' \ |' `|' `. | | .' \ / \ | / | (
4 | # | |' ` | | | | | | | | | | | /\ / | | | ' | ,' | `--.
5 | # / / | `.__/| / | \__/ `._.' / ' / |,' \,' `._.' / /\__ `___,' \___.'
6 |
7 | # Should PW run an update check from the Spigot page on startup?
8 | run-update-checker: true
9 |
10 | #Configurations relating to spawn controls.
11 | spawning:
12 |
13 | #What is the spawn world for the server? If the player hasn't played before this is the world that
14 | #they will go to.
15 | default-world: world
16 |
17 | #Should players respawn at the world spawn if they don't have a bed?
18 | respawn-world: true
19 |
20 | #Should players be sent to the world spawn each time they change worlds?
21 | change: false
22 |
23 | #Should worlds deleted be moved to an archive folder in deletedworlds?
24 | delete-archive: true
25 |
26 | #Should worlds be automatically backed up to the backup folder?
27 | backup-scheduler: true
28 |
29 | #The time, in seconds, to back up every PhantomWorlds-managed world.
30 | backup-delay: 600
31 |
32 | # Do not touch anything here unless you know what you are doing.
33 | advanced:
34 | file-version: 2
35 | generated-with: '${project.version}'
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/TeleportCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.misc.Utils;
21 | import org.bukkit.World;
22 | import org.bukkit.command.CommandSender;
23 | import org.bukkit.entity.Player;
24 |
25 | /**
26 | * TeleportCommand
27 | *
28 | * @author creatorfromhell
29 | * @since 2.0.5.0
30 | */
31 | public class TeleportCommand {
32 |
33 | public static void onCommand(final CommandSender sender, final World world, final Player player) {
34 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.teleport.usage", world)) {
35 | return;
36 | }
37 | Utils.teleportToWorld(sender, "teleport", "teleport", (player == null)? sender.getName() : player.getName(), world.getName());
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/SpawnCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.misc.Utils;
21 | import org.bukkit.World;
22 | import org.bukkit.command.CommandSender;
23 | import org.bukkit.entity.Player;
24 |
25 | /**
26 | * SpawnCommand
27 | *
28 | * @author creatorfromhell
29 | * @since 2.0.5.0
30 | */
31 | public class SpawnCommand {
32 |
33 | public static void onCommand(final CommandSender sender, final World world, final Player player) {
34 | if(!(sender instanceof Player) && !Utils.checkWorld(sender, "command.phantomworlds.subcommands.spawn.usage", world)) {
35 | return;
36 | }
37 | Utils.teleportToWorld(sender, "spawn", "spawn", (player == null)? sender.getName() : player.getName(), (sender instanceof Player && world == null)? ((Player)sender).getWorld().getName() : world.getName());
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/listeners/world/WorldInitListener.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.listeners.world;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import org.bukkit.event.EventHandler;
22 | import org.bukkit.event.Listener;
23 | import org.bukkit.event.world.WorldInitEvent;
24 |
25 | /**
26 | * WorldInitListener
27 | *
28 | * @author creatorfromhell
29 | * @since 2.0.5.0
30 | */
31 | public class WorldInitListener implements Listener {
32 |
33 | final PhantomWorlds plugin;
34 |
35 | public WorldInitListener(PhantomWorlds plugin) {
36 | this.plugin = plugin;
37 | }
38 |
39 | @EventHandler
40 | public void onInit(WorldInitEvent event) {
41 | if(PhantomWorlds.instance().data.getConfig().contains("worlds-to-load." + event.getWorld().getName())) {
42 |
43 | }
44 | if(!plugin.isWorldLoaded()) {
45 | plugin.loadWorlds();
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/handler/PWInvalidUsageHandler.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.handler;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.handler.result.ResultHandlerChain;
21 | import dev.rollczi.litecommands.invalidusage.InvalidUsage;
22 | import dev.rollczi.litecommands.invalidusage.InvalidUsageHandler;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.schematic.Schematic;
25 | import org.bukkit.command.CommandSender;
26 |
27 | /**
28 | * InvalidUsageHandler
29 | *
30 | * @author creatorfromhell
31 | * @since 2.0.5.0
32 | */
33 | public class PWInvalidUsageHandler implements InvalidUsageHandler {
34 | @Override
35 | public void handle(Invocation invocation, InvalidUsage result, ResultHandlerChain chain) {
36 |
37 | final CommandSender sender = invocation.sender();
38 | final Schematic schematic = result.getSchematic();
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/misc/CompatibilityChecker.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.misc;
2 |
3 | import java.util.LinkedList;
4 |
5 | /**
6 | * Handles various checks that attempt to warn administrators about potential compatibility issues
7 | * with their server configuration.
8 | *
9 | * @author lokka30
10 | * @since v2.0.0
11 | */
12 | public class CompatibilityChecker {
13 |
14 | public final LinkedList incompatibilities = new LinkedList<>();
15 |
16 | /**
17 | * Run all PW compatibility checks.
18 | *
19 | * @since v2.0.0
20 | */
21 | public void checkAll() {
22 | incompatibilities.clear();
23 |
24 | //checkPlugins();
25 | }
26 |
27 | /**
28 | * Enum storing the different types of incompatibility detections.
29 | *
30 | * @author lokka30
31 | * @since v2.0.0
32 | */
33 | @SuppressWarnings("unused")
34 | public enum IncompatibilityType {
35 | MISSING_DEPENDENCY, // A dependency required for an operation is missing.
36 | INCOMPATIBLE_PLUGIN, // Another plugin is installed on the server which may be incompatible.
37 | SERVER_SOFTWARE, // The server software (e.g. Paper/Spigot/Tuinity) is incompatible.
38 | JAVA_VERSION // The server's version of Java is outdated.
39 | }
40 |
41 | /**
42 | * This class is used as an object to store each incompatibility that is detected.
43 | *
44 | * @author lokka30
45 | * @since v2.0.0
46 | */
47 | public static class Incompatibility {
48 |
49 | public final IncompatibilityType type;
50 | public final String reason;
51 | public final String recommendation;
52 |
53 | public Incompatibility(IncompatibilityType type, String reason, String recommendation) {
54 | this.type = type;
55 | this.reason = reason;
56 | this.recommendation = recommendation;
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/listeners/player/PlayerDeathListener.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.listeners.player;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import me.lokka30.phantomworlds.misc.Utils;
22 | import org.bukkit.event.EventHandler;
23 | import org.bukkit.event.Listener;
24 | import org.bukkit.event.entity.PlayerDeathEvent;
25 |
26 | /**
27 | * PlayerDeathListener
28 | *
29 | * @author creatorfromhell
30 | * @since 2.0.5.0
31 | */
32 | public class PlayerDeathListener implements Listener {
33 |
34 | final PhantomWorlds plugin;
35 |
36 | public PlayerDeathListener(PhantomWorlds plugin) {
37 | this.plugin = plugin;
38 | }
39 |
40 | @EventHandler
41 | public void onDeath(PlayerDeathEvent event) {
42 | if(!PhantomWorlds.instance().settings.getConfig().getBoolean("spawning.respawn-world", false)) {
43 | return;
44 | }
45 |
46 | if(event.getEntity().getBedSpawnLocation() == null) {
47 |
48 | event.getEntity().teleport(Utils.parseSpawn(event.getEntity().getWorld()));
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/params/SettingParameter.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.params;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.argument.Argument;
21 | import dev.rollczi.litecommands.argument.parser.ParseResult;
22 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.suggestion.SuggestionContext;
25 | import dev.rollczi.litecommands.suggestion.SuggestionResult;
26 | import me.lokka30.phantomworlds.PhantomWorlds;
27 | import org.bukkit.command.CommandSender;
28 |
29 | /**
30 | * SettingParameterRedux
31 | *
32 | * @author creatorfromhell
33 | * @since 2.0.5.0
34 | */
35 | public class SettingParameter extends ArgumentResolver {
36 | @Override
37 | protected ParseResult parse(Invocation invocation, Argument context, String argument) {
38 | return ParseResult.success(argument);
39 | }
40 |
41 | @Override
42 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) {
43 | return SuggestionResult.of(PhantomWorlds.createTabs);
44 | }
45 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/scheduler/BackupScheduler.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.scheduler;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import org.bukkit.Bukkit;
22 | import org.bukkit.World;
23 | import org.bukkit.scheduler.BukkitRunnable;
24 |
25 | /**
26 | * BackupScheduler
27 | *
28 | * @author creatorfromhell
29 | * @since 2.0.5.0
30 | */
31 | public class BackupScheduler extends BukkitRunnable {
32 | /**
33 | * When an object implementing interface {@code Runnable} is used to create a thread, starting the
34 | * thread causes the object's {@code run} method to be called in that separately executing
35 | * thread.
36 | *
37 | * The general contract of the method {@code run} is that it may take any action whatsoever.
38 | *
39 | * @see Thread#run()
40 | */
41 | @Override
42 | public void run() {
43 | PhantomWorlds.logger().info("Running World Backup Task...");
44 |
45 | for(final World world : Bukkit.getWorlds()) {
46 | PhantomWorlds.logger().info("Backing up world '" + world.getName() + "'...");
47 | PhantomWorlds.worldManager().backupWorld(world.getName());
48 | }
49 | PhantomWorlds.logger().info("World Backup Task has completed!");
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/DebugCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MessageUtils;
21 | import org.bukkit.command.CommandSender;
22 |
23 | import java.util.Locale;
24 |
25 | /**
26 | * DebugCommand
27 | *
28 | * @author creatorfromhell
29 | * @since 2.0.5.0
30 | */
31 | public class DebugCommand {
32 |
33 | public static void onCommand(final CommandSender sender, final String level) {
34 |
35 | final String parsed = (level == null)? "nothing" : level;
36 | switch(parsed.toLowerCase(Locale.ROOT)) {
37 | case "dump":
38 | sender.sendMessage(
39 | MessageUtils.colorizeStandardCodes("&b&lPhantomWorlds: &7Incomplete."));
40 | break;
41 | default:
42 | sender.sendMessage(MessageUtils.colorizeStandardCodes(
43 | "&b&lPhantomWorlds: &7Invalid debug method '%method%'.")
44 | .replace("%method%", parsed)
45 | );
46 |
47 | sender.sendMessage(MessageUtils.colorizeStandardCodes(
48 | "&b&lPhantomWorlds: &7Note: Please do not run this subcommand unless you are sure you are meant to be doing so."));
49 | break;
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/listeners/player/PlayerJoinListener.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.listeners.player;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import me.lokka30.phantomworlds.misc.Utils;
22 | import org.bukkit.Bukkit;
23 | import org.bukkit.World;
24 | import org.bukkit.event.EventHandler;
25 | import org.bukkit.event.Listener;
26 | import org.bukkit.event.player.PlayerJoinEvent;
27 |
28 | /**
29 | * PlayerLoginListener
30 | *
31 | * @author creatorfromhell
32 | * @since 2.0.5.0
33 | */
34 | public class PlayerJoinListener implements Listener {
35 |
36 | final PhantomWorlds plugin;
37 |
38 | public PlayerJoinListener(PhantomWorlds plugin) {
39 | this.plugin = plugin;
40 | }
41 |
42 | @EventHandler
43 | public void onJoin(PlayerJoinEvent event) {
44 | final String spawnWorld = PhantomWorlds.instance().settings.getConfig().getString("spawning.default-world", "world");
45 | final World sWorld = Bukkit.getWorld(spawnWorld);
46 | if(sWorld == null) {
47 | plugin.getLogger().warning("Configured spawn world doesn't exist! Not changing player spawn location.");
48 | return;
49 | }
50 |
51 | //We don't manage so send the player to the spawn world
52 | if(!event.getPlayer().hasPlayedBefore()) {
53 | event.getPlayer().teleport(Utils.parseSpawn(sWorld));
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/listeners/player/PlayerTeleportListener.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.listeners.player;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import org.bukkit.event.EventHandler;
22 | import org.bukkit.event.Listener;
23 | import org.bukkit.event.player.PlayerTeleportEvent;
24 |
25 | /**
26 | * PlayerTeleportEvent
27 | *
28 | * @author creatorfromhell
29 | * @since 2.0.5.0
30 | */
31 | public class PlayerTeleportListener implements Listener {
32 |
33 | final PhantomWorlds plugin;
34 |
35 | public PlayerTeleportListener(PhantomWorlds plugin) {
36 | this.plugin = plugin;
37 | }
38 |
39 | @EventHandler
40 | public void onPortal(PlayerTeleportEvent event) {
41 | if(event.getTo() == null || event.getTo().getWorld() == null || event.getFrom().getWorld() == null) {
42 | return;
43 | }
44 |
45 | if(event.getFrom().getWorld().getUID().equals(event.getTo().getWorld().getUID())) {
46 | return;
47 | }
48 |
49 | final String cfgPath = "worlds-to-load." + event.getTo().getWorld().getName();
50 |
51 | if(PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + ".whitelist", false)
52 | && !event.getPlayer().hasPermission("phantomworlds.world.access." + event.getTo().getWorld().getName())) {
53 | event.setCancelled(true);
54 | return;
55 | }
56 |
57 | if(!event.getPlayer().isOp() && event.getPlayer().hasPermission("phantomworlds.world.deny." + event.getTo().getWorld().getName())) {
58 | event.setCancelled(true);
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/params/AliasWorldParameter.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.params;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.argument.Argument;
21 | import dev.rollczi.litecommands.argument.parser.ParseResult;
22 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.suggestion.SuggestionContext;
25 | import dev.rollczi.litecommands.suggestion.SuggestionResult;
26 | import me.lokka30.phantomworlds.PhantomWorlds;
27 | import org.bukkit.Bukkit;
28 | import org.bukkit.World;
29 | import org.bukkit.command.CommandSender;
30 |
31 | import java.util.ArrayList;
32 | import java.util.List;
33 |
34 | /**
35 | * AliasWorldParameter
36 | *
37 | * @author creatorfromhell
38 | * @since 2.0.5.0
39 | */
40 | public class AliasWorldParameter extends ArgumentResolver {
41 | @Override
42 | protected ParseResult parse(Invocation invocation, Argument context, String argument) {
43 | return ParseResult.success(PhantomWorlds.worldManager().findWorld(argument));
44 | }
45 |
46 | @Override
47 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) {
48 |
49 | final List worlds = new ArrayList<>(PhantomWorlds.worldManager().aliases.keySet());
50 |
51 | for(final World world : Bukkit.getWorlds()) {
52 | worlds.add(world.getName());
53 | }
54 | return SuggestionResult.of(worlds);
55 | }
56 | }
--------------------------------------------------------------------------------
/PW Code Style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/params/PotionEffectParameter.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.params;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.argument.Argument;
21 | import dev.rollczi.litecommands.argument.parser.ParseResult;
22 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.suggestion.SuggestionContext;
25 | import dev.rollczi.litecommands.suggestion.SuggestionResult;
26 | import org.bukkit.command.CommandSender;
27 | import org.bukkit.potion.PotionEffectType;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 |
32 | /**
33 | * PotionEffectParameter
34 | *
35 | * @author creatorfromhell
36 | * @since 2.0.5.0
37 | */
38 | public class PotionEffectParameter extends ArgumentResolver {
39 |
40 | private static final List POTION_EFFECTS = new ArrayList<>();
41 |
42 | static {
43 | for(PotionEffectType value : PotionEffectType.values()) {
44 | POTION_EFFECTS.add(value.getKey() + ",duration,amplifier");
45 | POTION_EFFECTS.add(value.getKey() + ",-1,1");
46 | }
47 | }
48 |
49 | @Override
50 | protected ParseResult parse(Invocation invocation, Argument context, String argument) {
51 | return ParseResult.success(argument);
52 | }
53 |
54 | @Override
55 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) {
56 | return SuggestionResult.of(POTION_EFFECTS);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/params/PortalParameter.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.params;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.argument.Argument;
21 | import dev.rollczi.litecommands.argument.parser.ParseResult;
22 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.suggestion.SuggestionContext;
25 | import dev.rollczi.litecommands.suggestion.SuggestionResult;
26 | import org.bukkit.PortalType;
27 | import org.bukkit.command.CommandSender;
28 |
29 | import java.util.HashMap;
30 | import java.util.Map;
31 |
32 | /**
33 | * PotionEffectParameter
34 | *
35 | * @author creatorfromhell
36 | * @since 2.0.5.0
37 | */
38 | public class PortalParameter extends ArgumentResolver {
39 |
40 | private static final Map PORTAL_ARGUMENTS = new HashMap<>();
41 |
42 | static {
43 | PORTAL_ARGUMENTS.put("end", PortalType.ENDER);
44 | PORTAL_ARGUMENTS.put("nether", PortalType.NETHER);
45 | }
46 |
47 | @Override
48 | protected ParseResult parse(Invocation invocation, Argument context, String argument) {
49 | PortalType gameMode = PORTAL_ARGUMENTS.get(argument.toLowerCase());
50 |
51 | if (gameMode == null) {
52 | return ParseResult.failure("Invalid portal type argument!");
53 | }
54 |
55 | return ParseResult.success(gameMode);
56 | }
57 |
58 | @Override
59 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) {
60 | return SuggestionResult.of(PORTAL_ARGUMENTS.keySet());
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/InfoCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import org.bukkit.command.CommandSender;
23 |
24 | import java.util.Arrays;
25 |
26 | /**
27 | * InfoCommand
28 | *
29 | * @author creatorfromhell
30 | * @since 2.0.5.0
31 | */
32 | public class InfoCommand {
33 |
34 | public static void onCommand(final CommandSender sender) {
35 |
36 | (new MultiMessage(
37 | PhantomWorlds.instance().messages.getConfig()
38 | .getStringList("command.phantomworlds.subcommands.info.success"), Arrays.asList(
39 | new MultiMessage.Placeholder("prefix",
40 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
41 | true),
42 | new MultiMessage.Placeholder("version", PhantomWorlds.instance().getDescription().getVersion(), false),
43 | new MultiMessage.Placeholder("authors",
44 | String.join(PhantomWorlds.instance().messages.getConfig().getString("common.list-delimiter", "&7, &b"),
45 | PhantomWorlds.instance().getDescription().getAuthors()), false),
46 | new MultiMessage.Placeholder("contributors",
47 | String.join(PhantomWorlds.instance().messages.getConfig().getString("common.list-delimiter", "&7, &b"),
48 | PhantomWorlds.CONTRIBUTORS), false),
49 | new MultiMessage.Placeholder("supportedServerVersions", PhantomWorlds.instance().supportedServerVersions,
50 | false)
51 | ))).send(sender);
52 | }
53 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/listeners/player/PlayerPortalListener.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.listeners.player;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import org.bukkit.Bukkit;
22 | import org.bukkit.Location;
23 | import org.bukkit.event.EventHandler;
24 | import org.bukkit.event.Listener;
25 | import org.bukkit.event.player.PlayerPortalEvent;
26 |
27 | import static org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL;
28 |
29 | /**
30 | * EntityPortalListener
31 | *
32 | * @author creatorfromhell
33 | * @since 2.0.5.0
34 | */
35 | public class PlayerPortalListener implements Listener {
36 |
37 | final PhantomWorlds plugin;
38 |
39 | public PlayerPortalListener(PhantomWorlds plugin) {
40 | this.plugin = plugin;
41 | }
42 |
43 | @EventHandler
44 | public void onPortal(PlayerPortalEvent event) {
45 | if(event.getFrom().getWorld() == null) return;
46 |
47 | final String cfgPath = "worlds-to-load." + event.getFrom().getWorld().getName();
48 |
49 | final boolean end = event.getCause().equals(END_PORTAL);
50 | final String config = (end)? ".end" : ".nether";
51 |
52 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath + config)) {
53 | final String to = PhantomWorlds.instance().data.getConfig().getString(cfgPath + config);
54 |
55 | if(to == null || Bukkit.getWorld(to) == null) {
56 | plugin.getLogger().warning("Configured portal world doesn't exist! Not changing player portal location.");
57 | return;
58 | }
59 |
60 | final Location toLocation = event.getTo();
61 | if(toLocation == null) {
62 | plugin.getLogger().warning("Configured portal world doesn't exist! Not changing player portal location.");
63 | return;
64 | }
65 | toLocation.setWorld(Bukkit.getWorld(to));
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/params/GamemodeParameter.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.params;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.argument.Argument;
21 | import dev.rollczi.litecommands.argument.parser.ParseResult;
22 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.suggestion.SuggestionContext;
25 | import dev.rollczi.litecommands.suggestion.SuggestionResult;
26 | import org.bukkit.GameMode;
27 | import org.bukkit.command.CommandSender;
28 |
29 | import java.util.HashMap;
30 | import java.util.Map;
31 |
32 | /**
33 | * PotionEffectParameter
34 | *
35 | * @author creatorfromhell
36 | * @since 2.0.5.0
37 | */
38 | public class GamemodeParameter extends ArgumentResolver {
39 |
40 | private static final Map GAME_MODE_ARGUMENTS = new HashMap<>();
41 |
42 | static {
43 | for (GameMode value : GameMode.values()) {
44 | GAME_MODE_ARGUMENTS.put(value.name().toLowerCase(), value);
45 |
46 | //noinspection deprecation
47 | GAME_MODE_ARGUMENTS.put(String.valueOf(value.getValue()), value);
48 | }
49 | }
50 |
51 | @Override
52 | protected ParseResult parse(Invocation invocation, Argument context, String argument) {
53 | GameMode gameMode = GAME_MODE_ARGUMENTS.get(argument.toLowerCase());
54 |
55 | if (gameMode == null) {
56 | return ParseResult.failure("Invalid gamemode argument!");
57 | }
58 |
59 | return ParseResult.success(gameMode);
60 | }
61 |
62 | @Override
63 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) {
64 | return SuggestionResult.of(GAME_MODE_ARGUMENTS.keySet());
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/BackupCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 |
3 | /*
4 | * Phantom Worlds
5 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU Affero General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU Affero General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | import me.lokka30.microlib.messaging.MultiMessage;
22 | import me.lokka30.phantomworlds.PhantomWorlds;
23 | import me.lokka30.phantomworlds.misc.Utils;
24 | import org.bukkit.World;
25 | import org.bukkit.command.CommandSender;
26 |
27 | import java.util.Arrays;
28 |
29 | /**
30 | * BackupCommand
31 | *
32 | * @author creatorfromhell
33 | * @since 2.0.5.0
34 | */
35 | public class BackupCommand {
36 |
37 | public static void onCommand(final CommandSender sender, final World world) {
38 |
39 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.backup.usage", world)) {
40 | return;
41 | }
42 |
43 | if(!PhantomWorlds.worldManager().backupWorld(world.getName())) {
44 | (new MultiMessage(
45 | PhantomWorlds.instance().messages.getConfig()
46 | .getStringList("command.phantomworlds.subcommands.backup.failure"), Arrays.asList(
47 | new MultiMessage.Placeholder("prefix",
48 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
49 | true),
50 | new MultiMessage.Placeholder("world", world.getName(), false)
51 | ))).send(sender);
52 | }
53 |
54 | (new MultiMessage(
55 | PhantomWorlds.instance().messages.getConfig()
56 | .getStringList("command.phantomworlds.subcommands.backup.success"), Arrays.asList(
57 | new MultiMessage.Placeholder("prefix",
58 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
59 | true),
60 | new MultiMessage.Placeholder("world", world.getName(), false)
61 | ))).send(sender);
62 | }
63 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/params/WorldFolderParameter.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.params;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.argument.Argument;
21 | import dev.rollczi.litecommands.argument.parser.ParseResult;
22 | import dev.rollczi.litecommands.argument.resolver.ArgumentResolver;
23 | import dev.rollczi.litecommands.invocation.Invocation;
24 | import dev.rollczi.litecommands.suggestion.SuggestionContext;
25 | import dev.rollczi.litecommands.suggestion.SuggestionResult;
26 | import me.lokka30.phantomworlds.commandsredux.utils.WorldFolder;
27 | import org.bukkit.Bukkit;
28 | import org.bukkit.command.CommandSender;
29 |
30 | import java.io.File;
31 | import java.util.ArrayList;
32 | import java.util.List;
33 |
34 | /**
35 | * WorldFolderParameter
36 | *
37 | * @author creatorfromhell
38 | * @since 2.0.5.0
39 | */
40 | public class WorldFolderParameter extends ArgumentResolver {
41 | @Override
42 | protected ParseResult parse(Invocation invocation, Argument context, String argument) {
43 | final File directory = Bukkit.getWorldContainer();
44 | final File worldDir = new File(directory, argument);
45 |
46 | if(!worldDir.exists()) {
47 | return ParseResult.failure("Invalid world directory specified!");
48 | }
49 | return ParseResult.success(new WorldFolder(argument));
50 | }
51 |
52 | @Override
53 | public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) {
54 | final List folders = new ArrayList<>();
55 | final File directory = Bukkit.getWorldContainer();
56 |
57 | if(directory.exists()) {
58 | for(File file : directory.listFiles()) {
59 | final File levelDat = new File(file, "level.dat");
60 | if(file.isDirectory() && levelDat.exists()) {
61 | folders.add(file.getName());
62 | }
63 | }
64 | }
65 | return SuggestionResult.of(folders);
66 | }
67 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/set/SetWhitelistCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub.set;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.World;
24 | import org.bukkit.command.CommandSender;
25 | import org.bukkit.entity.Player;
26 |
27 | import java.io.IOException;
28 | import java.util.Arrays;
29 |
30 | /**
31 | * SetWhitelistCommand
32 | *
33 | * @author creatorfromhell
34 | * @since 2.0.5.0
35 | */
36 | public class SetWhitelistCommand {
37 |
38 | public static void onCommand(final CommandSender sender, final World world, final boolean whitelist) {
39 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.setwhitelist.usage", world)) {
40 | return;
41 | }
42 |
43 | final World finalWorld = (world == null)? ((Player)sender).getWorld() : world;
44 |
45 | final String cfgPath = "worlds-to-load." + finalWorld.getName();
46 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath)) {
47 | //PhantomWorlds manages this world so let's set the spawn here for better accuracy.
48 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".whitelist", whitelist);
49 |
50 | try {
51 | PhantomWorlds.instance().data.save();
52 | } catch(final IOException ex) {
53 | throw new RuntimeException(ex);
54 | }
55 |
56 | }
57 |
58 | (new MultiMessage(
59 | PhantomWorlds.instance().messages.getConfig()
60 | .getStringList("command.phantomworlds.subcommands.setwhitelist.success"), Arrays.asList(
61 | new MultiMessage.Placeholder("prefix",
62 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
63 | true),
64 | new MultiMessage.Placeholder("world", finalWorld.getName(), false),
65 | new MultiMessage.Placeholder("whitelist", whitelist + "", false)
66 | ))).send(sender);
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/UnloadCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.World;
24 | import org.bukkit.command.CommandSender;
25 | import org.bukkit.entity.Player;
26 |
27 | import java.util.Arrays;
28 |
29 | /**
30 | * UnloadCommand
31 | *
32 | * @author creatorfromhell
33 | * @since 2.0.5.0
34 | */
35 | public class UnloadCommand {
36 |
37 | public static void onCommand(final CommandSender sender, final World world) {
38 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.unload.usage", world)) {
39 | return;
40 | }
41 |
42 | if(sender instanceof Player) {
43 |
44 | if(world.getPlayers().contains((Player)sender)) {
45 | (new MultiMessage(
46 | PhantomWorlds.instance().messages.getConfig().getStringList(
47 | "command.phantomworlds.subcommands.unload.in-specified-world"),
48 | Arrays.asList(
49 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
50 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
51 | new MultiMessage.Placeholder("world", world.getName(), false)
52 | ))).send(sender);
53 | return;
54 | }
55 | }
56 |
57 | //noinspection ConstantConditions
58 | Utils.unloadWorld(world);
59 |
60 | (new MultiMessage(
61 | PhantomWorlds.instance().messages.getConfig()
62 | .getStringList("command.phantomworlds.subcommands.unload.success"), Arrays.asList(
63 | new MultiMessage.Placeholder("prefix",
64 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
65 | true),
66 | new MultiMessage.Placeholder("world", world.getName(), false)
67 | ))).send(sender);
68 | }
69 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/set/SetGamemodeCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub.set;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.GameMode;
24 | import org.bukkit.World;
25 | import org.bukkit.command.CommandSender;
26 | import org.bukkit.entity.Player;
27 |
28 | import java.io.IOException;
29 | import java.util.Arrays;
30 |
31 | /**
32 | * SetGamemodeCommand
33 | *
34 | * @author creatorfromhell
35 | * @since 2.0.5.0
36 | */
37 | public class SetGamemodeCommand {
38 |
39 | public static void onCommand(final CommandSender sender, final World world, final GameMode mode) {
40 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.setgamemode.usage", world)) {
41 | return;
42 | }
43 |
44 | final World finalWorld = (world == null)? ((Player)sender).getWorld() : world;
45 |
46 | final String cfgPath = "worlds-to-load." + finalWorld.getName();
47 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath)) {
48 | //PhantomWorlds manages this world so let's set the spawn here for better accuracy.
49 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".gameMode", mode.name());
50 |
51 | try {
52 | PhantomWorlds.instance().data.save();
53 | } catch(final IOException ex) {
54 | throw new RuntimeException(ex);
55 | }
56 |
57 | }
58 |
59 | (new MultiMessage(
60 | PhantomWorlds.instance().messages.getConfig()
61 | .getStringList("command.phantomworlds.subcommands.setgamemode.success"), Arrays.asList(
62 | new MultiMessage.Placeholder("prefix",
63 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
64 | true),
65 | new MultiMessage.Placeholder("world", finalWorld.getName(), false),
66 | new MultiMessage.Placeholder("gamemode", mode.name(), false)
67 | ))).send(sender);
68 | }
69 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/ReloadCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import org.bukkit.command.CommandSender;
23 |
24 | import java.util.Collections;
25 |
26 | /**
27 | * ReloadCommand
28 | *
29 | * @author creatorfromhell
30 | * @since 2.0.5.0
31 | */
32 | public class ReloadCommand {
33 |
34 | public static void onCommand(final CommandSender sender) {
35 | (new MultiMessage(
36 | PhantomWorlds.instance().messages.getConfig()
37 | .getStringList("command.phantomworlds.subcommands.reload.reloading-files"),
38 | Collections.singletonList(
39 | new MultiMessage.Placeholder("prefix",
40 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
41 | true)
42 | ))).send(sender);
43 |
44 | PhantomWorlds.instance().loadFiles();
45 |
46 | (new MultiMessage(
47 | PhantomWorlds.instance().messages.getConfig()
48 | .getStringList("command.phantomworlds.subcommands.reload.reloading-worlds"),
49 | Collections.singletonList(
50 | new MultiMessage.Placeholder("prefix",
51 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
52 | true)
53 | ))).send(sender);
54 |
55 | PhantomWorlds.instance().loadWorlds();
56 |
57 | (new MultiMessage(
58 | PhantomWorlds.instance().messages.getConfig()
59 | .getStringList("command.phantomworlds.subcommands.reload.reload-complete"),
60 | Collections.singletonList(
61 | new MultiMessage.Placeholder("prefix",
62 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
63 | true)
64 | ))).send(sender);
65 | }
66 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/set/SetPortalCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub.set;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.PortalType;
24 | import org.bukkit.World;
25 | import org.bukkit.command.CommandSender;
26 | import org.bukkit.entity.Player;
27 |
28 | import java.io.IOException;
29 | import java.util.Arrays;
30 |
31 | /**
32 | * SetPortalCommand
33 | *
34 | * @author creatorfromhell
35 | * @since 2.0.5.0
36 | */
37 | public class SetPortalCommand {
38 |
39 | public static void onCommand(final CommandSender sender, final World world, final PortalType portal, final World worldTo) {
40 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.setportal.usage", world)) {
41 | return;
42 | }
43 |
44 | final String type = (portal.equals(PortalType.ENDER))? "end" : "nether";
45 |
46 | final World finalWorld = (world == null)? ((Player)sender).getWorld() : world;
47 |
48 | final String cfgPath = "worlds-to-load." + finalWorld.getName();
49 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath)) {
50 | //PhantomWorlds manages this world so let's set the spawn here for better accuracy.
51 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "." + type, worldTo.getName());
52 |
53 | try {
54 | PhantomWorlds.instance().data.save();
55 | } catch(final IOException ex) {
56 | throw new RuntimeException(ex);
57 | }
58 |
59 | }
60 |
61 | (new MultiMessage(
62 | PhantomWorlds.instance().messages.getConfig()
63 | .getStringList("command.phantomworlds.subcommands.setportal.success"), Arrays.asList(
64 | new MultiMessage.Placeholder("prefix",
65 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
66 | true),
67 | new MultiMessage.Placeholder("world", finalWorld.getName(), false),
68 | new MultiMessage.Placeholder("portal", portal.name(), false),
69 | new MultiMessage.Placeholder("world_to", worldTo.getName(), false)
70 | ))).send(sender);
71 | }
72 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/DeleteCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.World;
24 | import org.bukkit.command.CommandSender;
25 | import org.bukkit.entity.Player;
26 |
27 | import java.util.Arrays;
28 |
29 | /**
30 | * DeleteCommand
31 | *
32 | * @author creatorfromhell
33 | * @since 2.0.5.0
34 | */
35 | public class DeleteCommand {
36 |
37 | public static void onCommand(final CommandSender sender, final World world) {
38 |
39 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.delete.usage", world)) {
40 | return;
41 | }
42 |
43 | if(sender instanceof Player) {
44 |
45 | if(world.getPlayers().contains((Player)sender)) {
46 | (new MultiMessage(
47 | PhantomWorlds.instance().messages.getConfig().getStringList(
48 | "command.phantomworlds.subcommands.unload.in-specified-world"),
49 | Arrays.asList(
50 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
51 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
52 | new MultiMessage.Placeholder("world", world.getName(), false)
53 | ))).send(sender);
54 | return;
55 | }
56 | }
57 |
58 | if(!PhantomWorlds.worldManager().backupAndDeleteWorld(world.getName())) {
59 | (new MultiMessage(
60 | PhantomWorlds.instance().messages.getConfig()
61 | .getStringList("command.phantomworlds.subcommands.delete.failure"), Arrays.asList(
62 | new MultiMessage.Placeholder("prefix",
63 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
64 | true),
65 | new MultiMessage.Placeholder("world", world.getName(), false)
66 | ))).send(sender);
67 | }
68 |
69 | (new MultiMessage(
70 | PhantomWorlds.instance().messages.getConfig()
71 | .getStringList("command.phantomworlds.subcommands.delete.success"), Arrays.asList(
72 | new MultiMessage.Placeholder("prefix",
73 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
74 | true),
75 | new MultiMessage.Placeholder("world", world.getName(), false)
76 | ))).send(sender);
77 | }
78 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/set/SetEffectsCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub.set;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.World;
24 | import org.bukkit.command.CommandSender;
25 | import org.bukkit.entity.Player;
26 |
27 | import java.io.IOException;
28 | import java.util.Arrays;
29 | import java.util.List;
30 |
31 | /**
32 | * SetEffectsCommand
33 | *
34 | * @author creatorfromhell
35 | * @since 2.0.5.0
36 | */
37 | public class SetEffectsCommand {
38 | public static void onCommand(final CommandSender sender, final World world, final List effects) {
39 | if(!Utils.checkWorld(sender, "command.phantomworlds.subcommands.seteffects.usage", world)) {
40 | return;
41 | }
42 |
43 | final StringBuilder eff = new StringBuilder();
44 |
45 | final World finalWorld = (world == null)? ((Player)sender).getWorld() : world;
46 |
47 | final String cfgPath = "worlds-to-load." + finalWorld.getName();
48 |
49 | for(String effString : effects) {
50 |
51 | if(eff.length() > 0) {
52 | eff.append(", ");
53 | }
54 |
55 | final String[] effSettings = effString.split(",");
56 |
57 | int duration = -1;
58 | if(effSettings.length > 1) {
59 | try {
60 | duration = Integer.parseInt(effSettings[1]);
61 | } catch(NumberFormatException ignore) {
62 | }
63 | }
64 |
65 |
66 | int amplifier = 1;
67 | if(effSettings.length > 2) {
68 | try {
69 | amplifier = Integer.parseInt(effSettings[2]);
70 | } catch(NumberFormatException ignore) {
71 | }
72 | }
73 |
74 | eff.append(effSettings[0]);
75 |
76 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".effects." + effSettings[0] + ".duration", duration);
77 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".effects." + effSettings[0] + ".amplifier", amplifier);
78 | }
79 |
80 | try {
81 | PhantomWorlds.instance().data.save();
82 | } catch(final IOException ex) {
83 | throw new RuntimeException(ex);
84 | }
85 |
86 | (new MultiMessage(
87 | PhantomWorlds.instance().messages.getConfig()
88 | .getStringList("command.phantomworlds.subcommands.seteffects.success"), Arrays.asList(
89 | new MultiMessage.Placeholder("prefix",
90 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
91 | true),
92 | new MultiMessage.Placeholder("world", finalWorld.getName(), false),
93 | new MultiMessage.Placeholder("effects", eff.toString(), false)
94 | ))).send(sender);
95 | }
96 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/ImportCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.world.PhantomWorld;
23 | import org.bukkit.GameMode;
24 | import org.bukkit.World;
25 | import org.bukkit.command.CommandSender;
26 |
27 | import java.util.Arrays;
28 | import java.util.Collections;
29 |
30 | /**
31 | * ImportCommand
32 | *
33 | * @author creatorfromhell
34 | * @since 2.0.5.0
35 | */
36 | public class ImportCommand {
37 |
38 | public static void onCommand(final CommandSender sender, final World world) {
39 |
40 | if(world == null) {
41 | (new MultiMessage(
42 | PhantomWorlds.instance().messages.getConfig().getStringList(
43 | "command.phantomworlds.subcommands.import.failure-exist"),
44 | Collections.singletonList(
45 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
46 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true)
47 | ))).send(sender);
48 | return;
49 | }
50 |
51 | final String cfgPath = "worlds-to-load." + world.getName() + ".";
52 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath)) {
53 | (new MultiMessage(
54 | PhantomWorlds.instance().messages.getConfig().getStringList(
55 | "command.phantomworlds.subcommands.import.failure-already"),
56 | Arrays.asList(
57 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
58 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
59 | new MultiMessage.Placeholder("world", world.getName(), false)
60 | ))).send(sender);
61 | return;
62 | }
63 |
64 | final PhantomWorld pworld = new PhantomWorld(
65 | world.getName(), world.getEnvironment(), world.canGenerateStructures(), null,
66 | null, world.isHardcore(), world.getSeed(), world.getWorldType(), world.getAllowMonsters(),
67 | world.getAllowAnimals(), world.getKeepSpawnInMemory(), world.getPVP(), world.getDifficulty(), GameMode.SURVIVAL
68 | );
69 | pworld.save();
70 | (new MultiMessage(
71 | PhantomWorlds.instance().messages.getConfig().getStringList(
72 | "command.phantomworlds.subcommands.import.success"),
73 | Arrays.asList(
74 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
75 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
76 | new MultiMessage.Placeholder("world", world.getName(), false)
77 | ))).send(sender);
78 | }
79 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/CompatibilityCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.CompatibilityChecker;
23 | import org.bukkit.command.CommandSender;
24 |
25 | import java.util.Arrays;
26 | import java.util.Collections;
27 |
28 | /**
29 | * CompatibilityCommand
30 | *
31 | * @author creatorfromhell
32 | * @since 2.0.5.0
33 | */
34 | public class CompatibilityCommand {
35 |
36 | public static void onCommand(final CommandSender sender) {
37 | (new MultiMessage(
38 | PhantomWorlds.instance().messages.getConfig()
39 | .getStringList("command.phantomworlds.subcommands.compatibility.start"),
40 | Collections.singletonList(
41 | new MultiMessage.Placeholder("prefix",
42 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
43 | true)
44 | ))).send(sender);
45 |
46 | PhantomWorlds.instance().compatibilityChecker.checkAll();
47 |
48 | if(PhantomWorlds.instance().compatibilityChecker.incompatibilities.isEmpty()) {
49 | (new MultiMessage(
50 | PhantomWorlds.instance().messages.getConfig()
51 | .getStringList("command.phantomworlds.subcommands.compatibility.found-none"),
52 | Collections.singletonList(
53 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
54 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true)
55 | ))).send(sender);
56 | return;
57 | }
58 |
59 | (new MultiMessage(
60 | PhantomWorlds.instance().messages.getConfig()
61 | .getStringList("command.phantomworlds.subcommands.compatibility.found"),
62 | Arrays.asList(
63 | new MultiMessage.Placeholder("prefix",
64 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
65 | true),
66 | new MultiMessage.Placeholder("amount",
67 | String.valueOf(PhantomWorlds.instance().compatibilityChecker.incompatibilities.size()), false)
68 | ))).send(sender);
69 |
70 | for(int i = 0; i < PhantomWorlds.instance().compatibilityChecker.incompatibilities.size(); i++) {
71 | CompatibilityChecker.Incompatibility incompatibility = PhantomWorlds.instance().compatibilityChecker.incompatibilities.get(
72 | i);
73 |
74 | (new MultiMessage(
75 | PhantomWorlds.instance().messages.getConfig()
76 | .getStringList("command.phantomworlds.subcommands.compatibility.entry"),
77 | Arrays.asList(
78 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
79 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
80 | new MultiMessage.Placeholder("index", String.valueOf(i + 1), false),
81 | new MultiMessage.Placeholder("type", incompatibility.type.toString(), false),
82 | new MultiMessage.Placeholder("reason", incompatibility.reason, true),
83 | new MultiMessage.Placeholder("recommendation", incompatibility.recommendation,
84 | true)
85 | ))).send(sender);
86 | }
87 | }
88 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/listeners/player/PlayerChangeWorldListener.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.listeners.player;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import org.bukkit.GameMode;
22 | import org.bukkit.Location;
23 | import org.bukkit.NamespacedKey;
24 | import org.bukkit.event.EventHandler;
25 | import org.bukkit.event.Listener;
26 | import org.bukkit.event.player.PlayerChangedWorldEvent;
27 | import org.bukkit.potion.PotionEffect;
28 | import org.bukkit.potion.PotionEffectType;
29 |
30 | /**
31 | * PlayerChangeWorldListener
32 | *
33 | * @author creatorfromhell
34 | * @since 2.0.5.0
35 | */
36 | public class PlayerChangeWorldListener implements Listener {
37 |
38 | final PhantomWorlds plugin;
39 |
40 | public PlayerChangeWorldListener(PhantomWorlds plugin) {
41 | this.plugin = plugin;
42 | }
43 |
44 | @EventHandler
45 | public void onChangeWorld(PlayerChangedWorldEvent event) {
46 |
47 | //Check if this world has a PhantomWorlds managed spawn. If so, teleport the player there.
48 | final String spawnPath = "worlds-to-load." + event.getPlayer().getWorld().getName() + ".spawn";
49 | if(PhantomWorlds.instance().settings.getConfig().getBoolean("spawning.change", false) && PhantomWorlds.instance().data.getConfig().contains(spawnPath)) {
50 | final double x = PhantomWorlds.instance().data.getConfig().getDouble(spawnPath + ".x", event.getPlayer().getWorld().getSpawnLocation().getX());
51 | final double y = PhantomWorlds.instance().data.getConfig().getDouble(spawnPath + ".y", event.getPlayer().getWorld().getSpawnLocation().getY());
52 | final double z = PhantomWorlds.instance().data.getConfig().getDouble(spawnPath + ".z", event.getPlayer().getWorld().getSpawnLocation().getZ());
53 | final float yaw = (float)PhantomWorlds.instance().data.getConfig().getDouble(spawnPath + ".yaw", event.getPlayer().getWorld().getSpawnLocation().getYaw());
54 | final float pitch = (float)PhantomWorlds.instance().data.getConfig().getDouble(spawnPath + ".pitch", event.getPlayer().getWorld().getSpawnLocation().getPitch());
55 |
56 | event.getPlayer().teleport(new Location(event.getPlayer().getWorld(), x, y, z, yaw, pitch));
57 | }
58 |
59 | final String cfgPath = "worlds-to-load." + event.getPlayer().getWorld().getName();
60 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath + ".gameMode") && !event.getPlayer().hasPermission("phantomworlds.world.bypass.gamemode")) {
61 | final GameMode mode = GameMode.valueOf(PhantomWorlds.instance().data.getConfig().getString(cfgPath + ".gameMode"));
62 | event.getPlayer().setGameMode(mode);
63 | }
64 |
65 | final String cfgPrevPath = "worlds-to-load." + event.getFrom().getName();
66 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPrevPath + ".effects") &&
67 | PhantomWorlds.instance().data.getConfig().isConfigurationSection(cfgPrevPath + ".effects")) {
68 | for(final String effName : PhantomWorlds.instance().data.getConfig().getConfigurationSection(cfgPrevPath + ".effects").getKeys(false)) {
69 |
70 | final PotionEffectType type = PotionEffectType.getByKey(NamespacedKey.fromString(effName));
71 | if(type != null) {
72 | event.getPlayer().removePotionEffect(type);
73 | }
74 | }
75 | }
76 |
77 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath + ".effects") &&
78 | PhantomWorlds.instance().data.getConfig().isConfigurationSection(cfgPath + ".effects") && !event.getPlayer().hasPermission("phantomworlds.world.bypass.effects")) {
79 |
80 | for(final String effName : PhantomWorlds.instance().data.getConfig().getConfigurationSection(cfgPath + ".effects").getKeys(false)) {
81 | final int duration = PhantomWorlds.instance().data.getConfig().getInt(cfgPath + ".effects." + effName + ".duration", -1);
82 | final int amplifier = PhantomWorlds.instance().data.getConfig().getInt(cfgPath + ".effects." + effName + ".amplifier", 1);
83 |
84 | final PotionEffectType type = PotionEffectType.getByKey(NamespacedKey.fromString(effName));
85 | if(type != null) {
86 | final PotionEffect effect = new PotionEffect(type, duration, amplifier);
87 | event.getPlayer().addPotionEffect(effect);
88 | }
89 | }
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/LoadCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.commandsredux.utils.WorldFolder;
23 | import me.lokka30.phantomworlds.misc.WorldLoadResponse;
24 | import org.bukkit.command.CommandSender;
25 |
26 | import java.util.Arrays;
27 |
28 | import static me.lokka30.phantomworlds.misc.WorldLoadResponse.ALREADY_LOADED;
29 | import static me.lokka30.phantomworlds.misc.WorldLoadResponse.INVALID;
30 | import static me.lokka30.phantomworlds.misc.WorldLoadResponse.LOADED;
31 |
32 | /**
33 | * LoadCommand
34 | *
35 | * @author creatorfromhell
36 | * @since 2.0.5.0
37 | */
38 | public class LoadCommand {
39 |
40 | public static void onCommand(final CommandSender sender, final WorldFolder world) {
41 |
42 | if(world == null || world.getFolder() == null) {
43 | (new MultiMessage(
44 | PhantomWorlds.instance().messages.getConfig()
45 | .getStringList("command.phantomworlds.usages.load"), Arrays.asList(
46 | new MultiMessage.Placeholder("prefix",
47 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
48 | true),
49 | new MultiMessage.Placeholder("label", "pw", false)
50 | ))).send(sender);
51 | return;
52 | }
53 |
54 | final WorldLoadResponse response = PhantomWorlds.worldManager().loadWorld(world.getFolder());
55 |
56 | if(response == ALREADY_LOADED) {
57 | (new MultiMessage(
58 | PhantomWorlds.instance().messages.getConfig()
59 | .getStringList("command.phantomworlds.subcommands.create.already-loaded"),
60 | Arrays.asList(
61 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
62 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
63 | new MultiMessage.Placeholder("world", world.getFolder(), false),
64 | new MultiMessage.Placeholder("label", "pw", false)
65 | ))).send(sender);
66 | return;
67 | }
68 |
69 | if(response == INVALID) {
70 | (new MultiMessage(
71 | PhantomWorlds.instance().messages.getConfig()
72 | .getStringList("command.phantomworlds.subcommands.create.failure-folder"),
73 | Arrays.asList(
74 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
75 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
76 | new MultiMessage.Placeholder("world", world.getFolder(), false),
77 | new MultiMessage.Placeholder("label", "pw", false)
78 | ))).send(sender);
79 | return;
80 | }
81 |
82 | if(response != LOADED) {
83 |
84 | (new MultiMessage(
85 | PhantomWorlds.instance().messages.getConfig()
86 | .getStringList("command.phantomworlds.subcommands.create.failure-loading"),
87 | Arrays.asList(
88 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
89 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
90 | new MultiMessage.Placeholder("world", world.getFolder(), false),
91 | new MultiMessage.Placeholder("label", "pw", false)
92 | ))).send(sender);
93 | return;
94 | }
95 |
96 | (new MultiMessage(
97 | PhantomWorlds.instance().messages.getConfig().getStringList(
98 | "command.phantomworlds.subcommands.load.success"),
99 | Arrays.asList(
100 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
101 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
102 | new MultiMessage.Placeholder("world", world.getFolder(), false)
103 | ))).send(sender);
104 | }
105 | }
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | # .___ _ . . __ . _
2 | # / \ / ___ , __ _/_ __. , _ , _ / | __. .___ | ___/ ____
3 | # |,_-' |,---. / ` |' `. | .' \ |' `|' `. | | .' \ / \ | / | (
4 | # | |' ` | | | | | | | | | | | /\ / | | | ' | ,' | `--.
5 | # / / | `.__/| / | \__/ `._.' / ' / |,' \,' `._.' / /\__ `___,' \___.'
6 |
7 | name: 'PhantomWorlds'
8 | version: '2.05'
9 | description: 'The Robust World Manager for Minecraft Servers'
10 | authors: [ 'creatorfromhell', 'lokka30' ]
11 | website: 'https://github.com/lokka30/PhantomWorlds'
12 |
13 | main: 'me.lokka30.phantomworlds.PhantomWorlds'
14 | api-version: '1.13'
15 | load: STARTUP
16 |
17 | commands:
18 | phantomworlds:
19 | description: 'Create, manage or teleport to worlds.'
20 | aliases: [ 'pw', 'world' ]
21 | usage: '/'
22 |
23 | permissions:
24 | phantomworlds.*:
25 | default: op
26 | description: 'All PhantomWorlds permissions, ideally given to administrators.'
27 | children:
28 | phantomworlds.knows-vanished-users: true
29 | phantomworlds.command.phantomworlds.*: true
30 |
31 |
32 | phantomworlds.world.bypass.gamemode:
33 | default: op
34 | description: 'Used to bypass the gamemode setting for worlds.'
35 |
36 |
37 | phantomworlds.world.bypass.effects:
38 | default: op
39 | description: 'Used to bypass the effects setting for worlds.'
40 |
41 | phantomworlds.knows-vanished-users:
42 | default: op
43 | description: 'Users with this permission will ignore the status of vanished players when using commands from PhantomWorlds, such as in tab-completion suggestions.'
44 |
45 | phantomworlds.command.phantomworlds.*:
46 | default: op
47 | description: 'Ability to run all /pw commands.'
48 | children:
49 | phantomworlds.command.phantomworlds: true
50 | phantomworlds.command.phantomworlds.backup: true
51 | phantomworlds.command.phantomworlds.compatibility: true
52 | phantomworlds.command.phantomworlds.create: true
53 | phantomworlds.command.phantomworlds.debug: true
54 | phantomworlds.command.phantomworlds.import: true
55 | phantomworlds.command.phantomworlds.info: true
56 | phantomworlds.command.phantomworlds.list: true
57 | phantomworlds.command.phantomworlds.load: true
58 | phantomworlds.command.phantomworlds.setspawn: true
59 | phantomworlds.command.phantomworlds.set.effects: true
60 | phantomworlds.command.phantomworlds.set.gamemode: true
61 | phantomworlds.command.phantomworlds.set.portal: true
62 | phantomworlds.command.phantomworlds.set.whitelist: true
63 | phantomworlds.command.phantomworlds.teleport: true
64 | phantomworlds.command.phantomworlds.spawn: true
65 | phantomworlds.command.phantomworlds.unload: true
66 | phantomworlds.command.phantomworlds.reload: true
67 |
68 | phantomworlds.command.phantomworlds:
69 | default: op
70 | description: 'Ability to run /pw'
71 |
72 | phantomworlds.command.phantomworlds.backup:
73 | default: op
74 | description: 'Ability to run /pw backup'
75 |
76 | phantomworlds.command.phantomworlds.compatibility:
77 | default: op
78 | description: 'Ability to run /pw compatibility'
79 |
80 | phantomworlds.command.phantomworlds.debug:
81 | default: op
82 | description: 'Ability to run /pw debug'
83 |
84 | phantomworlds.command.phantomworlds.create:
85 | default: op
86 | description: 'Ability to run /pw create'
87 |
88 | phantomworlds.command.phantomworlds.import:
89 | default: op
90 | description: 'Ability to run /pw import'
91 |
92 | phantomworlds.command.phantomworlds.info:
93 | default: true
94 | description: 'Ability to run /pw info'
95 |
96 | phantomworlds.command.phantomworlds.list:
97 | default: op
98 | description: 'Ability to run /pw list'
99 |
100 | phantomworlds.command.phantomworlds.load:
101 | default: op
102 | description: 'Ability to run /pw load'
103 |
104 | phantomworlds.command.phantomworlds.setspawn:
105 | default: op
106 | description: 'Ability to run /pw setspawn'
107 |
108 | phantomworlds.command.phantomworlds.set.effects:
109 | default: op
110 | description: 'Ability to run /pw set effects'
111 |
112 | phantomworlds.command.phantomworlds.set.gamemode:
113 | default: op
114 | description: 'Ability to run /pw set gamemode'
115 |
116 | phantomworlds.command.phantomworlds.set.portal:
117 | default: op
118 | description: 'Ability to run /pw set portal'
119 |
120 | phantomworlds.command.phantomworlds.set.whitelist:
121 | default: op
122 | description: 'Ability to run /pw set whitelist'
123 |
124 | phantomworlds.command.phantomworlds.teleport:
125 | default: op
126 | description: 'Ability to run /pw teleport'
127 |
128 | phantomworlds.command.phantomworlds.spawn:
129 | default: op
130 | description: 'Ability to run /pw spawn'
131 |
132 | phantomworlds.command.phantomworlds.unload:
133 | default: op
134 | description: 'Ability to run /pw unload'
135 |
136 | phantomworlds.command.phantomworlds.reload:
137 | default: op
138 | description: 'Ability to run /pw reload'
139 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/SetSpawnCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import me.lokka30.phantomworlds.misc.Utils;
23 | import org.bukkit.Location;
24 | import org.bukkit.World;
25 | import org.bukkit.command.CommandSender;
26 | import org.bukkit.entity.Player;
27 |
28 | import java.io.IOException;
29 | import java.util.Arrays;
30 |
31 | /**
32 | * SetSpawnCommand
33 | *
34 | * @author creatorfromhell
35 | * @since 2.0.5.0
36 | */
37 | public class SetSpawnCommand {
38 |
39 | public static void onCommand(final CommandSender sender, Double x, Double y, Double z, World world, Float yaw, Float pitch) {
40 |
41 | if(!(sender instanceof Player)) {
42 | if(x == null || y == null || z == null || world == null) {
43 | (new MultiMessage(
44 | PhantomWorlds.instance().messages.getConfig()
45 | .getStringList("command.phantomworlds.subcommands.setspawn.usage-console"),
46 | Arrays.asList(
47 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
48 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
49 | new MultiMessage.Placeholder("label", "setspawn", false)
50 | ))).send(sender);
51 | return;
52 | }
53 | }
54 |
55 | final Player player = (Player)sender;
56 |
57 | final World finalWorld = (world == null)? ((Player)sender).getWorld() : world;
58 | final double finalX = (x == null)? ((Player)sender).getLocation().getX() : x;
59 | final double finalY = (y == null)? ((Player)sender).getLocation().getY() : y;
60 | final double finalZ = (z == null)? ((Player)sender).getLocation().getZ() : z;
61 | float finalYaw = (yaw == null)? 0 : yaw;
62 | float finalPitch = (pitch == null)? 0 : pitch;
63 |
64 | if(yaw == null && sender instanceof Player) {
65 | finalYaw = ((Player)sender).getLocation().getYaw();
66 | }
67 |
68 | if(pitch == null && sender instanceof Player) {
69 | finalPitch = ((Player)sender).getLocation().getPitch();
70 | }
71 |
72 | final String cfgPath = "worlds-to-load." + finalWorld.getName();
73 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath)) {
74 | //PhantomWorlds manages this world so let's set the spawn here for better accuracy.
75 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".spawn.x", finalX);
76 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".spawn.y", finalY);
77 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".spawn.z", finalZ);
78 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".spawn.yaw", finalYaw);
79 | PhantomWorlds.instance().data.getConfig().set(cfgPath + ".spawn.pitch", finalPitch);
80 |
81 | try {
82 | PhantomWorlds.instance().data.save();
83 | } catch(final IOException ex) {
84 | throw new RuntimeException(ex);
85 | }
86 |
87 | } else {
88 | //PhantomWorlds doesn't manage the spawn here so let Mojang deal with it.
89 | try {
90 | finalWorld.setSpawnLocation(new Location(finalWorld, finalX, finalY, finalZ, finalYaw, finalPitch));
91 | } catch(NoSuchMethodError err) {
92 | //This is dumb that the setSpawn method in spigot uses integers... great design.
93 | finalWorld.setSpawnLocation((int)finalX, (int)finalY, (int)finalZ);
94 | // 1.8 doesn't let us set pitch and yaw ... yawn
95 | }
96 | }
97 |
98 | (new MultiMessage(
99 | PhantomWorlds.instance().messages.getConfig()
100 | .getStringList("command.phantomworlds.subcommands.setspawn.success"), Arrays.asList(
101 | new MultiMessage.Placeholder("prefix",
102 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
103 | true),
104 | new MultiMessage.Placeholder("world", finalWorld.getName(), false),
105 | new MultiMessage.Placeholder("x", String.valueOf(Utils.roundTwoDecimalPlaces(finalX)), false),
106 | new MultiMessage.Placeholder("y", String.valueOf(Utils.roundTwoDecimalPlaces(finalY)), false),
107 | new MultiMessage.Placeholder("z", String.valueOf(Utils.roundTwoDecimalPlaces(finalZ)), false),
108 | new MultiMessage.Placeholder("yaw", String.valueOf(Utils.roundTwoDecimalPlaces(finalYaw)), false),
109 | new MultiMessage.Placeholder("pitch", String.valueOf(Utils.roundTwoDecimalPlaces(finalPitch)), false)
110 | ))).send(sender);
111 | }
112 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/ListCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.messaging.MultiMessage;
21 | import me.lokka30.phantomworlds.PhantomWorlds;
22 | import org.bukkit.Bukkit;
23 | import org.bukkit.World;
24 | import org.bukkit.command.CommandSender;
25 |
26 | import java.io.File;
27 | import java.util.Arrays;
28 | import java.util.HashSet;
29 |
30 | /**
31 | * ListCommand
32 | *
33 | * @author creatorfromhell
34 | * @since 2.0.5.0
35 | */
36 | public class ListCommand {
37 |
38 | public static void onCommand(final CommandSender sender) {
39 | (new MultiMessage(
40 | PhantomWorlds.instance().messages.getConfig()
41 | .getStringList("command.phantomworlds.subcommands.list.header-loaded"), Arrays.asList(
42 | new MultiMessage.Placeholder("prefix",
43 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
44 | true),
45 | new MultiMessage.Placeholder("amount", String.valueOf(Bukkit.getWorlds().size()), false)
46 | ))).send(sender);
47 |
48 | final HashSet loaded = new HashSet<>();
49 |
50 | //TODO: archived, last backup times.
51 | for(final World world : Bukkit.getWorlds()) {
52 | loaded.add(world.getName());
53 | }
54 |
55 | for(String world : loaded) {
56 | (new MultiMessage(
57 | PhantomWorlds.instance().messages.getConfig()
58 | .getStringList("command.phantomworlds.subcommands.list.entry"), Arrays.asList(
59 | new MultiMessage.Placeholder("prefix",
60 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
61 | true),
62 | new MultiMessage.Placeholder("world", world, false)
63 | ))).send(sender);
64 | }
65 |
66 | final HashSet unloaded = new HashSet<>();
67 | final File directory = Bukkit.getWorldContainer();
68 |
69 | for(File file : directory.listFiles()) {
70 | if(file.isDirectory() && !loaded.contains(file.getName())) {
71 | final File levelDat = new File(file, "level.dat");
72 | if(levelDat.exists()) {
73 | unloaded.add(file.getName());
74 | }
75 | }
76 | }
77 |
78 | (new MultiMessage(
79 | PhantomWorlds.instance().messages.getConfig()
80 | .getStringList("command.phantomworlds.subcommands.list.header-unloaded"), Arrays.asList(
81 | new MultiMessage.Placeholder("prefix",
82 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
83 | true),
84 | new MultiMessage.Placeholder("amount", String.valueOf(unloaded.size()), false)
85 | ))).send(sender);
86 |
87 | for(String world : unloaded) {
88 | (new MultiMessage(
89 | PhantomWorlds.instance().messages.getConfig()
90 | .getStringList("command.phantomworlds.subcommands.list.entry"), Arrays.asList(
91 | new MultiMessage.Placeholder("prefix",
92 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
93 | true),
94 | new MultiMessage.Placeholder("world", world, false)
95 | ))).send(sender);
96 | }
97 |
98 | final HashSet archived = new HashSet<>();
99 | final File dir = new File(PhantomWorlds.instance().getDataFolder(), PhantomWorlds.BACKUP_FOLDER);
100 | for(File file : dir.listFiles()) {
101 | if(file.isDirectory() && !loaded.contains(file.getName()) && !unloaded.contains(file.getName())) {
102 | archived.add(file.getName());
103 | }
104 | }
105 |
106 | (new MultiMessage(
107 | PhantomWorlds.instance().messages.getConfig()
108 | .getStringList("command.phantomworlds.subcommands.list.header-archived"), Arrays.asList(
109 | new MultiMessage.Placeholder("prefix",
110 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
111 | true),
112 | new MultiMessage.Placeholder("amount", String.valueOf(archived.size()), false)
113 | ))).send(sender);
114 |
115 | for(String world : archived) {
116 | (new MultiMessage(
117 | PhantomWorlds.instance().messages.getConfig()
118 | .getStringList("command.phantomworlds.subcommands.list.entry"), Arrays.asList(
119 | new MultiMessage.Placeholder("prefix",
120 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
121 | true),
122 | new MultiMessage.Placeholder("world", world, false)
123 | ))).send(sender);
124 | }
125 | }
126 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/managers/FileManager.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.managers;
2 |
3 | import me.lokka30.phantomworlds.PhantomWorlds;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.World;
6 |
7 | import java.io.IOException;
8 |
9 | /**
10 | * Contains methods that concern the loading of PW's data/config files.
11 | *
12 | * @author lokka30
13 | * @since v2.0.0
14 | */
15 | public class FileManager {
16 |
17 | /**
18 | * Run all loading sequences for a file from this method.
19 | *
20 | * @param pwFile file to load
21 | *
22 | * @since v2.0.0
23 | */
24 | public void init(final PWFile pwFile) {
25 | PhantomWorlds.logger().info("Loading file " + pwFile + "...");
26 |
27 | try {
28 | load(pwFile);
29 |
30 | switch(pwFile) {
31 | case SETTINGS:
32 | migrate(pwFile, PhantomWorlds.instance().settings.getConfig().getInt("advanced.file-version"));
33 | break;
34 | case ADVANCED_SETTINGS:
35 | migrate(pwFile,
36 | PhantomWorlds.instance().advancedSettings.getConfig().getInt("advanced.file-version"));
37 | break;
38 | case MESSAGES:
39 | migrate(pwFile, PhantomWorlds.instance().messages.getConfig().getInt("advanced.file-version"));
40 | break;
41 | case DATA:
42 | migrate(pwFile, PhantomWorlds.instance().data.getConfig().getInt("advanced.file-version"));
43 | break;
44 | default:
45 | break;
46 | }
47 | } catch(IOException ex) {
48 | PhantomWorlds.logger().severe("Unable to init file " + pwFile + ". Stack trace:");
49 | ex.printStackTrace();
50 | }
51 | }
52 |
53 | /**
54 | * Run MicroLib's YamlConfigFile load sequence for each file.
55 | *
56 | * @since v2.0.0
57 | */
58 | private void load(final PWFile pwFile) throws IOException {
59 | switch(pwFile) {
60 | case SETTINGS:
61 | PhantomWorlds.instance().settings.load();
62 | break;
63 | case ADVANCED_SETTINGS:
64 | PhantomWorlds.instance().advancedSettings.load();
65 | break;
66 | case MESSAGES:
67 | PhantomWorlds.instance().messages.load();
68 | break;
69 | case DATA:
70 | PhantomWorlds.instance().data.load();
71 | break;
72 | default:
73 | throw new IllegalStateException("Unexpected value " + pwFile);
74 | }
75 | }
76 |
77 | /**
78 | * Attempt to update outdated files automatically.
79 | *
80 | * @since v2.0.0
81 | */
82 | private void migrate(final PWFile pwFile, final int currentVersion) {
83 | // Values of -1 indicate that it is not to be migrated
84 | if(pwFile.latestFileVersion == -1) {
85 | return;
86 | }
87 |
88 | switch(pwFile) {
89 | case SETTINGS:
90 | if(currentVersion == PWFile.SETTINGS.latestFileVersion) {
91 | return;
92 | }
93 | alertIncorrectVersion(pwFile);
94 | break;
95 | case ADVANCED_SETTINGS:
96 | if(currentVersion == PWFile.ADVANCED_SETTINGS.latestFileVersion) {
97 | return;
98 | }
99 | alertIncorrectVersion(pwFile);
100 | break;
101 | case MESSAGES:
102 | if(currentVersion == PWFile.MESSAGES.latestFileVersion) {
103 | return;
104 | }
105 | alertIncorrectVersion(pwFile);
106 | break;
107 | case DATA:
108 | if(currentVersion == PWFile.DATA.latestFileVersion) {
109 | return;
110 | }
111 |
112 | //Switch below is for future-proofing the code, in case more data versions are added.
113 | //noinspection SwitchStatementWithTooFewBranches
114 | switch(currentVersion) {
115 | case 1:
116 | PhantomWorlds.logger().info("Automatically migrating the " + pwFile
117 | + " file to the latest format (it was outdated).");
118 |
119 | if(!PhantomWorlds.instance().data.getConfig().contains("worlds")) {
120 | return;
121 | }
122 |
123 | for(String worldName : PhantomWorlds.instance().data.getConfig().getStringList("worlds")) {
124 | if(Bukkit.getWorld(worldName) != null) {
125 | continue; // Don't add worlds that are already loaded (most likely by Bukkit).
126 | }
127 |
128 | PhantomWorlds.instance().data.getConfig()
129 | .set("worlds-to-load." + worldName + ".environment",
130 | World.Environment.NORMAL.toString());
131 | }
132 |
133 | PhantomWorlds.instance().data.getConfig().set("worlds", null);
134 |
135 | PhantomWorlds.instance().data.getConfig().set("advanced.file-version", 2);
136 |
137 | PhantomWorlds.logger().info("File '" + pwFile + "' has been migrated.");
138 | break;
139 | default:
140 | alertIncorrectVersion(pwFile);
141 | break;
142 | }
143 | break;
144 | default:
145 | throw new IllegalStateException("Unexpected value " + pwFile);
146 | }
147 | }
148 |
149 | void alertIncorrectVersion(final PWFile pwFile) {
150 | PhantomWorlds.logger().severe("You are running the incorrect version of the " +
151 | "file '" + pwFile + "'! Please back it up and allow the plugin to generate a new file, "
152 | + "or you will most likely experience errors.");
153 | }
154 |
155 | /**
156 | * Each data/config file and their latest (current) version are mapped here.
157 | *
158 | * @author lokka30
159 | * @since v2.0.0
160 | */
161 | public enum PWFile {
162 | SETTINGS(2),
163 | ADVANCED_SETTINGS(1),
164 | MESSAGES(8),
165 | DATA(2);
166 |
167 | public final int latestFileVersion; // If == -1: 'do not migrate me!'
168 |
169 | PWFile(final int latestFileVersion) {
170 | this.latestFileVersion = latestFileVersion;
171 | }
172 | }
173 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | me.lokka30
8 | PhantomWorlds
9 | 2.0.5
10 |
11 | PhantomWorlds
12 | The Robust World Manager for Minecraft Servers
13 |
14 |
15 | phantomworlds.libs
16 | 1.8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | spigot-repo
23 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/
24 |
25 |
26 | CodeMC
27 | https://repo.codemc.org/repository/maven-public
28 |
29 |
30 | jitpack.io
31 | https://jitpack.io
32 |
33 |
34 | litecommands-repo
35 | https://repo.panda-lang.org/releases
36 |
37 |
38 |
39 |
40 |
41 | org.spigotmc
42 | spigot-api
43 | 1.20.1-R0.1-SNAPSHOT
44 | provided
45 |
46 |
47 | com.github.lokka30
48 | MicroLib
49 | 3.2.1
50 | compile
51 |
52 |
53 | org.bstats
54 | bstats-bukkit
55 | 3.0.2
56 | compile
57 |
58 |
59 | org.jetbrains
60 | annotations
61 | 24.0.1
62 | provided
63 |
64 |
65 | dev.dejvokep
66 | boosted-yaml
67 | 1.3.2
68 | compile
69 |
70 |
71 | dev.rollczi
72 | litecommands-core
73 | 3.3.4
74 | compile
75 |
76 |
77 | dev.rollczi
78 | litecommands-bukkit
79 | 3.3.4
80 | compile
81 |
82 |
83 |
84 |
85 | clean package
86 |
87 |
88 | org.apache.maven.plugins
89 | maven-compiler-plugin
90 | 3.11.0
91 |
92 | 1.8
93 | 1.8
94 |
95 |
96 |
97 | org.apache.maven.plugins
98 | maven-shade-plugin
99 | 3.5.0
100 |
101 |
102 |
103 | me.lokka30.microlib
104 | ${phantom.relocation}.microlib
105 |
106 |
107 | org.bstats
108 | ${phantom.relocation}.bstats
109 |
110 |
111 | revxrsal
112 | ${phantom.relocation}.lamp
113 |
114 |
115 | dev.rollczi
116 | ${phantom.relocation}.lc
117 |
118 |
119 | panda.std
120 | ${phantom.relocation}.panda
121 |
122 |
123 | org.panda-lang
124 | ${phantom.relocation}.panda
125 |
126 |
127 | dev.dejvokep.boostedyaml
128 | ${phantom.relocation}.yaml
129 |
130 |
131 | true
132 |
133 |
134 |
135 | package
136 |
137 | shade
138 |
139 |
140 | false
141 |
142 |
143 | dev.dejvokep.boostedyaml:*
144 | org.bstats:*
145 | com.github.lokka30:MicroLib
146 | com.github.Revxrsal.Lamp:*
147 | dev.rollczi:*
148 | panda.std:*
149 | org.panda-lang:*
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/world/PhantomWorld.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.world;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.phantomworlds.PhantomWorlds;
21 | import org.bukkit.Difficulty;
22 | import org.bukkit.GameMode;
23 | import org.bukkit.GameRule;
24 | import org.bukkit.World;
25 | import org.bukkit.WorldCreator;
26 | import org.bukkit.WorldType;
27 | import org.jetbrains.annotations.NotNull;
28 | import org.jetbrains.annotations.Nullable;
29 |
30 | import java.io.IOException;
31 | import java.util.HashMap;
32 | import java.util.Map;
33 |
34 | /**
35 | * PhantomWorld object to make it easier to work with PW-managed worlds.
36 | *
37 | * @author lokka30
38 | * @since v2.0.0
39 | */
40 | public class PhantomWorld {
41 |
42 | private final Map gamerules = new HashMap<>();
43 |
44 | private final String name;
45 | private final World.Environment environment;
46 | private final boolean generateStructures;
47 | private final String generator;
48 | private final String generatorSettings;
49 | private final boolean hardcore;
50 | private final Long seed;
51 | private final WorldType worldType;
52 | private final boolean spawnMobs;
53 | private final boolean spawnAnimals;
54 | private final boolean keepSpawnInMemory;
55 | private final boolean allowPvP;
56 | private final Difficulty difficulty;
57 |
58 | private final GameMode gameMode;
59 |
60 | public PhantomWorld(
61 | @NotNull String name,
62 | @NotNull World.Environment environment,
63 | boolean generateStructures,
64 | @Nullable String generator,
65 | @Nullable String generatorSettings,
66 | boolean hardcore,
67 | @Nullable Long seed,
68 | @NotNull WorldType worldType,
69 | boolean spawnMobs,
70 | boolean spawnAnimals,
71 | boolean keepSpawnInMemory,
72 | boolean allowPvP,
73 | @NotNull Difficulty difficulty,
74 | @NotNull GameMode gameMode
75 | ) {
76 | this.name = name;
77 | this.environment = environment;
78 | this.generateStructures = generateStructures;
79 | this.generator = generator;
80 | this.generatorSettings = generatorSettings;
81 | this.hardcore = hardcore;
82 | this.seed = seed;
83 | this.worldType = worldType;
84 | this.spawnMobs = spawnMobs;
85 | this.spawnAnimals = spawnAnimals;
86 | this.keepSpawnInMemory = keepSpawnInMemory;
87 | this.allowPvP = allowPvP;
88 | this.difficulty = difficulty;
89 | this.gameMode = gameMode;
90 | }
91 |
92 | /**
93 | * Create/import the world with specified settings.
94 | *
95 | * @since v2.0.0
96 | */
97 | public void create() {
98 | final WorldCreator worldCreator = new WorldCreator(name);
99 |
100 | worldCreator.environment(environment);
101 | worldCreator.generateStructures(generateStructures);
102 | try {
103 | worldCreator.hardcore(hardcore);
104 | } catch(NoSuchMethodError ignored) {
105 | }
106 | worldCreator.type(worldType);
107 |
108 | if(generator != null) {
109 | worldCreator.generator(generator);
110 | }
111 | if(generatorSettings != null) {
112 | worldCreator.generatorSettings(generatorSettings);
113 | }
114 | if(seed != null) {
115 | worldCreator.seed(seed);
116 | }
117 |
118 | final World world = worldCreator.createWorld();
119 |
120 | if(world == null) {
121 | PhantomWorlds.logger().severe("Unable to create/load world '" + name + "'!");
122 | return;
123 | }
124 |
125 | world.setSpawnFlags(spawnMobs, spawnAnimals);
126 | world.setKeepSpawnInMemory(keepSpawnInMemory);
127 | world.setPVP(allowPvP);
128 | world.setDifficulty(difficulty);
129 |
130 | for(Map.Entry entry : gamerules.entrySet()) {
131 | final GameRule> rule = GameRule.getByName(entry.getKey());
132 | if(rule == null) continue;
133 |
134 | if(rule.getType() == Boolean.class) {
135 | try {
136 | world.setGameRule((GameRule)rule, Boolean.valueOf(entry.getValue()));
137 | } catch(Exception ignore) {
138 | PhantomWorlds.logger().warning("Error setting gamerule: " + entry.getKey() + " for world: " + name + "! Invalid boolean value!");
139 | }
140 | } else if(rule.getType() == Integer.class) {
141 | try {
142 | world.setGameRule((GameRule)rule, Integer.valueOf(entry.getValue()));
143 | } catch(Exception ignore) {
144 | PhantomWorlds.logger().warning("Error setting gamerule: " + entry.getKey() + " for world: " + name + "! Invalid integer value!");
145 | }
146 | }
147 | }
148 | }
149 |
150 | public void save() {
151 |
152 | final String cfgPath = "worlds-to-load." + name + ".";
153 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "environment", environment.toString());
154 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "generateStructures", generateStructures);
155 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "generator", generator);
156 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "generatorSettings", generatorSettings);
157 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "hardcore", hardcore);
158 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "seed", seed);
159 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "worldType", worldType.toString());
160 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "spawnMobs", spawnMobs);
161 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "spawnAnimals", spawnAnimals);
162 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "keepSpawnInMemory", keepSpawnInMemory);
163 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "allowPvP", allowPvP);
164 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "difficulty", difficulty.toString());
165 | PhantomWorlds.instance().data.getConfig().set(cfgPath + "gameMode", gameMode.name());
166 |
167 | try {
168 | PhantomWorlds.instance().data.save();
169 | } catch(final IOException ex) {
170 | throw new RuntimeException(ex);
171 | }
172 | }
173 |
174 | public void loadGameRules() {
175 |
176 | }
177 |
178 | public Map getGamerules() {
179 | return gamerules;
180 | }
181 |
182 | public String name() {
183 | return name;
184 | }
185 |
186 | public World.Environment environment() {
187 | return environment;
188 | }
189 |
190 | public boolean generateStructures() {
191 | return generateStructures;
192 | }
193 |
194 | public String generator() {
195 | return generator;
196 | }
197 |
198 | public String generatorSettings() {
199 | return generatorSettings;
200 | }
201 |
202 | public boolean hardcore() {
203 | return hardcore;
204 | }
205 |
206 | public Long seed() {
207 | return seed;
208 | }
209 |
210 | public WorldType worldType() {
211 | return worldType;
212 | }
213 |
214 | public boolean spawnMobs() {
215 | return spawnMobs;
216 | }
217 |
218 | public boolean spawnAnimals() {
219 | return spawnAnimals;
220 | }
221 |
222 | public boolean keepSpawnInMemory() {
223 | return keepSpawnInMemory;
224 | }
225 |
226 | public boolean allowPvP() {
227 | return allowPvP;
228 | }
229 |
230 | public Difficulty difficulty() {
231 | return difficulty;
232 | }
233 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/managers/WorldManager.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.managers;
2 |
3 | import me.lokka30.phantomworlds.PhantomWorlds;
4 | import me.lokka30.phantomworlds.misc.Utils;
5 | import me.lokka30.phantomworlds.misc.WorldLoadResponse;
6 | import me.lokka30.phantomworlds.world.PhantomWorld;
7 | import org.bukkit.Bukkit;
8 | import org.bukkit.Difficulty;
9 | import org.bukkit.GameMode;
10 | import org.bukkit.World;
11 | import org.bukkit.WorldType;
12 | import org.jetbrains.annotations.Nullable;
13 |
14 | import java.io.File;
15 | import java.io.IOException;
16 | import java.util.HashSet;
17 | import java.util.LinkedHashMap;
18 | import java.util.Map;
19 |
20 | import static me.lokka30.phantomworlds.misc.Utils.zipFolder;
21 |
22 | /**
23 | * Contains an assortment of methods to handle world management in PW.
24 | *
25 | * @author lokka30
26 | * @since v2.0.0
27 | */
28 | public class WorldManager {
29 |
30 | public final Map aliases = new LinkedHashMap<>();
31 |
32 | /**
33 | * For all worlds listed in PW's data file, if they aren't already loaded by Bukkit, then tell
34 | * Bukkit to load them
35 | *
36 | * @since v2.0.0
37 | */
38 | public void loadManagedWorlds() {
39 | PhantomWorlds.logger().info("Loading managed worlds...");
40 |
41 | if(!PhantomWorlds.instance().data.getConfig().contains("worlds-to-load")) {
42 | return;
43 | }
44 |
45 | final HashSet worldsToDiscardFromDataFile = new HashSet<>();
46 |
47 | //This should be outside our for each
48 | if(!Bukkit.getWorldContainer().exists()) {
49 | PhantomWorlds.logger().severe("World container doesn't exist!");
50 | return;
51 | }
52 |
53 | final String defaultWorld = Utils.defaultWorld();
54 |
55 | //noinspection ConstantConditions
56 | for(final String worldName : PhantomWorlds.instance().data.getConfig().getConfigurationSection("worlds-to-load").getKeys(false)) {
57 |
58 | if(worldName.equalsIgnoreCase(defaultWorld) || worldName.startsWith(defaultWorld)) {
59 | continue;
60 | }
61 |
62 | final WorldLoadResponse response = loadWorld(worldName);
63 |
64 | if(response.equals(WorldLoadResponse.INVALID)) {
65 | worldsToDiscardFromDataFile.add(worldName);
66 | }
67 |
68 | }
69 |
70 | for(String worldName : worldsToDiscardFromDataFile) {
71 | PhantomWorlds.instance().data.getConfig().set("worlds-to-load." + worldName, null);
72 | }
73 |
74 | try {
75 | PhantomWorlds.instance().data.save();
76 | } catch(IOException ex) {
77 | PhantomWorlds.logger().severe("Unable to save data file. Stack trace:");
78 | ex.printStackTrace();
79 | }
80 | }
81 |
82 | /**
83 | * Used to load a world based on the name.
84 | * @param worldName The name of the world.
85 | * @return The {@link WorldLoadResponse response} from the loading process.
86 | */
87 | public WorldLoadResponse loadWorld(final String worldName) {
88 |
89 | if(Bukkit.getWorld(worldName) != null) {
90 | return WorldLoadResponse.NOT_FOUND;
91 | }
92 |
93 | final File worldFolder = new File(Bukkit.getWorldContainer(), worldName);
94 | final File levelDat = new File(worldFolder, "level.dat");
95 | if(!worldFolder.exists() || !levelDat.exists()) {
96 |
97 | // The world was deleted/moved by the user so it must be re-imported. PW should no longer attempt to load that world.
98 | PhantomWorlds.logger().info("Discarding world '" + worldName + "' from PhantomWorlds' "
99 | + "data file as it no longer exists on the server.");
100 | return WorldLoadResponse.INVALID;
101 | }
102 |
103 | if(PhantomWorlds.instance().data.getConfig().getBoolean("worlds-to-load." + worldName + ".skip-autoload", false)) {
104 | PhantomWorlds.logger().info("Skipping autoload of world '" + worldName + "'.");
105 | return WorldLoadResponse.CONFIG_SKIPPED;
106 | }
107 |
108 | PhantomWorlds.logger().info("Loading world '" + worldName + "'...");
109 | getPhantomWorldFromData(worldName).create();
110 | return WorldLoadResponse.LOADED;
111 | }
112 |
113 | /**
114 | * This creates a PhantomWorld object by scanning the data file by the specified name. Developers
115 | * are expected to make sure the specified world exists prior to retrieving it.
116 | *
117 | * @since v2.0.0
118 | */
119 | public PhantomWorld getPhantomWorldFromData(final String name) {
120 | final String cfgPath = "worlds-to-load." + name + ".";
121 |
122 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath + "alias")) {
123 | for(final String alias : PhantomWorlds.instance().data.getConfig().getConfigurationSection(cfgPath + "alias").getKeys(false)) {
124 | aliases.put(alias, name);
125 | }
126 | }
127 |
128 | final PhantomWorld world = new PhantomWorld(
129 | name,
130 | World.Environment.valueOf(
131 | PhantomWorlds.instance().data.getConfig().getString(cfgPath + "environment", "NORMAL")
132 | ),
133 | PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + "generateStructures", true),
134 | PhantomWorlds.instance().data.getConfig().getString(cfgPath + "generator", null),
135 | PhantomWorlds.instance().data.getConfig().getString(cfgPath + "generatorSettings", null),
136 | PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + "hardcore", false),
137 | PhantomWorlds.instance().data.getConfig().getLong(cfgPath + "seed", 0),
138 | WorldType.valueOf(
139 | PhantomWorlds.instance().data.getConfig().getString(cfgPath + "worldType", "NORMAL")
140 | ),
141 | PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + "spawnMobs", true),
142 | PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + "spawnAnimals", true),
143 | PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + "keepSpawnInMemory", false),
144 | PhantomWorlds.instance().data.getConfig().getBoolean(cfgPath + "allowPvP", true),
145 | Difficulty.valueOf(
146 | PhantomWorlds.instance().data.getConfig().getString(cfgPath + "difficulty", "NORMAL")
147 | ),
148 | GameMode.valueOf(
149 | PhantomWorlds.instance().data.getConfig().getString(cfgPath + "gameMode", "SURVIVAL")
150 | )
151 | );
152 |
153 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath + "rules") &&
154 | PhantomWorlds.instance().data.getConfig().isConfigurationSection(cfgPath + "rules")) {
155 | for(final String rule : PhantomWorlds.instance().data.getConfig().getConfigurationSection(cfgPath + "rules").getKeys(false)) {
156 | world.getGamerules().put(rule, PhantomWorlds.instance().data.getConfig().getString(cfgPath + "rules." + rule));
157 | }
158 | }
159 | return world;
160 | }
161 |
162 | @Nullable
163 | public World findWorld(final String name) {
164 |
165 | return Bukkit.getWorld(aliases.getOrDefault(name, name));
166 | }
167 |
168 | public boolean backupWorld(final String world) {
169 | return backupWorld(world, new File(PhantomWorlds.instance().getDataFolder(), PhantomWorlds.BACKUP_FOLDER));
170 | }
171 |
172 | public boolean backupWorld(final String world, final File backupFolder) {
173 | final File worldFolder = new File(Bukkit.getWorldContainer(), world);
174 |
175 | try {
176 | final File worldBackupFolder = new File(backupFolder, world);
177 | worldBackupFolder.mkdir();
178 |
179 | final String timestamp = String.valueOf(System.currentTimeMillis());
180 | final String zipFilePath = new File(worldBackupFolder, world + "-" + timestamp + ".zip").getPath();
181 | zipFolder(worldFolder, zipFilePath);
182 |
183 | PhantomWorlds.logger().info("World '" + world + "' backed up to: " + worldBackupFolder.getPath());
184 | return true;
185 | } catch (IOException e) {
186 | e.printStackTrace();
187 | return false;
188 | }
189 | }
190 |
191 | public boolean backupAndDeleteWorld(final String worldName) {
192 | final World world = Bukkit.getWorld(worldName);
193 |
194 | if(world == null) {
195 | PhantomWorlds.logger().warning("Unable to locate world '" + worldName + "'! Halting deletion.");
196 | return false;
197 | }
198 |
199 | if(PhantomWorlds.instance().settings.getConfig().getBoolean("delete-archive", true)) {
200 | if(!backupWorld(world.getName(), new File(PhantomWorlds.instance().getDataFolder(), PhantomWorlds.ARCHIVE_FOLDER))) {
201 | PhantomWorlds.logger().warning("Unable to backup world '" + worldName + "'! Halting deletion.");
202 | return false;
203 | }
204 | }
205 |
206 | if(!Bukkit.unloadWorld(world, true)) {
207 | PhantomWorlds.logger().warning("Unable to unload world '" + worldName + "'! Halting deletion.");
208 | return false;
209 | }
210 | final File worldFolder = new File(Bukkit.getWorldContainer(), worldName);
211 | if(!worldFolder.exists()) {
212 | PhantomWorlds.logger().warning("Unable to locate folder for world '" + worldName + "'! Halting deletion.");
213 | return false;
214 | }
215 |
216 | if(!Utils.deleteFolder(worldFolder)) {
217 | PhantomWorlds.logger().warning("Unable to delete world '" + worldName + "'! Halting deletion.");
218 | return false;
219 | }
220 | return true;
221 | }
222 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/PWCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import dev.rollczi.litecommands.annotations.argument.Arg;
21 | import dev.rollczi.litecommands.annotations.command.Command;
22 | import dev.rollczi.litecommands.annotations.context.Context;
23 | import dev.rollczi.litecommands.annotations.description.Description;
24 | import dev.rollczi.litecommands.annotations.execute.Execute;
25 | import dev.rollczi.litecommands.annotations.optional.OptionalArg;
26 | import dev.rollczi.litecommands.annotations.permission.Permission;
27 | import me.lokka30.phantomworlds.commandsredux.sub.BackupCommand;
28 | import me.lokka30.phantomworlds.commandsredux.sub.CompatibilityCommand;
29 | import me.lokka30.phantomworlds.commandsredux.sub.CreateCommand;
30 | import me.lokka30.phantomworlds.commandsredux.sub.DebugCommand;
31 | import me.lokka30.phantomworlds.commandsredux.sub.DeleteCommand;
32 | import me.lokka30.phantomworlds.commandsredux.sub.ImportCommand;
33 | import me.lokka30.phantomworlds.commandsredux.sub.InfoCommand;
34 | import me.lokka30.phantomworlds.commandsredux.sub.ListCommand;
35 | import me.lokka30.phantomworlds.commandsredux.sub.LoadCommand;
36 | import me.lokka30.phantomworlds.commandsredux.sub.ReloadCommand;
37 | import me.lokka30.phantomworlds.commandsredux.sub.SetSpawnCommand;
38 | import me.lokka30.phantomworlds.commandsredux.sub.SpawnCommand;
39 | import me.lokka30.phantomworlds.commandsredux.sub.TeleportCommand;
40 | import me.lokka30.phantomworlds.commandsredux.sub.UnloadCommand;
41 | import me.lokka30.phantomworlds.commandsredux.sub.set.SetEffectsCommand;
42 | import me.lokka30.phantomworlds.commandsredux.sub.set.SetGamemodeCommand;
43 | import me.lokka30.phantomworlds.commandsredux.sub.set.SetPortalCommand;
44 | import me.lokka30.phantomworlds.commandsredux.sub.set.SetWhitelistCommand;
45 | import me.lokka30.phantomworlds.commandsredux.utils.WorldFolder;
46 | import org.bukkit.GameMode;
47 | import org.bukkit.PortalType;
48 | import org.bukkit.World;
49 | import org.bukkit.command.CommandSender;
50 | import org.bukkit.entity.Player;
51 |
52 | import java.util.List;
53 |
54 | /**
55 | * PWCommand
56 | *
57 | * @author creatorfromhell
58 | * @since 2.0.5.0
59 | */
60 | @Command(name = "phantomworlds", aliases = {"pw"})
61 | public class PWCommand {
62 |
63 | @Execute(name = "backup", aliases = {"archive", "bu"})
64 | @Permission("phantomworlds.command.phantomworlds.backup")
65 | @Description("command.phantomworlds.help.backup")
66 | public void backup(@Context CommandSender commandSender, @OptionalArg("world") final World world) {
67 | BackupCommand.onCommand(commandSender, world);
68 | }
69 |
70 | @Execute(name = "create", aliases = {"+", "new"})
71 | @Permission("phantomworlds.command.phantomworlds.create")
72 | @Description("command.phantomworlds.help.create")
73 | public void create(@Context CommandSender commandSender, @Arg("world name") final String name, @Arg("environment")World.Environment environment, @Arg("world-setting") List settings) {
74 | CreateCommand.onCommand(commandSender, name, environment, settings);
75 | }
76 |
77 | @Execute(name = "compatibility")
78 | @Permission("phantomworlds.command.phantomworlds.compatibility")
79 | @Description("command.phantomworlds.help.compatibility")
80 | public void compatibility(@Context CommandSender commandSender) {
81 | CompatibilityCommand.onCommand(commandSender);
82 | }
83 |
84 | @Execute(name = "debug")
85 | @Permission("phantomworlds.command.phantomworlds.debug")
86 | @Description("command.phantomworlds.help.debug")
87 | public void debug(@Context CommandSender commandSender, @OptionalArg("level") final String level) {
88 | DebugCommand.onCommand(commandSender, level);
89 | }
90 |
91 | @Execute(name = "delete", aliases = {"-", "remove", "del"})
92 | @Permission("phantomworlds.command.phantomworlds.delete")
93 | @Description("command.phantomworlds.help.delete")
94 | public void delete(@Context CommandSender commandSender, @OptionalArg("world") final World world) {
95 | DeleteCommand.onCommand(commandSender, world);
96 | }
97 |
98 | @Execute(name = "list", aliases = {"l"})
99 | @Permission("phantomworlds.command.phantomworlds.list")
100 | @Description("command.phantomworlds.help.list")
101 | public void list(@Context CommandSender commandSender) {
102 | ListCommand.onCommand(commandSender);
103 | }
104 |
105 | @Execute(name = "import", aliases = {"im"})
106 | @Permission("phantomworlds.command.phantomworlds.import")
107 | @Description("command.phantomworlds.help.import")
108 | public void importCMD(@Context CommandSender commandSender, @OptionalArg("world") final World world) {
109 | ImportCommand.onCommand(commandSender, world);
110 | }
111 |
112 | @Execute(name = "info", aliases = {"i"})
113 | @Permission("phantomworlds.command.phantomworlds.info")
114 | @Description("command.phantomworlds.help.info")
115 | public void info(@Context CommandSender commandSender) {
116 | InfoCommand.onCommand(commandSender);
117 | }
118 |
119 | @Execute(name = "load")
120 | @Permission("phantomworlds.command.phantomworlds.load")
121 | @Description("command.phantomworlds.help.load")
122 | public void load(@Context CommandSender commandSender, @OptionalArg("world folder") final WorldFolder world) {
123 | LoadCommand.onCommand(commandSender, world);
124 | }
125 |
126 | @Execute(name = "reload", aliases = {"r"})
127 | @Permission("phantomworlds.command.phantomworlds.reload")
128 | @Description("command.phantomworlds.help.reload")
129 | public void reload(@Context CommandSender commandSender) {
130 | ReloadCommand.onCommand(commandSender);
131 | }
132 |
133 | @Execute(name = "set effects", aliases = {"set eff"})
134 | @Permission("phantomworlds.command.phantomworlds.set.effects")
135 | @Description("command.phantomworlds.help.seteffects")
136 | public void setEffects(@Context CommandSender commandSender, @Arg("world") World world, @Arg("potion-effects") List effects) {
137 | SetEffectsCommand.onCommand(commandSender, world, effects);
138 | }
139 |
140 | @Execute(name = "set gamemode", aliases = {"set mode"})
141 | @Permission("phantomworlds.command.phantomworlds.set.gamemode")
142 | @Description("command.phantomworlds.help.setgamemode")
143 | public void setGamemode(@Context CommandSender commandSender, @Arg("world") World world, @Arg("mode") GameMode mode) {
144 | SetGamemodeCommand.onCommand(commandSender, world, mode);
145 | }
146 |
147 | @Execute(name = "set portal")
148 | @Permission("phantomworlds.command.phantomworlds.set.portal")
149 | @Description("command.phantomworlds.help.setportal")
150 | public void setPortal(@Context CommandSender commandSender, @Arg("world") World world, @Arg("portal type") PortalType portal, @Arg("world to") World worldTo) {
151 | SetPortalCommand.onCommand(commandSender, world, portal, worldTo);
152 | }
153 |
154 | @Execute(name = "set whitelist")
155 | @Permission("phantomworlds.command.phantomworlds.set.whitelist")
156 | @Description("command.phantomworlds.help.setwhitelist")
157 | public void setWhitelist(@Context CommandSender commandSender, @Arg("world") World world, @Arg("whitelist") boolean whitelist) {
158 | SetWhitelistCommand.onCommand(commandSender, world, whitelist);
159 | }
160 |
161 | @Execute(name = "setspawn", aliases = {"ss"})
162 | @Permission("phantomworlds.command.phantomworlds.setspawn")
163 | @Description("command.phantomworlds.help.setspawn")
164 | public void setspawn(@Context CommandSender commandSender, @OptionalArg("x") Double x, @OptionalArg("y") Double y, @OptionalArg("z") Double z, @OptionalArg("world") World world, @OptionalArg("yaw") Float yaw, @OptionalArg("pitch") Float pitch) {
165 | SetSpawnCommand.onCommand(commandSender, x, y, z, world, yaw, pitch);
166 | }
167 |
168 | @Execute(name = "spawn")
169 | @Permission("phantomworlds.command.phantomworlds.spawn")
170 | @Description("command.phantomworlds.help.spawn")
171 | public void spawn(@Context CommandSender commandSender, @OptionalArg("world") final World world, @OptionalArg("target") final Player player) {
172 | SpawnCommand.onCommand(commandSender, world, player);
173 | }
174 |
175 | @Execute(name = "teleport", aliases = {"tp"})
176 | @Permission("phantomworlds.command.phantomworlds.teleport")
177 | @Description("command.phantomworlds.help.tp")
178 | public void tp(@Context CommandSender commandSender, @OptionalArg("world") final World world, @OptionalArg("target") final Player player) {
179 | TeleportCommand.onCommand(commandSender, world, player);
180 | }
181 |
182 | @Execute(name = "unload", aliases = {"u"})
183 | @Permission("phantomworlds.command.phantomworlds.unload")
184 | @Description("command.phantomworlds.help.unload")
185 | public void unload(@Context CommandSender commandSender, @OptionalArg("world") final World world) {
186 | UnloadCommand.onCommand(commandSender, world);
187 | }
188 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/PhantomWorlds.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds;
2 |
3 | import dev.rollczi.litecommands.LiteCommands;
4 | import dev.rollczi.litecommands.argument.ArgumentKey;
5 | import dev.rollczi.litecommands.bukkit.LiteBukkitFactory;
6 | import me.lokka30.microlib.files.YamlConfigFile;
7 | import me.lokka30.microlib.maths.QuickTimer;
8 | import me.lokka30.microlib.other.UpdateChecker;
9 | import me.lokka30.phantomworlds.commandsredux.PWCommand;
10 | import me.lokka30.phantomworlds.commandsredux.params.AliasWorldParameter;
11 | import me.lokka30.phantomworlds.commandsredux.params.GamemodeParameter;
12 | import me.lokka30.phantomworlds.commandsredux.params.PortalParameter;
13 | import me.lokka30.phantomworlds.commandsredux.params.PotionEffectParameter;
14 | import me.lokka30.phantomworlds.commandsredux.params.SettingParameter;
15 | import me.lokka30.phantomworlds.commandsredux.params.WorldFolderParameter;
16 | import me.lokka30.phantomworlds.commandsredux.utils.WorldFolder;
17 | import me.lokka30.phantomworlds.listeners.player.PlayerChangeWorldListener;
18 | import me.lokka30.phantomworlds.listeners.player.PlayerDeathListener;
19 | import me.lokka30.phantomworlds.listeners.player.PlayerJoinListener;
20 | import me.lokka30.phantomworlds.listeners.player.PlayerPortalListener;
21 | import me.lokka30.phantomworlds.listeners.player.PlayerTeleportListener;
22 | import me.lokka30.phantomworlds.listeners.world.WorldInitListener;
23 | import me.lokka30.phantomworlds.managers.FileManager;
24 | import me.lokka30.phantomworlds.managers.WorldManager;
25 | import me.lokka30.phantomworlds.misc.CompatibilityChecker;
26 | import me.lokka30.phantomworlds.misc.UpdateCheckerResult;
27 | import me.lokka30.phantomworlds.scheduler.BackupScheduler;
28 | import org.bstats.bukkit.Metrics;
29 | import org.bukkit.GameMode;
30 | import org.bukkit.PortalType;
31 | import org.bukkit.World;
32 | import org.bukkit.WorldType;
33 | import org.bukkit.plugin.java.JavaPlugin;
34 | import org.bukkit.scheduler.BukkitTask;
35 |
36 | import java.io.File;
37 | import java.util.ArrayList;
38 | import java.util.LinkedList;
39 | import java.util.List;
40 | import java.util.concurrent.TimeUnit;
41 | import java.util.logging.Logger;
42 |
43 | /**
44 | * This is the main class of the PhantomWorlds plugin.
45 | *
46 | * @author lokka30
47 | * @since v2.0.0
48 | */
49 | public class PhantomWorlds extends JavaPlugin {
50 |
51 | public static final List createTabs = new ArrayList<>();
52 |
53 | /*
54 | *TODO:
55 | * - Translate backslash character in world names as a space so world names with a space can be used in the plugin
56 | * - Vanish compatibility
57 | * - don't send 'by' messages unless the sender is not a player / target can see the (player) sender
58 | * - add vanish compatibility to 'teleport' subcommand
59 | * - add ability to toggle vanish compatibility
60 | * - log in console (LogLevel:INFO) when a command is prevented due to a target player seemingly being vanished to the command sender.
61 | */
62 |
63 |
64 | private static PhantomWorlds instance;
65 |
66 | protected LiteCommands> command;
67 |
68 | private BukkitTask backupService = null;
69 |
70 | /**
71 | * If you have contributed code to the plugin, add your name to the end of this list! :)
72 | */
73 | public static final String[] CONTRIBUTORS = new String[]{"madison-allen"};
74 |
75 | public static final List COMMAND_HELP = new LinkedList<>();
76 |
77 | public static final String BACKUP_FOLDER = "backups";
78 | public static final String ARCHIVE_FOLDER = "archives";
79 |
80 | /**
81 | * This is reported in the 'pw info' command to inform the command sender of what MC versions that
82 | * this version of PW is designed to run on, and is therefore supported.
83 | */
84 | public final String supportedServerVersions = "1.7.x and newer";
85 |
86 | /**
87 | * Frequently used vars.
88 | */
89 | public final FileManager fileManager = new FileManager();
90 | public final WorldManager worldManager = new WorldManager();
91 |
92 | /**
93 | * Miscellaneous vars.
94 | */
95 | public final CompatibilityChecker compatibilityChecker = new CompatibilityChecker();
96 | public UpdateCheckerResult updateCheckerResult = null;
97 |
98 | /**
99 | * Data/configuration files.
100 | */
101 | public final YamlConfigFile settings = new YamlConfigFile(this,
102 | new File(getDataFolder(), "settings.yml"));
103 | public final YamlConfigFile advancedSettings = new YamlConfigFile(this,
104 | new File(getDataFolder(), "advancedSettings.yml"));
105 | public final YamlConfigFile messages = new YamlConfigFile(this,
106 | new File(getDataFolder(), "messages.yml"));
107 | public final YamlConfigFile data = new YamlConfigFile(this,
108 | new File(getDataFolder(), "data.yml"));
109 |
110 | /*
111 | Used to check if world are loaded
112 | */
113 | private boolean isWorldLoaded = false;
114 |
115 | /**
116 | * This method is called by Bukkit when it loads PhantomWorlds.
117 | *
118 | * @since v2.0.0
119 | */
120 | @Override
121 | public void onEnable() {
122 |
123 | instance = this;
124 |
125 | createTabs.addAll(generateCreateSuggestions());
126 |
127 | QuickTimer timer = new QuickTimer(TimeUnit.MILLISECONDS);
128 | checkCompatibility();
129 | loadFiles();
130 |
131 | registerCommands();
132 | registerListeners();
133 | miscStartupProcedures();
134 |
135 | if(settings.getConfig().getBoolean("backup-scheduler", true)) {
136 | getLogger().info("Starting up Backup scheduler...");
137 | backupService = new BackupScheduler().runTaskTimerAsynchronously(this, settings.getConfig().getInt("backup-delay") * 20L, settings.getConfig().getInt("backup-delay") * 20L);
138 | }
139 |
140 | getLogger().info("Start-up complete (took " + timer.getDuration() + "ms)");
141 | }
142 |
143 | public boolean isWorldLoaded() {
144 | return isWorldLoaded;
145 | }
146 |
147 | /**
148 | * This method is called by Bukkit when it disables PhantomWorlds.
149 | *
150 | * @since v2.0.0
151 | */
152 | @Override
153 | public void onDisable() {
154 | final QuickTimer timer = new QuickTimer(TimeUnit.MILLISECONDS);
155 |
156 | if(backupService != null) {
157 | getLogger().info("Shutting down backup scheduler...");
158 | backupService.cancel();
159 | }
160 |
161 | getLogger().info("Shut-down complete (took " + timer.getDuration() + "ms)");
162 | }
163 |
164 | /**
165 | * Run the compatibility checkker. Reports in the console if it finds any possible issues.
166 | *
167 | * @since v2.0.0
168 | */
169 | void checkCompatibility() {
170 | getLogger().info("Checking compatibility with server...");
171 |
172 | compatibilityChecker.checkAll();
173 |
174 | if(compatibilityChecker.incompatibilities.isEmpty()) {
175 | return;
176 | }
177 |
178 | for(int i = 0; i < compatibilityChecker.incompatibilities.size(); i++) {
179 | CompatibilityChecker.Incompatibility incompatibility = compatibilityChecker.incompatibilities.get(
180 | i);
181 | getLogger().warning(
182 | "Incompatibility #" + (i + 1) + " (Type: " + incompatibility.type + "):");
183 | getLogger().info(" -> Reason: " + incompatibility.reason);
184 | getLogger().info(" -> Recommendation: " + incompatibility.recommendation);
185 | }
186 | }
187 |
188 | /**
189 | * (Re)load all data/configuration files. Creates them if they don't exist. Applies version
190 | * checking where suitable.
191 | *
192 | * @since v2.0.0
193 | */
194 | public void loadFiles() {
195 | getLogger().info("Checking for backup directory...");
196 |
197 | final File backup = new File(getDataFolder(), BACKUP_FOLDER);
198 | if(!backup.exists()) {
199 | backup.mkdirs();
200 | }
201 |
202 | getLogger().info("Loading files...");
203 |
204 | for(FileManager.PWFile pwFile : FileManager.PWFile.values()) {
205 | fileManager.init(pwFile);
206 | }
207 | }
208 |
209 | /**
210 | * Checks on the worlds that are created through PhantomWorlds. If they aren't already loaded, PW
211 | * loads them.
212 | *
213 | * @since v2.0.0
214 | */
215 | public void loadWorlds() {
216 | getLogger().info("Loading worlds...");
217 | worldManager.loadManagedWorlds();
218 | isWorldLoaded = true;
219 | }
220 |
221 | /**
222 | * Registers the commands for the plugin. In this case, only one command is registered (with an
223 | * array of sub-commands of course).
224 | *
225 | * @since v2.0.0
226 | */
227 | void registerCommands() {
228 | getLogger().info("Registering commands...");
229 |
230 | this.command = LiteBukkitFactory.builder()
231 | .commands(new PWCommand())
232 | .settings(settings -> settings
233 | .fallbackPrefix("phantomworlds")
234 | .nativePermissions(false)
235 | )
236 | .argument(GameMode.class, new GamemodeParameter())
237 | .argument(PortalType.class, new PortalParameter())
238 | .argument(String.class, ArgumentKey.of("world-setting"), new SettingParameter())
239 | .argument(String.class, ArgumentKey.of("potion-effects"), new PotionEffectParameter())
240 | .argument(World.class, new AliasWorldParameter())
241 | .argument(WorldFolder.class, new WorldFolderParameter()).build();
242 | }
243 |
244 | /**
245 | * Registers the listeners for the plugin. These classes run code when Events happen on the
246 | * server, e.g. 'player joins server' or 'player changes world'.
247 | *
248 | * @since v2.0.0
249 | */
250 | void registerListeners() {
251 | getLogger().info("Registering listeners...");
252 | getServer().getPluginManager().registerEvents(new PlayerChangeWorldListener(this), this);
253 | getServer().getPluginManager().registerEvents(new PlayerDeathListener(this), this);
254 | getServer().getPluginManager().registerEvents(new PlayerJoinListener(this), this);
255 | getServer().getPluginManager().registerEvents(new PlayerPortalListener(this), this);
256 | getServer().getPluginManager().registerEvents(new PlayerTeleportListener(this), this);
257 |
258 | getServer().getPluginManager().registerEvents(new WorldInitListener(this), this);
259 | }
260 |
261 | /**
262 | * Miscellaneous startup procedures.
263 | *
264 | * @since v2.0.0
265 | */
266 | void miscStartupProcedures() {
267 | getLogger().info("Running misc startup procedures...");
268 |
269 | /* bStats Metrics */
270 | new Metrics(this, 8916);
271 |
272 | /* Update Checker */
273 | if(settings.getConfig().getBoolean("run-update-checker", true)) {
274 | try {
275 | final UpdateChecker updateChecker = new UpdateChecker(this, 84017);
276 | updateChecker.getLatestVersion(latestVersion->{
277 | updateCheckerResult = new UpdateCheckerResult(
278 | !latestVersion.equals(updateChecker.getCurrentVersion()),
279 | updateChecker.getCurrentVersion(),
280 | latestVersion
281 | );
282 |
283 | if(updateCheckerResult.isOutdated()) {
284 | if(!messages.getConfig()
285 | .getBoolean("update-checker.console.enabled", true)) {
286 | return;
287 | }
288 |
289 | messages.getConfig().getStringList("update-checker.console.text")
290 | .forEach(message->getLogger().info(message
291 | .replace("%currentVersion%",
292 | updateCheckerResult.getCurrentVersion())
293 | .replace("%latestVersion%", updateCheckerResult.getLatestVersion())
294 | ));
295 | }
296 | });
297 | } catch(Exception ex) {
298 | getLogger().warning("Unable to check for updates - check your internet connection: "
299 | + ex.getMessage());
300 | }
301 | }
302 | }
303 |
304 | public static PhantomWorlds instance() {
305 | return instance;
306 | }
307 |
308 | public static Logger logger() {
309 | return instance.getLogger();
310 | }
311 |
312 | public static WorldManager worldManager() {
313 | return instance.worldManager;
314 | }
315 |
316 | private ArrayList generateCreateSuggestions() {
317 | final ArrayList suggestions = new ArrayList<>();
318 |
319 | suggestions.addAll(addTrueFalseValues("generatestructures"));
320 | suggestions.addAll(addTrueFalseValues("genstructures"));
321 | suggestions.addAll(addTrueFalseValues("structures"));
322 | suggestions.addAll(addTrueFalseValues("spawnmobs"));
323 | suggestions.addAll(addTrueFalseValues("mobs"));
324 | suggestions.addAll(addTrueFalseValues("spawnanimals"));
325 | suggestions.addAll(addTrueFalseValues("animals"));
326 | suggestions.addAll(addTrueFalseValues("keepspawninmemory"));
327 | suggestions.addAll(addTrueFalseValues("spawninmemory"));
328 | suggestions.addAll(addTrueFalseValues("hardcore"));
329 | suggestions.addAll(addTrueFalseValues("allowpvp"));
330 | suggestions.addAll(addTrueFalseValues("pvp"));
331 | suggestions.addAll(addTrueFalseValues("difficulty"));
332 | suggestions.addAll(addTrueFalseValues("diff"));
333 |
334 | suggestions.add("generator:");
335 | suggestions.add("gen:");
336 |
337 | suggestions.add("generatorsettings:");
338 | suggestions.add("gensettings:");
339 |
340 | suggestions.add("gamemode:ADVENTURE");
341 | suggestions.add("gamemode:CREATIVE");
342 | suggestions.add("gamemode:HARDCORE");
343 | suggestions.add("gamemode:SURVIVAL");
344 |
345 | suggestions.add("seed:");
346 |
347 | for(WorldType worldType : WorldType.values()) {
348 | suggestions.add("type:" + worldType.toString());
349 | }
350 |
351 | return suggestions;
352 | }
353 |
354 | private ArrayList addTrueFalseValues(String option) {
355 | final ArrayList list = new ArrayList<>();
356 | option = option + ":";
357 |
358 | list.add(option + "true");
359 | list.add(option + "false");
360 |
361 | return list;
362 | }
363 | }
--------------------------------------------------------------------------------
/src/main/resources/messages.yml:
--------------------------------------------------------------------------------
1 | # .___ _ . . __ . _
2 | # / \ / ___ , __ _/_ __. , _ , _ / | __. .___ | ___/ ____
3 | # |,_-' |,---. / ` |' `. | .' \ |' `|' `. | | .' \ / \ | / | (
4 | # | |' ` | | | | | | | | | | | /\ / | | | ' | ,' | `--.
5 | # / / | `.__/| / | \__/ `._.' / ' / |,' \,' `._.' / /\__ `___,' \___.'
6 |
7 | common:
8 |
9 | prefix: '&b&lPhantomWorlds:&7'
10 |
11 | no-permission: '%prefix% You don''t have access to that. &8(%permission%)'
12 |
13 | list-delimiter: '&7, &b'
14 |
15 | command:
16 |
17 | phantomworlds:
18 |
19 | usage:
20 | - '%prefix% Available commands:'
21 | - '&8 &m->&b /%label% create &8- &7create a world'
22 | - '&8 &m->&b /%label% import &8- &7import a world'
23 | - '&8 &m->&b /%label% list &8- &7list loaded worlds'
24 | - '&8 &m->&b /%label% teleport &8- &7teleport to a loaded world''s spawnpoint'
25 | - '&8 &m->&b /%label% spawn [player] &8- &7teleport to the spawn of the current world'
26 | - '&8 &m->&b /%label% set effects [effects] &8- &7set the potion effects to be applied to players in this world.'
27 | - '&8 &m->&b /%label% set gamemode &8- &7set the gamemode for this world.'
28 | - '&8 &m->&b /%label% set portal &8- &7set where the specified portal type takes players in this world.'
29 | - '&8 &m->&b /%label% set whitelist &8- &7set whether there is a whitelist for this world or not.'
30 | - '&8 &m->&b /%label% setspawn &8- &7set the spawnpoint of a world'
31 | - '&8 &m->&b /%label% delete &8- &7delete a world'
32 | - '&8 &m->&b /%label% backup &8- &7Backup a world'
33 | - '&8 &m->&b /%label% unload &8- &7unload a loaded world'
34 | - '&8 &m->&b /%label% load &8- &7load an unloaded world'
35 | - '&8 &m->&b /%label% reload &8- &7reload all config & data files'
36 | - '&8 &m->&b /%label% info &8- &7view info about the plugin'
37 | - '&8 &m->&b /%label% compatibility &8- &7check for incompatibilities'
38 |
39 | help-header: '&7=== %prefix% &f[&7%page%&f/&b%max%&f] &7==='
40 |
41 | help:
42 | create: '&b/pw create [options...] &8- &7create a world'
43 | import: '&b/pw import &8- &7import a world'
44 | list: '&b/pw list &8- &7list worlds'
45 | tp: '&b/pw teleport [player] &8- &7teleport to a loaded world''s spawnpoint'
46 | spawn: '&b/pw spawn &8- &7teleport to the spawn of the current world'
47 | debug: '&b/pw debug &8- &7Change the debug mode for PhantomWorlds.'
48 | seteffects: '&b/pw set effects [effects] &8- &7set the potion effects to be applied to players in this world.'
49 | setgamemode: '&b/pw set gamemode &8- &7set the gamemode for this world.'
50 | setportal: '&b/pw set portal &8- &7set where the specified portal type takes players in this world.'
51 | setwhitelist: '&b/pw set whitelist &8- &7set whether there is a whitelist for this world or not.'
52 | setspawn: '&b/pw setspawn [x] [y] [z] [world] [yaw] [pitch] &8- &7set the spawnpoint of a world'
53 | delete: '&b/pw delete &8- &7delete a world'
54 | backup: '&b/pw backup &8- &7backup a world'
55 | unload: '&b/pw unload &8- &7unload a loaded world'
56 | load: '&b/pw load &8- &7load an unloaded world'
57 | reload: '&b/pw reload &8- &7reload all config & data files'
58 | info: '&b/pw info &8- &7view info about the plugin'
59 | compatibility: '&b/pw compatibility &8- &7check for incompatibilities'
60 |
61 | invalid-subcommand:
62 | - '%prefix% Invalid subcommand ''&b%arg%&7''.'
63 |
64 | subcommands:
65 |
66 | # Messages inside this 'common' branch are used
67 | # among multiple subcommands.
68 | common:
69 |
70 | invalid-world:
71 | - '%prefix% World ''&b%world%&7'' is not loaded.'
72 |
73 | player-offline:
74 | - '%prefix% Player ''&b%player%&7'' is offline.'
75 |
76 | backup:
77 |
78 | usage:
79 | - '%prefix% Invalid usage, try ''&b/%label% backup &7''.'
80 |
81 | success:
82 | - '%prefix% You have created a back up for the world ''&b%world%&7''.'
83 |
84 | failure:
85 | - '%prefix% Issue while creating a back up for the world ''&b%world%&7''.'
86 |
87 | compatibility:
88 |
89 | start:
90 | - '%prefix% Starting compatibility checker...'
91 |
92 | found-none:
93 | - '%prefix% Compatibility check finished with no incompatibilities detected.'
94 |
95 | found:
96 | - '%prefix% Compatibility check finished with &b%amount%&7 detections:'
97 |
98 | entry:
99 | - '&8| &3#%index% &8(&7Type: &b%type%&8)&7:'
100 | - '&8| &m->&f Reason: &7%reason%'
101 | - '&8| &m->&f Recommendation: &7%recommendation%'
102 | - ' '
103 |
104 | usage:
105 | - '%prefix% Invalid usage, try ''&b/%label% compatibility&7''.'
106 |
107 | create:
108 |
109 | already-loaded:
110 | - '%prefix% World ''&b%world%&7'' is already loaded - you may teleport to it using ''&b/%label% tp %world%&7''.'
111 |
112 | creation:
113 |
114 | starting:
115 | - '%prefix% Starting creation of world ''&b%world%&7''...'
116 |
117 | saving-world-data:
118 | - '%prefix% &8[%world%: 1/2]: &7Saving world data...'
119 |
120 | constructing-world:
121 | - '%prefix% &8[%world%: 2/2]: &7Constructing the world...'
122 | - '%prefix% &8[%world%: 2/2]: &7(The server may briefly freeze)'
123 |
124 | complete:
125 | - '%prefix% World ''&b%world%&7'' created:'
126 | - '&8 &m->&7 Took &b%time%ms&7.'
127 | - '&8 &m->&7 You may teleport to it using ''&b/%label% tp %world%&7''.'
128 |
129 | options:
130 |
131 | invalid-option:
132 | - '%prefix% Invalid world option ''&b%option%&7''.'
133 | - '%prefix% Valid world options: &b%options%&7.'
134 |
135 | invalid-value:
136 | - '%prefix% Invalid world option value ''&b%value%&7'' for option ''&b%option%&7'', a &b%expected%&7 value was expected.'
137 |
138 | invalid-value-list:
139 | - '%prefix% Invalid world option value ''&b%value%&7'' for option ''&b%option%&7'', a valid &b%expected%&7 was expected.'
140 | - '%prefix% Valid values: &b%values%&7.'
141 |
142 | invalid-environment:
143 | - '%prefix% Environment ''&b%type%&7'' doesn''t exist.'
144 | - '%prefix% Valid environments: &b%types%&7.'
145 |
146 | usage:
147 | - '%prefix% Invalid usage, try ''&b/%label% create [options...]&7''.'
148 |
149 | debug:
150 |
151 | usage:
152 | - '%prefix% Invalid usage, try ''&b/%label% debug &7''.'
153 |
154 | success:
155 | - '%prefix%: &7Note: Please do not run this subcommand unless you are sure you are meant to be doing so'
156 |
157 | failure:
158 | - '%prefix%: &7Invalid debug method ''%method%''.'
159 |
160 | delete:
161 |
162 | usage:
163 | - '%prefix% Invalid usage, try ''&b/%label% delete &7''.'
164 |
165 | success:
166 | - '%prefix% You have deleted the world ''&b%world%&7''.'
167 |
168 | failure:
169 | - '%prefix% Issue while deleting the world ''&b%world%&7''.'
170 |
171 | import:
172 |
173 | usage:
174 | - '%prefix% Invalid usage, try ''&b/%label% import &7''.'
175 |
176 | success:
177 | - '%prefix% You have imported the world ''&b%world%&7''.'
178 |
179 | failure-exist:
180 | - '%prefix% Issue while importing the world. The world does not exist!'
181 |
182 | failure-already:
183 | - '%prefix% Issue while importing the world ''&b%world%&7''. The world is already managed by PhantomWorlds!'
184 |
185 | info:
186 |
187 | success:
188 | - '%prefix% Plugin information:'
189 | - '&8| &7Running &bPhantomWorlds v%version%'
190 | - '&8| &7Authors: &b%authors%'
191 | - '&8| &7Contributors: &b%contributors%'
192 | - '&8| &7Supported MC versions: &b%supportedServerVersions%'
193 |
194 | usage:
195 | - '%prefix% Invalid usage, try ''&b/%label% info&7''.'
196 |
197 | load:
198 |
199 | usage:
200 | - '%prefix% Invalid usage, try ''&b/%label% load &7''.'
201 |
202 | success:
203 | - '%prefix% You have loaded the world ''&b%world%&7''.'
204 |
205 | failure-folder:
206 | - '%prefix% Issue while loading the world. The world folder does not exist!'
207 |
208 | failure-loading:
209 | - '%prefix% Unknown issue while loading the world.'
210 |
211 | list:
212 |
213 | usage:
214 | - '%prefix% Invalid usage, try ''&b/%label% list&7''.'
215 |
216 | header-loaded:
217 | - '%prefix% Worlds loaded &8(&b%amount%&8)&7:'
218 |
219 | header-unloaded:
220 | - '%prefix% Worlds unloaded &8(&b%amount%&8)&7:'
221 |
222 | header-archived:
223 | - '%prefix% Worlds archived &8(&b%amount%&8)&7:'
224 |
225 | entry:
226 | - '&8 &m->&b %world%'
227 |
228 | reload:
229 |
230 | usage:
231 | - '%prefix% Invalid usage, try ''&b/%label% reload&7''.'
232 |
233 | reloading-files:
234 | - '%prefix% &8[1/2] &7Reloading files...'
235 |
236 | reloading-worlds:
237 | - '%prefix% &8[2/2] &7Reloading worlds...'
238 |
239 | reload-complete:
240 | - '%prefix% Reload complete.'
241 |
242 | seteffects:
243 |
244 | usage:
245 | - '%prefix% Invalid usage, try ''&b/%label% set effects [effects] &8- &7''.'
246 |
247 | success:
248 | - '%prefix% Successfully set the potion effects of world ''&b%world%&7'' to ''&b%effects%&7''.'
249 |
250 | setgamemode:
251 |
252 | usage:
253 | - '%prefix% Invalid usage, try ''&b/%label% set gamemode &8- &7''.'
254 |
255 | success:
256 | - '%prefix% Successfully set the gamemode of world ''&b%world%&7'' to ''&b%gamemode%&7''.'
257 |
258 | setportal:
259 |
260 | usage:
261 | - '%prefix% Invalid usage, try ''&b/%label% set portal &8- &7''.'
262 |
263 | success:
264 | - '%prefix% Successfully set the portal destination for portal ''&b%portal%&7'' of world ''&b%world%&7'' to world ''&b%world_to%&7''.'
265 |
266 | setwhitelist:
267 |
268 | usage:
269 | - '%prefix% Invalid usage, try ''&b/%label% set whitelist &8- &7''.'
270 |
271 | success:
272 | - '%prefix% Successfully set whitelist of world ''&b%world%&7'' to ''&b%whitelist%&7''.'
273 |
274 | setspawn:
275 |
276 | usage:
277 | - '%prefix% Invalid usage, try ''&b/%label% setspawn [x] [y] [z] [world] [yaw] [pitch]&7''.'
278 |
279 | usage-console:
280 | - '%prefix% Invalid usage for console, try ''&b/%label% setspawn [yaw] [pitch]&7''.'
281 |
282 | invalid-number:
283 | - '%prefix% ''&b%arg%&7'' isn''t a valid number.'
284 |
285 | success:
286 | - '%prefix% Spawn location set for world ''&b%world%&7''!'
287 | - '&8 &m->&7 Coordinates: &b%x%&7, &b%y%&7, &b%z%'
288 | - '&8 &m->&7 Yaw/Pitch: &b%yaw%&8/&b%pitch%'
289 |
290 | teleport:
291 |
292 | usage:
293 | - '%prefix% Invalid usage, try ''&b/%label% teleport [player]&7''.'
294 |
295 | usage-console:
296 | - '%prefix% Invalid usage for console, try ''&b/%label% teleport &7''.'
297 |
298 | success:
299 | - '%prefix% Teleported player ''&b%player%&7'' to the spawn point of world ''&b%world%&7''.'
300 |
301 | spawn:
302 |
303 | usage:
304 | - '%prefix% Invalid usage, try ''&b/%label% spawn [player]&7''.'
305 |
306 | usage-console:
307 | - '%prefix% Invalid usage for console, try ''&b/%label% spawn &7''.'
308 |
309 | success:
310 | - '%prefix% Teleported player ''&b%player%&7'' to the spawn point of world ''&b%world%&7''.'
311 |
312 | gamerule:
313 |
314 | rules:
315 |
316 | invalid-rule:
317 | - '%prefix% Invalid gamerule ''&b%rule%&7''.'
318 | - '%prefix% Valid world gamerules: &b%rules%&7.'
319 |
320 | invalid-value:
321 | - '%prefix% Invalid gamerule value ''&b%value%&7'' for gamerule ''&b%rule%&7'', a &b%expected%&7 value was expected.'
322 |
323 | usage:
324 | - '%prefix% Invalid usage, try ''&b/%label% gamerule [gamerules]&7''.'
325 |
326 | usage-console:
327 | - '%prefix% Invalid usage for console, try ''&b/%label% [gamerules]&7''.'
328 |
329 | success:
330 | - '%prefix% Set the gamerules of world ''&b%world%&7''.'
331 |
332 | unload:
333 |
334 | usage:
335 | - '%prefix% Invalid usage, try ''&b/%label% unload &7''.'
336 |
337 | in-specified-world:
338 | - '%prefix% You can''t unload world ''&b%world%&7'' as you are currently in it.'
339 |
340 | success:
341 | - '%prefix% You have unloaded the world ''&b%world%&7''.'
342 | - '%prefix% &eWarning: &7If the unloaded world''s folder is still present when you re-start your server, it will be loaded again. If you wish to prevent this, transfer the world''s directory elsewhere.'
343 |
344 | kick:
345 | - '%prefix% The world you were in was unloaded. Please re-join.'
346 |
347 | # Do not touch anything here unless you know what you are doing.
348 | advanced:
349 | file-version: 8
350 | generated-with: '${project.version}'
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/commandsredux/sub/CreateCommand.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.commandsredux.sub;
2 | /*
3 | * Phantom Worlds
4 | * Copyright (C) 2023 - 2024 Daniel "creatorfromhell" Vidmar
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | import me.lokka30.microlib.maths.QuickTimer;
21 | import me.lokka30.microlib.messaging.MultiMessage;
22 | import me.lokka30.phantomworlds.PhantomWorlds;
23 | import me.lokka30.phantomworlds.misc.Utils;
24 | import me.lokka30.phantomworlds.world.PhantomWorld;
25 | import org.bukkit.Bukkit;
26 | import org.bukkit.Difficulty;
27 | import org.bukkit.GameMode;
28 | import org.bukkit.World;
29 | import org.bukkit.WorldType;
30 | import org.bukkit.command.CommandSender;
31 |
32 | import java.util.Arrays;
33 | import java.util.List;
34 | import java.util.Locale;
35 | import java.util.Optional;
36 | import java.util.concurrent.TimeUnit;
37 |
38 | /**
39 | * CreateCommand
40 | *
41 | * @author creatorfromhell
42 | * @since 2.0.5.0
43 | */
44 | public class CreateCommand {
45 |
46 | public static void onCommand(final CommandSender sender, final String worldName, final World.Environment environment, final List settings) {
47 |
48 | if(Bukkit.getWorld(worldName) != null) {
49 | (new MultiMessage(
50 | PhantomWorlds.instance().messages.getConfig()
51 | .getStringList("command.phantomworlds.subcommands.create.already-loaded"),
52 | Arrays.asList(
53 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
54 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
55 | new MultiMessage.Placeholder("world", worldName, false),
56 | new MultiMessage.Placeholder("label", "pw", false)
57 | ))).send(sender);
58 | return;
59 | }
60 |
61 | if(environment == null) {
62 | (new MultiMessage(
63 | PhantomWorlds.instance().messages.getConfig().getStringList(
64 | "command.phantomworlds.subcommands.create.options.invalid-environment"),
65 | Arrays.asList(
66 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
67 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
68 | new MultiMessage.Placeholder("type", "", false),
69 | new MultiMessage.Placeholder("types", String.join(
70 | PhantomWorlds.instance().messages.getConfig().getString("common.list-delimiter", "&7, &b"),
71 | Utils.enumValuesToStringList(World.Environment.values())), true)
72 | ))).send(sender);
73 | return;
74 | }
75 |
76 | /* Default options: */
77 | boolean generateStructures = true;
78 | String generator = null;
79 | String generatorSettings = null;
80 | boolean hardcore = false;
81 | Long seed = null;
82 | WorldType worldType = WorldType.NORMAL;
83 | boolean spawnMobs = true;
84 | boolean spawnAnimals = true;
85 | boolean keepSpawnInMemory = false;
86 | boolean allowPvP = true;
87 | Difficulty difficulty = Difficulty.NORMAL;
88 | GameMode mode = GameMode.SURVIVAL;
89 | for(final String setting : settings) {
90 |
91 | final String[] split = setting.split(":", 2);
92 | if(split.length != 2) {
93 | (new MultiMessage(
94 | PhantomWorlds.instance().messages.getConfig().getStringList(
95 | "command.phantomworlds.subcommands.create.options.invalid-option"),
96 | Arrays.asList(
97 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
98 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
99 | new MultiMessage.Placeholder("option", setting, false),
100 | new MultiMessage.Placeholder("options", String.join(
101 | PhantomWorlds.instance().messages.getConfig()
102 | .getString("common.list-delimiter", "&7, &b"),
103 | Arrays.asList("genStructures", "gen", "genSettings", "hardcore",
104 | "seed", "type", "spawnMobs", "spawnAnimals",
105 | "keepSpawnInMemory", "allowPvP", "difficulty", "gamemode")
106 | ), true)
107 | ))).send(sender);
108 | return;
109 | }
110 |
111 | final String option = split[0].toLowerCase(Locale.ROOT);
112 | final StringBuilder value = new StringBuilder(split[1]);
113 |
114 | switch(option) {
115 | case "generatestructures":
116 | case "genstructures":
117 | case "structures":
118 |
119 | final Optional gen = Utils.parseFromString(sender, value, option);
120 | if(!gen.isPresent()) {
121 | return;
122 | }
123 | generateStructures = gen.get();
124 | break;
125 |
126 | case "generator":
127 | case "gen":
128 | generator = value.toString();
129 | break;
130 |
131 | case "generatorsettings":
132 | case "gensettings":
133 | generatorSettings = value.toString();
134 | break;
135 | case "gamemode":
136 | mode = GameMode.valueOf(value.toString());
137 | break;
138 | case "hardcore":
139 |
140 | final Optional hard = Utils.parseFromString(sender, value, option);
141 | if(!hard.isPresent()) {
142 | return;
143 | }
144 | hardcore = hard.get();
145 | break;
146 |
147 | case "seed":
148 | try {
149 | seed = Long.valueOf(value.toString());
150 | } catch(NumberFormatException ex) {
151 | (new MultiMessage(
152 | PhantomWorlds.instance().messages.getConfig().getStringList(
153 | "command.phantomworlds.subcommands.create.options.invalid-value"),
154 | Arrays.asList(
155 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
156 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
157 | new MultiMessage.Placeholder("value", value.toString(), false),
158 | new MultiMessage.Placeholder("option", option, false),
159 | new MultiMessage.Placeholder("expected", "Long (any number)",
160 | false)
161 | ))).send(sender);
162 | return;
163 | }
164 | break;
165 | case "type":
166 | case "worldtype":
167 | try {
168 | worldType = WorldType.valueOf(
169 | value.toString().toUpperCase(Locale.ROOT));
170 | } catch(IllegalArgumentException ex) {
171 | (new MultiMessage(
172 | PhantomWorlds.instance().messages.getConfig().getStringList(
173 | "command.phantomworlds.subcommands.create.options.invalid-value-list"),
174 | Arrays.asList(
175 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
176 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
177 | new MultiMessage.Placeholder("value", value.toString(), false),
178 | new MultiMessage.Placeholder("option", option, false),
179 | new MultiMessage.Placeholder("expected", "WorldType", false),
180 | new MultiMessage.Placeholder("values", String.join(
181 | PhantomWorlds.instance().messages.getConfig()
182 | .getString("common.list-delimiter", "&7, &b"),
183 | Utils.enumValuesToStringList(WorldType.values())), true)
184 | ))).send(sender);
185 | return;
186 | }
187 | break;
188 | case "spawnmobs":
189 | case "mobs":
190 |
191 | final Optional mobs = Utils.parseFromString(sender, value, option);
192 | if(!mobs.isPresent()) {
193 | return;
194 | }
195 | spawnMobs = mobs.get();
196 | break;
197 |
198 | case "spawnanimals":
199 | case "animals":
200 |
201 | final Optional animals = Utils.parseFromString(sender, value, option);
202 | if(!animals.isPresent()) {
203 | return;
204 | }
205 | spawnAnimals = animals.get();
206 | break;
207 |
208 | case "keepspawninmemory":
209 | case "spawninmemory":
210 |
211 | final Optional spawn = Utils.parseFromString(sender, value, option);
212 | if(!spawn.isPresent()) {
213 | return;
214 | }
215 | keepSpawnInMemory = spawn.get();
216 | break;
217 |
218 | case "allowpvp":
219 | case "pvp":
220 |
221 | final Optional pvp = Utils.parseFromString(sender, value, option);
222 | if(!pvp.isPresent()) {
223 | return;
224 | }
225 | allowPvP = pvp.get();
226 | break;
227 |
228 | case "difficulty":
229 | case "diff":
230 | try {
231 | difficulty = Difficulty.valueOf(
232 | value.toString().toUpperCase(Locale.ROOT));
233 | } catch(IllegalArgumentException ex) {
234 | (new MultiMessage(
235 | PhantomWorlds.instance().messages.getConfig().getStringList(
236 | "command.phantomworlds.subcommands.create.options.invalid-value-list"),
237 | Arrays.asList(
238 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
239 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
240 | new MultiMessage.Placeholder("value", value.toString(), false),
241 | new MultiMessage.Placeholder("option", option, false),
242 | new MultiMessage.Placeholder("expected", "Difficulty", false),
243 | new MultiMessage.Placeholder("values", String.join(
244 | PhantomWorlds.instance().messages.getConfig()
245 | .getString("common.list-delimiter", "&7, &b"),
246 | Utils.enumValuesToStringList(Difficulty.values())), true)
247 | ))).send(sender);
248 | return;
249 | }
250 | break;
251 | default:
252 | (new MultiMessage(
253 | PhantomWorlds.instance().messages.getConfig().getStringList(
254 | "command.phantomworlds.subcommands.create.options.invalid-option"),
255 | Arrays.asList(
256 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
257 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
258 | new MultiMessage.Placeholder("option", option, false),
259 | new MultiMessage.Placeholder("options", String.join(
260 | PhantomWorlds.instance().messages.getConfig()
261 | .getString("common.list-delimiter", "&7, &b"),
262 | Arrays.asList("genStructures", "gen", "genSettings", "hardcore",
263 | "seed", "type", "spawnMobs", "spawnAnimals",
264 | "keepSpawnInMemory", "allowPvP", "difficulty")
265 | ), true)
266 | ))).send(sender);
267 | return;
268 | }
269 | }
270 |
271 | final PhantomWorld pworld = new PhantomWorld(
272 | worldName, environment, generateStructures, generator,
273 | generatorSettings, hardcore, seed, worldType, spawnMobs,
274 | spawnAnimals, keepSpawnInMemory, allowPvP, difficulty, mode
275 | );
276 |
277 | final QuickTimer quickTimer = new QuickTimer(TimeUnit.MILLISECONDS);
278 |
279 | (new MultiMessage(
280 | PhantomWorlds.instance().messages.getConfig()
281 | .getStringList("command.phantomworlds.subcommands.create.creation.starting"),
282 | Arrays.asList(
283 | new MultiMessage.Placeholder("prefix",
284 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
285 | true),
286 | new MultiMessage.Placeholder("world", worldName, false)
287 | ))).send(sender);
288 |
289 | (new MultiMessage(
290 | PhantomWorlds.instance().messages.getConfig().getStringList(
291 | "command.phantomworlds.subcommands.create.creation.saving-world-data"),
292 | Arrays.asList(
293 | new MultiMessage.Placeholder("prefix",
294 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
295 | true),
296 | new MultiMessage.Placeholder("world", worldName, false)
297 | ))).send(sender);
298 |
299 | pworld.save();
300 |
301 | (new MultiMessage(
302 | PhantomWorlds.instance().messages.getConfig().getStringList(
303 | "command.phantomworlds.subcommands.create.creation.constructing-world"),
304 | Arrays.asList(
305 | new MultiMessage.Placeholder("prefix",
306 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
307 | true),
308 | new MultiMessage.Placeholder("world", worldName, false)
309 | ))).send(sender);
310 |
311 | pworld.create();
312 |
313 | (new MultiMessage(
314 | PhantomWorlds.instance().messages.getConfig()
315 | .getStringList("command.phantomworlds.subcommands.create.creation.complete"),
316 | Arrays.asList(
317 | new MultiMessage.Placeholder("prefix",
318 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
319 | true),
320 | new MultiMessage.Placeholder("world", worldName, false),
321 | new MultiMessage.Placeholder("time", Long.toString(quickTimer.getDuration()), false),
322 | new MultiMessage.Placeholder("label", "pw", false)
323 | ))).send(sender);
324 | }
325 | }
--------------------------------------------------------------------------------
/src/main/java/me/lokka30/phantomworlds/misc/Utils.java:
--------------------------------------------------------------------------------
1 | package me.lokka30.phantomworlds.misc;
2 |
3 | import me.lokka30.microlib.messaging.MessageUtils;
4 | import me.lokka30.microlib.messaging.MultiMessage;
5 | import me.lokka30.phantomworlds.PhantomWorlds;
6 | import org.bukkit.Bukkit;
7 | import org.bukkit.Location;
8 | import org.bukkit.World;
9 | import org.bukkit.command.CommandExecutor;
10 | import org.bukkit.command.CommandSender;
11 | import org.bukkit.entity.Player;
12 | import org.jetbrains.annotations.NotNull;
13 | import org.jetbrains.annotations.Nullable;
14 |
15 | import java.io.File;
16 | import java.io.FileInputStream;
17 | import java.io.FileOutputStream;
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.nio.file.Files;
21 | import java.util.ArrayList;
22 | import java.util.Arrays;
23 | import java.util.HashSet;
24 | import java.util.List;
25 | import java.util.Locale;
26 | import java.util.Optional;
27 | import java.util.Properties;
28 | import java.util.zip.ZipEntry;
29 | import java.util.zip.ZipOutputStream;
30 |
31 | /**
32 | * This class contains Utility methods which are public & static which are used by multiple classes.
33 | * If a method is only used by one class then it is advised to keep it in the class to avoid
34 | * bloating this class.
35 | *
36 | * @author lokka30
37 | * @since v2.0.0
38 | */
39 | public class Utils {
40 |
41 | /**
42 | * This is used for tab completion where numbers are expected, for example, coordinates in the
43 | * setspawn subcommand.
44 | */
45 | public static final List ZERO_THRU_NINE = Arrays.asList("0", "1", "2", "3", "4", "5",
46 | "6", "7", "8", "9");
47 |
48 | /**
49 | * This method returns a list of the names of worlds that are loaded on the server. Used in tab
50 | * completion, for example.
51 | *
52 | * @return set of world names
53 | *
54 | * @since v2.0.0
55 | */
56 | public static HashSet getLoadedWorldsNameList() {
57 | final HashSet loadedWorlds = new HashSet<>();
58 | Bukkit.getWorlds().forEach(world->loadedWorlds.add(world.getName()));
59 | return loadedWorlds;
60 | }
61 |
62 | /**
63 | * Attempts to register specified command. Sends status to console as logs.
64 | *
65 | * @param clazz CommandExecutor to be registered
66 | * @param command Name of the command as stated in plugin.yml
67 | *
68 | * @since v2.0.0
69 | */
70 | public static void registerCommand(@NotNull final CommandExecutor clazz, @NotNull final String command) {
71 | if(PhantomWorlds.instance().getCommand(command) == null) {
72 | PhantomWorlds.logger().severe("Unable to register command '/" + command + "' - PluginCommand "
73 | + "is null. Was plugin.yml tampered with?");
74 | } else {
75 | //noinspection ConstantConditions
76 | PhantomWorlds.instance().getCommand(command).setExecutor(clazz);
77 | PhantomWorlds.logger().info("Registered command '/" + command + "'.");
78 | }
79 | }
80 |
81 | /**
82 | * Tells the server to unload specified world so it can be deleted. Additionally: -> Kicks all
83 | * players from it before unloading. -> It does not transfer users to other worlds for security
84 | * purposes. This may be changed in the future.
85 | *
86 | * @param world World to be unloaded
87 | *
88 | * @since v2.0.0
89 | */
90 | public static void unloadWorld(@NotNull final World world) {
91 | // inform console
92 | PhantomWorlds.logger().info(String.format(
93 | "Unloading world %s; kicking %s players from the world...",
94 | world.getName(),
95 | world.getPlayers().size()
96 | ));
97 |
98 | // kick players in world
99 | // using an iterator to avoid a possible ConcurrentModificationException
100 | world.getPlayers().iterator().forEachRemaining(player->
101 | // yikes, this gets messy. :P
102 | player.kickPlayer(MessageUtils.colorizeAll(
103 | String.join("\n",
104 | PhantomWorlds.instance().messages.getConfig()
105 | .getStringList("command.phantomworlds.subcommands.unload.kick")
106 | )
107 | .replace("%prefix%",
108 | PhantomWorlds.instance().messages.getConfig()
109 | .getString("common.prefix", "PhantomWorlds: "))
110 | .replace("%world%", world.getName())
111 | ))
112 | );
113 |
114 | // time to unload the world
115 | Bukkit.unloadWorld(world, true);
116 | }
117 |
118 | /**
119 | * For the CommandSender specified, this method will list every player that the tab list will show
120 | * them. This does not work with vanish plugins that **exclusively** use packets, as it relies on
121 | * Bukkit's 'hidePlayer' system.
122 | *
123 | * @param sender commandsender to check. if console, all players are visible.
124 | *
125 | * @return list of usernames
126 | *
127 | * @since v2.0.0
128 | */
129 | public static List getPlayersCanSeeList(@NotNull final CommandSender sender) {
130 | final List suggestions = new ArrayList<>();
131 |
132 | if(!sender.hasPermission("phantomworlds.knows-vanished-users")
133 | && sender instanceof Player) {
134 | final Player player = (Player)sender;
135 | for(Player listedPlayer : Bukkit.getOnlinePlayers()) {
136 | if(player.canSee(listedPlayer)) {
137 | suggestions.add(listedPlayer.getName());
138 | }
139 | }
140 | } else {
141 | for(Player listedPlayer : Bukkit.getOnlinePlayers()) {
142 | suggestions.add(listedPlayer.getName());
143 | }
144 | }
145 |
146 | return suggestions;
147 | }
148 |
149 | /**
150 | * @param values Enum#values() call
151 | *
152 | * @return a list of string conversions of each enum value
153 | *
154 | * @since v2.0.0
155 | */
156 | public static List enumValuesToStringList(final Object[] values) {
157 | final List strings = new ArrayList<>();
158 | for(Object value : values) {
159 | strings.add(value.toString());
160 | }
161 | return strings;
162 | }
163 |
164 | /**
165 | * Credit: StackOverflow
166 | *
167 | * @param val value to round
168 | *
169 | * @return val, rounded to 2 decimal places.
170 | */
171 | public static double roundTwoDecimalPlaces(final double val) {
172 | return Math.round(val * 100) / 100.0;
173 | }
174 |
175 | public static Optional parseFromString(CommandSender sender, final StringBuilder value, final String option) {
176 | switch(value.toString().toLowerCase(Locale.ROOT)) {
177 | case "false":
178 | case "f":
179 | case "no":
180 | case "n":
181 | return Optional.of(false);
182 | case "true":
183 | case "t":
184 | case "yes":
185 | case "y":
186 | return Optional.of(true);
187 | default:
188 | (new MultiMessage(
189 | PhantomWorlds.instance().messages.getConfig().getStringList(
190 | "command.phantomworlds.subcommands.create.options.invalid-value"),
191 | Arrays.asList(
192 | new MultiMessage.Placeholder("prefix",
193 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix",
194 | "&b&lPhantomWorlds: &7"), true),
195 | new MultiMessage.Placeholder("value", value.toString(),
196 | false),
197 | new MultiMessage.Placeholder("option", option, false),
198 | new MultiMessage.Placeholder("expected",
199 | "Boolean (true/false)", false)
200 | ))).send(sender);
201 | return Optional.empty();
202 | }
203 | }
204 |
205 | public static void zipFolder(File sourceFolder, String destinationZipFile) throws IOException {
206 | try(FileOutputStream fos = new FileOutputStream(destinationZipFile);
207 | ZipOutputStream zos = new ZipOutputStream(fos)) {
208 |
209 | //zipFolder(sourceFolder, sourceFolder.getName(), zos);
210 |
211 | zipFile(sourceFolder, sourceFolder.getName(), zos);
212 | zos.closeEntry();
213 | zos.flush();
214 | zos.close();
215 | fos.flush();
216 | } catch(Exception e) {
217 | e.printStackTrace();
218 | }
219 | }
220 |
221 | public static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
222 | if(fileToZip.isHidden()) {
223 | return;
224 | }
225 |
226 | if(fileToZip.isDirectory()) {
227 |
228 | if(fileName.endsWith("/")) {
229 |
230 | zipOut.putNextEntry(new ZipEntry(fileName));
231 | zipOut.closeEntry();
232 | } else {
233 |
234 | zipOut.putNextEntry(new ZipEntry(fileName + "/"));
235 | zipOut.closeEntry();
236 | }
237 |
238 | File[] children = fileToZip.listFiles();
239 | if(children == null) {
240 | return;
241 | }
242 |
243 | for(File childFile : children) {
244 | zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
245 | }
246 | return;
247 | }
248 |
249 | FileInputStream fis = new FileInputStream(fileToZip);
250 | ZipEntry zipEntry = new ZipEntry(fileName);
251 | zipOut.putNextEntry(zipEntry);
252 |
253 | byte[] bytes = new byte[1024];
254 | int length;
255 |
256 | while((length = fis.read(bytes)) >= 0) {
257 | zipOut.write(bytes, 0, length);
258 | }
259 | fis.close();
260 | }
261 |
262 | public static void zipFolder(final File folder, final String parentFolder, final ZipOutputStream zos) throws IOException {
263 |
264 | if(folder == null || folder.exists()) {
265 | return;
266 | }
267 |
268 | final File[] files = folder.listFiles();
269 | if(files == null) {
270 | return;
271 | }
272 |
273 | for (File file : files) {
274 | if (file.isDirectory()) {
275 | zipFolder(file, parentFolder + File.separator + file.getName(), zos);
276 | continue;
277 | }
278 |
279 | final ZipEntry zipEntry = new ZipEntry(parentFolder + File.separator + file.getName());
280 | zos.putNextEntry(zipEntry);
281 |
282 | try (FileInputStream fis = new FileInputStream(file)) {
283 | final byte[] buffer = new byte[1024];
284 | int length;
285 | while ((length = fis.read(buffer)) > 0) {
286 | zos.write(buffer, 0, length);
287 | }
288 | }
289 | zos.closeEntry();
290 | }
291 | }
292 |
293 | public static boolean deleteFolder(File folder) {
294 | if (folder.exists()) {
295 | final File[] files = folder.listFiles();
296 | if (files != null) {
297 | for (File file : files) {
298 | if (file.isDirectory()) {
299 | deleteFolder(file);
300 | } else {
301 | file.delete();
302 | }
303 | }
304 | }
305 | }
306 | return folder.delete();
307 | }
308 |
309 | public static void teleportToWorld(@NotNull CommandSender sender, @NotNull String subCommand,
310 | @NotNull String label, @Nullable String targetPlayerName,
311 | @Nullable String worldName) {
312 | Player targetPlayer;
313 | if(targetPlayerName != null) {
314 | targetPlayer = Bukkit.getPlayer(targetPlayerName);
315 |
316 | // If the target is offline or invisible to the sender, then stop
317 | if(targetPlayer == null || !Utils.getPlayersCanSeeList(sender)
318 | .contains(targetPlayer.getName())) {
319 | (new MultiMessage(
320 | PhantomWorlds.instance().messages.getConfig()
321 | .getStringList("command.phantomworlds.subcommands.common.player-offline"),
322 | Arrays.asList(
323 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
324 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
325 | new MultiMessage.Placeholder("player", targetPlayerName, false)
326 | ))).send(sender);
327 | return;
328 | }
329 | } else {
330 | if(sender instanceof Player) {
331 | targetPlayer = (Player)sender;
332 | } else {
333 | (new MultiMessage(
334 | PhantomWorlds.instance().messages.getConfig().getStringList(
335 | "command.phantomworlds.subcommands." + subCommand + ".usage-console"),
336 | Arrays.asList(
337 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
338 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
339 | new MultiMessage.Placeholder("label", label, false)
340 | ))).send(sender);
341 | return;
342 | }
343 | }
344 |
345 | if(worldName == null) {
346 | worldName = targetPlayer.getWorld().getName();
347 | }
348 |
349 | final World world = Bukkit.getWorld(worldName);
350 | if(world == null) {
351 | (new MultiMessage(
352 | PhantomWorlds.instance().messages.getConfig()
353 | .getStringList("command.phantomworlds.subcommands.common.invalid-world"),
354 | Arrays.asList(
355 | new MultiMessage.Placeholder("prefix", PhantomWorlds.instance().messages.getConfig()
356 | .getString("common.prefix", "&b&lPhantomWorlds: &7"), true),
357 | new MultiMessage.Placeholder("world", worldName, false)
358 | ))).send(sender);
359 | return;
360 | }
361 | targetPlayer.teleport(parseSpawn(world));
362 |
363 | (new MultiMessage(
364 | PhantomWorlds.instance().messages.getConfig()
365 | .getStringList("command.phantomworlds.subcommands." + subCommand + ".success"),
366 | Arrays.asList(
367 | new MultiMessage.Placeholder("prefix",
368 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
369 | true),
370 | new MultiMessage.Placeholder("player", targetPlayer.getName(), false),
371 | new MultiMessage.Placeholder("world", worldName, false)
372 | ))).send(sender);
373 | }
374 |
375 | public static Location parseSpawn(final World world) {
376 | final String cfgPath = "worlds-to-load." + world.getName() + ".spawn";
377 | if(PhantomWorlds.instance().data.getConfig().contains(cfgPath)) {
378 | final double x = PhantomWorlds.instance().data.getConfig().getDouble(cfgPath + ".x", world.getSpawnLocation().getX());
379 | final double y = PhantomWorlds.instance().data.getConfig().getDouble(cfgPath + ".y", world.getSpawnLocation().getY());
380 | final double z = PhantomWorlds.instance().data.getConfig().getDouble(cfgPath + ".z", world.getSpawnLocation().getZ());
381 | final float yaw = (float)PhantomWorlds.instance().data.getConfig().getDouble(cfgPath + ".yaw", world.getSpawnLocation().getYaw());
382 | final float pitch = (float)PhantomWorlds.instance().data.getConfig().getDouble(cfgPath + ".pitch", world.getSpawnLocation().getPitch());
383 |
384 | return new Location(world, x, y, z, yaw, pitch);
385 | }
386 | return world.getSpawnLocation();
387 | }
388 |
389 | public static boolean checkWorld(@NotNull final CommandSender sender, final String usage, @Nullable final World world) {
390 | if(world == null) {
391 |
392 | (new MultiMessage(
393 | PhantomWorlds.instance().messages.getConfig()
394 | .getStringList(usage), Arrays.asList(
395 | new MultiMessage.Placeholder("prefix",
396 | PhantomWorlds.instance().messages.getConfig().getString("common.prefix", "&b&lPhantomWorlds: &7"),
397 | true),
398 | new MultiMessage.Placeholder("label", "pw", false)
399 | ))).send(sender);
400 |
401 | return false;
402 | }
403 | return true;
404 | }
405 |
406 | public static String defaultWorld() {
407 | try (InputStream input = Files.newInputStream(new File(PhantomWorlds.instance().getDataFolder(), "../../server.properties").toPath())) {
408 |
409 | final Properties prop = new Properties();
410 | prop.load(input);
411 |
412 | return prop.getProperty("level-name");
413 | } catch(Exception ignore) {
414 | return "world";
415 | }
416 | }
417 | }
--------------------------------------------------------------------------------