net.redstoneore.legacyfactions.Factions.java Source code

Java tutorial

Introduction

Here is the source code for net.redstoneore.legacyfactions.Factions.java

Source

package net.redstoneore.legacyfactions;

import java.io.IOException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import net.redstoneore.legacyfactions.adapter.CrossColourAdapter;
import net.redstoneore.legacyfactions.adapter.CrossEntityTypeAdapter;
import net.redstoneore.legacyfactions.adapter.LazyLocationAdapter;
import net.redstoneore.legacyfactions.adapter.MapFlocationSetAdapter;
import net.redstoneore.legacyfactions.adapter.MapLocalitySetAdapter;
import net.redstoneore.legacyfactions.cmd.CmdFactions;
import net.redstoneore.legacyfactions.config.CommandAliases;
import net.redstoneore.legacyfactions.config.Config;
import net.redstoneore.legacyfactions.config.meta.Meta;
import net.redstoneore.legacyfactions.entity.Board;
import net.redstoneore.legacyfactions.entity.FPlayerColl;
import net.redstoneore.legacyfactions.entity.FactionColl;
import net.redstoneore.legacyfactions.entity.persist.memory.json.FactionsJSON;
import net.redstoneore.legacyfactions.entity.persist.memory.json.JSONBoard;
import net.redstoneore.legacyfactions.entity.persist.memory.json.JSONFPlayerColl;
import net.redstoneore.legacyfactions.entity.persist.memory.json.JSONFactionColl;
import net.redstoneore.legacyfactions.expansion.FactionsExpansions;
import net.redstoneore.legacyfactions.expansion.Provider;
import net.redstoneore.legacyfactions.flag.Flags;
import net.redstoneore.legacyfactions.integration.Integrations;
import net.redstoneore.legacyfactions.integration.bstats.BStatsIntegration;
import net.redstoneore.legacyfactions.integration.conquer.ConquerIntegration;
import net.redstoneore.legacyfactions.integration.dynmap.DynmapIntegration;
import net.redstoneore.legacyfactions.integration.essentials.EssentialsIntegration;
import net.redstoneore.legacyfactions.integration.metrics.MetricsIntegration;
import net.redstoneore.legacyfactions.integration.novucsftop.NovucsFactionsTopIntegration;
import net.redstoneore.legacyfactions.integration.playervaults.PlayerVaultsIntegration;
import net.redstoneore.legacyfactions.integration.vault.VaultIntegration;
import net.redstoneore.legacyfactions.integration.venturechat.VentureChatIntegration;
import net.redstoneore.legacyfactions.integration.worldguard.WorldGuardIntegration;
import net.redstoneore.legacyfactions.lang.Lang;
import net.redstoneore.legacyfactions.listeners.AbstractConditionalListener;
import net.redstoneore.legacyfactions.listeners.FactionsArmorStandListener;
import net.redstoneore.legacyfactions.listeners.FactionsBlockListener;
import net.redstoneore.legacyfactions.listeners.FactionsCommandsListener;
import net.redstoneore.legacyfactions.listeners.FactionsEntityListener;
import net.redstoneore.legacyfactions.listeners.FactionsExploitListener;
import net.redstoneore.legacyfactions.listeners.FactionsPermissionGroups;
import net.redstoneore.legacyfactions.listeners.FactionsPlayerListener;
import net.redstoneore.legacyfactions.locality.Locality;
import net.redstoneore.legacyfactions.mixin.PlayerMixin;
import net.redstoneore.legacyfactions.placeholder.FactionsPlaceholders;
import net.redstoneore.legacyfactions.task.TaskManager;
import net.redstoneore.legacyfactions.util.LazyLocation;
import net.redstoneore.legacyfactions.util.LibraryUtil;
import net.redstoneore.legacyfactions.util.MiscUtil;
import net.redstoneore.legacyfactions.util.TextUtil;
import net.redstoneore.legacyfactions.util.cross.CrossColour;
import net.redstoneore.legacyfactions.util.cross.CrossEntityType;

import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.msgpack.jackson.dataformat.MessagePackFactory;

/**
 *  A high-performance maintained version of Factions 1.6.<br>
 *  Copyright (C) 2011 Olof Larsson  <br>
 *  Copyright (C) 2011 - 2017 contributors <br>
 *  <br>
 *  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.<br>
 *  <br>
 *  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.<br>
 *  <br>
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/
 *
 */
public class Factions extends FactionsPluginBase {

    // -------------------------------------------------- //
    // INSTANCE & CONSTRUCT 
    // -------------------------------------------------- //

    private static Factions instance = null;

    public static Factions get() {
        return instance;
    }

    // -------------------------------------------------- //
    // FIELDS
    // -------------------------------------------------- //

    private GsonBuilder gsonBuilder = null;

    private Gson gson = this.getGsonBuilder().create();

    private ObjectMapper objectMapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .setVisibility(PropertyAccessor.ALL, Visibility.NONE)
            .setVisibility(PropertyAccessor.FIELD, Visibility.ANY)

    ;

    private ObjectMapper msgPackobjectMapper = new ObjectMapper(new MessagePackFactory())
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .setVisibility(PropertyAccessor.ALL, Visibility.NONE)
            .setVisibility(PropertyAccessor.FIELD, Visibility.ANY)

    ;

    protected boolean loadSuccessful = false;

    // -------------------------------------------------- //
    // METHODS
    // -------------------------------------------------- //

    /**
     * Check if writing is currently locked.
     * @return true if locked
     */
    public boolean isLocked() {
        return Volatile.get().locked();
    }

    /**
     * Lock the database from writing. 
     * @param locked 
     */
    public void setLocked(boolean locked) {
        Volatile.get().locked(locked);
        this.setAutoSave(locked);
    }

    /**
     * Get the autosave state.
     * @return autosave state
     */
    public boolean getAutoSave() {
        return Volatile.get().autosave();
    }

    /**
     * Set the autosave state.
     * @param autoSave the autosave state.
     */
    public void setAutoSave(boolean autoSave) {
        Volatile.get().autosave(autoSave);
    }

    public Path getPluginFolder() {
        return Paths.get(this.getDataFolder().getAbsolutePath());
    }

    @Override
    public void enable() throws Exception {
        if (instance != null || Volatile.get().provider() != null) {
            this.warn("Unsafe reload detected!");
        }
        instance = this;

        this.loadSuccessful = false;

        this.loadLibraries();

        Volatile.get().provider(Provider.of("LegacyFactions", this));

        this.getDataFolder().mkdirs();

        this.migrations();

        this.timeEnableStart = System.currentTimeMillis();

        // Load meta from disk
        Meta.get().load().save();

        Lang.reload(null);

        // Load Conf from disk
        Config.loadSave();

        // Load command aliases from disk
        CommandAliases.load();
        CommandAliases.save();
        if (CommandAliases.baseCommandAliases == null || CommandAliases.baseCommandAliases.isEmpty()) {
            Factions.get().warn("Base command arguments were null or empty, reset to 'f'");
            CommandAliases.baseCommandAliases = Lists.newArrayList("f");
        }

        // Initialise our persist handler
        Config.backEnd.getHandler().init();

        if (this.getDescription().getVersion().contains("RC")
                || this.getDescription().getVersion().contains("SNAPSHOT")) {
            Config.debug = true;
            this.debug("Debug mode has been enabled for this snapshot.");
            this.debug("conf.json 'debug' has been set to 'true' ");
            this.debug("Please put this entire log file on pastebin.com when reporting an issue.");
            this.debug("To disable this type use the command `/f config debug false`");
            Config.save();
        }

        FPlayerColl.load();

        FactionColl.get().load();
        FactionColl.get().validate();

        Board.get().load();
        Board.get().clean();

        TaskManager.get().startTasks();

        // Add base commands.
        Volatile.get().baseCommands().add(CmdFactions.get());

        // Add our integrations.
        Integrations.add(VaultIntegration.get(), WorldGuardIntegration.get(), EssentialsIntegration.get(),
                PlayerVaultsIntegration.get(), MetricsIntegration.get(), BStatsIntegration.get(),
                VentureChatIntegration.get(), NovucsFactionsTopIntegration.get(), DynmapIntegration.get(),
                ConquerIntegration.get());

        // Sync expansions
        FactionsExpansions.sync();

        // Add our placeholders.
        FactionsPlaceholders.get().init();
        FactionsPlaceholders.get().adaptAll();

        // Register Event Handlers
        this.register(FactionsPlayerListener.get(), FactionsEntityListener.get(), FactionsExploitListener.get(),
                FactionsBlockListener.get(), FactionsArmorStandListener.get(), FactionsCommandsListener.get(),
                FactionsPermissionGroups.get());

        // since some other plugins execute commands directly through this command interface, provide it
        CommandAliases.baseCommandAliases.forEach(ref -> {
            if (ref != null) {
                this.getCommand(ref).setExecutor(this);
            }
        });

        this.loadSuccessful = true;

        FactionColl.all();

        // Initialise default flags.
        Flags.init();
    }

    private void migrations() throws IOException {
        // Move all database files in database folder 
        if (!Files.exists(FactionsJSON.getDatabasePath())) {
            Files.createDirectories(FactionsJSON.getDatabasePath());
        }

        Path oldBoardJson = this.getPluginFolder().resolve("board.json");
        Path oldFactionsJson = this.getPluginFolder().resolve("factions.json");
        Path oldPlayersJson = this.getPluginFolder().resolve("players.json");

        if (Files.exists(oldBoardJson)) {
            if (Files.exists(JSONBoard.getJsonFile())) {
                Files.move(JSONBoard.getJsonFile(), Paths.get(JSONBoard.getJsonFile().toString() + ".backup"));
                Factions.get().log("Moving 'database/board.json' -> 'database/board.json.backup'");
            }

            Files.move(oldBoardJson, JSONBoard.getJsonFile());
            Factions.get().log("Moving 'board.json' -> 'database/board.json'");
        }

        if (Files.exists(oldFactionsJson)) {
            if (Files.exists(JSONFactionColl.getJsonFile())) {
                Files.move(JSONFactionColl.getJsonFile(),
                        Paths.get(JSONFactionColl.getJsonFile().toString() + ".backup"));
                Factions.get().log("Moving 'database/factions.json' -> 'database/factions.json.backup'");
            }

            Files.move(oldFactionsJson, JSONFactionColl.getJsonFile());
            Factions.get().log("Moving 'factions.json' -> 'database/factions.json'");
        }

        if (Files.exists(oldPlayersJson)) {
            if (Files.exists(JSONFPlayerColl.getJsonFile())) {
                Files.move(JSONFPlayerColl.getJsonFile(),
                        Paths.get(JSONFPlayerColl.getJsonFile().toString() + ".backup"));
                Factions.get().log("Moving 'database/players.json' -> 'database/players.json.backup'");
            }

            Files.move(oldPlayersJson, JSONFPlayerColl.getJsonFile());
            Factions.get().log("Moving 'players.json' -> 'database/players.json'");
        }

        // using new .js format

        Path oldConfJson = this.getPluginFolder().resolve("conf.json");
        Path oldCommandAliasesJson = this.getPluginFolder().resolve("commandAliases.json");
        Path oldTagsJson = this.getPluginFolder().resolve("tags.json");

        Path newConfigJs = this.getPluginFolder().resolve("config.js");
        Path newCommandAliasesJs = this.getPluginFolder().resolve("commandAliases.js");
        Path newTagsJs = this.getPluginFolder().resolve("tags.js");

        if (Files.exists(oldConfJson)) {
            if (Files.exists(newConfigJs)) {
                Files.move(newConfigJs, Paths.get(newConfigJs.toString() + ".backup"),
                        StandardCopyOption.REPLACE_EXISTING);
                Factions.get().log("Moving 'config.js' -> 'config.js.backup'");
            }
            Files.move(oldConfJson, newConfigJs, StandardCopyOption.REPLACE_EXISTING);
            Factions.get().log("Moving 'config.json' -> 'config.js'");
        }

        if (Files.exists(oldCommandAliasesJson)) {
            if (Files.exists(newCommandAliasesJs)) {
                Files.move(newCommandAliasesJs, Paths.get(newCommandAliasesJs.toString() + ".backup"),
                        StandardCopyOption.REPLACE_EXISTING);
                Factions.get().log("Moving 'commandAliases.js' -> 'commandAliases.js.backup'");
            }
            Files.move(oldCommandAliasesJson, newCommandAliasesJs, StandardCopyOption.REPLACE_EXISTING);
            Factions.get().log("Moving 'commandAliases.json' -> 'commandAliases.js'");
        }

        if (Files.exists(oldTagsJson)) {
            if (Files.exists(newTagsJs)) {
                Files.move(newTagsJs, Paths.get(newTagsJs.toString() + ".backup"),
                        StandardCopyOption.REPLACE_EXISTING);
                Factions.get().log("Moving 'tags.js' -> 'tags.js.backup'");
            }
            Files.move(oldTagsJson, newTagsJs, StandardCopyOption.REPLACE_EXISTING);
            Factions.get().log("Moving 'tags.json' -> 'tags.js'");
        }

        // Move lang.yml to locale.yml

        Path localeOld = this.getPluginFolder().resolve("lang.yml");
        Path localeNew = this.getPluginFolder().resolve("locale.yml");

        if (Files.exists(localeOld)) {
            if (Files.exists(localeNew)) {
                Files.move(localeNew, Paths.get(localeNew.toString() + ".backup"),
                        StandardCopyOption.REPLACE_EXISTING);
                Factions.get().log("Moving 'locale.yml' -> 'locale.yml.backup'");
            }
            Files.move(localeOld, localeNew, StandardCopyOption.REPLACE_EXISTING);
            Factions.get().log("Moving 'lang.yml' -> 'locale.yml'");
        }

    }

    public Gson getGson() {
        return this.gson;
    }

    public ObjectMapper getObjectMapper() {
        return this.objectMapper;
    }

    public ObjectMapper getMsgPackObjectMapper() {
        return this.msgPackobjectMapper;
    }

    public GsonBuilder getGsonBuilder() {
        if (this.gsonBuilder == null) {
            Type mapFLocToStringSetType = new TypeToken<Map<FLocation, Set<String>>>() {
            }.getType();
            Type mapLocalityToStringSetType = new TypeToken<Map<Locality, Set<String>>>() {
            }.getType();
            GsonBuilder builder = new GsonBuilder().setPrettyPrinting();

            try {
                builder.setLenient();
            } catch (NoSuchMethodError e) {
                // older minecraft plugins don't have this in their version of Gson
            }

            this.gsonBuilder = builder.disableHtmlEscaping()
                    .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE)
                    .registerTypeAdapter(LazyLocation.class, new LazyLocationAdapter())
                    .registerTypeAdapter(mapFLocToStringSetType, new MapFlocationSetAdapter())
                    .registerTypeAdapter(mapLocalityToStringSetType, new MapLocalitySetAdapter())
                    .registerTypeAdapter(CrossColour.class, new CrossColourAdapter())
                    .registerTypeAdapter(CrossEntityType.class, new CrossEntityTypeAdapter())

            ;
        }

        return this.gsonBuilder;
    }

    @Override
    public void onDisable() {
        TaskManager.get().stopTasks();

        if (this.loadSuccessful) {
            // Only save data if plugin actually completely loaded successfully
            Config.save();
            CommandAliases.save();
            FactionColl.get().forceSave();
            FPlayerColl.save();
            Board.get().forceSave();
        }
    }

    @Override
    public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) {
        return sender instanceof Player
                && FactionsCommandsListener.get().preventCommand(commandString, (Player) sender, testOnly)
                || super.handleCommand(sender, commandString, testOnly);
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] split) {
        if (split.length == 0)
            return this.handleCommand(sender, "/f help", false);

        // otherwise, needs to be handled; presumably another plugin directly ran the command
        String cmd = CommandAliases.baseCommandAliases.isEmpty() ? "/f"
                : "/" + CommandAliases.baseCommandAliases.get(0);
        return this.handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false);
    }

    private void loadLibraries() {
        if (!MiscUtil.classExists("com.github.benmanes.caffeine.cache.Caffeine")) {
            try {
                LibraryUtil.loadLibrary(
                        "https://repo1.maven.org/maven2/com/github/ben-manes/caffeine/caffeine/2.5.5/caffeine-2.5.5.jar");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (!MiscUtil.classExists("org.apache.commons.io.Charsets")) {
            try {
                LibraryUtil.loadLibrary(
                        "https://repo1.maven.org/maven2/org/apache/commons/commons-io/1.3.2/commons-io-1.3.2.jar");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // -------------------------------------------------- //
    // LISTENERS
    // -------------------------------------------------- //

    public void register(Listener... listeners) {
        for (Listener listener : listeners) {
            if (listener instanceof AbstractConditionalListener) {
                AbstractConditionalListener conditionalListener = (AbstractConditionalListener) listener;
                if (conditionalListener.shouldEnable()) {
                    this.getServer().getPluginManager().registerEvents(listener, this);
                }
            } else {
                this.getServer().getPluginManager().registerEvents(listener, this);
            }
        }
    }

    // -------------------------------------------------- //
    // DEPRECATED
    // -------------------------------------------------- //

    /**
     * Deprecated, use {@link PlayerMixin#shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent)}
     */
    @Deprecated
    public boolean shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent event) {
        return PlayerMixin.shouldLetFactionsHandleThisChat(event);
    }

    /**
     * Deprecated, use {@link PlayerMixin#isPlayerFactionChatting(Player)}
     */
    @Deprecated
    public boolean isPlayerFactionChatting(Player player) {
        return PlayerMixin.isPlayerFactionChatting(player);
    }

    /**
     * Deprecated, use {@link PlayerMixin#isFactionsCommand(Player, String)}
     */
    @Deprecated
    public boolean isFactionsCommand(Player player, String check) {
        return PlayerMixin.isFactionsCommand(player, check);
    }

    /**
     * Deprecated, use {@link PlayerMixin#getPlayerFactionTag(Player)}
     */
    @Deprecated
    public String getPlayerFactionTag(Player player) {
        return PlayerMixin.getPlayerFactionTag(player);
    }

    /**
     * Deprecated, use {@link PlayerMixin#getPlayerFactionTagRelation(Player, Player)}
     */
    @Deprecated
    public String getPlayerFactionTagRelation(Player speaker, Player listener) {
        return PlayerMixin.getPlayerFactionTagRelation(speaker, listener);
    }
}