PlotSquared/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java

1259 lines
56 KiB
Java
Raw Normal View History

/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2020-04-11 02:19:18 +02:00
package com.plotsquared.bukkit;
2015-07-05 17:44:10 +02:00
2020-07-10 22:12:37 +02:00
import com.google.inject.Guice;
2020-07-12 12:25:44 +02:00
import com.google.inject.Inject;
2020-07-10 22:12:37 +02:00
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Singleton;
2020-07-10 22:12:37 +02:00
import com.google.inject.Stage;
2020-07-23 14:56:06 +02:00
import com.google.inject.TypeLiteral;
2020-04-11 02:19:18 +02:00
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
2020-07-10 22:12:37 +02:00
import com.plotsquared.bukkit.inject.BackupModule;
import com.plotsquared.bukkit.inject.BukkitModule;
import com.plotsquared.bukkit.inject.PermissionModule;
2020-07-10 22:12:37 +02:00
import com.plotsquared.bukkit.inject.WorldManagerModule;
import com.plotsquared.bukkit.listener.BlockEventListener;
2021-06-26 21:08:25 +02:00
import com.plotsquared.bukkit.listener.BlockEventListener117;
2020-04-15 21:26:54 +02:00
import com.plotsquared.bukkit.listener.ChunkListener;
import com.plotsquared.bukkit.listener.EntityEventListener;
2020-04-15 21:26:54 +02:00
import com.plotsquared.bukkit.listener.EntitySpawnListener;
2020-04-30 18:23:18 +02:00
import com.plotsquared.bukkit.listener.PaperListener;
import com.plotsquared.bukkit.listener.PaperListener113;
import com.plotsquared.bukkit.listener.PlayerEventListener;
import com.plotsquared.bukkit.listener.ProjectileEventListener;
2020-07-16 18:04:17 +02:00
import com.plotsquared.bukkit.listener.ServerListener;
2020-04-15 21:26:54 +02:00
import com.plotsquared.bukkit.listener.SingleWorldListener;
import com.plotsquared.bukkit.listener.WorldEvents;
import com.plotsquared.bukkit.placeholder.PAPIPlaceholders;
2020-04-15 21:26:54 +02:00
import com.plotsquared.bukkit.placeholder.PlaceholderFormatter;
2020-07-23 15:03:27 +02:00
import com.plotsquared.bukkit.player.BukkitPlayer;
2020-05-19 00:28:52 +02:00
import com.plotsquared.bukkit.player.BukkitPlayerManager;
2020-04-11 02:19:18 +02:00
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.BukkitWorld;
2020-04-11 02:19:18 +02:00
import com.plotsquared.bukkit.util.SetGenCB;
import com.plotsquared.bukkit.util.UpdateUtility;
import com.plotsquared.bukkit.util.task.BukkitTaskManager;
2020-07-15 13:18:09 +02:00
import com.plotsquared.bukkit.util.task.PaperTimeConverter;
import com.plotsquared.bukkit.util.task.SpigotTimeConverter;
import com.plotsquared.bukkit.uuid.EssentialsUUIDService;
import com.plotsquared.bukkit.uuid.LuckPermsUUIDService;
2020-05-18 00:22:34 +02:00
import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService;
import com.plotsquared.bukkit.uuid.PaperUUIDService;
import com.plotsquared.bukkit.uuid.SQLiteUUIDService;
import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService;
import com.plotsquared.core.PlotPlatform;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.PlotSquared;
2020-05-10 14:02:25 +02:00
import com.plotsquared.core.backup.BackupManager;
import com.plotsquared.core.components.ComponentPresetManager;
2020-04-30 12:01:52 +02:00
import com.plotsquared.core.configuration.ConfigurationNode;
import com.plotsquared.core.configuration.ConfigurationSection;
import com.plotsquared.core.configuration.ConfigurationUtil;
2020-04-30 12:01:52 +02:00
import com.plotsquared.core.configuration.Settings;
2020-12-07 23:05:25 +01:00
import com.plotsquared.core.configuration.Storage;
2020-12-21 20:33:49 +01:00
import com.plotsquared.core.configuration.caption.ChatFormatter;
import com.plotsquared.core.configuration.file.YamlConfiguration;
2020-05-19 00:28:52 +02:00
import com.plotsquared.core.database.DBFunc;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.generator.GeneratorWrapper;
import com.plotsquared.core.generator.IndependentPlotGenerator;
2020-04-30 12:01:52 +02:00
import com.plotsquared.core.generator.SingleWorldGenerator;
2020-07-10 22:12:37 +02:00
import com.plotsquared.core.inject.annotations.BackgroundPipeline;
import com.plotsquared.core.inject.annotations.DefaultGenerator;
import com.plotsquared.core.inject.annotations.ImpromptuPipeline;
import com.plotsquared.core.inject.annotations.WorldConfig;
import com.plotsquared.core.inject.annotations.WorldFile;
import com.plotsquared.core.inject.modules.PlotSquaredModule;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.listener.PlotListener;
2020-07-10 22:12:37 +02:00
import com.plotsquared.core.listener.WESubscriber;
2020-04-30 12:01:52 +02:00
import com.plotsquared.core.player.PlotPlayer;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotAreaTerrainType;
import com.plotsquared.core.plot.PlotAreaType;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.plot.PlotId;
2020-07-14 18:49:40 +02:00
import com.plotsquared.core.plot.comment.CommentManager;
import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.plot.world.SinglePlotAreaManager;
2020-06-05 02:19:37 +02:00
import com.plotsquared.core.setup.PlotAreaBuilder;
import com.plotsquared.core.setup.SettingsNodesWrapper;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.PlatformWorldManager;
2020-07-23 15:03:27 +02:00
import com.plotsquared.core.util.PlayerManager;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.util.PremiumVerification;
import com.plotsquared.core.util.ReflectionUtils;
import com.plotsquared.core.util.SetupUtils;
2020-04-30 12:01:52 +02:00
import com.plotsquared.core.util.WorldUtil;
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.util.task.TaskManager;
2020-07-15 13:18:09 +02:00
import com.plotsquared.core.util.task.TaskTime;
2020-05-18 00:22:34 +02:00
import com.plotsquared.core.uuid.CacheUUIDService;
import com.plotsquared.core.uuid.UUIDPipeline;
import com.plotsquared.core.uuid.offline.OfflineModeUUIDService;
2016-06-01 22:50:35 +02:00
import com.sk89q.worldedit.WorldEdit;
2020-04-30 18:23:18 +02:00
import io.papermc.lib.PaperLib;
2020-07-05 18:14:29 +02:00
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
2021-08-18 11:58:18 +02:00
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
2020-04-11 19:52:45 +02:00
import org.bstats.bukkit.Metrics;
2021-01-24 10:39:03 +01:00
import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SimplePie;
2019-11-04 18:44:23 +01:00
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
2021-04-27 11:58:49 +02:00
import org.incendo.serverlib.ServerLib;
2016-03-23 02:41:37 +01:00
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
2020-05-20 15:12:09 +02:00
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
2020-07-22 21:06:23 +02:00
import java.util.Locale;
2019-11-25 23:38:03 +01:00
import java.util.Map;
2020-05-20 15:12:09 +02:00
import java.util.Queue;
import java.util.Set;
import java.util.UUID;
2020-05-20 15:12:09 +02:00
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
2020-04-30 12:01:52 +02:00
import static com.plotsquared.core.util.PremiumVerification.getDownloadID;
import static com.plotsquared.core.util.PremiumVerification.getResourceID;
import static com.plotsquared.core.util.PremiumVerification.getUserID;
2020-04-15 21:26:54 +02:00
import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
@SuppressWarnings("unused")
@Singleton
public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPlatform<Player> {
2016-03-20 23:19:37 +01:00
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitPlatform.class.getSimpleName());
2020-05-10 14:02:25 +02:00
private static final int BSTATS_ID = 1404;
static {
try {
Settings.load(new File(PlotSquared.platform().getDirectory(), "settings.yml"));
2019-04-24 00:48:22 +02:00
} catch (Throwable ignored) {
}
}
private int[] version;
2020-07-17 17:24:45 +02:00
private String pluginName;
private SingleWorldListener singleWorldListener;
2018-08-10 17:01:10 +02:00
private Method methodUnloadChunk0;
private boolean methodUnloadSetup = false;
private boolean metricsStarted;
2021-06-08 19:36:45 +02:00
private boolean faweHook = false;
2020-07-17 17:24:45 +02:00
private Injector injector;
2020-07-10 22:12:37 +02:00
@Inject
private PlotAreaManager plotAreaManager;
@Inject
private EventDispatcher eventDispatcher;
@Inject
private PlotListener plotListener;
@Inject
@WorldConfig
private YamlConfiguration worldConfiguration;
@Inject
@WorldFile
private File worldfile;
@Inject
private BukkitPlayerManager playerManager;
@Inject
private BackupManager backupManager;
@Inject
@ImpromptuPipeline
private UUIDPipeline impromptuPipeline;
@Inject
@BackgroundPipeline
private UUIDPipeline backgroundPipeline;
@Inject
private PlatformWorldManager<World> worldManager;
2020-07-22 21:06:23 +02:00
private Locale serverLocale;
2020-07-10 19:25:05 +02:00
@SuppressWarnings("StringSplitter")
@Override
public int @NonNull [] serverVersion() {
if (this.version == null) {
try {
this.version = new int[3];
String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\.");
this.version[0] = Integer.parseInt(split[0]);
this.version[1] = Integer.parseInt(split[1]);
if (split.length == 3) {
this.version[2] = Integer.parseInt(split[2]);
}
} catch (NumberFormatException e) {
e.printStackTrace();
return new int[]{1, 13, 0};
}
}
return this.version;
}
Implement extended world heights from Y-64 to Y319 #3473 (#3473) * Begin to implement extended world heights: - Implemented in Bukkit module (and where required in Core module) * Implement extended world heights into core module * Add min gen height to setup, * Default gen/build heights based on minecraft version * Few fixes * Fix up queues * Address comments * Make road schematic stuff slightly more efficient by sharing queues * Minor fixes, don't overlay error many times for the same y * Fix incorrect schematic paste height, undo changes to HybridUtils * Overhall regenallroads method to make it work, make sure BukkitChunkCoordinator can/will finish * Process chunks in order when regenerating all roads * Address comments * Address comments * Ground level//bedrock is at min gen height - Add comment on == rather than <= being used - It's because it's only checking for the bedrock layer being broken if that's disabled * Fix offset for min build height in SchematicHandler * Better javadoc Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com> * Address inclusivity issues for max world height * Javadocs/comments/deprecation * Use world min/max heights if present in QueueCoordinator * Address some deprecations for regions and biome setting * Add a count for chunks we're currently trying to load to not skip chunks at the end of a queue's edit * Use minGenHeight + 1 rather than build height in AugmentedUtils * Create utility method for layer index in GenChunk * Correct height in HybridUtils, also use minGenHeight + 1 * Don't magically split to 128 height in regeneration * Add utility methods for world height in QueueCoordinator * Clean up ClassicPlotManager road creation/removal * Start generation at min gen height if bedrock is disabled * min gen height is set in PlotArea * Add note on schem y normalisation * Improve plot getVolume method readability * Don't overly extend height when regenerating road region * y index utility method in ChunknQueueCoordinator * Layer index utility method in LocalChunk * Use version min/max heights if world not present in QueueCoordinator * Fix min -> max * Don't allow players to modify outside build height when using plot set / schematics. - Also fixes schematic height issues * Remove debug * Address comments * Switch loadingChunks to AtomicInteger to be safe (in case of multi-threaded) * Fix "security" issue that was already present * Ensure sign isn't physicsed Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2022-03-05 19:03:39 +01:00
@Override
public int versionMinHeight() {
return serverVersion()[1] >= 18 ? -64 : 0;
}
@Override
public int versionMaxHeight() {
return serverVersion()[1] >= 18 ? 319 : 255;
}
@Override
public @NonNull String serverImplementation() {
return Bukkit.getVersion();
}
@Override
public void onEnable() {
2018-08-10 20:46:38 +02:00
this.pluginName = getDescription().getName();
2020-07-10 22:12:37 +02:00
2020-07-15 13:18:09 +02:00
final TaskTime.TimeConverter timeConverter;
if (PaperLib.isPaper()) {
timeConverter = new PaperTimeConverter();
} else {
timeConverter = new SpigotTimeConverter();
}
2020-07-10 22:12:37 +02:00
// Stuff that needs to be created before the PlotSquared instance
PlotPlayer.registerConverter(Player.class, BukkitUtil::adapt);
2020-07-17 16:38:07 +02:00
TaskManager.setPlatformImplementation(new BukkitTaskManager(this, timeConverter));
2020-07-10 17:32:07 +02:00
final PlotSquared plotSquared = new PlotSquared(this, "Bukkit");
2019-03-18 19:49:22 +01:00
// FastAsyncWorldEdit
if (Settings.FAWE_Components.FAWE_HOOK) {
Plugin fawe = getServer().getPluginManager().getPlugin("FastAsyncWorldEdit");
if (fawe != null) {
try {
2021-06-26 17:19:07 +02:00
Class.forName("com.fastasyncworldedit.bukkit.regions.plotsquared.FaweQueueCoordinator");
faweHook = true;
} catch (Exception ignored) {
LOGGER.error("Incompatible version of FastAsyncWorldEdit to enable hook, please upgrade: https://ci.athion" +
".net/job/FastAsyncWorldEdit/");
}
}
}
2020-07-10 22:12:37 +02:00
// We create the injector after PlotSquared has been initialized, so that we have access
// to generated instances and settings
2020-07-24 17:24:53 +02:00
this.injector = Guice
2021-08-18 11:58:18 +02:00
.createInjector(
Stage.PRODUCTION,
new PermissionModule(),
new WorldManagerModule(),
new PlotSquaredModule(),
new BukkitModule(this),
new BackupModule()
);
2020-07-10 22:12:37 +02:00
this.injector.injectMembers(this);
2020-07-22 21:06:23 +02:00
this.serverLocale = Locale.forLanguageTag(Settings.Enabled_Components.DEFAULT_LOCALE);
if (PremiumVerification.isPremium() && Settings.Enabled_Components.UPDATE_NOTIFICATIONS) {
2020-07-10 22:12:37 +02:00
injector.getInstance(UpdateUtility.class).updateChecker();
}
2019-03-18 19:49:22 +01:00
2020-02-19 23:55:43 +01:00
if (PremiumVerification.isPremium()) {
LOGGER.info("PlotSquared version licensed to Spigot user {}", getUserID());
LOGGER.info("https://www.spigotmc.org/resources/{}", getResourceID());
LOGGER.info("Download ID: {}", getDownloadID());
LOGGER.info("Thanks for supporting us :)");
2020-02-19 23:55:43 +01:00
} else {
LOGGER.info("Couldn't verify purchase :(");
2020-02-19 23:55:43 +01:00
}
2020-07-14 18:49:40 +02:00
// Database
if (Settings.Enabled_Components.DATABASE) {
plotSquared.setupDatabase();
}
// Check if we need to convert old flag values, etc
if (!plotSquared.getConfigurationVersion().equalsIgnoreCase("v5")) {
// Perform upgrade
if (DBFunc.dbManager.convertFlags()) {
LOGGER.info("Flags were converted successfully!");
2020-07-14 18:49:40 +02:00
// Update the config version
try {
plotSquared.setConfigurationVersion("v5");
} catch (final Exception e) {
e.printStackTrace();
}
}
}
// Comments
CommentManager.registerDefaultInboxes();
2020-07-10 22:12:37 +02:00
// Do stuff that was previously done in PlotSquared
// Kill entities
2020-07-24 17:24:53 +02:00
if (Settings.Enabled_Components.KILL_ROAD_MOBS || Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
2020-07-10 22:12:37 +02:00
this.runEntityTask();
}
// WorldEdit
if (Settings.Enabled_Components.WORLDEDIT_RESTRICTIONS) {
try {
WorldEdit.getInstance().getEventBus().register(this.injector().getInstance(WESubscriber.class));
2021-06-08 19:36:45 +02:00
LOGGER.info("{} hooked into WorldEdit", this.pluginName());
2020-07-10 22:12:37 +02:00
} catch (Throwable e) {
LOGGER.error(
"Incompatible version of WorldEdit, please upgrade: https://builds.enginehub.org/job/worldedit?branch=master");
2020-07-10 22:12:37 +02:00
}
}
if (Settings.Enabled_Components.EVENTS) {
getServer().getPluginManager().registerEvents(injector().getInstance(PlayerEventListener.class), this);
getServer().getPluginManager().registerEvents(injector().getInstance(BlockEventListener.class), this);
2021-06-26 21:08:25 +02:00
if (serverVersion()[1] >= 17) {
getServer().getPluginManager().registerEvents(injector().getInstance(BlockEventListener117.class), this);
}
getServer().getPluginManager().registerEvents(injector().getInstance(EntityEventListener.class), this);
getServer().getPluginManager().registerEvents(injector().getInstance(ProjectileEventListener.class), this);
getServer().getPluginManager().registerEvents(injector().getInstance(ServerListener.class), this);
getServer().getPluginManager().registerEvents(injector().getInstance(EntitySpawnListener.class), this);
2020-07-10 22:12:37 +02:00
if (PaperLib.isPaper() && Settings.Paper_Components.PAPER_LISTENERS) {
if (serverVersion()[1] == 13) {
getServer().getPluginManager().registerEvents(injector().getInstance(PaperListener113.class), this);
} else {
getServer().getPluginManager().registerEvents(injector().getInstance(PaperListener.class), this);
}
2020-07-10 22:12:37 +02:00
}
this.plotListener.startRunnable();
}
// Required
getServer().getPluginManager().registerEvents(injector().getInstance(WorldEvents.class), this);
2020-07-10 22:12:37 +02:00
if (Settings.Enabled_Components.CHUNK_PROCESSOR) {
getServer().getPluginManager().registerEvents(injector().getInstance(ChunkListener.class), this);
2020-07-10 22:12:37 +02:00
}
// Commands
if (Settings.Enabled_Components.COMMANDS) {
this.registerCommands();
2020-02-19 23:55:43 +01:00
}
// Permissions
this.permissionHandler().initialize();
2020-07-10 22:12:37 +02:00
if (Settings.Enabled_Components.COMPONENT_PRESETS) {
try {
injector().getInstance(ComponentPresetManager.class);
2020-07-10 22:12:37 +02:00
} catch (final Exception e) {
LOGGER.error("Failed to initialize the preset system", e);
2020-07-10 22:12:37 +02:00
}
}
// World generators:
final ConfigurationSection section = this.worldConfiguration.getConfigurationSection("worlds");
final WorldUtil worldUtil = injector().getInstance(WorldUtil.class);
2020-07-10 22:12:37 +02:00
if (section != null) {
for (String world : section.getKeys(false)) {
if (world.equals("CheckingPlotSquaredGenerator")) {
continue;
}
if (worldUtil.isWorld(world)) {
this.setGenerator(world);
}
}
TaskManager.runTaskLater(() -> {
for (String world : section.getKeys(false)) {
if (world.equals("CheckingPlotSquaredGenerator")) {
continue;
}
if (!worldUtil.isWorld(world) && !world.equals("*")) {
if (Settings.DEBUG) {
LOGGER.warn(
"`{}` was not properly loaded - {} will now try to load it properly",
world,
this.pluginName()
);
LOGGER.warn(
"- Are you trying to delete this world? Remember to remove it from the worlds.yml, bukkit.yml and multiverse worlds.yml");
LOGGER.warn("- Your world management plugin may be faulty (or non existent)");
LOGGER.warn("- The named world is not a plot world");
LOGGER.warn("This message may also be a false positive and could be ignored.");
}
2020-07-10 22:12:37 +02:00
this.setGenerator(world);
}
}
2020-07-15 13:18:09 +02:00
}, TaskTime.ticks(1L));
2020-07-10 22:12:37 +02:00
}
plotSquared.startExpiryTasks();
// Once the server has loaded force updating all generators known to PlotSquared
2021-09-07 15:47:37 +02:00
TaskManager.runTaskLater(() -> PlotSquared.platform().setupUtils().updateGenerators(true), TaskTime.ticks(1L));
2020-05-18 00:22:34 +02:00
// Services are accessed in order
2020-07-10 22:12:37 +02:00
final CacheUUIDService cacheUUIDService = new CacheUUIDService(Settings.UUID.UUID_CACHE_SIZE);
this.impromptuPipeline.registerService(cacheUUIDService);
this.backgroundPipeline.registerService(cacheUUIDService);
this.impromptuPipeline.registerConsumer(cacheUUIDService);
this.backgroundPipeline.registerConsumer(cacheUUIDService);
2020-05-18 00:22:34 +02:00
// Now, if the server is in offline mode we can only use profiles and direct UUID
// access, and so we skip the player profile stuff as well as SquirrelID (Mojang lookups)
if (Settings.UUID.OFFLINE) {
final OfflineModeUUIDService offlineModeUUIDService = new OfflineModeUUIDService();
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(offlineModeUUIDService);
this.backgroundPipeline.registerService(offlineModeUUIDService);
LOGGER.info("(UUID) Using the offline mode UUID service");
2020-05-18 00:22:34 +02:00
}
if (Settings.UUID.SERVICE_BUKKIT) {
final OfflinePlayerUUIDService offlinePlayerUUIDService = new OfflinePlayerUUIDService();
this.impromptuPipeline.registerService(offlinePlayerUUIDService);
this.backgroundPipeline.registerService(offlinePlayerUUIDService);
}
2020-05-20 15:12:09 +02:00
final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService("user_cache.db");
final SQLiteUUIDService legacyUUIDService;
if (Settings.UUID.LEGACY_DATABASE_SUPPORT && FileUtils
.getFile(PlotSquared.platform().getDirectory(), "usercache.db")
.exists()) {
legacyUUIDService = new SQLiteUUIDService("usercache.db");
} else {
legacyUUIDService = null;
}
final LuckPermsUUIDService luckPermsUUIDService;
2020-07-24 17:24:53 +02:00
if (Settings.UUID.SERVICE_LUCKPERMS && Bukkit.getPluginManager().getPlugin("LuckPerms") != null) {
luckPermsUUIDService = new LuckPermsUUIDService();
LOGGER.info("(UUID) Using LuckPerms as a complementary UUID service");
} else {
luckPermsUUIDService = null;
}
final EssentialsUUIDService essentialsUUIDService;
if (Settings.UUID.SERVICE_ESSENTIALSX && Bukkit.getPluginManager().getPlugin("Essentials") != null) {
essentialsUUIDService = new EssentialsUUIDService();
LOGGER.info("(UUID) Using EssentialsX as a complementary UUID service");
} else {
essentialsUUIDService = null;
}
2020-05-24 04:27:20 +02:00
if (!Settings.UUID.OFFLINE) {
2020-05-24 04:28:29 +02:00
// If running Paper we'll also try to use their profiles
if (Bukkit.getOnlineMode() && PaperLib.isPaper() && Settings.UUID.SERVICE_PAPER) {
2020-05-24 04:28:29 +02:00
final PaperUUIDService paperUUIDService = new PaperUUIDService();
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(paperUUIDService);
this.backgroundPipeline.registerService(paperUUIDService);
LOGGER.info("(UUID) Using Paper as a complementary UUID service");
2020-05-24 04:28:29 +02:00
}
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(sqLiteUUIDService);
this.backgroundPipeline.registerService(sqLiteUUIDService);
this.impromptuPipeline.registerConsumer(sqLiteUUIDService);
this.backgroundPipeline.registerConsumer(sqLiteUUIDService);
if (legacyUUIDService != null) {
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(legacyUUIDService);
this.backgroundPipeline.registerService(legacyUUIDService);
}
// Plugin providers
if (luckPermsUUIDService != null) {
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(luckPermsUUIDService);
this.backgroundPipeline.registerService(luckPermsUUIDService);
}
if (essentialsUUIDService != null) {
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(essentialsUUIDService);
this.backgroundPipeline.registerService(essentialsUUIDService);
}
if (Settings.UUID.IMPROMPTU_SERVICE_MOJANG_API) {
final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT);
this.impromptuPipeline.registerService(impromptuMojangService);
}
2020-07-24 17:24:53 +02:00
final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT);
2020-07-10 22:12:37 +02:00
this.backgroundPipeline.registerService(backgroundMojangService);
2020-05-20 15:12:09 +02:00
} else {
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(sqLiteUUIDService);
this.backgroundPipeline.registerService(sqLiteUUIDService);
this.impromptuPipeline.registerConsumer(sqLiteUUIDService);
this.backgroundPipeline.registerConsumer(sqLiteUUIDService);
if (legacyUUIDService != null) {
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.registerService(legacyUUIDService);
this.backgroundPipeline.registerService(legacyUUIDService);
}
2020-05-18 00:22:34 +02:00
}
2020-07-10 22:12:37 +02:00
this.impromptuPipeline.storeImmediately("*", DBFunc.EVERYONE);
if (Settings.UUID.BACKGROUND_CACHING_ENABLED) {
this.startUuidCaching(sqLiteUUIDService, cacheUUIDService);
}
2020-05-19 00:28:52 +02:00
2020-02-16 20:33:24 +01:00
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
injector.getInstance(PAPIPlaceholders.class).register();
if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) {
ChatFormatter.formatters.add(injector().getInstance(PlaceholderFormatter.class));
}
LOGGER.info("PlotSquared hooked into PlaceholderAPI");
2020-02-16 20:33:24 +01:00
}
2020-08-17 19:39:43 +02:00
this.startMetrics();
2020-08-14 11:36:17 +02:00
if (Settings.Enabled_Components.WORLDS) {
2020-07-17 16:38:07 +02:00
TaskManager.getPlatformImplementation().taskRepeat(this::unload, TaskTime.seconds(1L));
try {
singleWorldListener = injector().getInstance(SingleWorldListener.class);
2021-01-07 22:24:38 +01:00
Bukkit.getPluginManager().registerEvents(singleWorldListener, this);
} catch (Exception e) {
e.printStackTrace();
}
}
2020-05-10 14:02:25 +02:00
// Clean up potential memory leak
Bukkit.getScheduler().runTaskTimer(this, () -> {
try {
for (final PlotPlayer<? extends Player> player : this.playerManager().getPlayers()) {
if (player.getPlatformPlayer() == null || !player.getPlatformPlayer().isOnline()) {
this.playerManager().removePlayer(player);
}
}
} catch (final Exception e) {
getLogger().warning("Failed to clean up players: " + e.getMessage());
}
}, 100L, 100L);
2020-12-04 12:25:53 +01:00
2021-01-22 23:34:47 +01:00
// Check if we are in a safe environment
ServerLib.checkUnsafeForks();
}
private void unload() {
2018-08-10 20:46:38 +02:00
if (!this.methodUnloadSetup) {
this.methodUnloadSetup = true;
try {
ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
this.methodUnloadChunk0 = classCraftWorld.getRealClass().getDeclaredMethod(
"unloadChunk0",
int.class,
int.class,
boolean.class
);
2018-08-10 20:46:38 +02:00
this.methodUnloadChunk0.setAccessible(true);
} catch (Throwable event) {
event.printStackTrace();
}
}
2020-07-10 17:32:07 +02:00
if (this.plotAreaManager instanceof SinglePlotAreaManager) {
long start = System.currentTimeMillis();
2020-07-10 17:32:07 +02:00
final SinglePlotArea area = ((SinglePlotAreaManager) this.plotAreaManager).getArea();
2018-08-10 20:46:38 +02:00
outer:
2018-08-10 20:46:38 +02:00
for (final World world : Bukkit.getWorlds()) {
final String name = world.getName();
final char char0 = name.charAt(0);
if (!Character.isDigit(char0) && char0 != '-') {
2018-08-10 17:01:10 +02:00
continue;
2018-08-10 20:46:38 +02:00
}
if (!world.getPlayers().isEmpty()) {
continue;
}
PlotId id;
try {
id = PlotId.fromString(name);
} catch (IllegalArgumentException ignored) {
continue;
}
final Plot plot = area.getOwnedPlot(id);
if (plot != null) {
if (!plot.getFlag(ServerPlotFlag.class) || PlotSquared
.platform()
.playerManager()
.getPlayerIfExists(plot.getOwner()) == null) {
if (world.getKeepSpawnInMemory()) {
world.setKeepSpawnInMemory(false);
return;
}
final Chunk[] chunks = world.getLoadedChunks();
if (chunks.length == 0) {
if (!Bukkit.unloadWorld(world, true)) {
LOGGER.warn("Failed to unload {}", world.getName());
}
return;
} else {
int index = 0;
do {
final Chunk chunkI = chunks[index++];
boolean result;
if (methodUnloadChunk0 != null) {
try {
2020-07-24 17:24:53 +02:00
result = (boolean) methodUnloadChunk0.invoke(world, chunkI.getX(), chunkI.getZ(), true);
} catch (Throwable e) {
methodUnloadChunk0 = null;
e.printStackTrace();
continue outer;
}
} else {
2019-04-24 00:48:22 +02:00
result = world.unloadChunk(chunkI.getX(), chunkI.getZ(), true);
}
if (!result) {
continue outer;
}
if (System.currentTimeMillis() - start > 5) {
return;
}
} while (index < chunks.length);
}
}
}
}
}
}
private void startUuidCaching(
final @NonNull SQLiteUUIDService sqLiteUUIDService,
final @NonNull CacheUUIDService cacheUUIDService
) {
2020-05-20 15:12:09 +02:00
// Load all uuids into a big chunky boi queue
final Queue<UUID> uuidQueue = new LinkedBlockingQueue<>();
PlotSquared.get().forEachPlotRaw(plot -> {
final Set<UUID> uuids = new HashSet<>();
uuids.add(plot.getOwnerAbs());
uuids.addAll(plot.getMembers());
uuids.addAll(plot.getTrusted());
uuids.addAll(plot.getDenied());
for (final UUID uuid : uuids) {
if (!uuidQueue.contains(uuid)) {
uuidQueue.add(uuid);
}
}
});
LOGGER.info("(UUID) {} UUIDs will be cached", uuidQueue.size());
2020-05-20 15:12:09 +02:00
Executors.newSingleThreadScheduledExecutor().schedule(() -> {
// Begin by reading all the SQLite cache at once
cacheUUIDService.accept(sqLiteUUIDService.getAll());
// Now fetch names for all known UUIDs
final int totalSize = uuidQueue.size();
int read = 0;
LOGGER.info("(UUID) PlotSquared will fetch UUIDs in groups of {}", Settings.UUID.BACKGROUND_LIMIT);
2020-05-20 15:12:09 +02:00
final List<UUID> uuidList = new ArrayList<>(Settings.UUID.BACKGROUND_LIMIT);
// Used to indicate that the second retrieval has been attempted
boolean secondRun = false;
while (!uuidQueue.isEmpty() || !uuidList.isEmpty()) {
if (!uuidList.isEmpty() && secondRun) {
LOGGER.warn("(UUID) Giving up on last batch. Fetching new batch instead");
uuidList.clear();
}
if (uuidList.isEmpty()) {
// Retrieve the secondRun variable to indicate that we're retrieving a
// fresh batch
secondRun = false;
// Populate the request list
2020-07-24 17:24:53 +02:00
for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) {
uuidList.add(uuidQueue.poll());
read++;
}
} else {
// If the list isn't empty then this is a second run for
// an old batch, so we re-use the patch
secondRun = true;
2020-05-20 15:12:09 +02:00
}
try {
PlotSquared.get().getBackgroundUUIDPipeline().getNames(uuidList).get();
// Clear the list if we successfully index all the names
uuidList.clear();
// Print progress
final double percentage = ((double) read / (double) totalSize) * 100.0D;
if (Settings.DEBUG) {
LOGGER.info("(UUID) PlotSquared has cached {} of UUIDs", String.format("%.1f%%", percentage));
}
2020-05-20 15:12:09 +02:00
} catch (final InterruptedException | ExecutionException e) {
LOGGER.error("(UUID) Failed to retrieve last batch. Will try again", e);
2020-05-20 15:12:09 +02:00
}
}
LOGGER.info("(UUID) PlotSquared has cached all UUIDs");
2020-05-20 15:12:09 +02:00
}, 10, TimeUnit.SECONDS);
}
@Override
public void onDisable() {
PlotSquared.get().disable();
Bukkit.getScheduler().cancelTasks(this);
}
@Override
public void shutdown() {
this.getServer().getPluginManager().disablePlugin(this);
}
2020-07-10 22:12:37 +02:00
private void registerCommands() {
2018-08-10 20:46:38 +02:00
final BukkitCommand bukkitCommand = new BukkitCommand();
final PluginCommand plotCommand = getCommand("plots");
2019-09-08 20:02:45 +02:00
if (plotCommand != null) {
plotCommand.setExecutor(bukkitCommand);
plotCommand.setAliases(Arrays.asList("p", "ps", "plotme", "plot"));
plotCommand.setTabCompleter(bukkitCommand);
}
}
@Override
public @NonNull File getDirectory() {
return getDataFolder();
}
@Override
public @NonNull File worldContainer() {
return Bukkit.getWorldContainer();
}
@SuppressWarnings("deprecation")
private void runEntityTask() {
2020-07-10 17:32:07 +02:00
TaskManager.runTaskRepeat(() -> this.plotAreaManager.forEachPlotArea(plotArea -> {
final World world = Bukkit.getWorld(plotArea.getWorldName());
try {
if (world == null) {
return;
}
List<Entity> entities = world.getEntities();
Iterator<Entity> iterator = entities.iterator();
while (iterator.hasNext()) {
Entity entity = iterator.next();
2020-06-29 00:45:40 +02:00
switch (entity.getType().toString()) {
case "EGG":
case "FISHING_HOOK":
case "ENDER_SIGNAL":
case "AREA_EFFECT_CLOUD":
case "EXPERIENCE_ORB":
case "LEASH_HITCH":
case "FIREWORK":
case "LIGHTNING":
case "WITHER_SKULL":
case "UNKNOWN":
case "PLAYER":
// non moving / unmovable
continue;
2020-06-29 00:45:40 +02:00
case "THROWN_EXP_BOTTLE":
case "SPLASH_POTION":
case "SNOWBALL":
case "SHULKER_BULLET":
case "SPECTRAL_ARROW":
case "ENDER_PEARL":
case "ARROW":
case "LLAMA_SPIT":
case "TRIDENT":
// managed elsewhere | projectile
continue;
2020-06-29 00:45:40 +02:00
case "ITEM_FRAME":
case "PAINTING":
// Not vehicles
continue;
2020-06-29 00:45:40 +02:00
case "ARMOR_STAND":
// Temporarily classify as vehicle
2020-06-29 00:45:40 +02:00
case "MINECART":
case "MINECART_CHEST":
case "MINECART_COMMAND":
case "MINECART_FURNACE":
case "MINECART_HOPPER":
case "MINECART_MOB_SPAWNER":
case "ENDER_CRYSTAL":
case "MINECART_TNT":
case "BOAT":
if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
2020-07-24 17:24:53 +02:00
com.plotsquared.core.location.Location location = BukkitUtil.adapt(entity.getLocation());
Plot plot = location.getPlot();
if (plot == null) {
if (location.isPlotArea()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
continue;
}
List<MetadataValue> meta = entity.getMetadata("plot");
if (meta.isEmpty()) {
continue;
}
Plot origin = (Plot) meta.get(0).value();
if (!plot.equals(origin.getBasePlot(false))) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
}
continue;
2020-06-29 00:45:40 +02:00
case "SMALL_FIREBALL":
case "FIREBALL":
case "DRAGON_FIREBALL":
case "DROPPED_ITEM":
2020-07-24 17:24:53 +02:00
if (Settings.Enabled_Components.KILL_ROAD_ITEMS
&& plotArea.getOwnedPlotAbs(BukkitUtil.adapt(entity.getLocation())) == null) {
entity.remove();
}
// dropped item
continue;
2020-06-29 00:45:40 +02:00
case "PRIMED_TNT":
case "FALLING_BLOCK":
// managed elsewhere
continue;
2020-06-29 00:45:40 +02:00
case "SHULKER":
if (Settings.Enabled_Components.KILL_ROAD_MOBS) {
LivingEntity livingEntity = (LivingEntity) entity;
List<MetadataValue> meta = entity.getMetadata("shulkerPlot");
2019-04-23 19:45:24 +02:00
if (!meta.isEmpty()) {
if (livingEntity.isLeashed()) {
continue;
}
List<MetadataValue> keep = entity.getMetadata("keep");
2019-04-23 19:45:24 +02:00
if (!keep.isEmpty()) {
continue;
}
PlotId originalPlotId = (PlotId) meta.get(0).value();
if (originalPlotId != null) {
2020-07-24 17:24:53 +02:00
com.plotsquared.core.location.Location pLoc = BukkitUtil.adapt(entity.getLocation());
PlotArea area = pLoc.getPlotArea();
if (area != null) {
2020-07-18 11:05:16 +02:00
PlotId currentPlotId = area.getPlotAbs(pLoc).getId();
if (!originalPlotId.equals(currentPlotId) && (currentPlotId == null || !area.getPlot(
2021-08-18 11:58:18 +02:00
originalPlotId)
.equals(area.getPlot(currentPlotId)))) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
}
}
} else {
//This is to apply the metadata to already spawned shulkers (see EntitySpawnListener.java)
2020-07-24 17:24:53 +02:00
com.plotsquared.core.location.Location pLoc = BukkitUtil.adapt(entity.getLocation());
PlotArea area = pLoc.getPlotArea();
if (area != null) {
2020-07-18 11:05:16 +02:00
PlotId currentPlotId = area.getPlotAbs(pLoc).getId();
if (currentPlotId != null) {
entity.setMetadata(
"shulkerPlot",
new FixedMetadataValue((Plugin) PlotSquared.platform(), currentPlotId)
);
}
}
}
}
continue;
2020-06-29 00:45:40 +02:00
case "ZOMBIFIED_PIGLIN":
case "PIGLIN_BRUTE":
2020-06-29 00:45:40 +02:00
case "LLAMA":
case "DONKEY":
case "MULE":
case "ZOMBIE_HORSE":
case "SKELETON_HORSE":
case "HUSK":
case "ELDER_GUARDIAN":
case "WITHER_SKELETON":
case "STRAY":
case "ZOMBIE_VILLAGER":
case "EVOKER":
case "EVOKER_FANGS":
case "VEX":
case "VINDICATOR":
case "POLAR_BEAR":
case "BAT":
case "BLAZE":
case "CAVE_SPIDER":
case "CHICKEN":
case "COW":
case "CREEPER":
case "ENDERMAN":
case "ENDERMITE":
case "ENDER_DRAGON":
case "GHAST":
case "GIANT":
case "GUARDIAN":
case "HORSE":
case "IRON_GOLEM":
case "MAGMA_CUBE":
case "MUSHROOM_COW":
case "OCELOT":
case "PIG":
case "PIG_ZOMBIE":
case "RABBIT":
case "SHEEP":
case "SILVERFISH":
case "SKELETON":
case "SLIME":
case "SNOWMAN":
case "SPIDER":
case "SQUID":
case "VILLAGER":
case "WITCH":
case "WITHER":
case "WOLF":
case "ZOMBIE":
case "PARROT":
case "SALMON":
case "DOLPHIN":
case "TROPICAL_FISH":
case "DROWNED":
case "COD":
case "TURTLE":
case "PUFFERFISH":
case "PHANTOM":
case "ILLUSIONER":
case "CAT":
case "PANDA":
case "FOX":
case "PILLAGER":
case "TRADER_LLAMA":
case "WANDERING_TRADER":
case "RAVAGER":
case "BEE":
case "HOGLIN":
case "PIGLIN":
case "ZOGLIN":
default: {
if (Settings.Enabled_Components.KILL_ROAD_MOBS) {
Location location = entity.getLocation();
if (BukkitUtil.adapt(location).isPlotRoad()) {
if (entity instanceof LivingEntity livingEntity) {
if ((Settings.Enabled_Components.KILL_OWNED_ROAD_MOBS || !livingEntity.isLeashed())
|| !entity.hasMetadata("keep")) {
Entity passenger = entity.getPassenger();
if ((Settings.Enabled_Components.KILL_OWNED_ROAD_MOBS
|| !(passenger instanceof Player)) && entity.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
2019-02-11 00:03:14 +01:00
}
iterator.remove();
entity.remove();
2019-02-11 00:03:14 +01:00
}
}
} else {
Entity passenger = entity.getPassenger();
if ((Settings.Enabled_Components.KILL_OWNED_ROAD_MOBS
|| !(passenger instanceof Player)) && entity.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
}
}
}
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
2020-07-15 13:18:09 +02:00
}), TaskTime.seconds(1L));
}
@Override
2021-08-18 11:58:18 +02:00
public @Nullable
final ChunkGenerator getDefaultWorldGenerator(
2021-01-10 00:01:48 +01:00
final @NonNull String worldName,
2021-08-18 11:58:18 +02:00
final @Nullable String id
) {
Merge branch 'master' into breaking # Conflicts: # Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/events/PlotRateEvent.java # Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEventUtil.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Add.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Auto.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Delete.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Kick.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Load.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Music.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Owner.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Reload.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/SchematicCmd.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Trust.java # Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flag/GameModeFlag.java # Core/src/main/java/com/intellectualcrafters/plot/commands/Clear.java # Core/src/main/java/com/intellectualcrafters/plot/commands/PluginCmd.java # Core/src/main/java/com/intellectualcrafters/plot/commands/Relight.java # Core/src/main/java/com/intellectualcrafters/plot/commands/SetHome.java # Core/src/main/java/com/intellectualcrafters/plot/config/C.java # Core/src/main/java/com/intellectualcrafters/plot/config/Configuration.java # Core/src/main/java/com/intellectualcrafters/plot/config/Settings.java # Core/src/test/java/com/github/intellectualsites/plotsquared/plot/util/EventUtilTest.java # Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitEventUtil.java # README.md # Sponge/src/main/java/com/github/intellectualsites/plotsquared/sponge/events/PlotRateEvent.java # Sponge/src/main/java/com/github/intellectualsites/plotsquared/sponge/util/SpongeSchematicHandler.java # Sponge/src/main/java/com/github/intellectualsites/plotsquared/sponge/util/block/SpongeLocalQueue.java # Sponge/src/main/java/com/plotsquared/sponge/util/SpongeEventUtil.java
2018-11-14 15:44:07 +01:00
final IndependentPlotGenerator result;
if (id != null && id.equalsIgnoreCase("single")) {
result = injector().getInstance(SingleWorldGenerator.class);
} else {
result = injector().getInstance(Key.get(IndependentPlotGenerator.class, DefaultGenerator.class));
if (!PlotSquared.get().setupPlotWorld(worldName, id, result)) {
return null;
}
}
return (ChunkGenerator) result.specify(worldName);
}
@Override
2021-01-10 00:01:48 +01:00
public @Nullable GeneratorWrapper<?> getGenerator(
final @NonNull String world,
final @Nullable String name
) {
if (name == null) {
return null;
}
2018-08-10 20:46:38 +02:00
final Plugin genPlugin = Bukkit.getPluginManager().getPlugin(name);
if (genPlugin != null && genPlugin.isEnabled()) {
ChunkGenerator gen = genPlugin.getDefaultWorldGenerator(world, "");
if (gen instanceof GeneratorWrapper<?>) {
return (GeneratorWrapper<?>) gen;
}
2020-07-10 17:32:07 +02:00
return new BukkitPlotGenerator(world, gen, this.plotAreaManager);
} else {
2021-08-18 11:58:18 +02:00
return new BukkitPlotGenerator(
world,
injector().getInstance(Key.get(IndependentPlotGenerator.class, DefaultGenerator.class)),
this.plotAreaManager
);
}
}
@Override
public void startMetrics() {
if (this.metricsStarted) {
return;
}
this.metricsStarted = true;
2020-08-17 19:39:43 +02:00
Metrics metrics = new Metrics(this, BSTATS_ID); // bstats
2021-01-24 10:39:03 +01:00
metrics.addCustomChart(new DrilldownPie("area_types", () -> {
final Map<String, Map<String, Integer>> map = new HashMap<>();
for (final PlotAreaType plotAreaType : PlotAreaType.values()) {
final Map<String, Integer> terrainTypes = new HashMap<>();
for (final PlotAreaTerrainType plotAreaTerrainType : PlotAreaTerrainType.values()) {
terrainTypes.put(plotAreaTerrainType.name().toLowerCase(), 0);
}
map.put(plotAreaType.name().toLowerCase(), terrainTypes);
}
2020-07-10 17:32:07 +02:00
for (final PlotArea plotArea : this.plotAreaManager.getAllPlotAreas()) {
2020-07-24 17:24:53 +02:00
final Map<String, Integer> terrainTypeMap = map.get(plotArea.getType().name().toLowerCase());
terrainTypeMap.put(
plotArea.getTerrain().name().toLowerCase(),
terrainTypeMap.get(plotArea.getTerrain().name().toLowerCase()) + 1
);
}
return map;
}));
2021-01-24 10:39:03 +01:00
metrics.addCustomChart(new SimplePie(
"premium",
() -> PremiumVerification.isPremium() ? "Premium" : "Non-Premium"
));
2021-01-24 10:39:03 +01:00
metrics.addCustomChart(new SimplePie("worlds", () -> Settings.Enabled_Components.WORLDS ? "true" : "false"));
metrics.addCustomChart(new SimplePie("economy", () -> Settings.Enabled_Components.ECONOMY ? "true" : "false"));
metrics.addCustomChart(new SimplePie(
"plot_expiry",
() -> Settings.Enabled_Components.PLOT_EXPIRY ? "true" : "false"
));
2021-01-24 10:39:03 +01:00
metrics.addCustomChart(new SimplePie("database_type", () -> Storage.MySQL.USE ? "MySQL" : "SQLite"));
metrics.addCustomChart(new SimplePie(
"worldedit_implementation",
() -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ? "FastAsyncWorldEdit" : "WorldEdit"
));
2021-02-22 15:18:20 +01:00
metrics.addCustomChart(new SimplePie("offline_mode", () -> Settings.UUID.OFFLINE ? "true" : "false"));
metrics.addCustomChart(new SimplePie("offline_mode_force", () -> Settings.UUID.FORCE_LOWERCASE ? "true" : "false"));
}
@Override
public void unregister(final @NonNull PlotPlayer<?> player) {
PlotSquared.platform().playerManager().removePlayer(player.getUUID());
}
@Override
public void setGenerator(final @NonNull String worldName) {
World world = BukkitUtil.getWorld(worldName);
if (world == null) {
// create world
2020-07-10 19:25:05 +02:00
ConfigurationSection worldConfig = this.worldConfiguration.getConfigurationSection("worlds." + worldName);
String manager = worldConfig.getString("generator.plugin", pluginName());
2020-07-24 17:24:53 +02:00
PlotAreaBuilder builder =
PlotAreaBuilder.newBuilder().plotManager(manager).generatorName(worldConfig.getString(
2021-08-18 11:58:18 +02:00
"generator.init",
manager
))
.plotAreaType(ConfigurationUtil.getType(worldConfig)).terrainType(ConfigurationUtil.getTerrain(
2021-08-18 11:58:18 +02:00
worldConfig))
.settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)).worldName(worldName);
injector().getInstance(SetupUtils.class).setupWorld(builder);
world = Bukkit.getWorld(worldName);
} else {
try {
2020-07-10 17:32:07 +02:00
if (!this.plotAreaManager.hasPlotArea(worldName)) {
SetGenCB.setGenerator(BukkitUtil.getWorld(worldName));
}
} catch (final Exception e) {
LOGGER.error("Failed to reload world: {} | {}", world, e.getMessage());
Bukkit.getServer().unloadWorld(world, false);
return;
}
}
2019-04-23 19:45:24 +02:00
assert world != null;
ChunkGenerator gen = world.getGenerator();
if (gen instanceof BukkitPlotGenerator) {
PlotSquared.get().loadWorld(worldName, (BukkitPlotGenerator) gen);
} else if (gen != null) {
2020-07-10 17:32:07 +02:00
PlotSquared.get().loadWorld(worldName, new BukkitPlotGenerator(worldName, gen, this.plotAreaManager));
2020-07-10 19:25:05 +02:00
} else if (this.worldConfiguration.contains("worlds." + worldName)) {
PlotSquared.get().loadWorld(worldName, null);
}
}
@Override
public @NonNull String serverNativePackage() {
2018-08-10 20:46:38 +02:00
final String name = Bukkit.getServer().getClass().getPackage().getName();
return name.substring(name.lastIndexOf('.') + 1);
}
@Override
public @NonNull GeneratorWrapper<?> wrapPlotGenerator(
2021-01-10 00:01:48 +01:00
final @NonNull String world,
final @NonNull IndependentPlotGenerator generator
) {
2020-07-10 17:32:07 +02:00
return new BukkitPlotGenerator(world, generator, this.plotAreaManager);
}
@Override
public @NonNull String pluginsFormatted() {
2020-10-04 18:19:29 +02:00
StringBuilder msg = new StringBuilder();
List<Plugin> plugins = new ArrayList<>();
Collections.addAll(plugins, Bukkit.getServer().getPluginManager().getPlugins());
plugins.sort(Comparator.comparing(Plugin::getName));
msg.append("Plugins (").append(plugins.size()).append("): \n");
2020-10-04 18:19:29 +02:00
for (Plugin p : plugins) {
msg.append(" - ").append(p.getName()).append(":").append("\n")
.append(" • Version: ").append(p.getDescription().getVersion()).append("\n")
.append(" • Enabled: ").append(p.isEnabled()).append("\n")
.append(" • Main: ").append(p.getDescription().getMain()).append("\n")
.append(" • Authors: ").append(p.getDescription().getAuthors()).append("\n")
.append(" • Load Before: ").append(p.getDescription().getLoadBefore()).append("\n")
.append(" • Dependencies: ").append(p.getDescription().getDepend()).append("\n")
.append(" • Soft Dependencies: ").append(p.getDescription().getSoftDepend()).append("\n");
}
2020-10-04 18:19:29 +02:00
return msg.toString();
}
2019-11-04 22:55:40 +01:00
@Override
@SuppressWarnings("ConstantConditions")
public @NonNull String worldEditImplementations() {
StringBuilder msg = new StringBuilder();
if (Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null) {
msg.append("FastAsyncWorldEdit: ").append(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit").getDescription().getVersion());
} else if (Bukkit.getPluginManager().getPlugin("AsyncWorldEdit") != null) {
msg.append("AsyncWorldEdit: ").append(Bukkit.getPluginManager().getPlugin("AsyncWorldEdit").getDescription().getVersion()).append("\n");
msg.append("WorldEdit: ").append(Bukkit.getPluginManager().getPlugin("WorldEdit").getDescription().getVersion());
} else {
msg.append("WorldEdit: ").append(Bukkit.getPluginManager().getPlugin("WorldEdit").getDescription().getVersion());
}
return msg.toString();
}
@Override
public com.plotsquared.core.location.@NonNull World<?> getPlatformWorld(final @NonNull String worldName) {
return BukkitWorld.of(worldName);
}
@Override
public @NonNull Audience consoleAudience() {
return BukkitUtil.BUKKIT_AUDIENCES.console();
2020-07-05 18:14:29 +02:00
}
@Override
public @NonNull String pluginName() {
2020-07-17 17:24:45 +02:00
return this.pluginName;
}
public SingleWorldListener getSingleWorldListener() {
return this.singleWorldListener;
}
@Override
public @NonNull Injector injector() {
2020-07-17 17:24:45 +02:00
return this.injector;
}
2020-07-22 21:06:23 +02:00
@Override
public @NonNull PlotAreaManager plotAreaManager() {
return this.plotAreaManager;
}
@NonNull
@Override
public Locale getLocale() {
2020-07-22 21:06:23 +02:00
return this.serverLocale;
}
@Override
public void setLocale(final @NonNull Locale locale) {
2020-07-22 21:06:23 +02:00
throw new UnsupportedOperationException("Cannot replace server locale");
}
@Override
public @NonNull PlatformWorldManager<?> worldManager() {
return injector().getInstance(Key.get(new TypeLiteral<PlatformWorldManager<World>>() {
2020-07-24 17:24:53 +02:00
}));
2020-07-23 14:56:06 +02:00
}
@Override
@NonNull
@SuppressWarnings("unchecked")
public PlayerManager<? extends PlotPlayer<Player>, ? extends Player> playerManager() {
return (PlayerManager<BukkitPlayer, Player>) injector().getInstance(PlayerManager.class);
2020-07-23 15:03:27 +02:00
}
@Override
public void copyCaptionMaps() {
/* Make this prettier at some point */
final String[] languages = new String[]{"en"};
for (final String language : languages) {
if (!new File(new File(this.getDataFolder(), "lang"), String.format("messages_%s.json", language)).exists()) {
this.saveResource(String.format("lang/messages_%s.json", language), false);
LOGGER.info("Copied language file 'messages_{}.json'", language);
}
}
}
@NonNull
@Override
2021-01-10 00:01:48 +01:00
public String toLegacyPlatformString(final @NonNull Component component) {
return LegacyComponentSerializer.legacyAmpersand().serialize(component);
}
2021-06-08 19:36:45 +02:00
@Override
public boolean isFaweHooking() {
return faweHook;
}
2018-08-10 17:01:10 +02:00
}