diff --git a/src/main/java/kamkeel/npcs/controllers/ProfileController.java b/src/main/java/kamkeel/npcs/controllers/ProfileController.java index 96ee90145..f9367dfac 100644 --- a/src/main/java/kamkeel/npcs/controllers/ProfileController.java +++ b/src/main/java/kamkeel/npcs/controllers/ProfileController.java @@ -22,8 +22,7 @@ import java.io.InputStreamReader; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; -import java.util.HashMap; -import java.util.UUID; +import java.util.*; public class ProfileController { @@ -234,6 +233,19 @@ public class ProfileController { LogWriter.error("Profile is locked; cannot clone slot."); return ProfileOperation.LOCKED; } + + // Run verification checks on all IProfileData in priority order. + if(profile.player != null) { + List dataList = new ArrayList<>(profileTypes.values()); + dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority)); + for(IProfileData pd : dataList) { + if(!pd.verifySwitch(profile.player)) { + LogWriter.error("Verification check failed for profile type: " + pd.getTagName()); + return ProfileOperation.VERIFICATION_FAILED; + } + } + } + if(!profile.slots.containsKey(sourceSlotId)) { LogWriter.error("Source slot " + sourceSlotId + " does not exist."); return ProfileOperation.ERROR; @@ -442,14 +454,16 @@ public class ProfileController { dataCompound = new NBTTagCompound(); slot.setCompound(dataCompound); } - for(IProfileData profileData : profileTypes.values()){ + + List dataList = new ArrayList<>(profileTypes.values()); + dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority)); + for(IProfileData profileData : dataList){ NBTTagCompound cloned = (NBTTagCompound) profileData.getCurrentNBT(player).copy(); dataCompound.setTag(profileData.getTagName(), cloned); } slot.setCompound(dataCompound); } - // TODO: public static void loadSlotData(EntityPlayer player) { if(player == null || !activeProfiles.containsKey(player.getUniqueID())) return; @@ -462,7 +476,9 @@ public class ProfileController { NBTTagCompound slotCompound = (NBTTagCompound) profile.slots.get(profile.currentID).getCompound().copy(); // For each registered profile data type, load its saved compound onto the player. - for(IProfileData profileData : profileTypes.values()){ + List dataList = new ArrayList<>(profileTypes.values()); + dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority)); + for(IProfileData profileData : dataList){ NBTTagCompound data; if(slotCompound.hasKey(profileData.getTagName())) data = slotCompound.getCompoundTag(profileData.getTagName()); @@ -470,6 +486,9 @@ public class ProfileController { data = new NBTTagCompound(); profileData.setNBT(player, data); + } + + for(IProfileData profileData : dataList){ profileData.save(player); } } diff --git a/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java b/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java index d4e61530f..8662e0b84 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java +++ b/src/main/java/kamkeel/npcs/controllers/data/CNPCData.java @@ -33,10 +33,19 @@ public class CNPCData implements IProfileData { PlayerData newData = new PlayerData(); newData.player = player; customNPCData.setNBT((NBTTagCompound) newData.getNBT().copy()); - } - else { + } else { customNPCData.setNBT(replace); } customNPCData.updateClient = true; } + + @Override + public int getSwitchPriority() { + return 0; + } + + @Override + public boolean verifySwitch(EntityPlayer player) { + return true; + } } diff --git a/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java b/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java index a68abc597..853ddf1e0 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java +++ b/src/main/java/kamkeel/npcs/controllers/data/IProfileData.java @@ -6,24 +6,37 @@ import net.minecraft.nbt.NBTTagCompound; public interface IProfileData { /** - * Do not use the tag: - Name, lastLoaded, ID + * Do not use the tags: Name, lastLoaded, ID. * - * @return The Save Tag utilized in the Profile + * @return The save tag utilized in the Profile. */ public String getTagName(); /** - * @return NBTTagCompound of their Current Data for a given Entity Player + * @return NBTTagCompound of the current data for a given EntityPlayer. */ public NBTTagCompound getCurrentNBT(EntityPlayer player); /** - * Called immediately after setNBT() Replaces existing NBT + * Called immediately after setNBT() to replace existing NBT. */ public void save(EntityPlayer player); /** - * Replaces their Current Data operation when changing Profiles + * Replaces the current data operation when changing profiles. */ public void setNBT(EntityPlayer player, NBTTagCompound replace); + + /** + * Returns the priority for this ProfileData's verification check. + * Lower numbers run first. + */ + public int getSwitchPriority(); + + /** + * Called before a profile switch occurs. + * @param player The player switching profiles. + * @return true if allowed, false if not. + */ + public boolean verifySwitch(EntityPlayer player); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java b/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java index 62ec9508a..f3d6d1179 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ProfileOperation.java @@ -4,5 +4,7 @@ public enum ProfileOperation { SUCCESS, ERROR, LOCKED, - PLAYER_NOT_FOUND + PLAYER_NOT_FOUND, + VERIFICATION_FAILED } +