Boxed/src/main/java/world/bentobox/boxed/Boxed.java

409 lines
15 KiB
Java
Raw Normal View History

2021-01-30 18:59:42 +01:00
package world.bentobox.boxed;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
2021-03-28 04:07:55 +02:00
import org.bukkit.Difficulty;
import org.bukkit.Material;
2021-01-30 18:59:42 +01:00
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
import org.bukkit.entity.SpawnCategory;
import org.bukkit.generator.BiomeProvider;
2021-01-30 18:59:42 +01:00
import org.bukkit.generator.ChunkGenerator;
import org.eclipse.jdt.annotation.NonNull;
2021-01-30 18:59:42 +01:00
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.admin.DefaultAdminCommand;
import world.bentobox.bentobox.api.commands.island.DefaultPlayerCommand;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.Flag.Mode;
import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.api.hooks.Hook;
import world.bentobox.bentobox.hooks.WorldManagementHook;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.boxed.commands.AdminPlaceStructureCommand;
2022-12-21 20:11:50 +01:00
import world.bentobox.boxed.generators.biomes.BoxedBiomeGenerator;
2022-12-22 05:43:05 +01:00
import world.bentobox.boxed.generators.biomes.NetherSeedBiomeGenerator;
2022-12-21 20:11:50 +01:00
import world.bentobox.boxed.generators.biomes.SeedBiomeGenerator;
import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator;
import world.bentobox.boxed.generators.chunks.BoxedChunkGenerator;
import world.bentobox.boxed.generators.chunks.BoxedSeedChunkGenerator;
2021-01-30 18:59:42 +01:00
import world.bentobox.boxed.listeners.AdvancementListener;
2021-02-16 00:58:15 +01:00
import world.bentobox.boxed.listeners.EnderPearlListener;
import world.bentobox.boxed.listeners.NewAreaListener;
2021-01-30 18:59:42 +01:00
/**
* Main Boxed class - provides a survival game inside a box
2021-01-30 18:59:42 +01:00
* @author tastybento
*/
public class Boxed extends GameModeAddon {
2021-01-30 18:59:42 +01:00
public static final Flag MOVE_BOX = new Flag.Builder("MOVE_BOX", Material.COMPOSTER)
.mode(Mode.BASIC)
.type(Type.PROTECTION)
.defaultRank(RanksManager.OWNER_RANK)
.build();
public static final Flag ALLOW_MOVE_BOX = new Flag.Builder("ALLOW_MOVE_BOX", Material.COMPOSTER)
.mode(Mode.BASIC)
.type(Type.WORLD_SETTING)
.defaultSetting(true)
.build();
2022-12-10 05:22:06 +01:00
private static final String SEED = "seed";
2021-01-30 18:59:42 +01:00
private static final String NETHER = "_nether";
private static final String THE_END = "_the_end";
// Settings
private Settings settings;
2024-03-13 07:23:55 +01:00
private AbstractBoxedChunkGenerator worldGen;
private BoxedSeedChunkGenerator seedGen;
private AbstractBoxedChunkGenerator netherGen;
private BoxedSeedChunkGenerator netherSeedGen;
2024-03-13 06:45:58 +01:00
2021-07-31 20:05:40 +02:00
private final Config<Settings> configObject = new Config<>(this, Settings.class);
private AdvancementsManager advManager;
private World seedWorld;
2023-07-05 02:28:18 +02:00
private final Map<World, ChunkGenerator> generatorMap = new HashMap<>();
2024-03-13 06:45:58 +01:00
private final Map<String, ChunkGenerator> generatorMaps = new HashMap<>();
private BiomeProvider boxedBiomeProvider;
2021-01-30 18:59:42 +01:00
@Override
public void onLoad() {
// Save the default config from config.yml
saveDefaultConfig();
// Load settings from config.yml. This will check if there are any issues with it too.
loadSettings();
2021-01-30 18:59:42 +01:00
// Register commands
2021-03-04 05:51:31 +01:00
playerCommand = new DefaultPlayerCommand(this) {};
2021-01-30 18:59:42 +01:00
adminCommand = new DefaultAdminCommand(this) {
@Override
public void setup()
{
super.setup();
new AdminPlaceStructureCommand(this);
}
};
2021-01-30 18:59:42 +01:00
}
private boolean loadSettings() {
// Load settings again to get worlds
settings = configObject.loadConfigObject();
if (settings == null) {
// Disable
logError("Boxed settings could not load! Addon disabled.");
2021-01-30 18:59:42 +01:00
setState(State.DISABLED);
return false;
}
// Initialize the Generator because createWorlds will be run after onLoad
2024-03-13 07:23:55 +01:00
this.worldGen = new BoxedChunkGenerator(this);
generatorMaps.put(settings.getWorldName(), worldGen);
2024-03-13 06:45:58 +01:00
2024-03-13 07:23:55 +01:00
seedGen = new BoxedSeedChunkGenerator(this, Environment.NORMAL,
new SeedBiomeGenerator(this));
2024-03-13 07:23:55 +01:00
generatorMaps.put(settings.getWorldName() + "/" + SEED, seedGen);
2024-03-13 06:45:58 +01:00
// Nether generators
2024-03-13 07:23:55 +01:00
this.netherGen = new BoxedChunkGenerator(this);
generatorMaps.put(settings.getWorldName() + NETHER, netherGen);
2024-03-13 06:45:58 +01:00
2024-03-13 07:23:55 +01:00
netherSeedGen = new BoxedSeedChunkGenerator(this, Environment.NETHER,
new NetherSeedBiomeGenerator(this));
2024-03-13 07:23:55 +01:00
generatorMaps.put(settings.getWorldName() + "/" + SEED + NETHER, netherSeedGen);
2024-03-13 06:45:58 +01:00
2021-01-30 18:59:42 +01:00
return true;
}
@Override
public void onEnable() {
// Check for recommended addons
2021-07-31 20:05:40 +02:00
if (this.getPlugin().getAddonsManager().getAddonByName("Border").isEmpty()) {
this.logWarning("Boxed normally requires the Border addon.");
}
2021-07-31 20:05:40 +02:00
if (this.getPlugin().getAddonsManager().getAddonByName("InvSwitcher").isEmpty()) {
this.logWarning("Boxed normally requires the InvSwitcher addon for per-world Advancements.");
}
// Advancements manager
advManager = new AdvancementsManager(this);
// Make flags only applicable to this game mode
MOVE_BOX.setGameModes(Collections.singleton(this));
ALLOW_MOVE_BOX.setGameModes(Collections.singleton(this));
// Register protection flag with BentoBox
getPlugin().getFlagsManager().registerFlag(this, ALLOW_MOVE_BOX);
if (ALLOW_MOVE_BOX.isSetForWorld(getOverWorld())) {
getPlugin().getFlagsManager().registerFlag(this, MOVE_BOX);
} else {
getPlugin().getFlagsManager().unregister(MOVE_BOX);
}
// Register listeners
this.registerListener(new AdvancementListener(this));
this.registerListener(new EnderPearlListener(this));
this.registerListener(new NewAreaListener(this));
// Register placeholders
2021-07-31 07:17:04 +02:00
PlaceholdersManager phManager = new PlaceholdersManager(this);
getPlugin().getPlaceholdersManager().registerPlaceholder(this,"visited_island_advancements", phManager::getCountByLocation);
getPlugin().getPlaceholdersManager().registerPlaceholder(this,"island_advancements", phManager::getCount);
2021-01-30 18:59:42 +01:00
}
@Override
public void onDisable() {
// Save the advancements cache
getAdvManager().save();
2021-01-30 18:59:42 +01:00
}
@Override
public void onReload() {
if (loadSettings()) {
log("Reloaded Boxed settings");
2021-01-30 18:59:42 +01:00
}
}
/**
* @return the settings
*/
public Settings getSettings() {
return settings;
}
@Override
public void createWorlds() {
String worldName = settings.getWorldName().toLowerCase();
// Create overworld
createOverWorld(worldName);
// Make the nether if it does not exist
if (settings.isNetherGenerate()) {
createNether(worldName);
}
/*
// Make the end if it does not exist
if (settings.isEndGenerate()) {
//TODO
*/
}
private void createNether(String worldName) {
2022-12-22 05:43:05 +01:00
// Create vanilla seed nether world
log("Creating Boxed Seed Nether world ...");
2023-07-05 02:28:18 +02:00
World seedWorldNether = WorldCreator
.name(worldName + "/" + SEED + NETHER)
2024-03-13 07:23:55 +01:00
.generator(netherSeedGen)
.environment(Environment.NETHER)
.seed(getSettings().getSeed())
.createWorld();
2022-12-22 05:43:05 +01:00
seedWorldNether.setDifficulty(Difficulty.EASY);
seedWorldNether.setSpawnLocation(settings.getNetherSeedX(), 64, settings.getNetherSeedZ());
2024-03-13 07:23:55 +01:00
generatorMap.put(seedWorldNether, netherSeedGen);
getPlugin().getIWM().addWorld(seedWorldNether, this);
2024-03-13 07:23:55 +01:00
copyChunks(seedWorldNether, netherGen);
if (getServer().getWorld(worldName + NETHER) == null) {
log("Creating Boxed's Nether...");
}
netherWorld = getWorld(worldName, World.Environment.NETHER);
}
private void createOverWorld(String worldName) {
// Create vanilla seed world
log("Creating Boxed Seed world ...");
seedWorld = WorldCreator
2023-03-12 06:37:21 +01:00
.name(worldName + "/" + SEED)
2024-03-13 07:23:55 +01:00
.generator(seedGen)
.environment(Environment.NORMAL)
.seed(getSettings().getSeed())
.createWorld();
seedWorld.setDifficulty(Difficulty.EASY);
seedWorld.setSpawnLocation(settings.getSeedX(), 64, settings.getSeedZ());
2022-12-10 05:22:06 +01:00
2024-03-13 07:23:55 +01:00
generatorMap.put(seedWorld, seedGen);
getPlugin().getIWM().addWorld(seedWorld, this);
2024-03-13 07:23:55 +01:00
copyChunks(seedWorld, worldGen);
2021-01-30 18:59:42 +01:00
if (getServer().getWorld(worldName) == null) {
log("Creating Boxed world ...");
2021-01-30 18:59:42 +01:00
}
// Create the world if it does not exist
islandWorld = getWorld(worldName, World.Environment.NORMAL);
2022-12-10 05:22:06 +01:00
}
/**
* Registers a world with world management plugins
*
* @param world the World to register
*/
private void registerToWorldManagementPlugins(@NonNull World world) {
if (getPlugin().getHooks() != null) {
for (Hook hook : getPlugin().getHooks().getHooks()) {
if (hook instanceof final WorldManagementHook worldManagementHook) {
if (Bukkit.isPrimaryThread()) {
worldManagementHook.registerWorld(world, true);
} else {
Bukkit.getScheduler().runTask(getPlugin(), () -> worldManagementHook.registerWorld(world, true));
}
}
}
}
}
/**
2023-07-05 02:28:18 +02:00
* Copies chunks from the seed world, so they can be pasted in the game world
* @param world - source world
* @param gen - generator to store the chunks
*/
private void copyChunks(World world, AbstractBoxedChunkGenerator gen) {
2022-12-10 05:22:06 +01:00
int startX = 0;
int startZ = 0;
if (world.getEnvironment().equals(Environment.NORMAL)) {
2022-12-10 05:22:06 +01:00
startX = this.settings.getSeedX() >> 4;
startZ = this.settings.getSeedZ() >> 4;
} else {
startX = this.settings.getNetherSeedX() >> 4;
startZ = this.settings.getNetherSeedZ() >> 4;
}
// Convert to chunks
int size = (int)(this.getSettings().getIslandDistance() / 16D);
double percent = size * 4D * size;
int count = 0;
int last = 0;
for (int x = -size; x <= size; x ++) {
for (int z = -size; z <= size; z++) {
gen.setChunk(x, z, world.getChunkAt(startX + x, startZ + z));
count++;
int p = (int) (count / percent * 100);
if (p % 10 == 0 && p != last) {
last = p;
2024-03-13 07:23:55 +01:00
this.log("Pregenerating seed chunks for " + world.getName() + "'s " + world.getEnvironment() + " "
+ p + "% done");
}
}
2021-01-30 18:59:42 +01:00
}
}
/**
2022-12-10 05:22:06 +01:00
* Get the chunk generator for a Boxed world
* @param env - nether, normal, or end
* @return the chunkGenerator for the environment
*/
public AbstractBoxedChunkGenerator getChunkGenerator(Environment env) {
2024-03-13 07:23:55 +01:00
return env.equals(Environment.NORMAL) ? worldGen : netherGen;
}
2021-01-30 18:59:42 +01:00
/**
* Gets a world or generates a new world if it does not exist
* @param worldName2 - the overworld name
* @param env - the environment
* @return world loaded or generated
*/
private World getWorld(String worldName2, Environment env) {
2021-01-30 18:59:42 +01:00
// Set world name
worldName2 = env.equals(World.Environment.NETHER) ? worldName2 + NETHER : worldName2;
worldName2 = env.equals(World.Environment.THE_END) ? worldName2 + THE_END : worldName2;
boxedBiomeProvider = new BoxedBiomeGenerator(this);
World w = WorldCreator
.name(worldName2)
.generator(getChunkGenerator(env))
.environment(env)
.seed(seedWorld.getSeed()) // For development
.createWorld();
2021-01-30 18:59:42 +01:00
// Set spawn rates
if (w != null) {
2021-03-04 05:51:31 +01:00
setSpawnRates(w);
2021-01-30 18:59:42 +01:00
}
// Store main generators
generatorMap.put(w, getChunkGenerator(env));
2021-01-30 18:59:42 +01:00
return w;
}
/**
* @return the boxedBiomeProvider
*/
public BiomeProvider getBoxedBiomeProvider() {
return boxedBiomeProvider;
}
2021-03-04 05:51:31 +01:00
private void setSpawnRates(World w) {
if (getSettings().getSpawnLimitMonsters() > 0) {
w.setSpawnLimit(SpawnCategory.MONSTER, getSettings().getSpawnLimitMonsters());
2021-03-04 05:51:31 +01:00
}
if (getSettings().getSpawnLimitAmbient() > 0) {
w.setSpawnLimit(SpawnCategory.AMBIENT, getSettings().getSpawnLimitAmbient());
2021-03-04 05:51:31 +01:00
}
if (getSettings().getSpawnLimitAnimals() > 0) {
w.setSpawnLimit(SpawnCategory.ANIMAL, getSettings().getSpawnLimitAnimals());
2021-03-04 05:51:31 +01:00
}
if (getSettings().getSpawnLimitWaterAnimals() > 0) {
w.setSpawnLimit(SpawnCategory.WATER_ANIMAL, getSettings().getSpawnLimitWaterAnimals());
2021-03-04 05:51:31 +01:00
}
if (getSettings().getTicksPerAnimalSpawns() > 0) {
w.setTicksPerSpawns(SpawnCategory.ANIMAL, getSettings().getTicksPerAnimalSpawns());
2021-03-04 05:51:31 +01:00
}
if (getSettings().getTicksPerMonsterSpawns() > 0) {
w.setTicksPerSpawns(SpawnCategory.MONSTER, getSettings().getTicksPerMonsterSpawns());
2021-03-24 05:45:52 +01:00
}
2021-03-04 05:51:31 +01:00
}
2021-01-30 18:59:42 +01:00
@Override
public WorldSettings getWorldSettings() {
return getSettings();
}
@Override
public @Nullable ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
2024-03-13 06:45:58 +01:00
for (Entry<String, ChunkGenerator> en : generatorMaps.entrySet()) {
if (en.getKey().equalsIgnoreCase(worldName)) {
return en.getValue();
}
}
return null;
2021-01-30 18:59:42 +01:00
}
@Override
public void saveWorldSettings() {
if (settings != null) {
configObject.saveConfigObject(settings);
}
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.addons.Addon#allLoaded()
*/
@Override
public void allLoaded() {
// Save settings. This will occur after all addons have loaded
2021-01-30 18:59:42 +01:00
this.saveWorldSettings();
// Register generators for worlds with multiverse etc.
this.log("Registering Boxed worlds with other plugins (if applicable)...");
generatorMap.keySet().forEach(this::registerToWorldManagementPlugins);
2021-01-30 18:59:42 +01:00
}
/**
* @return the advManager
*/
public AdvancementsManager getAdvManager() {
return advManager;
}
2023-03-12 06:37:21 +01:00
@Override
public boolean isUsesNewChunkGeneration() {
return true;
}
2021-01-30 18:59:42 +01:00
}