From e71eba3d1f48e15b6597afb1c42c5ff5f78efcf9 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Tue, 4 Oct 2011 10:13:44 +0100 Subject: Fix for /tjail not teleporting users back due to cooldown. --- Essentials/src/com/earth2me/essentials/Teleport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/Teleport.java b/Essentials/src/com/earth2me/essentials/Teleport.java index 608663561..845f9c3a3 100644 --- a/Essentials/src/com/earth2me/essentials/Teleport.java +++ b/Essentials/src/com/earth2me/essentials/Teleport.java @@ -256,7 +256,7 @@ public class Teleport implements Runnable public void back() throws Exception { - back(null); + now(new Target(user.getLastLocation())); } public void home(IUser user, String home, Trade chargeFor) throws Exception -- cgit v1.2.3 From 52e674459fc823c0bca2881c2da35e1d689feac8 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Tue, 4 Oct 2011 10:16:35 +0100 Subject: Less dupe code on last commit. --- Essentials/src/com/earth2me/essentials/Teleport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/Teleport.java b/Essentials/src/com/earth2me/essentials/Teleport.java index 845f9c3a3..b4dd819aa 100644 --- a/Essentials/src/com/earth2me/essentials/Teleport.java +++ b/Essentials/src/com/earth2me/essentials/Teleport.java @@ -256,7 +256,7 @@ public class Teleport implements Runnable public void back() throws Exception { - now(new Target(user.getLastLocation())); + now(user.getLastLocation()); } public void home(IUser user, String home, Trade chargeFor) throws Exception -- cgit v1.2.3 From 40f1309d7e17c41e8df69f3874bd874e8177686f Mon Sep 17 00:00:00 2001 From: KHobbits Date: Tue, 4 Oct 2011 10:27:58 +0100 Subject: Revert "Less dupe code on last commit." This reverts commit 52e674459fc823c0bca2881c2da35e1d689feac8. --- Essentials/src/com/earth2me/essentials/Teleport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/Teleport.java b/Essentials/src/com/earth2me/essentials/Teleport.java index b4dd819aa..845f9c3a3 100644 --- a/Essentials/src/com/earth2me/essentials/Teleport.java +++ b/Essentials/src/com/earth2me/essentials/Teleport.java @@ -256,7 +256,7 @@ public class Teleport implements Runnable public void back() throws Exception { - now(user.getLastLocation()); + now(new Target(user.getLastLocation())); } public void home(IUser user, String home, Trade chargeFor) throws Exception -- cgit v1.2.3 From 9c6d49a9e2deddc97c2da2bf5c887f764e4a3530 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Tue, 4 Oct 2011 14:39:40 +0100 Subject: Nick length patch --- Essentials/src/com/earth2me/essentials/User.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/User.java b/Essentials/src/com/earth2me/essentials/User.java index fe811e50f..3e335a1df 100644 --- a/Essentials/src/com/earth2me/essentials/User.java +++ b/Essentials/src/com/earth2me/essentials/User.java @@ -286,7 +286,10 @@ public class User extends UserData implements Comparable, IReplyTo, IUser public void setDisplayNick(String name) { setDisplayName(name); - setPlayerListName(name); + //TODO: Maybe we need to limit nick length, or try use a string trim. + if (name.length() <= 16) { + setPlayerListName(name); + } } public Teleport getTeleport() -- cgit v1.2.3 From 0ee6985c563703f0c54fb941049e8b3c25a97a1f Mon Sep 17 00:00:00 2001 From: snowleo Date: Tue, 4 Oct 2011 21:33:02 +0200 Subject: Null check for probably corrupted worlds --- Essentials/src/com/earth2me/essentials/signs/EssentialsSign.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/signs/EssentialsSign.java b/Essentials/src/com/earth2me/essentials/signs/EssentialsSign.java index 026fb0557..b9d224cec 100644 --- a/Essentials/src/com/earth2me/essentials/signs/EssentialsSign.java +++ b/Essentials/src/com/earth2me/essentials/signs/EssentialsSign.java @@ -223,7 +223,7 @@ public class EssentialsSign if (signblock.getType() == Material.WALL_SIGN) { final org.bukkit.material.Sign signMat = (org.bukkit.material.Sign)signblock.getState().getData(); - if (signMat.getFacing() == blockFace && isValidSign(new BlockSign(signblock))) + if (signMat != null && signMat.getFacing() == blockFace && isValidSign(new BlockSign(signblock))) { return true; } -- cgit v1.2.3 From d4af9804d51303b4ffe5c3c2cd0efeb84fb50875 Mon Sep 17 00:00:00 2001 From: snowleo Date: Tue, 4 Oct 2011 21:58:47 +0200 Subject: Removing obsolete Nether portal code. If you want more control over the worlds, I recommend using Multiverse. /world command still exists, it can be used to switch between worlds. The default ratio of 8 is used for nether. --- .../src/com/earth2me/essentials/Essentials.java | 5 - .../essentials/EssentialsPlayerListener.java | 105 +------------ .../src/com/earth2me/essentials/ISettings.java | 12 -- .../src/com/earth2me/essentials/NetherPortal.java | 167 --------------------- .../src/com/earth2me/essentials/Settings.java | 40 ----- .../earth2me/essentials/commands/Commandworld.java | 43 +++--- Essentials/src/config.yml | 6 - .../com/earth2me/essentials/EssentialsTest.java | 45 ------ 8 files changed, 23 insertions(+), 400 deletions(-) delete mode 100644 Essentials/src/com/earth2me/essentials/NetherPortal.java delete mode 100644 Essentials/test/com/earth2me/essentials/EssentialsTest.java diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index c98671d94..fe0c3560c 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -201,11 +201,6 @@ public class Essentials extends JavaPlugin implements IEssentials pm.registerEvent(Type.PLAYER_TELEPORT, jailPlayerListener, Priority.High, this); pm.registerEvent(Type.PLAYER_JOIN, jailPlayerListener, Priority.High, this); - if (settings.isNetherEnabled() && getServer().getWorlds().size() < 2) - { - getServer().createWorld(settings.getNetherName(), World.Environment.NETHER); - } - pm.registerEvent(Type.ENTITY_EXPLODE, tntListener, Priority.High, this); final EssentialsTimer timer = new EssentialsTimer(this); diff --git a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java index ddf0a6806..026e4632b 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java @@ -100,114 +100,11 @@ public class EssentialsPlayerListener extends PlayerListener return; } - Location afk = user.getAfkPosition(); + final Location afk = user.getAfkPosition(); if (afk == null || !event.getTo().getWorld().equals(afk.getWorld()) || afk.distanceSquared(event.getTo()) > 9) { user.updateActivity(true); } - - if (!ess.getSettings().getNetherPortalsEnabled()) - { - return; - } - - final Block block = event.getPlayer().getWorld().getBlockAt(event.getTo().getBlockX(), event.getTo().getBlockY(), event.getTo().getBlockZ()); - final List worlds = server.getWorlds(); - - if (block.getType() == Material.PORTAL && worlds.size() > 1 && user.isAuthorized("essentials.portal")) - { - if (user.getJustPortaled()) - { - return; - } - - World nether = server.getWorld(ess.getSettings().getNetherName()); - if (nether == null) - { - for (World world : worlds) - { - if (world.getEnvironment() == World.Environment.NETHER) - { - nether = world; - break; - } - } - if (nether == null) - { - return; - } - } - final World world = user.getWorld() == nether ? worlds.get(0) : nether; - - double factor; - if (user.getWorld().getEnvironment() == World.Environment.NETHER && world.getEnvironment() == World.Environment.NORMAL) - { - factor = ess.getSettings().getNetherRatio(); - } - else if (user.getWorld().getEnvironment() == World.Environment.NORMAL && world.getEnvironment() == World.Environment.NETHER) - { - factor = 1.0 / ess.getSettings().getNetherRatio(); - } - else - { - factor = 1.0; - } - - Location loc = event.getTo(); - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - - if (user.getWorld().getBlockAt(x, y, z - 1).getType() == Material.PORTAL) - { - z--; - } - if (user.getWorld().getBlockAt(x - 1, y, z).getType() == Material.PORTAL) - { - x--; - } - - x = (int)(x * factor); - z = (int)(z * factor); - loc = new Location(world, x + .5, y, z + .5); - - Block dest = world.getBlockAt(x, y, z); - NetherPortal portal = NetherPortal.findPortal(dest); - if (portal == null) - { - if (world.getEnvironment() == World.Environment.NETHER || ess.getSettings().getGenerateExitPortals()) - { - portal = NetherPortal.createPortal(dest); - LOGGER.info(Util.format("userCreatedPortal", event.getPlayer().getName())); - user.sendMessage(Util.i18n("generatingPortal")); - loc = portal.getSpawn(); - } - } - else - { - LOGGER.info(Util.format("userUsedPortal", event.getPlayer().getName())); - user.sendMessage(Util.i18n("usingPortal")); - loc = portal.getSpawn(); - } - - event.setFrom(loc); - event.setTo(loc); - try - { - user.getTeleport().now(loc, new Trade("portal", ess)); - } - catch (Exception ex) - { - user.sendMessage(ex.getMessage()); - } - user.setJustPortaled(true); - user.sendMessage(Util.i18n("teleportingPortal")); - - event.setCancelled(true); - return; - } - - user.setJustPortaled(false); } @Override diff --git a/Essentials/src/com/earth2me/essentials/ISettings.java b/Essentials/src/com/earth2me/essentials/ISettings.java index af95e2cbc..54d1b1495 100644 --- a/Essentials/src/com/earth2me/essentials/ISettings.java +++ b/Essentials/src/com/earth2me/essentials/ISettings.java @@ -35,8 +35,6 @@ public interface ISettings extends IConf int getDefaultStackSize(); - boolean getGenerateExitPortals(); - double getHealCooldown(); Object getKit(String name); @@ -45,12 +43,6 @@ public interface ISettings extends IConf String getLocale(); - String getNetherName(); - - boolean getNetherPortalsEnabled(); - - double getNetherRatio(); - String getNewbieSpawn(); String getNicknamePrefix(); @@ -105,8 +97,6 @@ public interface ISettings extends IConf boolean isEcoDisabled(); - boolean isNetherEnabled(); - boolean isTradeInStacks(int id); List itemSpawnBlacklist(); @@ -117,8 +107,6 @@ public interface ISettings extends IConf boolean spawnIfNoHome(); - boolean use1to1RatioInNether(); - boolean warnOnBuildDisallow(); boolean warnOnSmite(); diff --git a/Essentials/src/com/earth2me/essentials/NetherPortal.java b/Essentials/src/com/earth2me/essentials/NetherPortal.java deleted file mode 100644 index 8c8c9e52f..000000000 --- a/Essentials/src/com/earth2me/essentials/NetherPortal.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @author SpaceManiac - * @licent MIT - * @origin https://github.com/SpaceManiac/Nether/blob/master/org/innectis/Nether/NetherPortal.java - */ -package com.earth2me.essentials; - -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.Location; -import org.bukkit.Material; -import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; - - -public class NetherPortal -{ - private Block block; - - public NetherPortal(Block b) - { - block = b; - } - - public Block getBlock() - { - return block; - } - - public void setBlock(Block b) - { - block = b; - } - - // Return a random spawnable location - public Location getSpawn() - { - if (block.getWorld().getBlockAt(block.getX() + 1, block.getY(), block.getZ()).getType().equals(Material.PORTAL) - || block.getWorld().getBlockAt(block.getX() - 1, block.getY(), block.getZ()).getType().equals(Material.PORTAL)) - { - // portal is in X direction - return new Location(block.getWorld(), block.getX() + 1, - block.getY(), block.getZ() + 1 - 2 * Math.round(Math.random())); - } - else - { - // portal is in Z direction - return new Location(block.getWorld(), block.getX() + 1 - 2 * Math.round(Math.random()), - block.getY(), block.getZ() + 1); - } - } - - // ============================== - // Find a nearby portal within 16 blocks of the given block - // Not guaranteed to be the nearest - public static NetherPortal findPortal(Block dest) - { - World world = dest.getWorld(); - - // Get list of columns in a circle around the block - ArrayList columns = new ArrayList(); - for (int x = dest.getX() - 16; x <= dest.getX() + 16; ++x) - { - for (int z = dest.getZ() - 16; z <= dest.getZ() + 16; ++z) - { - int dx = dest.getX() - x, dz = dest.getZ() - z; - if (dx * dx + dz * dz <= 256) - { - columns.add(world.getBlockAt(x, 0, z)); - } - } - } - - // For each column try to find a portal block - for (Block col : columns) - { - for (int y = 127; y >= 0; --y) - { - Block b = world.getBlockAt(col.getX(), y, col.getZ()); - if (b.getType().equals(Material.PORTAL) && Math.abs(dest.getY() - y) <= 16) - { - // Huzzah! - return new NetherPortal(b); - } - } - } - - // Nope! - return null; - } - - // Create a new portal at the specified block, fudging position if needed - // Will occasionally end up making portals in bad places, but let's hope not - public static NetherPortal createPortal(Block dest) - { - World world = dest.getWorld(); - - // Try not to spawn within water or lava - Material m = dest.getType(); - while (((m.equals(Material.LAVA) || m.equals(Material.WATER) || m.equals(Material.STATIONARY_LAVA) - || m.equals(Material.STATIONARY_WATER) || m.equals(Material.SAND) || m.equals(Material.GRAVEL))) && - dest.getY() < 120) - { - dest = world.getBlockAt(dest.getX(), dest.getY() + 4, dest.getZ()); - m = dest.getType(); - } - - // Not too high or too low overall - if (dest.getY() > 120) - { - dest = world.getBlockAt(dest.getX(), 120, dest.getZ()); - } - else if (dest.getY() < 8) - { - dest = world.getBlockAt(dest.getX(), 8, dest.getZ()); - } - - // Create the physical portal - // For now, don't worry about direction - - int x = dest.getX(), y = dest.getY(), z = dest.getZ(); - Logger.getLogger("Minecraft").log(Level.INFO, Util.format("creatingPortal", x, y, z)); - - // Clear area around portal - ArrayList columns = new ArrayList(); - for (int x2 = x - 4; x2 <= x + 4; ++x2) - { - for (int z2 = z - 4; z2 <= z + 4; ++z2) - { - double dx = x + 0.5f - x2, dz = z - z2; - if (dx * dx + dz * dz <= 13) - { - columns.add(world.getBlockAt(x2, 0, z2)); - } - } - } - - // Clear area around portal - for (Block col : columns) - { - // Stone platform - world.getBlockAt(col.getX(), y - 1, col.getZ()).setType(Material.STONE); - for (int yd = 0; yd < 4; ++yd) - { - world.getBlockAt(col.getX(), y + yd, col.getZ()).setType(Material.AIR); - } - } - - // Build obsidian frame - for (int xd = -1; xd < 3; ++xd) - { - for (int yd = -1; yd < 4; ++yd) - { - if (xd == -1 || yd == -1 || xd == 2 || yd == 3) - { - world.getBlockAt(x + xd, y + yd, z).setType(Material.OBSIDIAN); - } - } - } - - // Set it alight! - dest.setType(Material.FIRE); - - return new NetherPortal(dest); - } -} diff --git a/Essentials/src/com/earth2me/essentials/Settings.java b/Essentials/src/com/earth2me/essentials/Settings.java index 3c06fb300..d6a649786 100644 --- a/Essentials/src/com/earth2me/essentials/Settings.java +++ b/Essentials/src/com/earth2me/essentials/Settings.java @@ -95,12 +95,6 @@ public class Settings implements ISettings return config.getInt("starting-balance", 0); } - @Override - public boolean getNetherPortalsEnabled() - { - return isNetherEnabled() && config.getBoolean("nether.portals-enabled", false); - } - @Override public boolean isCommandDisabled(final IEssentialsCommand cmd) { @@ -257,18 +251,6 @@ public class Settings implements ISettings return config.getBoolean("reclaim-onlogout", true); } - @Override - public String getNetherName() - { - return config.getString("nether.folder", "nether"); - } - - @Override - public boolean isNetherEnabled() - { - return config.getBoolean("nether.enabled", false); - } - @Override public int getSpawnMobLimit() { @@ -318,12 +300,6 @@ public class Settings implements ISettings config.getString("chat.format", "&7[{GROUP}]&f {DISPLAYNAME}&7:&f {MESSAGE}")); } - @Override - public boolean getGenerateExitPortals() - { - return config.getBoolean("nether.generate-exit-portals", true); - } - @Override public boolean getAnnounceNewPlayers() { @@ -403,22 +379,6 @@ public class Settings implements ISettings return config.getBoolean("protect.disable.warn-on-build-disallow", false); } - @Override - public boolean use1to1RatioInNether() - { - return config.getBoolean("nether.use-1to1-ratio", false); - } - - @Override - public double getNetherRatio() - { - if (config.getBoolean("nether.use-1to1-ratio", false)) - { - return 1.0; - } - return config.getDouble("nether.ratio", 8.0); - } - @Override public boolean isDebug() { diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandworld.java b/Essentials/src/com/earth2me/essentials/commands/Commandworld.java index 77db8e5e3..557f46dbf 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandworld.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandworld.java @@ -17,26 +17,28 @@ public class Commandworld extends EssentialsCommand } @Override - protected void run(Server server, User user, String commandLabel, String[] args) throws Exception + protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { World world; - List worlds = server.getWorlds(); if (args.length < 1) { - World nether = server.getWorld(ess.getSettings().getNetherName()); - if (nether == null) { - for (World world2 : worlds) + World nether = null; + + final List worlds = server.getWorlds(); + + for (World world2 : worlds) + { + if (world2.getEnvironment() == World.Environment.NETHER) { - if (world2.getEnvironment() == World.Environment.NETHER) { - nether = world2; - break; - } - } - if (nether == null) { - return; + nether = world2; + break; } } + if (nether == null) + { + return; + } world = user.getWorld() == nether ? worlds.get(0) : nether; } else @@ -54,23 +56,22 @@ public class Commandworld extends EssentialsCommand double factor; if (user.getWorld().getEnvironment() == World.Environment.NETHER && world.getEnvironment() == World.Environment.NORMAL) { - factor = ess.getSettings().getNetherRatio(); + factor = 8.0; } - else if (user.getWorld().getEnvironment() != world.getEnvironment()) + else if (user.getWorld().getEnvironment() == World.Environment.NORMAL && world.getEnvironment() == World.Environment.NETHER) { - factor = 1.0 / ess.getSettings().getNetherRatio(); + factor = 1.0 / 8.0; } - else - { + else { factor = 1.0; } - Location loc = user.getLocation(); - loc = new Location(world, loc.getBlockX() * factor + .5, loc.getBlockY(), loc.getBlockZ() * factor + .5); + final Location loc = user.getLocation(); + final Location target = new Location(world, loc.getBlockX() * factor + .5, loc.getBlockY(), loc.getBlockZ() * factor + .5); - Trade charge = new Trade(this.getName(), ess); + final Trade charge = new Trade(this.getName(), ess); charge.isAffordableFor(user); - user.getTeleport().teleport(loc, charge); + user.getTeleport().teleport(target, charge); throw new NoChargeException(); } } diff --git a/Essentials/src/config.yml b/Essentials/src/config.yml index 7b1525d40..61cb7aefa 100644 --- a/Essentials/src/config.yml +++ b/Essentials/src/config.yml @@ -79,12 +79,6 @@ reclaim-onlogout: false # Should primitive spawn protection be enabled? For most servers, this should be flase; it is better to use a third-party plugin to protect it. spawn-protection: false -# Nether settings -# Sets wether you want to change the default behaviour of the nether portals. -nether: - portals-enabled: false - generate-exit-portals: false - # Mob limit on spawnmob spawnmob-limit: 10 diff --git a/Essentials/test/com/earth2me/essentials/EssentialsTest.java b/Essentials/test/com/earth2me/essentials/EssentialsTest.java deleted file mode 100644 index 26c5c68e9..000000000 --- a/Essentials/test/com/earth2me/essentials/EssentialsTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.earth2me.essentials; - -import junit.framework.TestCase; - - -public class EssentialsTest extends TestCase -{ - public EssentialsTest(String testName) - { - super(testName); - } - - private static void should(String what) - { - System.out.println("Essentials should " + what); - } - - public void testLoadClasses() - { - should("make all classes accessible"); - try - { - ItemDb itemDb = null; - Mob mob = null; - NetherPortal netherPortal = null; - OfflinePlayer offlinePlayer = null; - Settings settings = null; - Spawn spawn = null; - TargetBlock targetBlock = null; - User user = null; - assertNull(itemDb); - assertNull(mob); - assertNull(netherPortal); - assertNull(offlinePlayer); - assertNull(settings); - assertNull(spawn); - assertNull(targetBlock); - assertNull(user); - } - catch (Throwable ex) - { - fail(ex.toString()); - } - } -} -- cgit v1.2.3 From 9fc92f3528150de081f453308ff4ab26a3afd384 Mon Sep 17 00:00:00 2001 From: snowleo Date: Tue, 4 Oct 2011 22:19:23 +0200 Subject: Since it will be released, it needs a new version number --- EssentialsGroupManager/src/Changelog.txt | 3 ++- EssentialsGroupManager/src/plugin.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index b8034e19c..e90d7e368 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -25,6 +25,7 @@ v 1.1: v 1.2: - Changed priority of Registered events to lowest. - Fixed an issue with superperms where plugins define perms with inheritance after the root perms +v 1.3: - Rewrote Config loading to use Bukkits Configuration features - Added an opOverride setting in config. If present and set to false, op's will not get overriding permissions in GroupManager. @@ -35,4 +36,4 @@ v 1.2: - Added event handling to manage new world creation at runtime. - Added the ability to handle unknown worlds at server start. (GM will create the data files for any worlds it finds which are not in the config.yml) - - Fix for Bukkit passing a null To location on a player Portaling \ No newline at end of file + - Fix for Bukkit passing a null To location on a player portaling. \ No newline at end of file diff --git a/EssentialsGroupManager/src/plugin.yml b/EssentialsGroupManager/src/plugin.yml index b0d2bc4d1..a247c7ad0 100644 --- a/EssentialsGroupManager/src/plugin.yml +++ b/EssentialsGroupManager/src/plugin.yml @@ -1,5 +1,5 @@ name: GroupManager -version: "1.2 (Phoenix)" +version: "1.3 (Phoenix)" main: org.anjocaido.groupmanager.GroupManager website: http://www.anjocaido.info/ description: Provides on-the-fly system for permissions system created by Nijikokun. But all in memory, and with flat-file saving schedule. -- cgit v1.2.3