package com.destroystokyo.paper; import java.util.List; import java.util.logging.Level; import net.minecraft.server.MinecraftServer; import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; import static com.destroystokyo.paper.PaperConfig.log; public class PaperWorldConfig { private final String worldName; private final SpigotWorldConfig spigotConfig; private final YamlConfiguration config; private boolean verbose; public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { this.worldName = worldName; this.spigotConfig = spigotConfig; this.config = PaperConfig.config; init(); } public void init() { log("-------- World Settings For [" + worldName + "] --------"); PaperConfig.readConfig(PaperWorldConfig.class, this); } private void set(String path, Object val) { config.set("world-settings.default." + path, val); if (config.get("world-settings." + worldName + "." + path) != null) { config.set("world-settings." + worldName + "." + path, val); } } private boolean getBoolean(String path, boolean def) { config.addDefault("world-settings.default." + path, def); return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); } private double getDouble(String path, double def) { config.addDefault("world-settings.default." + path, def); return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); } private int getInt(String path, int def) { config.addDefault("world-settings.default." + path, def); return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); } private float getFloat(String path, float def) { // TODO: Figure out why getFloat() always returns the default value. return (float) getDouble(path, def); } private <T> List getList(String path, T def) { config.addDefault("world-settings.default." + path, def); return config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); } private String getString(String path, String def) { config.addDefault("world-settings.default." + path, def); return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); } public double squidMinSpawnHeight; public double squidMaxSpawnHeight; private void squidSpawnHeights() { squidMinSpawnHeight = getDouble("squid-spawn-height.minimum", 45.0D); squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 63.0D); log("Squids will spawn between Y: " + squidMinSpawnHeight + " and Y: " + squidMaxSpawnHeight); } public int cactusMaxHeight; public int reedMaxHeight; private void blowGrowthHeight() { cactusMaxHeight = getInt("max-growth-height.cactus", 3); reedMaxHeight = getInt("max-growth-height.reeds", 3); log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight); } public double babyZombieMovementSpeed; private void babyZombieMovementSpeed() { babyZombieMovementSpeed = getDouble("baby-zombie-movement-speed", 0.5D); // Player moves at 0.1F, for reference log("Baby zombies will move at the speed of " + babyZombieMovementSpeed); } public int fishingMinTicks; public int fishingMaxTicks; private void fishingTickRange() { fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); } public boolean nerfedMobsShouldJump; private void nerfedMobsShouldJump() { nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); } public int softDespawnDistance; public int hardDespawnDistance; private void despawnDistances() { softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default if (softDespawnDistance > hardDespawnDistance) { softDespawnDistance = hardDespawnDistance; } log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); softDespawnDistance = softDespawnDistance*softDespawnDistance; hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; } public boolean keepSpawnInMemory; private void keepSpawnInMemory() { keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); log("Keep spawn chunk loaded: " + keepSpawnInMemory); } public int fallingBlockHeightNerf; public int entityTNTHeightNerf; private void heightNerfs() { fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); } public int waterOverLavaFlowSpeed; private void waterOverLawFlowSpeed() { waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); log("Water over lava flow speed: " + waterOverLavaFlowSpeed); } public boolean netherVoidTopDamage; private void netherVoidTopDamage() { netherVoidTopDamage = getBoolean( "nether-ceiling-void-damage", false ); log("Top of the nether void damage: " + netherVoidTopDamage); } public boolean queueLightUpdates; private void queueLightUpdates() { queueLightUpdates = getBoolean("queue-light-updates", false); log("Lighting Queue enabled: " + queueLightUpdates); } public boolean disableEndCredits; private void disableEndCredits() { disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); log("End credits disabled: " + disableEndCredits); } public boolean generateCanyon; public boolean generateCaves; public boolean generateDungeon; public boolean generateFortress; public boolean generateMineshaft; public boolean generateMonument; public boolean generateStronghold; public boolean generateTemple; public boolean generateVillage; public boolean generateFlatBedrock; private void generatorSettings() { generateCanyon = getBoolean("generator-settings.canyon", true); generateCaves = getBoolean("generator-settings.caves", true); generateDungeon = getBoolean("generator-settings.dungeon", true); generateFortress = getBoolean("generator-settings.fortress", true); generateMineshaft = getBoolean("generator-settings.mineshaft", true); generateMonument = getBoolean("generator-settings.monument", true); generateStronghold = getBoolean("generator-settings.stronghold", true); generateTemple = getBoolean("generator-settings.temple", true); generateVillage = getBoolean("generator-settings.village", true); generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); } public boolean optimizeExplosions; private void optimizeExplosions() { optimizeExplosions = getBoolean("optimize-explosions", false); log("Optimize explosions: " + optimizeExplosions); } public boolean fastDrainLava; public boolean fastDrainWater; private void fastDrain() { fastDrainLava = getBoolean("fast-drain.lava", false); fastDrainWater = getBoolean("fast-drain.water", false); } public int lavaFlowSpeedNormal; public int lavaFlowSpeedNether; private void lavaFlowSpeeds() { lavaFlowSpeedNormal = getInt("lava-flow-speed.normal", 30); lavaFlowSpeedNether = getInt("lava-flow-speed.nether", 10); } public boolean disableExplosionKnockback; private void disableExplosionKnockback(){ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); } public boolean disableThunder; private void disableThunder() { disableThunder = getBoolean("disable-thunder", false); } public boolean disableIceAndSnow; private void disableIceAndSnow(){ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); } public int mobSpawnerTickRate; private void mobSpawnerTickRate() { mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); } public int containerUpdateTickRate; private void containerUpdateTickRate() { containerUpdateTickRate = getInt("container-update-tick-rate", 1); } public boolean disableChestCatDetection; private void disableChestCatDetection() { disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); } public boolean allChunksAreSlimeChunks; private void allChunksAreSlimeChunks() { allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); } public int portalSearchRadius; private void portalSearchRadius() { portalSearchRadius = getInt("portal-search-radius", 128); } public boolean disableTeleportationSuffocationCheck; private void disableTeleportationSuffocationCheck() { disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); } public boolean nonPlayerEntitiesOnScoreboards = false; private void nonPlayerEntitiesOnScoreboards() { nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); } public boolean allowLeashingUndeadHorse = false; private void allowLeashingUndeadHorse() { allowLeashingUndeadHorse = getBoolean("allow-leashing-undead-horse", false); } public int nonPlayerArrowDespawnRate = -1; private void nonPlayerArrowDespawnRate() { nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); if (nonPlayerArrowDespawnRate == -1) { nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; } log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); } public double skeleHorseSpawnChance; private void skeleHorseSpawnChance() { skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); // -1.0D represents a "vanilla" state } public boolean firePhysicsEventForRedstone = false; private void firePhysicsEventForRedstone() { firePhysicsEventForRedstone = getBoolean("fire-physics-event-for-redstone", firePhysicsEventForRedstone); } public boolean useInhabitedTime = true; private void useInhabitedTime() { useInhabitedTime = getBoolean("use-chunk-inhabited-timer", true); } public int grassUpdateRate = 1; private void grassUpdateRate() { grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); log("Grass Spread Tick Rate: " + grassUpdateRate); } public short keepLoadedRange; private void keepLoadedRange() { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 8)) * 16); log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); } public boolean useVanillaScoreboardColoring; private void useVanillaScoreboardColoring() { useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); } public boolean frostedIceEnabled = true; public int frostedIceDelayMin = 20; public int frostedIceDelayMax = 40; private void frostedIce() { this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); } public boolean autoReplenishLootables; public boolean restrictPlayerReloot; public boolean changeLootTableSeedOnFill; public int maxLootableRefills; public int lootableRegenMin; public int lootableRegenMax; private void enhancedLootables() { autoReplenishLootables = getBoolean("lootables.auto-replenish", false); restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); maxLootableRefills = getInt("lootables.max-refills", -1); lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); if (autoReplenishLootables) { log("Lootables: Replenishing every " + PaperConfig.timeSummary(lootableRegenMin) + " to " + PaperConfig.timeSummary(lootableRegenMax) + (restrictPlayerReloot ? " (restricting reloot)" : "") ); } } public boolean oldCannonBehaviors; private void oldCannonBehaviors() { oldCannonBehaviors = getBoolean("enable-old-tnt-cannon-behaviors", false); if (oldCannonBehaviors) { log("Old Cannon Behaviors: This feature may not be working entirely properly at the moment"); } } public boolean altFallingBlockOnGround; private void altFallingBlockOnGround() { altFallingBlockOnGround = getBoolean("use-alternate-fallingblock-onGround-detection", false); } public boolean isHopperPushBased; private void isHopperPushBased() { isHopperPushBased = getBoolean("hopper.push-based", false); } public long delayChunkUnloadsBy; private void delayChunkUnloadsBy() { delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); if (delayChunkUnloadsBy > 0) { log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); delayChunkUnloadsBy *= 1000; } } public boolean elytraHitWallDamage = true; private void elytraHitWallDamage() { elytraHitWallDamage = getBoolean("elytra-hit-wall-damage", true); } public int autoSavePeriod = -1; private void autoSavePeriod() { autoSavePeriod = getInt("auto-save-interval", -1); if (autoSavePeriod > 0) { log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); } else if (autoSavePeriod < 0) { autoSavePeriod = MinecraftServer.getServer().autosavePeriod; } } public int maxAutoSaveChunksPerTick = 24; private void maxAutoSaveChunksPerTick() { maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); } public int queueSizeAutoSaveThreshold = 50; private void queueSizeAutoSaveThreshold() { queueSizeAutoSaveThreshold = getInt("save-queue-limit-for-auto-save", 50); } public boolean removeCorruptTEs = false; private void removeCorruptTEs() { removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); } public boolean filterNBTFromSpawnEgg = true; private void fitlerNBTFromSpawnEgg() { filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); if (!filterNBTFromSpawnEgg) { Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); } } public boolean enableTreasureMaps = true; public boolean treasureMapsAlreadyDiscovered = false; private void treasureMapsAlreadyDiscovered() { enableTreasureMaps = getBoolean("enable-treasure-maps", true); treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); if (treasureMapsAlreadyDiscovered) { log("Treasure Maps will return already discovered locations"); } } public boolean armorStandEntityLookups = true; private void armorStandEntityLookups() { armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); } public int maxCollisionsPerEntity; private void maxEntityCollision() { maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); log( "Max Entity Collisions: " + maxCollisionsPerEntity ); } }