io.github.mywarp.mywarp.bukkit.MyWarpPlugin.java Source code

Java tutorial

Introduction

Here is the source code for io.github.mywarp.mywarp.bukkit.MyWarpPlugin.java

Source

/*
 * Copyright (C) 2011 - 2018, MyWarp team and contributors
 *
 * This file is part of MyWarp.
 *
 * MyWarp 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.
 *
 * MyWarp 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 MyWarp. If not, see <http://www.gnu.org/licenses/>.
 */

package io.github.mywarp.mywarp.bukkit;

import static com.google.common.base.Preconditions.checkState;

import io.github.mywarp.mywarp.MyWarp;
import io.github.mywarp.mywarp.bukkit.settings.BukkitSettings;
import io.github.mywarp.mywarp.bukkit.util.conversation.AcceptancePromptFactory;
import io.github.mywarp.mywarp.bukkit.util.conversation.WelcomeEditorFactory;
import io.github.mywarp.mywarp.bukkit.util.jdbc.JdbcConfiguration;
import io.github.mywarp.mywarp.bukkit.util.material.ConfigurableMaterialInfo;
import io.github.mywarp.mywarp.bukkit.util.material.MaterialInfo;
import io.github.mywarp.mywarp.bukkit.util.permission.BukkitPermissionsRegistration;
import io.github.mywarp.mywarp.bukkit.util.permission.group.GroupResolver;
import io.github.mywarp.mywarp.bukkit.util.permission.group.GroupResolverFactory;
import io.github.mywarp.mywarp.platform.Actor;
import io.github.mywarp.mywarp.platform.InvalidFormatException;
import io.github.mywarp.mywarp.platform.LocalPlayer;
import io.github.mywarp.mywarp.util.MyWarpLogger;
import io.github.mywarp.mywarp.util.i18n.DynamicMessages;
import io.github.mywarp.mywarp.util.i18n.FolderSourcedControl;
import io.github.mywarp.mywarp.util.i18n.LocaleManager;
import io.github.mywarp.mywarp.warp.Warp;
import io.github.mywarp.mywarp.warp.storage.SqlDataService;
import io.github.mywarp.mywarp.warp.storage.StorageInitializationException;

import org.apache.commons.lang.text.StrBuilder;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.dynmap.DynmapCommonAPI;
import org.slf4j.Logger;

import java.io.Closeable;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.WeakHashMap;

import javax.annotation.Nullable;

/**
 * The MyWarp plugin singleton when running on Bukkit.
 *
 * <p>This class is loaded by Bukkit when the plugin is initialized.</p>
 */
public final class MyWarpPlugin extends JavaPlugin {

    public static final String CONVERSATION_RESOURCE_BUNDLE_NAME = "io.github.mywarp.mywarp.lang.Conversations";
    public static final int CONVERSATION_TIMEOUT = 30;

    private static final Logger log = MyWarpLogger.getLogger(MyWarpPlugin.class);

    private final ResourceBundle.Control control = new FolderSourcedControl(new File(getDataFolder(), "lang"));
    private final Set<AutoCloseable> closeables = Collections
            .newSetFromMap(new WeakHashMap<AutoCloseable, Boolean>());

    private BukkitPlatform platform;
    private MyWarp myWarp;
    private GroupResolver groupResolver;
    private AcceptancePromptFactory acceptancePromptFactory;
    private WelcomeEditorFactory welcomeEditorFactory;

    @Nullable
    private DynmapMarker marker;

    @Override
    public void onEnable() {

        // initialize platform
        DynamicMessages.setControl(control);
        File dataFolder = getDataFolder();
        if (!dataFolder.exists()) {
            if (!dataFolder.mkdirs()) {
                log.error("Failed to create MyWarp's data-folder: " + dataFolder);
                log.error("MyWarp is unable to continue and will be disabled.");
                Bukkit.getPluginManager().disablePlugin(this);
                return;
            }
        }
        platform = new BukkitPlatform(this, dataFolder,
                YamlConfiguration.loadConfiguration(this.getTextResource("config.yml")));

        // setup the core
        try {
            myWarp = MyWarp.initialize(platform, createDataService(getSettings().getJdbcStorageConfiguration()));
        } catch (StorageInitializationException | InvalidFormatException e) {
            log.error("Failed to initialize warp storage.", e);
            log.error("MyWarp is unable to continue and will be disabled.");
            Bukkit.getPluginManager().disablePlugin(this);
            return;
        }

        // further platform-specific objects
        groupResolver = GroupResolverFactory.createResolver();
        acceptancePromptFactory = new AcceptancePromptFactory(createConversationFactory(),
                myWarp.getAuthorizationResolver(), platform.getGame(), platform.getPlayerNameResolver(), this);
        welcomeEditorFactory = new WelcomeEditorFactory(createConversationFactory());

        notifyCoreInitialized();
    }

    @Override
    public void onDisable() {
        unregister();

        //close any registered Closables
        for (AutoCloseable closeable : closeables) {
            try {
                closeable.close();
            } catch (Exception e) {
                log.warn("Failed to close " + closeable.getClass().getCanonicalName(), e);
            }
        }
    }

    /**
     * Notifies the MyWarpPlugin instance that the core is fully initialized.
     */
    void notifyCoreInitialized() {

        //register profile service listener
        getProfileCache().registerEvents(this);

        //register warp sign listener
        if (getSettings().isWarpSignsEnabled()) {
            new WarpSignListener(this, myWarp.createWarpSignHandler()).registerEvents(this);
        }

        // register world access permissions
        for (World loadedWorld : Bukkit.getWorlds()) {
            Permission perm = new Permission("mywarp.world-access." + loadedWorld.getName());
            perm.addParent("mywarp.world-access.*", true);
            BukkitPermissionsRegistration.INSTANCE.register(perm);
        }
    }

    /**
     * Notifies the MyWarpPlugin instance about the availability of warps, so that it can execute additional callback (if
     * any).
     */
    void notifyWarpAvailability() {
        if (getSettings().isDynmapEnabled()) {
            Plugin dynmap = getServer().getPluginManager().getPlugin("dynmap");
            if (dynmap != null && dynmap.isEnabled() && dynmap instanceof DynmapCommonAPI) {
                marker = new DynmapMarker((DynmapCommonAPI) dynmap, this, platform,
                        w -> w.isType(Warp.Type.PUBLIC));
                marker.addMarker(myWarp.getWarpManager().getAll(warp -> true));
                myWarp.getEventBus().register(marker);
            } else {
                log.error("Failed to hook into Dynmap. Disabling Dynmap support.");
            }
        }
    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        Actor actor = wrap(sender);

        // set the locale for this command session
        LocaleManager.setLocale(actor.getLocale());

        // create the command string
        StrBuilder builder = new StrBuilder();
        builder.append(label);
        for (String argument : args) {
            builder.appendSeparator(' ');
            builder.append(argument);
        }
        myWarp.getCommandHandler().callCommand(builder.toString(), actor);
        return true;
    }

    @Override
    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
        Actor actor = wrap(sender);

        // set the locale for this command session
        LocaleManager.setLocale(actor.getLocale());

        // create the command string
        StrBuilder builder = new StrBuilder();
        builder.append(alias);
        for (String argument : args) {
            builder.appendSeparator(' ');
            builder.append(argument);
        }
        return myWarp.getCommandHandler().getSuggestions(builder.toString(), actor);
    }

    /**
     * Creates a new Actor instance by wrapping the given Bukkit {@code commandSender}.
     *
     * @param commandSender the CommandSender to wrap
     * @return a new Actor referencing the {@code commandSender}
     */
    public Actor wrap(CommandSender commandSender) {
        if (commandSender instanceof Player) {
            return wrap((Player) commandSender);
        }
        return new BukkitActor(commandSender, getSettings());
    }

    /**
     * Creates a new LocalPlayer instance by wrapping the given Bukkit {@code player}.
     *
     * @param player the Player to wrap
     * @return a new LocalPlayer referencing the {@code player}
     */
    public LocalPlayer wrap(Player player) {
        return new BukkitPlayer(player, getAcceptancePromptFactory(), getWelcomeEditorFactory(), getGroupResolver(),
                getSettings());
    }

    /**
     * Gets the GroupResolver that resolve's a player's group.
     *
     * @return the configured GroupResolver
     */
    GroupResolver getGroupResolver() {
        checkState(groupResolver != null, "'groupResolver' is not yet initialized");
        return groupResolver;
    }

    /**
     * Gets the conversation factory for welcome editor conversations.
     *
     * @return the configured welcome editor factory
     */
    WelcomeEditorFactory getWelcomeEditorFactory() {
        checkState(welcomeEditorFactory != null, "'welcomeEditorFactory' is not yet initialized");
        return welcomeEditorFactory;
    }

    /**
     * Gets the conversation factory for warp acceptance conversations.
     *
     * @return the configured acceptance prompt factory
     */
    AcceptancePromptFactory getAcceptancePromptFactory() {
        checkState(acceptancePromptFactory != null, "'acceptancePromptFactory' is not yet initialized");
        return acceptancePromptFactory;
    }

    /**
     * Gets the BukkitSettings instance that provides access to MyWarp's settings.
     *
     * @return the configured settings
     */
    protected BukkitSettings getSettings() {
        checkState(platform != null, "'platform' is not yet initialized");
        return platform.getSettings();
    }

    /**
     * Gets the PlayerNameResolver that stored Profiles for known players.
     *
     * @return the configured PlayerNameResolver
     */
    SquirrelIdPlayerNameResolver getProfileCache() {
        checkState(platform != null, "'platform' is not yet initialized");
        return platform.getPlayerNameResolver();
    }

    /**
     * Registers the given {@code closable} for closure when the plugin is disabled.
     *
     * <p>Registered Closables will be stored within a {@link WeakReference}. If MyWarp is disabled by
     * Bukkit and the reference is still valid, {@link Closeable#close()} is invoked.</p>
     *
     * @param closeable the Closable to register
     */
    void registerClosable(AutoCloseable closeable) {
        closeables.add(closeable);
    }

    private ConversationFactory createConversationFactory() {
        return new ConversationFactory(this).withModality(true).withTimeout(CONVERSATION_TIMEOUT);
    }

    /**
     * Unregisters all permissions registered by MyWarp, all active event-listeners and all created markers (if any).
     */
    void unregister() {
        HandlerList.unregisterAll(this);
        BukkitPermissionsRegistration.INSTANCE.unregisterAll();

        if (marker != null) {
            marker.clear();
        }
    }

    SqlDataService createDataService(JdbcConfiguration configuration) {
        SqlDataService ret = new SingleConnectionDataService(configuration);

        //add weak reference so it can be closed on shutdown if not done by the caller
        registerClosable(ret);

        return ret;
    }

    MaterialInfo createMaterialInformation() {
        return new ConfigurableMaterialInfo(
                YamlConfiguration.loadConfiguration(this.getTextResource("material-info.yml")));
    }

}