Moved Faction entity to useage of MStore as well.
This commit is contained in:
@@ -6,8 +6,6 @@ import java.util.logging.Level;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.EM;
|
||||
import com.massivecraft.factions.zcore.persist.SaveTask;
|
||||
import com.massivecraft.mcore.util.Txt;
|
||||
import com.massivecraft.mcore.xlib.gson.Gson;
|
||||
import com.massivecraft.mcore.xlib.gson.GsonBuilder;
|
||||
@@ -17,14 +15,6 @@ public abstract class MPlugin extends JavaPlugin
|
||||
{
|
||||
// Persist related
|
||||
public Gson gson;
|
||||
private Integer saveTask = null;
|
||||
private boolean autoSave = true;
|
||||
protected boolean loadSuccessful = false;
|
||||
public boolean getAutoSave() {return this.autoSave;}
|
||||
public void setAutoSave(boolean val) {this.autoSave = val;}
|
||||
|
||||
// Listeners
|
||||
public MPluginSecretPlayerListener mPluginSecretPlayerListener;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ENABLE
|
||||
@@ -39,18 +29,7 @@ public abstract class MPlugin extends JavaPlugin
|
||||
this.getDataFolder().mkdirs();
|
||||
|
||||
this.gson = this.getGsonBuilder().create();
|
||||
|
||||
// Create and register listeners
|
||||
this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this);
|
||||
|
||||
// Register recurring tasks
|
||||
long saveTicks = 20 * 60 * 30; // Approximately every 30 min
|
||||
if (saveTask == null)
|
||||
{
|
||||
saveTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(this), saveTicks, saveTicks);
|
||||
}
|
||||
|
||||
loadSuccessful = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,14 +40,6 @@ public abstract class MPlugin extends JavaPlugin
|
||||
|
||||
public void onDisable()
|
||||
{
|
||||
if (saveTask != null)
|
||||
{
|
||||
this.getServer().getScheduler().cancelTask(saveTask);
|
||||
saveTask = null;
|
||||
}
|
||||
// only save data if plugin actually loaded successfully
|
||||
if (loadSuccessful)
|
||||
EM.saveAllToDisc();
|
||||
log("Disabled");
|
||||
}
|
||||
|
||||
@@ -93,56 +64,6 @@ public abstract class MPlugin extends JavaPlugin
|
||||
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LANG AND TAGS
|
||||
// -------------------------------------------- //
|
||||
/*
|
||||
// These are not supposed to be used directly.
|
||||
// They are loaded and used through the TextUtil instance for the plugin.
|
||||
public Map<String, String> rawTags = new LinkedHashMap<String, String>();
|
||||
|
||||
public void addRawTags()
|
||||
{
|
||||
this.rawTags.put("l", "<green>"); // logo
|
||||
this.rawTags.put("a", "<gold>"); // art
|
||||
this.rawTags.put("n", "<silver>"); // notice
|
||||
this.rawTags.put("i", "<yellow>"); // info
|
||||
this.rawTags.put("g", "<lime>"); // good
|
||||
this.rawTags.put("b", "<rose>"); // bad
|
||||
this.rawTags.put("h", "<pink>"); // highligh
|
||||
this.rawTags.put("c", "<aqua>"); // command
|
||||
this.rawTags.put("p", "<teal>"); // parameter
|
||||
}
|
||||
|
||||
public void initTXT()
|
||||
{
|
||||
this.addRawTags();
|
||||
|
||||
Type type = new TypeToken<Map<String, String>>(){}.getType();
|
||||
|
||||
Map<String, String> tagsFromFile = this.persist.load(type, "tags");
|
||||
if (tagsFromFile != null) this.rawTags.putAll(tagsFromFile);
|
||||
this.persist.save(this.rawTags, "tags");
|
||||
|
||||
for (Entry<String, String> rawTag : this.rawTags.entrySet())
|
||||
{
|
||||
this.txt.tags.put(rawTag.getKey(), TextUtil.parseColor(rawTag.getValue()));
|
||||
}
|
||||
}*/
|
||||
|
||||
// -------------------------------------------- //
|
||||
// HOOKS
|
||||
// -------------------------------------------- //
|
||||
public void preAutoSave()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postAutoSave()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LOGGING
|
||||
// -------------------------------------------- //
|
||||
|
@@ -1,34 +0,0 @@
|
||||
package com.massivecraft.factions.zcore;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.EM;
|
||||
import com.massivecraft.factions.zcore.persist.Entity;
|
||||
import com.massivecraft.factions.zcore.persist.EntityCollection;
|
||||
import com.massivecraft.factions.zcore.persist.PlayerEntityCollection;
|
||||
|
||||
public class MPluginSecretPlayerListener implements Listener
|
||||
{
|
||||
public MPlugin p;
|
||||
public MPluginSecretPlayerListener(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
Bukkit.getPluginManager().registerEvents(this, this.p);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerPreLogin(PlayerLoginEvent event)
|
||||
{
|
||||
for (EntityCollection<? extends Entity> ecoll : EM.class2Entities.values())
|
||||
{
|
||||
if (ecoll instanceof PlayerEntityCollection)
|
||||
{
|
||||
ecoll.get(event.getPlayer().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,74 +0,0 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.Entity;
|
||||
import com.massivecraft.factions.zcore.persist.EntityCollection;
|
||||
|
||||
public class EM
|
||||
{
|
||||
public static Map<Class<? extends Entity>, EntityCollection<? extends Entity>> class2Entities = new LinkedHashMap<Class<? extends Entity>, EntityCollection<? extends Entity>>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> EntityCollection<T> getEntitiesCollectionForEntityClass(Class<T> entityClass)
|
||||
{
|
||||
return (EntityCollection<T>) class2Entities.get(entityClass);
|
||||
}
|
||||
|
||||
public static void setEntitiesCollectionForEntityClass(Class<? extends Entity> entityClass, EntityCollection<? extends Entity> entities)
|
||||
{
|
||||
class2Entities.put(entityClass, entities);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> void attach(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
ec.attach(entity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> void detach(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
ec.detach(entity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> boolean attached(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
return ec.attached(entity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> boolean detached(T entity)
|
||||
{
|
||||
EntityCollection<T> ec = (EntityCollection<T>) getEntitiesCollectionForEntityClass(entity.getClass());
|
||||
return ec.detached(entity);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DISC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static void saveAllToDisc()
|
||||
{
|
||||
for (EntityCollection<? extends Entity> ec : class2Entities.values())
|
||||
{
|
||||
ec.saveToDisc();
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadAllFromDisc()
|
||||
{
|
||||
for (EntityCollection<? extends Entity> ec : class2Entities.values())
|
||||
{
|
||||
ec.loadFromDisc();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
public abstract class Entity
|
||||
{
|
||||
public Entity()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected transient String id = null;
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
protected void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean shouldBeSaved()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void attach()
|
||||
{
|
||||
EM.attach(this);
|
||||
}
|
||||
|
||||
public void detach()
|
||||
{
|
||||
EM.detach(this);
|
||||
}
|
||||
|
||||
public boolean attached()
|
||||
{
|
||||
return EM.attached(this);
|
||||
}
|
||||
|
||||
public boolean detached()
|
||||
{
|
||||
return EM.detached(this);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EVENTS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void preDetach()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postDetach()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,292 +0,0 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import com.massivecraft.mcore.util.DiscUtil;
|
||||
import com.massivecraft.mcore.util.Txt;
|
||||
import com.massivecraft.mcore.xlib.gson.Gson;
|
||||
import com.massivecraft.mcore.xlib.gson.JsonSyntaxException;
|
||||
|
||||
public abstract class EntityCollection<E extends Entity>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// These must be instantiated in order to allow for different configuration (orders, comparators etc)
|
||||
private Collection<E> entities;
|
||||
protected Map<String, E> id2entity;
|
||||
|
||||
// If the entities are creative they will create a new instance if a non existent id was requested
|
||||
private boolean creative;
|
||||
public boolean isCreative() { return creative; }
|
||||
public void setCreative(boolean creative) { this.creative = creative; }
|
||||
|
||||
// This is the auto increment for the primary key "id"
|
||||
private int nextId;
|
||||
|
||||
// This ugly crap is necessary due to java type erasure
|
||||
private Class<E> entityClass;
|
||||
public abstract Type getMapType(); // This is special stuff for GSON.
|
||||
|
||||
// Info on how to persist
|
||||
private Gson gson;
|
||||
public Gson getGson() { return gson; }
|
||||
public void setGson(Gson gson) { this.gson = gson; }
|
||||
|
||||
private File file;
|
||||
public File getFile() { return file; }
|
||||
public void setFile(File file) { this.file = file; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCTORS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public EntityCollection(Class<E> entityClass, Collection<E> entities, Map<String, E> id2entity, File file, Gson gson, boolean creative)
|
||||
{
|
||||
this.entityClass = entityClass;
|
||||
this.entities = entities;
|
||||
this.id2entity = id2entity;
|
||||
this.file = file;
|
||||
this.gson = gson;
|
||||
this.creative = creative;
|
||||
this.nextId = 1;
|
||||
|
||||
EM.setEntitiesCollectionForEntityClass(this.entityClass, this);
|
||||
}
|
||||
|
||||
public EntityCollection(Class<E> entityClass, Collection<E> entities, Map<String, E> id2entity, File file, Gson gson)
|
||||
{
|
||||
this(entityClass, entities, id2entity, file, gson, false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GET
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Collection<E> get()
|
||||
{
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Map<String, E> getMap()
|
||||
{
|
||||
return this.id2entity;
|
||||
}
|
||||
|
||||
public E get(String id)
|
||||
{
|
||||
if (this.creative) return this.getCreative(id);
|
||||
return id2entity.get(id);
|
||||
}
|
||||
|
||||
public E getCreative(String id)
|
||||
{
|
||||
E e = id2entity.get(id);
|
||||
if (e != null) return e;
|
||||
return this.create(id);
|
||||
}
|
||||
|
||||
public boolean exists(String id)
|
||||
{
|
||||
if (id == null) return false;
|
||||
return id2entity.get(id) != null;
|
||||
}
|
||||
|
||||
public E getBestIdMatch(String pattern)
|
||||
{
|
||||
String id = Txt.getBestCIStart(this.id2entity.keySet(), pattern);
|
||||
|
||||
if (id == null) return null;
|
||||
return this.id2entity.get(id);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public synchronized E create()
|
||||
{
|
||||
return this.create(this.getNextId());
|
||||
}
|
||||
|
||||
public synchronized E create(String id)
|
||||
{
|
||||
if ( ! this.isIdFree(id)) return null;
|
||||
|
||||
E e = null;
|
||||
try
|
||||
{
|
||||
e = this.entityClass.newInstance();
|
||||
} catch (Exception ignored) {
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
|
||||
e.setId(id);
|
||||
this.entities.add(e);
|
||||
this.id2entity.put(e.getId(), e);
|
||||
this.updateNextIdForId(id);
|
||||
return e;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void attach(E entity)
|
||||
{
|
||||
if (entity.getId() != null) return;
|
||||
entity.setId(this.getNextId());
|
||||
this.entities.add(entity);
|
||||
this.id2entity.put(entity.getId(), entity);
|
||||
}
|
||||
|
||||
public void detach(E entity)
|
||||
{
|
||||
entity.preDetach();
|
||||
this.entities.remove(entity);
|
||||
this.id2entity.remove(entity.getId());
|
||||
entity.postDetach();
|
||||
}
|
||||
|
||||
public void detach(String id)
|
||||
{
|
||||
E entity = this.id2entity.get(id);
|
||||
if (entity == null) return;
|
||||
this.detach(entity);
|
||||
}
|
||||
|
||||
public boolean attached(E entity)
|
||||
{
|
||||
return this.entities.contains(entity);
|
||||
}
|
||||
|
||||
public boolean detached(E entity)
|
||||
{
|
||||
return ! this.attached(entity);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DISC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean saveToDisc()
|
||||
{
|
||||
Map<String, E> entitiesThatShouldBeSaved = new HashMap<String, E>();
|
||||
for (E entity : this.entities)
|
||||
{
|
||||
if (entity.shouldBeSaved())
|
||||
{
|
||||
entitiesThatShouldBeSaved.put(entity.getId(), entity);
|
||||
}
|
||||
}
|
||||
|
||||
return this.saveCore(entitiesThatShouldBeSaved);
|
||||
}
|
||||
|
||||
private boolean saveCore(Map<String, E> entities)
|
||||
{
|
||||
return DiscUtil.writeCatch(this.file, this.gson.toJson(entities));
|
||||
}
|
||||
|
||||
public boolean loadFromDisc()
|
||||
{
|
||||
Map<String, E> id2entity = this.loadCore();
|
||||
if (id2entity == null) return false;
|
||||
this.entities.clear();
|
||||
this.entities.addAll(id2entity.values());
|
||||
this.id2entity.clear();
|
||||
this.id2entity.putAll(id2entity);
|
||||
this.fillIds();
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String, E> loadCore()
|
||||
{
|
||||
if ( ! this.file.exists())
|
||||
{
|
||||
return new HashMap<String, E>();
|
||||
}
|
||||
|
||||
String content = DiscUtil.readCatch(this.file);
|
||||
if (content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type = this.getMapType();
|
||||
try
|
||||
{
|
||||
return this.gson.fromJson(content, type);
|
||||
}
|
||||
catch(JsonSyntaxException ex)
|
||||
{
|
||||
Bukkit.getLogger().log(Level.WARNING, "JSON error encountered loading \"" + file + "\": " + ex.getLocalizedMessage());
|
||||
|
||||
// backup bad file, so user can attempt to recover something from it
|
||||
File backup = new File(file.getPath()+"_bad");
|
||||
if (backup.exists()) backup.delete();
|
||||
Bukkit.getLogger().log(Level.WARNING, "Backing up copy of bad file to: "+backup);
|
||||
file.renameTo(backup);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ID MANAGEMENT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String getNextId()
|
||||
{
|
||||
while ( ! isIdFree(this.nextId) )
|
||||
{
|
||||
this.nextId += 1;
|
||||
}
|
||||
return Integer.toString(this.nextId);
|
||||
}
|
||||
|
||||
public boolean isIdFree(String id)
|
||||
{
|
||||
return ! this.id2entity.containsKey(id);
|
||||
}
|
||||
public boolean isIdFree(int id)
|
||||
{
|
||||
return this.isIdFree(Integer.toString(id));
|
||||
}
|
||||
|
||||
protected synchronized void fillIds()
|
||||
{
|
||||
this.nextId = 1;
|
||||
for(Entry<String, E> entry : this.id2entity.entrySet())
|
||||
{
|
||||
String id = entry.getKey();
|
||||
E entity = entry.getValue();
|
||||
entity.id = id;
|
||||
this.updateNextIdForId(id);
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void updateNextIdForId(int id)
|
||||
{
|
||||
if (this.nextId < id)
|
||||
{
|
||||
this.nextId = id + 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateNextIdForId(String id)
|
||||
{
|
||||
try
|
||||
{
|
||||
int idAsInt = Integer.parseInt(id);
|
||||
this.updateNextIdForId(idAsInt);
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
}
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerEntity extends Entity
|
||||
{
|
||||
public Player getPlayer()
|
||||
{
|
||||
return Bukkit.getPlayerExact(this.getId());
|
||||
}
|
||||
|
||||
public boolean isOnline()
|
||||
{
|
||||
return this.getPlayer() != null;
|
||||
}
|
||||
|
||||
// make sure target player should be able to detect that this player is online
|
||||
public boolean isOnlineAndVisibleTo(Player player)
|
||||
{
|
||||
Player target = this.getPlayer();
|
||||
return target != null && player.canSee(target);
|
||||
}
|
||||
|
||||
public boolean isOffline()
|
||||
{
|
||||
return ! isOnline();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Message Sending Helpers
|
||||
// -------------------------------------------- //
|
||||
|
||||
public void sendMessage(String msg)
|
||||
{
|
||||
Player player = this.getPlayer();
|
||||
if (player == null) return;
|
||||
player.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void sendMessage(List<String> msgs)
|
||||
{
|
||||
for(String msg : msgs)
|
||||
{
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.massivecraft.mcore.xlib.gson.Gson;
|
||||
|
||||
/**
|
||||
* The PlayerEntityCollection is an EntityCollection with the extra features
|
||||
* a player skin usually requires.
|
||||
*
|
||||
* This entity collection is not only creative. It even creates the instance for the player
|
||||
* when the player logs in to the server.
|
||||
*
|
||||
* This way we can be sure that PlayerEntityCollection.get() will contain
|
||||
* all entities in PlayerEntityCollection.getOnline()
|
||||
*/
|
||||
public abstract class PlayerEntityCollection<E extends Entity> extends EntityCollection<E>
|
||||
{
|
||||
public PlayerEntityCollection(Class<E> entityClass, Collection<E> entities, Map<String, E> id2entity, File file, Gson gson)
|
||||
{
|
||||
super(entityClass, entities, id2entity, file, gson, true);
|
||||
}
|
||||
|
||||
public E get(Player player)
|
||||
{
|
||||
return this.get(player.getName());
|
||||
}
|
||||
|
||||
public Set<E> getOnline()
|
||||
{
|
||||
Set<E> entities = new HashSet<E>();
|
||||
for (Player player : Bukkit.getServer().getOnlinePlayers())
|
||||
{
|
||||
entities.add(this.get(player));
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package com.massivecraft.factions.zcore.persist;
|
||||
|
||||
import com.massivecraft.factions.zcore.MPlugin;
|
||||
|
||||
public class SaveTask implements Runnable
|
||||
{
|
||||
MPlugin p;
|
||||
public SaveTask(MPlugin p)
|
||||
{
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
if ( ! p.getAutoSave()) return;
|
||||
p.preAutoSave();
|
||||
EM.saveAllToDisc();
|
||||
p.postAutoSave();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user