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.util; 020 021import com.google.inject.Inject; 022import com.google.inject.Singleton; 023import com.plotsquared.bukkit.generator.BukkitPlotGenerator; 024import com.plotsquared.core.PlotSquared; 025import com.plotsquared.core.configuration.ConfigurationNode; 026import com.plotsquared.core.configuration.ConfigurationSection; 027import com.plotsquared.core.configuration.file.YamlConfiguration; 028import com.plotsquared.core.generator.GeneratorWrapper; 029import com.plotsquared.core.inject.annotations.WorldConfig; 030import com.plotsquared.core.inject.annotations.WorldFile; 031import com.plotsquared.core.plot.PlotArea; 032import com.plotsquared.core.plot.PlotAreaType; 033import com.plotsquared.core.plot.world.PlotAreaManager; 034import com.plotsquared.core.setup.PlotAreaBuilder; 035import com.plotsquared.core.util.SetupUtils; 036import com.plotsquared.core.util.task.TaskManager; 037import org.bukkit.Bukkit; 038import org.bukkit.Chunk; 039import org.bukkit.Location; 040import org.bukkit.World; 041import org.bukkit.entity.Player; 042import org.bukkit.generator.ChunkGenerator; 043import org.bukkit.plugin.Plugin; 044import org.checkerframework.checker.nullness.qual.NonNull; 045 046import java.io.File; 047import java.io.IOException; 048import java.util.HashMap; 049import java.util.Map.Entry; 050import java.util.Objects; 051 052@Singleton 053public class BukkitSetupUtils extends SetupUtils { 054 055 private final PlotAreaManager plotAreaManager; 056 private final YamlConfiguration worldConfiguration; 057 private final File worldFile; 058 059 @Inject 060 public BukkitSetupUtils( 061 final @NonNull PlotAreaManager plotAreaManager, 062 @WorldConfig final @NonNull YamlConfiguration worldConfiguration, 063 @WorldFile final @NonNull File worldFile 064 ) { 065 this.plotAreaManager = plotAreaManager; 066 this.worldConfiguration = worldConfiguration; 067 this.worldFile = worldFile; 068 } 069 070 @Override 071 public void updateGenerators(final boolean force) { 072 if (loaded && !SetupUtils.generators.isEmpty() && !force) { 073 return; 074 } 075 String testWorld = "CheckingPlotSquaredGenerator"; 076 for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { 077 try { 078 if (plugin.isEnabled()) { 079 ChunkGenerator generator = plugin.getDefaultWorldGenerator(testWorld, ""); 080 if (generator != null) { 081 PlotSquared.get().removePlotAreas(testWorld); 082 String name = plugin.getDescription().getName(); 083 GeneratorWrapper<?> wrapped; 084 if (generator instanceof GeneratorWrapper<?>) { 085 wrapped = (GeneratorWrapper<?>) generator; 086 } else { 087 wrapped = new BukkitPlotGenerator(testWorld, generator, this.plotAreaManager); 088 } 089 SetupUtils.generators.put(name, wrapped); 090 } 091 } 092 } catch (Throwable e) { // Recover from third party generator error 093 e.printStackTrace(); 094 } 095 } 096 loaded = true; 097 } 098 099 @Override 100 public void unload(String worldName, boolean save) { 101 TaskManager.runTask(() -> { 102 World world = Bukkit.getWorld(worldName); 103 if (world == null) { 104 return; 105 } 106 Location location = Bukkit.getWorlds().get(0).getSpawnLocation(); 107 for (Player player : world.getPlayers()) { 108 player.teleport(location); 109 } 110 if (save) { 111 for (Chunk chunk : world.getLoadedChunks()) { 112 chunk.unload(true); 113 } 114 } else { 115 for (Chunk chunk : world.getLoadedChunks()) { 116 chunk.unload(false); 117 } 118 } 119 Bukkit.unloadWorld(world, false); 120 }); 121 } 122 123 @Override 124 public String setupWorld(PlotAreaBuilder builder) { 125 this.updateGenerators(false); 126 ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ? 127 new ConfigurationNode[0] : builder.settingsNodesWrapper().getSettingsNodes(); 128 String world = builder.worldName(); 129 PlotAreaType type = builder.plotAreaType(); 130 String worldPath = "worlds." + builder.worldName(); 131 switch (type) { 132 case PARTIAL -> { 133 if (builder.areaName() != null) { 134 if (!this.worldConfiguration.contains(worldPath)) { 135 this.worldConfiguration.createSection(worldPath); 136 } 137 ConfigurationSection worldSection = 138 this.worldConfiguration.getConfigurationSection(worldPath); 139 String areaName = builder.areaName() + "-" + builder.minimumId() + "-" + builder.maximumId(); 140 String areaPath = "areas." + areaName; 141 if (!worldSection.contains(areaPath)) { 142 worldSection.createSection(areaPath); 143 } 144 ConfigurationSection areaSection = 145 worldSection.getConfigurationSection(areaPath); 146 HashMap<String, Object> options = new HashMap<>(); 147 for (ConfigurationNode step : steps) { 148 options.put(step.getConstant(), step.getValue()); 149 } 150 options.put("generator.type", builder.plotAreaType().toString()); 151 options.put("generator.terrain", builder.terrainType().toString()); 152 options.put("generator.plugin", builder.plotManager()); 153 if (builder.generatorName() != null && !builder.generatorName() 154 .equals(builder.plotManager())) { 155 options.put("generator.init", builder.generatorName()); 156 } 157 for (Entry<String, Object> entry : options.entrySet()) { 158 String key = entry.getKey(); 159 Object value = entry.getValue(); 160 if (worldSection.contains(key)) { 161 Object current = worldSection.get(key); 162 if (!Objects.equals(value, current)) { 163 areaSection.set(key, value); 164 } 165 } else { 166 worldSection.set(key, value); 167 } 168 } 169 } 170 GeneratorWrapper<?> gen = SetupUtils.generators.get(builder.generatorName()); 171 if (gen != null && gen.isFull()) { 172 builder.generatorName(null); 173 } 174 } 175 case AUGMENTED -> { 176 if (!builder.plotManager().endsWith(":single")) { 177 if (!this.worldConfiguration.contains(worldPath)) { 178 this.worldConfiguration.createSection(worldPath); 179 } 180 if (steps.length != 0) { 181 ConfigurationSection worldSection = 182 this.worldConfiguration.getConfigurationSection(worldPath); 183 for (ConfigurationNode step : steps) { 184 worldSection.set(step.getConstant(), step.getValue()); 185 } 186 } 187 this.worldConfiguration 188 .set("worlds." + world + ".generator.type", builder.plotAreaType().toString()); 189 this.worldConfiguration 190 .set("worlds." + world + ".generator.terrain", builder.terrainType().toString()); 191 this.worldConfiguration 192 .set("worlds." + world + ".generator.plugin", builder.plotManager()); 193 if (builder.generatorName() != null && !builder.generatorName() 194 .equals(builder.plotManager())) { 195 this.worldConfiguration 196 .set("worlds." + world + ".generator.init", builder.generatorName()); 197 } 198 } 199 GeneratorWrapper<?> gen = SetupUtils.generators.get(builder.generatorName()); 200 if (gen != null && gen.isFull()) { 201 builder.generatorName(null); 202 } 203 } 204 case NORMAL -> { 205 if (steps.length != 0) { 206 if (!this.worldConfiguration.contains(worldPath)) { 207 this.worldConfiguration.createSection(worldPath); 208 } 209 ConfigurationSection worldSection = 210 this.worldConfiguration.getConfigurationSection(worldPath); 211 for (ConfigurationNode step : steps) { 212 worldSection.set(step.getConstant(), step.getValue()); 213 } 214 } 215 } 216 } 217 218 try { 219 this.worldConfiguration.save(this.worldFile); 220 } catch (IOException e) { 221 e.printStackTrace(); 222 } 223 224 Objects.requireNonNull(PlotSquared.platform()).worldManager() 225 .handleWorldCreation(builder.worldName(), builder.generatorName()); 226 227 if (Bukkit.getWorld(world) != null) { 228 return world; 229 } 230 231 return builder.worldName(); 232 } 233 234 @Override 235 public String getGenerator(PlotArea plotArea) { 236 if (SetupUtils.generators.isEmpty()) { 237 updateGenerators(false); 238 } 239 World world = Bukkit.getWorld(plotArea.getWorldName()); 240 if (world == null) { 241 return null; 242 } 243 ChunkGenerator generator = world.getGenerator(); 244 if (!(generator instanceof BukkitPlotGenerator)) { 245 return null; 246 } 247 for (Entry<String, GeneratorWrapper<?>> entry : SetupUtils.generators.entrySet()) { 248 GeneratorWrapper<?> current = entry.getValue(); 249 if (current.equals(generator)) { 250 return entry.getKey(); 251 } 252 } 253 return null; 254 } 255 256}