me.taylorkelly.mywarp.bukkit.MyWarpPlugin.java Source code

Java tutorial

Introduction

Here is the source code for me.taylorkelly.mywarp.bukkit.MyWarpPlugin.java

Source

/*
 * Copyright (C) 2011 - 2015, 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 me.taylorkelly.mywarp.bukkit;

import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.intake.CommandCallable;
import com.sk89q.intake.CommandException;
import com.sk89q.intake.InvalidUsageException;
import com.sk89q.intake.InvocationCommandException;
import com.sk89q.intake.context.CommandLocals;
import com.sk89q.intake.dispatcher.Dispatcher;
import com.sk89q.intake.fluent.CommandGraph;
import com.sk89q.intake.parametric.ParametricBuilder;
import com.sk89q.intake.util.auth.AuthorizationException;
import com.sk89q.intake.util.i18n.ResourceProvider;

import me.taylorkelly.mywarp.Actor;
import me.taylorkelly.mywarp.Game;
import me.taylorkelly.mywarp.InitializationException;
import me.taylorkelly.mywarp.MyWarp;
import me.taylorkelly.mywarp.Platform;
import me.taylorkelly.mywarp.bukkit.commands.ImportCommands;
import me.taylorkelly.mywarp.bukkit.commands.InformativeCommands;
import me.taylorkelly.mywarp.bukkit.commands.ManagementCommands;
import me.taylorkelly.mywarp.bukkit.commands.SocialCommands;
import me.taylorkelly.mywarp.bukkit.commands.UsageCommands;
import me.taylorkelly.mywarp.bukkit.commands.UtilityCommands;
import me.taylorkelly.mywarp.bukkit.conversation.WarpAcceptancePromptFactory;
import me.taylorkelly.mywarp.bukkit.conversation.WelcomeEditorFactory;
import me.taylorkelly.mywarp.bukkit.economy.BukkitFeeProvider;
import me.taylorkelly.mywarp.bukkit.economy.VaultService;
import me.taylorkelly.mywarp.bukkit.limits.BukkitLimitProvider;
import me.taylorkelly.mywarp.bukkit.markers.DynmapMarkers;
import me.taylorkelly.mywarp.bukkit.timer.BukkitDurationProvider;
import me.taylorkelly.mywarp.bukkit.timer.BukkitTimerService;
import me.taylorkelly.mywarp.bukkit.util.jdbc.DataSourceFactory;
import me.taylorkelly.mywarp.bukkit.util.jdbc.SingleConnectionDataSource;
import me.taylorkelly.mywarp.bukkit.util.parametric.ActorAuthorizer;
import me.taylorkelly.mywarp.bukkit.util.parametric.CommandResourceProvider;
import me.taylorkelly.mywarp.bukkit.util.parametric.ExceptionConverter;
import me.taylorkelly.mywarp.bukkit.util.parametric.FallbackDispatcher;
import me.taylorkelly.mywarp.bukkit.util.parametric.IntakeResourceProvider;
import me.taylorkelly.mywarp.bukkit.util.parametric.binding.ActorBindung;
import me.taylorkelly.mywarp.bukkit.util.parametric.binding.ConnectionConfigurationBinding;
import me.taylorkelly.mywarp.bukkit.util.parametric.binding.FileBinding;
import me.taylorkelly.mywarp.bukkit.util.parametric.binding.PlayerBinding;
import me.taylorkelly.mywarp.bukkit.util.parametric.binding.ProfileBinding;
import me.taylorkelly.mywarp.bukkit.util.parametric.binding.WarpBinding;
import me.taylorkelly.mywarp.bukkit.util.parametric.economy.EconomyInvokeHandler;
import me.taylorkelly.mywarp.bukkit.util.permissions.BukkitPermissionsRegistration;
import me.taylorkelly.mywarp.bukkit.util.permissions.group.GroupResolver;
import me.taylorkelly.mywarp.bukkit.util.permissions.group.GroupResolverManager;
import me.taylorkelly.mywarp.bukkit.util.profile.SquirrelIdProfileService;
import me.taylorkelly.mywarp.storage.ConnectionConfiguration;
import me.taylorkelly.mywarp.storage.RelationalDataService;
import me.taylorkelly.mywarp.util.CommandUtils;
import me.taylorkelly.mywarp.util.MyWarpLogger;
import me.taylorkelly.mywarp.util.i18n.DynamicMessages;
import me.taylorkelly.mywarp.util.i18n.FolderSourcedControl;
import me.taylorkelly.mywarp.util.i18n.LocaleManager;

import net.milkbowl.vault.economy.Economy;

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.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.dynmap.DynmapCommonAPI;
import org.slf4j.Logger;

import java.io.File;
import java.sql.SQLException;
import java.util.ResourceBundle;
import java.util.concurrent.Executors;

import javax.annotation.Nullable;

/**
 * The MyWarp plugin instance when running on Bukkit.
 */
public class MyWarpPlugin extends JavaPlugin implements Platform {

    private static final DynamicMessages MESSAGES = new DynamicMessages(CommandUtils.RESOURCE_BUNDLE_NAME);
    private static final Logger log = MyWarpLogger.getLogger(MyWarpPlugin.class);

    private final File bundleFolder = new File(getDataFolder(), "lang");
    private final ResourceBundle.Control control = new FolderSourcedControl(bundleFolder);

    private SingleConnectionDataService dataService;
    private GroupResolverManager groupResolverManager;
    private SquirrelIdProfileService profileService;
    private BukkitSettings settings;
    private BukkitAdapter adapter;
    private BukkitGame game;

    private MyWarp myWarp;

    private Dispatcher dispatcher;

    @Nullable
    private VaultService economyService;
    @Nullable
    private BukkitTimerService timerService;
    @Nullable
    private BukkitFeeProvider feeProvider;
    @Nullable
    private BukkitLimitProvider limitProvider;
    @Nullable
    private BukkitDurationProvider durationProvider;

    // -- JavaPlugin methods

    @Override
    public void onEnable() {

        // create the data-folder
        getDataFolder().mkdirs();

        profileService = new SquirrelIdProfileService(new File(getDataFolder(), "profiles.db"));
        groupResolverManager = new GroupResolverManager();
        adapter = new BukkitAdapter(this);

        // setup the configurations
        settings = new BukkitSettings(new File(getDataFolder(), "config.yml"),
                YamlConfiguration.loadConfiguration(getTextResource("config.yml")), adapter);

        // setup the DataService
        ConnectionConfiguration config = settings.getStorageConfiguration();

        //TODO fail for SQLite driver 3.7.x...

        SingleConnectionDataSource dataSource;
        try {
            dataSource = DataSourceFactory.createSingleConnectionDataSource(config);
        } catch (SQLException e) {
            log.error("Failed to connect to the database. MyWarp will be disabled.", e);
            Bukkit.getPluginManager().disablePlugin(this);
            return;
        }
        ListeningExecutorService executorService = MoreExecutors
                .listeningDecorator(Executors.newSingleThreadExecutor());

        dataService = new SingleConnectionDataService(dataSource, config, executorService);

        // setup the Game
        game = new BukkitGame(new BukkitExecutor(this), adapter);

        // try to setup the core
        try {
            myWarp = new MyWarp(this);
        } catch (InitializationException e) {
            log.error(
                    "A critical failure has been encountered and MyWarp is unable to continue. MyWarp will be disabled.",
                    e);
            Bukkit.getPluginManager().disablePlugin(this);
            return;
        }

        // command registration
        ResourceProvider resourceProvider = new IntakeResourceProvider(control);
        ExceptionConverter exceptionConverter = new ExceptionConverter();
        PlayerBinding playerBinding = new PlayerBinding(game);
        WarpBinding warpBinding = new WarpBinding(myWarp.getWarpManager());

        ParametricBuilder builder = new ParametricBuilder(resourceProvider);
        builder.setAuthorizer(new ActorAuthorizer());
        builder.setExternalResourceProvider(new CommandResourceProvider(control));
        builder.addBinding(new ActorBindung());
        builder.addBinding(new ConnectionConfigurationBinding());
        builder.addBinding(new FileBinding(getDataFolder()));
        builder.addBinding(playerBinding);
        builder.addBinding(new ProfileBinding(profileService));
        builder.addBinding(warpBinding);
        builder.addExceptionConverter(exceptionConverter);

        builder.addInvokeListener(new EconomyInvokeHandler(myWarp.getEconomyManager()));

        UsageCommands usageCommands = new UsageCommands(myWarp);

        //XXX this should be covered by unit tests
        CommandCallable fallback = Iterables.getOnlyElement(builder.build(usageCommands).values());

        // @formatter:off
        dispatcher = new CommandGraph(resourceProvider).builder(builder).commands().registerMethods(usageCommands)
                .group(new FallbackDispatcher(resourceProvider, fallback), "warp", "myWarp", "mw")
                .describeAs("warp-to.description")
                .registerMethods(
                        new InformativeCommands(myWarp.getLimitManager(), settings, myWarp.getWarpManager()))
                .registerMethods(new ManagementCommands(myWarp, this, new WelcomeEditorFactory(this, adapter)))
                .registerMethods(new SocialCommands(game, myWarp.getLimitManager(), profileService,
                        new WarpAcceptancePromptFactory(this, adapter)))
                .registerMethods(new UtilityCommands(myWarp, this)).group("import", "migrate")
                .describeAs("import.description").registerMethods(new ImportCommands(myWarp)).graph()
                .getDispatcher();
        // @formatter:on

        setupPlugin();
    }

    /**
     * Sets up the plugin. Calling this method will setup all functions that depend on configurations and are, by design,
     * optional.
     */
    private void setupPlugin() {
        profileService.registerEvents(this);

        if (settings.isWarpSignsEnabled()) {
            new WarpSignListener(adapter, myWarp.getWarpSignManager()).registerEvents(this);
        }

        if (settings.isDynmapEnabled()) {
            Plugin dynmap = getServer().getPluginManager().getPlugin("dynmap");
            if (dynmap != null && dynmap.isEnabled()) {
                new DynmapMarkers(this, (DynmapCommonAPI) dynmap, myWarp.getWarpManager(), myWarp.getEventBus());
            } else {
                log.error("Failed to hook into Dynmap. Disabling Dynmap support.");
            }
        }

        // 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);
        }
    }

    @Override
    public void onDisable() {
        HandlerList.unregisterAll(this);
        BukkitPermissionsRegistration.INSTANCE.unregisterAll();

        if (dataService != null) {
            dataService.shutdown();
        }
    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        // create the CommandLocals
        CommandLocals locals = new CommandLocals();
        Actor actor = wrap(sender);
        locals.put(Actor.class, actor);

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

        // No parent commands
        String[] parentCommands = new String[0];

        // create the command string
        StrBuilder builder = new StrBuilder();
        builder.append(label);
        for (String argument : args) {
            builder.appendSeparator(' ');
            builder.append(argument);
        }

        // call the command
        try {
            return dispatcher.call(builder.toString(), locals, parentCommands);
        } catch (IllegalStateException e) {
            log.error(String.format(
                    "The command '%s' could not be executed as the underling method could not be called.",
                    cmd.toString()), e);
            actor.sendError(MESSAGES.getString("exception.unknown"));
        } catch (InvocationCommandException e) {
            // An InvocationCommandException can only be thrown if a thrown
            // Exception is not covered by our ExceptionConverter and is
            // therefore unintended behavior.
            actor.sendError(MESSAGES.getString("exception.unknown"));
            log.error(String.format("The command '%s' could not be executed.", cmd), e);
        } catch (InvalidUsageException e) {
            StrBuilder error = new StrBuilder();
            error.append(e.getSimpleUsageString("/"));
            if (e.getMessage() != null) {
                error.appendNewLine();
                error.append(e.getMessage());
            }
            if (e.isFullHelpSuggested()) {
                error.appendNewLine();
                error.append(e.getCommand().getDescription().getHelp());
            }
            actor.sendError(error.toString());
        } catch (CommandException e) {
            actor.sendError(e.getMessage());
        } catch (AuthorizationException e) {
            actor.sendError(MESSAGES.getString("exception.insufficient-permission"));
        }
        return true;
    }

    // -- custom methods

    /**
     * Wraps a CommandSender to an Actor.
     *
     * @param sender the CommandSender
     * @return the Actor representing the given CommandSender
     */
    public Actor wrap(CommandSender sender) {
        if (sender instanceof Player) {
            return adapter.adapt((Player) sender);
        }
        return new BukkitActor(sender, settings.getLocalizationDefaultLocale());
    }

    /**
     * Gets the adapter.
     *
     * @return the adapter
     */
    public BukkitAdapter getAdapter() {
        return adapter;
    }

    /**
     * Gets the GroupResolver.
     *
     * @return the GroupResolver
     */
    public GroupResolver getGroupResolver() {
        return groupResolverManager;
    }

    /**
     * gets the Dispatcher.
     *
     * @return the Dispatcher
     */
    public Dispatcher getDispatcher() {
        return dispatcher;
    }
    // -- Platform methods

    @Override
    public void reload() {
        // cleanup old stuff
        HandlerList.unregisterAll(this);
        BukkitPermissionsRegistration.INSTANCE.unregisterAll();

        // load new stuff
        settings.reload();
        setupPlugin();
    }

    @Override
    public ResourceBundle.Control getResourceBundleControl() {
        return control;
    }

    @Override
    public Game getGame() {
        return game;
    }

    @Override
    public RelationalDataService getDataService() {
        return dataService;
    }

    @Override
    public BukkitSettings getSettings() {
        return settings;
    }

    @Override
    public SquirrelIdProfileService getProfileService() {
        return profileService;
    }

    @Override
    public VaultService getEconomyService() {
        if (economyService == null) {
            try {
                RegisteredServiceProvider<Economy> economyProvider = Bukkit.getServicesManager()
                        .getRegistration(Economy.class);
                if (economyProvider != null) {
                    economyService = new VaultService(economyProvider, adapter);
                } else {
                    log.error(
                            "Failed to hook into Vault (EconomyProvider is null). Economy support will not be available.");
                    throw new UnsupportedOperationException();
                }
            } catch (NoClassDefFoundError e) {
                log.error(
                        "Failed to hook into Vault (EconomyProviderClass not available). Economy support will not be available.");
                throw new UnsupportedOperationException();
            }
        }

        return economyService;
    }

    @Override
    public BukkitTimerService getTimerService() {
        if (timerService == null) {
            timerService = new BukkitTimerService(this);
        }
        return timerService;
    }

    @Override
    public BukkitFeeProvider getFeeProvider() {
        if (feeProvider == null) {
            feeProvider = new BukkitFeeProvider(settings.getEconomyConfiguredFeeBundles(),
                    settings.getEconomyDefaultFeeBundle());
        }
        return feeProvider;
    }

    @Override
    public BukkitLimitProvider getLimitProvider() {
        if (limitProvider == null) {
            limitProvider = new BukkitLimitProvider(settings.getLimitsConfiguredLimitBundles(),
                    settings.getLimitsDefaultLimitBundle());
        }
        return limitProvider;
    }

    @Override
    public BukkitDurationProvider getDurationProvider() {
        if (durationProvider == null) {
            durationProvider = new BukkitDurationProvider(settings.getTimersConfiguredDurationBundles(),
                    settings.getTimersDefaultDurationBundle());
        }
        return durationProvider;
    }

}