added access & save api from core machine

This commit is contained in:
DarkGuardsman 2013-12-18 07:28:00 -05:00
parent c3d6626cdd
commit fbfcd89d95
11 changed files with 1296 additions and 0 deletions

View file

@ -0,0 +1,132 @@
package dark.api.access;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import com.builtbroken.common.Group;
/** Used by a terminal to track what users are part of each group. As well used to setup access
* points to the terminal.
*
* @author DarkGuardsman */
public class AccessGroup extends Group<AccessUser>
{
protected List<String> nodes = new ArrayList<String>();
protected AccessGroup extendGroup;
public AccessGroup(String name, AccessUser... js)
{
super(name, js);
}
public void setToExtend(AccessGroup group)
{
this.extendGroup = group;
}
@Override
public boolean addMemeber(AccessUser obj)
{
if (obj != null)
{
for (AccessUser user : this.memebers)
{
if (user.getName().equalsIgnoreCase(obj.getName()))
{
return false;
}
}
if (super.addMemeber(obj))
{
obj.setGroup(this);
return true;
}
}
return false;
}
public AccessUser getMember(String name)
{
for (AccessUser user : this.memebers)
{
if (user.getName().equalsIgnoreCase(name))
{
return user;
}
}
return null;
}
public NBTTagCompound save(NBTTagCompound nbt)
{
nbt.setString("groupName", this.getName());
NBTTagList usersTag = new NBTTagList();
for (AccessUser user : this.memebers)
{
if (!user.isTempary)
{
NBTTagCompound accessData = new NBTTagCompound();
user.save(accessData);
usersTag.appendTag(accessData);
}
}
nbt.setTag("users", usersTag);
NBTTagList nodesTag = new NBTTagList();
for (String str : this.nodes)
{
NBTTagCompound accessData = new NBTTagCompound();
accessData.setString("name", str);
nodesTag.appendTag(accessData);
}
nbt.setTag("nodes", nodesTag);
return nbt;
}
public void load(NBTTagCompound nbt)
{
this.setName(nbt.getString("groupName"));
NBTTagList userList = nbt.getTagList("users");
for (int i = 0; i < userList.tagCount(); ++i)
{
this.addMemeber(AccessUser.loadFromNBT((NBTTagCompound) userList.tagAt(i)));
}
NBTTagList nodeList = nbt.getTagList("nodes");
for (int i = 0; i < nodeList.tagCount(); ++i)
{
this.nodes.add(((NBTTagCompound) nodeList.tagAt(i)).getString("name"));
}
}
public boolean hasNode(String node)
{
return this.nodes.contains(node);
}
public void addNode(String node)
{
this.nodes.add(node);
}
public void removeNode(String node)
{
if (this.nodes.contains(node))
{
this.nodes.remove(node);
}
}
public boolean isMemeber(String string)
{
for (AccessUser user : this.memebers)
{
if (user.getName().equalsIgnoreCase(string))
{
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,280 @@
package dark.api.access;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import dark.api.save.IVirtualObject;
import dark.api.save.NBTFileHelper;
import dark.api.save.SaveManager;
/** Designed to be used as a container for AccessGroups and AccessUser. If you plan to use this make
* sure to use it correctly. This is designed to be saved separate from the world save if marked for
* global access. Which means it can save/load at will from the world file.
*
* @author DarkGuardsman */
public class AccessProfile implements ISpecialAccess, IVirtualObject
{
/** A list of user access data. */
protected List<AccessGroup> groups = new ArrayList<AccessGroup>();
/** Display name */
protected String profileName = "";
/** Only used by global profiles that have no defined container. Also LocalHost means it was
* created by a tileEntity */
protected String profileID = "LocalHost";
/** Is this profile global */
protected boolean global = false;
/** Save file by which this was loaded from. Mainly used to save it in the same location again. */
protected File saveFile;
static
{
SaveManager.registerClass("AccessProfile", AccessProfile.class);
}
public AccessProfile()
{
if (global)
{
SaveManager.register(this);
}
}
public AccessProfile(NBTTagCompound nbt)
{
this(nbt, false);
}
public AccessProfile(NBTTagCompound nbt, boolean global)
{
this();
this.load(nbt);
if (this.profileName == null || this.profileID == null)
{
if (!global)
{
this.generateNew("Default", null);
}
else
{
this.generateNew("New Group", "global");
}
}
}
public AccessProfile generateNew(String name, Object object)
{
GroupRegistry.loadNewGroupSet(this);
this.profileName = name;
name.replaceAll(" ", "");
String id = null;
// Created by player for personal use
if (object instanceof EntityPlayer)
{
id = ((EntityPlayer) object).username + "_" + System.currentTimeMillis();
}//Created by a tile
else if (object instanceof TileEntity || object == null)
{
id = "LocalHost:" + name;
}//created by the game or player for global use
else if (object instanceof String && ((String) object).equalsIgnoreCase("global"))
{
id = "P_" + name + "_" + System.currentTimeMillis();
this.global = true;
}
this.profileID = id;
return this;
}
public String getName()
{
return this.profileName;
}
public String getID()
{
return this.profileID;
}
public boolean isGlobal()
{
return this.global;
}
@Override
public AccessUser getUserAccess(String username)
{
for (AccessGroup group : this.groups)
{
AccessUser user = group.getMember(username);
if (user != null)
{
return user;
}
}
return new AccessUser(username);
}
@Override
public List<AccessUser> getUsers()
{
List<AccessUser> users = new ArrayList<AccessUser>();
for (AccessGroup group : this.groups)
{
users.addAll(group.getMembers());
}
return users;
}
@Override
public boolean setUserAccess(String player, AccessGroup g, boolean save)
{
return setUserAccess(new AccessUser(player).setTempary(save), g);
}
@Override
public boolean setUserAccess(AccessUser user, AccessGroup group)
{
boolean bool = false;
if (user != null && user.getName() != null)
{
bool = this.removeUserAccess(user.getName()) && group == null;
if (group != null)
{
bool = group.addMemeber(user);
}
if (bool)
{
this.onProfileUpdate();
}
}
return bool;
}
public boolean removeUserAccess(String player)
{
boolean re = false;
for (AccessGroup group : this.groups)
{
AccessUser user = group.getMember(player);
if (user != null && group.removeMemeber(user))
{
re = true;
}
}
if (re)
{
this.onProfileUpdate();
}
return re;
}
public void onProfileUpdate()
{
}
@Override
public AccessGroup getGroup(String name)
{
for (AccessGroup group : this.getGroups())
{
if (group.getName().equalsIgnoreCase(name))
{
return group;
}
}
return null;
}
@Override
public boolean addGroup(AccessGroup group)
{
if (!this.groups.contains(group))
{
for (AccessGroup g : this.groups)
{
if (group.getName().equalsIgnoreCase(g.getName()))
{
return false;
}
}
if (this.groups.add(group))
{
this.onProfileUpdate();
return true;
}
}
return false;
}
@Override
public AccessGroup getOwnerGroup()
{
return this.getGroup("owner");
}
@Override
public List<AccessGroup> getGroups()
{
if (this.groups == null || this.groups.isEmpty())
{
GroupRegistry.loadNewGroupSet(this);
}
return this.groups;
}
@Override
public void save(NBTTagCompound nbt)
{
this.profileName = nbt.getString("name");
this.global = nbt.getBoolean("global");
NBTTagList userList = nbt.getTagList("groups");
if (userList != null && userList.tagCount() > 0)
{
this.groups.clear();
for (int i = 0; i < userList.tagCount(); i++)
{
AccessGroup group = new AccessGroup("");
group.load((NBTTagCompound) userList.tagAt(i));
this.groups.add(group);
}
}
}
@Override
public void load(NBTTagCompound nbt)
{
nbt.setString("name", this.profileName);
nbt.setBoolean("global", this.global);
NBTTagList usersTag = new NBTTagList();
for (AccessGroup group : this.getGroups())
{
usersTag.appendTag(group.save(new NBTTagCompound()));
}
nbt.setTag("groups", usersTag);
}
@Override
public File getSaveFile()
{
if (this.saveFile == null)
{
this.saveFile = new File(NBTFileHelper.getWorldSaveDirectory(MinecraftServer.getServer().getFolderName()), "CoreMachine/Access/" + this.getID() + ".dat");
}
return this.saveFile;
}
@Override
public void setSaveFile(File file)
{
this.saveFile = file;
}
}

View file

@ -0,0 +1,100 @@
package dark.api.access;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import com.builtbroken.common.User;
/** Used to define a users access to a terminal based object.
*
* @author DarkGuardsman */
public class AccessUser extends User
{
protected boolean isTempary = false;
protected NBTTagCompound extraData;
protected AccessGroup group;
protected List<String> nodes = new ArrayList<String>();
public AccessUser(String username)
{
super(username);
}
public AccessUser(EntityPlayer player)
{
super(player.username);
}
public AccessGroup getGroup()
{
return this.group;
}
public AccessUser setGroup(AccessGroup group)
{
this.group = group;
return this;
}
public boolean hasNode(String node)
{
if (group != null && group.hasNode(node))
{
return true;
}
return nodes.contains(node);
}
public NBTTagCompound save(NBTTagCompound nbt)
{
nbt.setString("username", this.username);
nbt.setCompoundTag("extraData", this.userData());
NBTTagList usersTag = new NBTTagList();
for (String str : this.nodes)
{
NBTTagCompound accessData = new NBTTagCompound();
accessData.setString("name", str);
usersTag.appendTag(accessData);
}
nbt.setTag("nodes", usersTag);
return nbt;
}
public AccessUser load(NBTTagCompound nbt)
{
this.username = nbt.getString("username");
this.extraData = nbt.getCompoundTag("extraData");
NBTTagList userList = nbt.getTagList("nodes");
for (int i = 0; i < userList.tagCount(); ++i)
{
this.nodes.add(((NBTTagCompound) userList.tagAt(i)).getString("name"));
}
return this;
}
public static AccessUser loadFromNBT(NBTTagCompound nbt)
{
return new AccessUser("").load(nbt);
}
public AccessUser setTempary(boolean si)
{
this.isTempary = si;
return this;
}
/** Used to add other data to the user */
public NBTTagCompound userData()
{
if (this.extraData == null)
{
this.extraData = new NBTTagCompound();
}
return this.extraData;
}
}

View file

@ -0,0 +1,114 @@
package dark.api.access;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
/** @author DarkGuardsman */
public class GroupRegistry
{
public static final List<String> nodes = new ArrayList<String>();
public static final HashMap<String, List<String>> groupDefaultNodes = new HashMap();
public static final HashMap<String, String> groupDefaultExtends = new HashMap();
static
{
List<String> list = new ArrayList<String>();
//Owner group defaults
list.add(Nodes.GROUP_OWNER_NODE);
list.add(Nodes.INV_DISABLE_NODE);
list.add(Nodes.INV_ENABLE_NODE);
createDefaultGroup("owner", "admin", list);
//Admin group defaults
List<String> list2 = new ArrayList<String>();
list2.add(Nodes.GROUP_ADMIN_NODE);
list2.add(Nodes.INV_EDIT_NODE);
list2.add(Nodes.INV_LOCK_NODE);
list2.add(Nodes.INV_UNLOCK_NODE);
list2.add(Nodes.INV_CHANGE_NODE);
createDefaultGroup("admin", "user", list2);
//User group defaults
List<String> list3 = new ArrayList<String>();
list3.add(Nodes.GROUP_USER_NODE);
list3.add(Nodes.INV_OPEN_NODE);
list3.add(Nodes.INV_TAKE_NODE);
list3.add(Nodes.INV_GIVE_NODE);
createDefaultGroup("user", null, list3);
}
/** Creates a default group for all machines to use. Only add a group if there is no option to
* really manage the group's settings
*
* @param name - group name
* @param prefabGroup - group this should extend. Make sure it exists.
* @param nodes - all commands or custom nodes */
public static void createDefaultGroup(String name, String prefabGroup, List<String> nodes)
{
if (name != null)
{
groupDefaultNodes.put(name, nodes);
groupDefaultExtends.put(name, prefabGroup);
}
}
/** Creates a default group for all machines to use. Only add a group if there is no option to
* really manage the group's settings
*
* @param name - group name
* @param prefabGroup - group this should extend. Make sure it exists.
* @param nodes - all commands or custom nodes */
public static void createDefaultGroup(String name, String prefabGroup, String... nodes)
{
List<String> nodeList = new ArrayList<String>();
if (nodes != null)
{
for (String node : nodes)
{
nodeList.add(node);
}
}
createDefaultGroup(name, prefabGroup, nodeList);
}
/** Builds a new default group list for a basic machine */
public static List<AccessGroup> getNewGroupSet()
{
List<AccessGroup> groups = new ArrayList<AccessGroup>();
for (Entry<String, List<String>> entry : groupDefaultNodes.entrySet())
{
AccessGroup group = new AccessGroup(entry.getKey());
if (entry.getValue() != null)
{
for (String string : entry.getValue())
{
group.addNode(string);
}
}
groups.add(group);
}
return groups;
}
/** Builds then loaded a new default group set into the terminal */
public static void loadNewGroupSet(ISpecialAccess terminal)
{
if (terminal != null)
{
List<AccessGroup> groups = getNewGroupSet();
for (AccessGroup group : groups)
{
terminal.addGroup(group);
}
}
}
public static void register(String node)
{
if (!nodes.contains(node))
{
nodes.add(node);
}
}
}

View file

@ -0,0 +1,15 @@
package dark.api.access;
/** Applied to tileEntities that contain an access profile that describes how the tile interacts with
* users
*
* @author DarkGuardsman */
public interface IProfileContainer
{
/** Return the active profile of the machine. When calling this avoid editing the profile */
public AccessProfile getAccessProfile();
/** Strait up yes or no can this user access the tile. Any future checks should be done after the
* user has accessed the machine */
public boolean canAccess(String username);
}

View file

@ -0,0 +1,39 @@
package dark.api.access;
import java.util.List;
/** Used by any object that needs to restrict access to it by a set of users or groups. Make sure to
* always use the default groups(user,admin,owner) so that things work smoothly.
*
* @author DarkGuardsman */
public interface ISpecialAccess
{
/** Gets the user access instance */
public AccessUser getUserAccess(String username);
/** gets the user access list for the machine */
public List<AccessUser> getUsers();
/** sets the players access level in the access map. Make sure to remove the old user first. This
* can also be used to remove users if group is set to null. */
public boolean setUserAccess(String username, AccessGroup group, boolean save);
/** Sets the players access by using a completed AccessUser instance. Make sure to set its group
* if there is none. As well remove the old user first. */
public boolean setUserAccess(AccessUser user, AccessGroup group);
/** Get a group by name */
public AccessGroup getGroup(String name);
/** Get the master owner group */
public AccessGroup getOwnerGroup();
/** Get all groups linked this */
public List<AccessGroup> getGroups();
/** Add a group to the group list
*
* @return */
public boolean addGroup(AccessGroup group);
}

View file

@ -0,0 +1,84 @@
package dark.api.access;
/** Constants that represent nodes by which machines and entities used in combination with
* ISpecialAccess to limit users on what they can do. These nodes should be used in the same way by
* all machines, entities, and other mods. Too change the meaning of the node will make it difficult
* to offer universal meaning for all machines. As well would create the need to add a per node per
* machine per group access list making it more complicated for users to use.
*
* @author DarkGuardsman */
public class Nodes
{
/*
* Rules for using nodes with groups and your machine:
*
* Keep everything the same.
* Eg: Open should be as simple as opening the gui and no more
*
* Enable is not the same as on
* Eg: you can disable a machine preventing users from using it
* Eg: When enabled the machine can still be turned off
*
* Lock node automatically includes unlock node but not the other way around
*
*
* Machine nodes override inv node as inv nodes are only designed for containers.
* Machines nodes are global for all guis inside the machine
*
*
* Groups do not need there own nodes. Group.user, Group.owner, Group.admin are designed to flag the default groups.
*
*
* Your machine must always have a group that at least has a owner group. This group should be flagged with Group.owner but is not required.
*
*
*
*/
//Inventory only nodes, overrided by machine nodes
public static final String INV_OPEN_NODE = "inv.open";
public static final String INV_TAKE_NODE = "inv.take";
public static final String INV_GIVE_NODE = "inv.give";
public static final String INV_EDIT_NODE = "inv.edit";
public static final String INV_CHANGE_NODE = "inv.change";
public static final String INV_LOCK_NODE = "inv.lock";
public static final String INV_UNLOCK_NODE = "inv.unlock";
public static final String INV_DISABLE_NODE = "inv.disable";
public static final String INV_ENABLE_NODE = "inv.enable";
//Master machines nodes, overrides all lower nodes of the same type
public static final String MACHINE_OPEN_NODE = "machine.open";
public static final String MACHINE_LOCK_NODE = "machine.lock";
public static final String MACHINE_UNLOCK_NODE = "machine.unlock";
public static final String MACHINE_ENABLE_NODE = "machine.enable";
public static final String MACHINE_DISABLE_NODE = "machine.disable";
public static final String MACHINE_TURN_ON_NODE = "machine.on";
public static final String MACHINE_TURN_OFF_NODE = "machine.off";
public static final String MACHINE_CONFIG_NODE = "machine.config";
public static final String MACHINE_UPGRADE_NODE = "machine.upgrade";
public static final String MACHINE_DOWNGRADE_NODE = "machine.downgrade";
//Group nodes, these are almost always held by only admins and owners
public static final String GROUP_CREATE_NODE = "group.create";
public static final String GROUP_DEL_NODE = "group.del";
public static final String GROUP_EDIT_NODE = "group.edit";//Still bound by other nodes
public static final String GROUP_ADD_NODE = "group.add";
public static final String GROUP_ADD_USER_NODE = "group.add.user";
public static final String GROUP_ADD_ENTITY_NODE = "group.add.entity";
public static final String GROUP_ADD_NODE_NODE = "group.add.node";
public static final String GROUP_REMOVE_NODE = "group.remove";
public static final String GROUP_REMOVE_USER_NODE = "group.remove.user";
public static final String GROUP_REMOVE_ENTITY_NODE = "group.remove.entity";
public static final String GROUP_REMOVE_NODE_NODE = "group.remove.node";
//Nodes for editing users inside of a group
public static final String USER_EDIT_NODE = "user.edit";
public static final String USER_CHANGE_GROUP_NODE = "user.change.group";
public static final String USER_ADD_NODE = "user.add.node";
public static final String USER_REMOVE_NODE = "user.remove.node";
//Prefab group nodes, designed to be placed on the master group of the type
public static final String GROUP_OWNER_NODE = "group.owner";
public static final String GROUP_ADMIN_NODE = "group.admin";
public static final String GROUP_USER_NODE = "group.user";
}

View file

@ -0,0 +1,12 @@
package dark.api.save;
import net.minecraft.nbt.NBTTagCompound;
public interface ISaveObj
{
/** Saves the object to NBT */
public void save(NBTTagCompound nbt);
/** Load the object from NBT */
public void load(NBTTagCompound nbt);
}

View file

@ -0,0 +1,18 @@
package dark.api.save;
import java.io.File;
/** Used in combination with the save manager and other managers to say this object needs to be save
* since its not connected with the world
*
* @author DarkGuardsman */
public interface IVirtualObject extends ISaveObj
{
/** File this is saved as, don't create anything here as the manager will do that for you */
public File getSaveFile();
/** Will only be called after an object has been loaded. Allows the object to know were its been
* loaded from and decide if it wants to use the location as its getSaveFile return */
public void setSaveFile(File file);
}

View file

@ -0,0 +1,338 @@
package dark.api.save;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagByte;
import net.minecraft.nbt.NBTTagByteArray;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagDouble;
import net.minecraft.nbt.NBTTagFloat;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.nbt.NBTTagLong;
import net.minecraft.nbt.NBTTagShort;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.server.MinecraftServer;
import universalelectricity.core.vector.Vector2;
import universalelectricity.core.vector.Vector3;
import com.builtbroken.common.science.units.UnitHelper;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
/** Helper class used to work with minecraft's NBT file system.
*
* @author DarkGuardsman */
public class NBTFileHelper
{
/** @param saveDirectory - file
* @param filename
* @param data
* @return */
public static boolean saveNBTFile(File saveDirectory, String filename, NBTTagCompound data)
{
return saveNBTFile(new File(saveDirectory, filename), data);
}
/** Saves an NBT file
*
* @param file - exact File
* @param data - nbt data
* @return */
public static boolean saveNBTFile(File file, NBTTagCompound data)
{
if (file != null && data != null)
{
try
{
File tempFile = new File(file.getParent(), file.getName() + ".tmp");
CompressedStreamTools.writeCompressed(data, new FileOutputStream(tempFile));
if (file.exists())
{
file.delete();
}
tempFile.renameTo(file);
FMLLog.fine("Saved " + file.getName() + " NBT data file successfully.");
return true;
}
catch (Exception e)
{
System.out.println("Failed to save " + file.getName());
e.printStackTrace();
}
}
return false;
}
/** Uses the default world directory to save the data to file by the given name
*
* @param filename - file name
* @param data - nbt data
* @return true if everything goes well */
public static boolean saveNBTFile(String filename, NBTTagCompound data)
{
return saveNBTFile(getWorldSaveDirectory(MinecraftServer.getServer().getFolderName()), filename + ".dat", data);
}
/** Reads NBT data from the world folder.
*
* @return The NBT data */
public static NBTTagCompound loadNBTFile(File saveDirectory, String filename, boolean create)
{
if (saveDirectory != null && filename != null)
{
if (create && !saveDirectory.exists())
{
saveDirectory.mkdirs();
}
return loadNBTFile(new File(saveDirectory, filename + ".dat"), create);
}
return null;
}
public static NBTTagCompound loadNBTFile(File file, boolean create)
{
if (file != null)
{
try
{
if (file.exists())
{
FMLLog.fine("Loaded " + file.getName() + " data.");
return CompressedStreamTools.readCompressed(new FileInputStream(file));
}
else if (create)
{
FMLLog.fine("Created new " + file.getName() + " data.");
return new NBTTagCompound();
}
}
catch (Exception e)
{
System.out.println("Failed to load " + file.getName() + ".dat!");
e.printStackTrace();
return null;
}
}
return null;
}
/** Loads an NBT file from the current world file
*
* @param filename - name of the file
* @return NBTTagCompound that was stored in the file */
public static NBTTagCompound loadNBTFile(String filename)
{
return loadNBTFile(getWorldSaveDirectory(MinecraftServer.getServer().getFolderName()), filename, true);
}
public static File getWorldSaveDirectory(String worldName)
{
File parent = getBaseDirectory();
if (FMLCommonHandler.instance().getSide().isClient())
{
parent = new File(getBaseDirectory(), "saves" + File.separator);
}
return new File(parent, worldName + File.separator);
}
public static File getBaseDirectory()
{
if (FMLCommonHandler.instance().getSide().isClient())
{
FMLClientHandler.instance().getClient();
return Minecraft.getMinecraft().mcDataDir;
}
else
{
return new File(".");
}
}
/** Used to save an object without knowing what the object is exactly. Supports most
* NBTTagCompound save methods including some special cases. Which includes boolean being saves
* as a string so it can be loaded as a boolean from an object save.
*
* @param tag - NBTTagCompound to save the tag too
* @param key - name to save the object as
* @param value - the actual object
* @return the tag when done saving too i */
public static NBTTagCompound saveObject(NBTTagCompound tag, String key, Object value)
{
if (value instanceof Float)
{
tag.setFloat(key, (Float) value);
}
else if (value instanceof Double)
{
tag.setDouble(key, (Double) value);
}
else if (value instanceof Integer)
{
tag.setInteger(key, (Integer) value);
}
else if (value instanceof String)
{
tag.setString(key, (String) value);
}
else if (value instanceof Short)
{
tag.setShort(key, (Short) value);
}
else if (value instanceof Byte)
{
tag.setByte(key, (Byte) value);
}
else if (value instanceof Long)
{
tag.setLong(key, (Long) value);
}
else if (value instanceof Boolean)
{
tag.setString(key, "NBT:SAVE:BOOLEAN:" + value);
}
else if (value instanceof NBTBase)
{
tag.setTag(key, (NBTBase) value);
}
else if (value instanceof String)
{
tag.setString(key, (String) value);
}
else if (value instanceof byte[])
{
tag.setByteArray(key, (byte[]) value);
}
else if (value instanceof int[])
{
tag.setIntArray(key, (int[]) value);
}
else if (value instanceof NBTTagCompound)
{
tag.setCompoundTag(key, (NBTTagCompound) value);
}
else if (value instanceof Vector2)
{
tag.setString(key, "NBT:SAVE:VECTOR:2:" + ((Vector2) value).x + ":" + ((Vector2) value).y);
}
else if (value instanceof Vector3)
{
tag.setString(key, "NBT:SAVE:VECTOR:3:" + ((Vector3) value).x + ":" + ((Vector3) value).y + ":" + ((Vector3) value).z);
}
return tag;
}
/** @param key
* @param value
* @return NBTTagCompound that then can be added to save file */
public static NBTTagCompound saveObject(String key, Object value)
{
return NBTFileHelper.saveObject(new NBTTagCompound(), key, value);
}
/** Reads an unknown object with a known name from NBT
*
* @param tag - tag to read the value from
* @param key - name of the value
* @param suggestionValue - value to return in case nothing is found
* @return object or suggestionValue if nothing is found */
public static Object loadObject(NBTTagCompound tag, String key)
{
if (tag != null && key != null)
{
NBTBase saveTag = tag.getTag(key);
if (saveTag instanceof NBTTagFloat)
{
return tag.getFloat(key);
}
else if (saveTag instanceof NBTTagDouble)
{
return tag.getDouble(key);
}
else if (saveTag instanceof NBTTagInt)
{
return tag.getInteger(key);
}
else if (saveTag instanceof NBTTagString)
{
String str = tag.getString(key);
if (str.startsWith("NBT:SAVE:"))
{
str.replaceAll("NBT:SAVE:", "");
if (str.startsWith("BOOLEAN:"))
{
str.replaceAll("BOOLEAN:", "");
if (str.equalsIgnoreCase("true"))
{
return true;
}
if (str.equalsIgnoreCase("false"))
{
return false;
}
}
if (str.startsWith("VECTOR:"))
{
str.replaceAll("VECTOR:", "");
String[] nums = str.split(":");
if (UnitHelper.tryToParseDouble(nums[0]) == 2)
{
return new Vector2(UnitHelper.tryToParseDouble(nums[1]), UnitHelper.tryToParseDouble(nums[2]));
}
if (UnitHelper.tryToParseDouble(nums[0]) == 3)
{
return new Vector3(UnitHelper.tryToParseDouble(nums[1]), UnitHelper.tryToParseDouble(nums[2]), UnitHelper.tryToParseDouble(nums[3]));
}
}
return null;
}
return str;
}
else if (saveTag instanceof NBTTagShort)
{
return tag.getShort(key);
}
else if (saveTag instanceof NBTTagByte)
{
return tag.getByte(key);
}
else if (saveTag instanceof NBTTagLong)
{
return tag.getLong(key);
}
else if (saveTag instanceof NBTBase)
{
return tag.getTag(key);
}
else if (saveTag instanceof NBTTagByteArray)
{
return tag.getByteArray(key);
}
else if (saveTag instanceof NBTTagIntArray)
{
return tag.getIntArray(key);
}
else if (saveTag instanceof NBTTagCompound)
{
return tag.getCompoundTag(key);
}
}
return null;
}
}

View file

@ -0,0 +1,164 @@
package dark.api.save;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.event.ForgeSubscribe;
import net.minecraftforge.event.world.WorldEvent;
import cpw.mods.fml.common.FMLLog;
public class SaveManager
{
private static HashMap<String, Class<?>> idToClassMap = new HashMap<String, Class<?>>();
private static HashMap<Class<?>, String> classToIDMap = new HashMap<Class<?>, String>();
private static List<Object> saveList = new ArrayList<Object>();
private static List<Object> objects = new ArrayList<Object>();
private static SaveManager instance;
public static SaveManager instance()
{
if (instance == null)
{
instance = new SaveManager();
}
return instance;
}
/** Called when the object wants to be save only on the next save call. Will be removed from the
* save manager after */
public static void markNeedsSaved(Object object)
{
if (object instanceof IVirtualObject && !saveList.contains(object))
{
saveList.add(object);
}
}
/** Registers the object to be saved on each world save event */
public static void register(Object object)
{
if (object instanceof IVirtualObject && !objects.contains(object))
{
objects.add(object);
}
}
public static void registerClass(String id, Class clazz)
{
if (id != null && clazz != null)
{
if (idToClassMap.containsKey(id) && idToClassMap.get(id) != null)
{
System.out.println("[CoreMachine]SaveManager: Something attempted to register a class with the id of another class");
System.out.println("[CoreMachine]SaveManager: Id:" + id + " Class:" + clazz.getName());
System.out.println("[CoreMachine]SaveManager: OtherClass:" + idToClassMap.get(id).getName());
}
else
{
idToClassMap.put(id, clazz);
classToIDMap.put(clazz, id);
}
}
}
public static Object createAndLoad(File file)
{
if (file.exists())
{
Object obj = createAndLoad(NBTFileHelper.loadNBTFile(file, false));
if (obj instanceof IVirtualObject)
{
((IVirtualObject) obj).setSaveFile(file);
}
return obj;
}
return null;
}
/** Creates an object from the save using its id */
public static Object createAndLoad(NBTTagCompound par0NBTTagCompound)
{
Object obj = null;
if (par0NBTTagCompound != null && par0NBTTagCompound.hasKey("id"))
{
try
{
Class clazz = getClass(par0NBTTagCompound.getString("id"));
if (clazz != null)
{
obj = clazz.newInstance();
}
}
catch (Exception exception)
{
exception.printStackTrace();
}
if (obj instanceof IVirtualObject)
{
try
{
((IVirtualObject) obj).load(par0NBTTagCompound);
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "An object %s(%s) has thrown an exception during loading, its state cannot be restored. Report this to the mod author", par0NBTTagCompound.getString("id"), obj.getClass().getName());
obj = null;
}
}
else
{
MinecraftServer.getServer().getLogAgent().logWarning("Skipping object with id " + par0NBTTagCompound.getString("id"));
}
return obj;
}
return null;
}
@ForgeSubscribe
public void worldSave(WorldEvent evt)
{
SaveManager.saveList.addAll(SaveManager.objects);
for (Object object : SaveManager.saveList)
{
if (object instanceof IVirtualObject)
{
saveObject(object);
}
}
saveList.clear();
}
/** Saves an object along with its ID */
public static void saveObject(Object object)
{
if (object instanceof IVirtualObject && getID(object.getClass()) != null && ((IVirtualObject) object).getSaveFile() != null)
{
File file = ((IVirtualObject) object).getSaveFile();
file.mkdirs();
NBTTagCompound tag = new NBTTagCompound();
((IVirtualObject) object).save(tag);
tag.setString("id", getID(object.getClass()));
NBTFileHelper.saveNBTFile(file, tag);
}
}
/** Gets the ID that the class will be saved using */
public static String getID(Class clazz)
{
return classToIDMap.get(clazz);
}
/** Gets the class that was registered with the ID */
public static Class getClass(String id)
{
return idToClassMap.get(id);
}
}