001/*
002 * PlotSquared, a land and world management plugin for Minecraft.
003 * Copyright (C) IntellectualSites <https://intellectualsites.com>
004 * Copyright (C) IntellectualSites team and contributors
005 *
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
018 */
019package com.plotsquared.bukkit.inject;
020
021import com.google.inject.AbstractModule;
022import com.google.inject.Provides;
023import com.google.inject.Singleton;
024import com.google.inject.assistedinject.FactoryModuleBuilder;
025import com.plotsquared.bukkit.BukkitPlatform;
026import com.plotsquared.bukkit.listener.ServerListener;
027import com.plotsquared.bukkit.listener.SingleWorldListener;
028import com.plotsquared.bukkit.player.BukkitPlayerManager;
029import com.plotsquared.bukkit.queue.BukkitChunkCoordinator;
030import com.plotsquared.bukkit.queue.BukkitQueueCoordinator;
031import com.plotsquared.bukkit.schematic.BukkitSchematicHandler;
032import com.plotsquared.bukkit.util.BukkitChunkManager;
033import com.plotsquared.bukkit.util.BukkitInventoryUtil;
034import com.plotsquared.bukkit.util.BukkitRegionManager;
035import com.plotsquared.bukkit.util.BukkitSetupUtils;
036import com.plotsquared.bukkit.util.BukkitUtil;
037import com.plotsquared.bukkit.util.fawe.FaweRegionManager;
038import com.plotsquared.bukkit.util.fawe.FaweSchematicHandler;
039import com.plotsquared.core.PlotPlatform;
040import com.plotsquared.core.PlotSquared;
041import com.plotsquared.core.configuration.Settings;
042import com.plotsquared.core.generator.HybridGen;
043import com.plotsquared.core.generator.IndependentPlotGenerator;
044import com.plotsquared.core.inject.annotations.ConsoleActor;
045import com.plotsquared.core.inject.annotations.DefaultGenerator;
046import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
047import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
048import com.plotsquared.core.inject.factory.HybridPlotWorldFactory;
049import com.plotsquared.core.inject.factory.ProgressSubscriberFactory;
050import com.plotsquared.core.player.OfflinePlotPlayer;
051import com.plotsquared.core.player.PlotPlayer;
052import com.plotsquared.core.plot.PlotArea;
053import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
054import com.plotsquared.core.plot.world.PlotAreaManager;
055import com.plotsquared.core.plot.world.SinglePlotAreaManager;
056import com.plotsquared.core.queue.ChunkCoordinator;
057import com.plotsquared.core.queue.GlobalBlockQueue;
058import com.plotsquared.core.queue.QueueProvider;
059import com.plotsquared.core.queue.subscriber.DefaultProgressSubscriber;
060import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
061import com.plotsquared.core.util.ChunkManager;
062import com.plotsquared.core.util.EconHandler;
063import com.plotsquared.core.util.InventoryUtil;
064import com.plotsquared.core.util.PlayerManager;
065import com.plotsquared.core.util.RegionManager;
066import com.plotsquared.core.util.SchematicHandler;
067import com.plotsquared.core.util.SetupUtils;
068import com.plotsquared.core.util.WorldUtil;
069import com.sk89q.worldedit.bukkit.WorldEditPlugin;
070import com.sk89q.worldedit.extension.platform.Actor;
071import org.apache.logging.log4j.LogManager;
072import org.apache.logging.log4j.Logger;
073import org.bukkit.Bukkit;
074import org.bukkit.command.ConsoleCommandSender;
075import org.bukkit.plugin.java.JavaPlugin;
076import org.checkerframework.checker.nullness.qual.NonNull;
077
078import java.util.Objects;
079
080public class BukkitModule extends AbstractModule {
081
082    private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitModule.class.getSimpleName());
083
084    private final BukkitPlatform bukkitPlatform;
085
086    public BukkitModule(final @NonNull BukkitPlatform bukkitPlatform) {
087        this.bukkitPlatform = bukkitPlatform;
088    }
089
090    @Override
091    protected void configure() {
092        bind(PlayerManager.class).to(BukkitPlayerManager.class);
093        bind(JavaPlugin.class).toInstance(bukkitPlatform);
094        bind(PlotPlatform.class).toInstance(bukkitPlatform);
095        bind(BukkitPlatform.class).toInstance(bukkitPlatform);
096        bind(IndependentPlotGenerator.class).annotatedWith(DefaultGenerator.class).to(HybridGen.class);
097        // Console actor
098        @NonNull ConsoleCommandSender console = Bukkit.getServer().getConsoleSender();
099        WorldEditPlugin wePlugin = ((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"));
100        bind(Actor.class).annotatedWith(ConsoleActor.class).toInstance(wePlugin.wrapCommandSender(console));
101        bind(InventoryUtil.class).to(BukkitInventoryUtil.class);
102        bind(SetupUtils.class).to(BukkitSetupUtils.class);
103        bind(WorldUtil.class).to(BukkitUtil.class);
104        install(new FactoryModuleBuilder()
105                .implement(ProgressSubscriber.class, DefaultProgressSubscriber.class)
106                .build(ProgressSubscriberFactory.class));
107        bind(ChunkManager.class).to(BukkitChunkManager.class);
108        if (PlotSquared.platform().isFaweHooking()) {
109            bind(SchematicHandler.class).to(FaweSchematicHandler.class);
110            bind(RegionManager.class).to(FaweRegionManager.class);
111        } else {
112            bind(SchematicHandler.class).to(BukkitSchematicHandler.class);
113            bind(RegionManager.class).to(BukkitRegionManager.class);
114        }
115        bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue(QueueProvider.of(BukkitQueueCoordinator.class)));
116        if (Settings.Enabled_Components.WORLDS) {
117            bind(PlotAreaManager.class).to(SinglePlotAreaManager.class);
118            try {
119                bind(SingleWorldListener.class).toInstance(new SingleWorldListener());
120            } catch (Exception e) {
121                e.printStackTrace();
122            }
123        } else {
124            bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class);
125        }
126        install(new FactoryModuleBuilder().build(HybridPlotWorldFactory.class));
127        install(new FactoryModuleBuilder()
128                .implement(ChunkCoordinator.class, BukkitChunkCoordinator.class)
129                .build(ChunkCoordinatorFactory.class));
130        install(new FactoryModuleBuilder().build(ChunkCoordinatorBuilderFactory.class));
131    }
132
133    @Provides
134    @Singleton
135    @NonNull EconHandler provideEconHandler() {
136        if (!Settings.Enabled_Components.ECONOMY || !Bukkit.getPluginManager().isPluginEnabled("Vault")) {
137            return EconHandler.nullEconHandler();
138        }
139        // Guice eagerly initializes singletons, so we need to bring the laziness ourselves
140        return new LazyEconHandler();
141    }
142
143    private static final class LazyEconHandler extends EconHandler implements ServerListener.MutableEconHandler {
144        private volatile EconHandler implementation;
145
146        public void setImplementation(EconHandler econHandler) {
147            this.implementation = econHandler;
148        }
149
150        @Override
151        public boolean init() {
152            return get().init();
153        }
154
155        @Override
156        public double getBalance(final PlotPlayer<?> player) {
157            return get().getBalance(player);
158        }
159
160        @Override
161        public void withdrawMoney(final PlotPlayer<?> player, final double amount) {
162            get().withdrawMoney(player, amount);
163        }
164
165        @Override
166        public void depositMoney(final PlotPlayer<?> player, final double amount) {
167            get().depositMoney(player, amount);
168        }
169
170        @Override
171        public void depositMoney(final OfflinePlotPlayer player, final double amount) {
172            get().depositMoney(player, amount);
173        }
174
175        @Override
176        public boolean isEnabled(final PlotArea plotArea) {
177            return get().isEnabled(plotArea);
178        }
179
180        @Override
181        public @NonNull String format(final double balance) {
182            return get().format(balance);
183        }
184
185        @Override
186        public boolean isSupported() {
187            return get().isSupported();
188        }
189
190        private EconHandler get() {
191            return Objects.requireNonNull(this.implementation, "EconHandler not ready yet.");
192        }
193
194    }
195
196}