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 @SuppressWarnings("deprecation") // Paper deprecation 071 @Override 072 public void updateGenerators(final boolean force) { 073 if (loaded && !SetupUtils.generators.isEmpty() && !force) { 074 return; 075 } 076 String testWorld = "CheckingPlotSquaredGenerator"; 077 for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { 078 try { 079 if (plugin.isEnabled()) { 080 ChunkGenerator generator = plugin.getDefaultWorldGenerator(testWorld, ""); 081 if (generator != null) { 082 PlotSquared.get().removePlotAreas(testWorld); 083 String name = plugin.getDescription().getName(); 084 GeneratorWrapper<?> wrapped; 085 if (generator instanceof GeneratorWrapper<?>) { 086 wrapped = (GeneratorWrapper<?>) generator; 087 } else { 088 wrapped = new BukkitPlotGenerator(testWorld, generator, this.plotAreaManager); 089 } 090 SetupUtils.generators.put(name, wrapped); 091 } 092 } 093 } catch (Throwable e) { // Recover from third party generator error 094 e.printStackTrace(); 095 } 096 } 097 loaded = true; 098 } 099 100 @Override 101 public void unload(String worldName, boolean save) { 102 TaskManager.runTask(() -> { 103 World world = Bukkit.getWorld(worldName); 104 if (world == null) { 105 return; 106 } 107 Location location = Bukkit.getWorlds().get(0).getSpawnLocation(); 108 for (Player player : world.getPlayers()) { 109 player.teleport(location); 110 } 111 if (save) { 112 for (Chunk chunk : world.getLoadedChunks()) { 113 chunk.unload(true); 114 } 115 } else { 116 for (Chunk chunk : world.getLoadedChunks()) { 117 chunk.unload(false); 118 } 119 } 120 Bukkit.unloadWorld(world, false); 121 }); 122 } 123 124 @Override 125 public String setupWorld(PlotAreaBuilder builder) { 126 this.updateGenerators(false); 127 ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ? 128 new ConfigurationNode[0] : builder.settingsNodesWrapper().settingsNodes(); 129 String world = builder.worldName(); 130 PlotAreaType type = builder.plotAreaType(); 131 String worldPath = "worlds." + builder.worldName(); 132 switch (type) { 133 case PARTIAL -> { 134 if (builder.areaName() != null) { 135 if (!this.worldConfiguration.contains(worldPath)) { 136 this.worldConfiguration.createSection(worldPath); 137 } 138 ConfigurationSection worldSection = 139 this.worldConfiguration.getConfigurationSection(worldPath); 140 String areaName = builder.areaName() + "-" + builder.minimumId() + "-" + builder.maximumId(); 141 String areaPath = "areas." + areaName; 142 if (!worldSection.contains(areaPath)) { 143 worldSection.createSection(areaPath); 144 } 145 ConfigurationSection areaSection = 146 worldSection.getConfigurationSection(areaPath); 147 HashMap<String, Object> options = new HashMap<>(); 148 for (ConfigurationNode step : steps) { 149 options.put(step.getConstant(), step.getValue()); 150 } 151 options.put("generator.type", builder.plotAreaType().toString()); 152 options.put("generator.terrain", builder.terrainType().toString()); 153 options.put("generator.plugin", builder.plotManager()); 154 if (builder.generatorName() != null && !builder.generatorName() 155 .equals(builder.plotManager())) { 156 options.put("generator.init", builder.generatorName()); 157 } 158 for (Entry<String, Object> entry : options.entrySet()) { 159 String key = entry.getKey(); 160 Object value = entry.getValue(); 161 if (worldSection.contains(key)) { 162 Object current = worldSection.get(key); 163 if (!Objects.equals(value, current)) { 164 areaSection.set(key, value); 165 } 166 } else { 167 worldSection.set(key, value); 168 } 169 } 170 } 171 GeneratorWrapper<?> gen = SetupUtils.generators.get(builder.generatorName()); 172 if (gen != null && gen.isFull()) { 173 builder.generatorName(null); 174 } 175 } 176 case AUGMENTED -> { 177 if (!builder.plotManager().endsWith(":single")) { 178 if (!this.worldConfiguration.contains(worldPath)) { 179 this.worldConfiguration.createSection(worldPath); 180 } 181 if (steps.length != 0) { 182 ConfigurationSection worldSection = 183 this.worldConfiguration.getConfigurationSection(worldPath); 184 for (ConfigurationNode step : steps) { 185 worldSection.set(step.getConstant(), step.getValue()); 186 } 187 } 188 this.worldConfiguration 189 .set("worlds." + world + ".generator.type", builder.plotAreaType().toString()); 190 this.worldConfiguration 191 .set("worlds." + world + ".generator.terrain", builder.terrainType().toString()); 192 this.worldConfiguration 193 .set("worlds." + world + ".generator.plugin", builder.plotManager()); 194 if (builder.generatorName() != null && !builder.generatorName() 195 .equals(builder.plotManager())) { 196 this.worldConfiguration 197 .set("worlds." + world + ".generator.init", builder.generatorName()); 198 } 199 } 200 GeneratorWrapper<?> gen = SetupUtils.generators.get(builder.generatorName()); 201 if (gen != null && gen.isFull()) { 202 builder.generatorName(null); 203 } 204 } 205 case NORMAL -> { 206 if (steps.length != 0) { 207 if (!this.worldConfiguration.contains(worldPath)) { 208 this.worldConfiguration.createSection(worldPath); 209 } 210 ConfigurationSection worldSection = 211 this.worldConfiguration.getConfigurationSection(worldPath); 212 for (ConfigurationNode step : steps) { 213 worldSection.set(step.getConstant(), step.getValue()); 214 } 215 } 216 } 217 } 218 219 try { 220 this.worldConfiguration.save(this.worldFile); 221 } catch (IOException e) { 222 e.printStackTrace(); 223 } 224 225 Objects.requireNonNull(PlotSquared.platform()).worldManager() 226 .handleWorldCreation(builder.worldName(), builder.generatorName()); 227 228 if (Bukkit.getWorld(world) != null) { 229 return world; 230 } 231 232 return builder.worldName(); 233 } 234 235 @Override 236 public String getGenerator(PlotArea plotArea) { 237 if (SetupUtils.generators.isEmpty()) { 238 updateGenerators(false); 239 } 240 World world = Bukkit.getWorld(plotArea.getWorldName()); 241 if (world == null) { 242 return null; 243 } 244 ChunkGenerator generator = world.getGenerator(); 245 if (!(generator instanceof BukkitPlotGenerator)) { 246 return null; 247 } 248 for (Entry<String, GeneratorWrapper<?>> entry : SetupUtils.generators.entrySet()) { 249 GeneratorWrapper<?> current = entry.getValue(); 250 if (current.equals(generator)) { 251 return entry.getKey(); 252 } 253 } 254 return null; 255 } 256 257}