Files
CustomNPC-Plus/src/main/java/kamkeel/npcs/controllers/ProfileController.java
T

784 lines
32 KiB
Java
Raw Normal View History

2025-01-29 13:20:04 -05:00
package kamkeel.npcs.controllers;
2025-01-23 16:10:01 -05:00
2025-02-19 05:43:28 -05:00
import kamkeel.npcs.controllers.data.*;
2025-01-23 16:10:01 -05:00
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import noppes.npcs.CustomNpcs;
import noppes.npcs.CustomNpcsPermissions;
2025-01-23 16:10:01 -05:00
import noppes.npcs.LogWriter;
2025-02-21 07:05:56 -05:00
import noppes.npcs.NoppesUtilServer;
2025-02-20 21:39:02 -05:00
import noppes.npcs.api.entity.IPlayer;
import noppes.npcs.api.handler.IPlayerData;
2025-02-21 17:30:57 -05:00
import noppes.npcs.api.handler.data.IProfile;
import noppes.npcs.api.handler.IProfileHandler;
import noppes.npcs.api.handler.data.ISlot;
2025-02-18 22:22:40 -05:00
import noppes.npcs.config.ConfigMain;
2025-02-21 06:19:24 -05:00
import noppes.npcs.controllers.QuestController;
2025-02-18 06:25:09 -05:00
import noppes.npcs.controllers.data.PlayerData;
2025-02-21 06:19:24 -05:00
import noppes.npcs.controllers.data.PlayerQuestData;
2025-01-23 16:10:01 -05:00
import noppes.npcs.util.CustomNPCsThreader;
import noppes.npcs.util.NBTJsonUtil;
2025-02-20 21:40:39 -05:00
2025-02-18 22:22:40 -05:00
import java.io.*;
2025-02-18 06:25:09 -05:00
import java.net.HttpURLConnection;
import java.net.URL;
2025-02-18 22:22:40 -05:00
import java.text.SimpleDateFormat;
2025-02-18 20:05:55 -05:00
import java.util.*;
2025-02-20 21:40:39 -05:00
2025-02-19 18:15:05 -05:00
import static noppes.npcs.CustomNpcsPermissions.PROFILE_REGION_BYPASS;
import static noppes.npcs.CustomNpcsPermissions.hasPermission;
2025-02-21 17:30:57 -05:00
public class ProfileController implements IProfileHandler {
2025-01-23 16:10:01 -05:00
2025-02-20 21:39:02 -05:00
// Message constants
2025-02-19 18:15:05 -05:00
private static final String MSG_PLAYER_NOT_FOUND = "Player not found.";
private static final String MSG_PROFILE_LOCKED_CLONE = "Profile is locked; cannot clone slot.";
private static final String MSG_SOURCE_SLOT_NOT_EXIST = "Source slot does not exist.";
private static final String MSG_CANNOT_CLONE_CURRENT = "Cannot clone to the current active slot.";
private static final String MSG_INVALID_DEST_SLOT = "Invalid destination slot id.";
private static final String MSG_CLONE_SUCCESS = "Slot cloned successfully.";
private static final String MSG_PROFILE_LOCKED_REMOVE = "Profile is locked; cannot remove slot.";
private static final String MSG_CANNOT_REMOVE_ACTIVE = "Cannot remove the currently active slot.";
private static final String MSG_SLOT_NOT_EXIST = "Slot does not exist.";
private static final String MSG_REMOVE_SUCCESS = "Slot removed successfully.";
private static final String MSG_PROFILE_LOCKED_CREATE = "Profile is locked; cannot create slot.";
private static final String MSG_MAX_SLOTS_REACHED = "Maximum allowed slots reached.";
private static final String MSG_NEW_SLOT_CREATED = "New slot created successfully.";
private static final String MSG_PROFILE_LOCKED_CHANGE = "Profile is locked; cannot change slot.";
private static final String MSG_SLOT_ALREADY_ACTIVE = "Slot is already active.";
private static final String MSG_REGION_NOT_ALLOWED = "Profile switching not allowed from your current location.";
private static final String MSG_CHANGE_SUCCESS = "Slot changed successfully.";
2025-02-20 21:39:02 -05:00
public static Map<String, IProfileData> profileTypes = new HashMap<>();
public static Map<UUID, Profile> activeProfiles = new HashMap<>();
2025-01-23 16:10:01 -05:00
public static String profile_directory = "profiles";
2025-02-20 21:39:02 -05:00
public static ProfileController Instance;
public ProfileController() {
Instance = this;
2025-01-23 16:10:01 -05:00
profileTypes = new HashMap<>();
activeProfiles = new HashMap<>();
}
2025-02-20 21:39:02 -05:00
public static boolean registerProfileType(IProfileData type) {
if (profileTypes.containsKey(type.getTagName()))
2025-01-23 16:10:01 -05:00
return false;
profileTypes.put(type.getTagName(), type);
return true;
}
2025-02-20 21:39:02 -05:00
public static File getProfileDir() {
2025-02-18 06:25:09 -05:00
try {
2025-01-23 16:10:01 -05:00
File file = new File(CustomNpcs.getWorldSaveDirectory(), profile_directory);
2025-02-20 21:39:02 -05:00
if (!file.exists())
2025-01-23 16:10:01 -05:00
file.mkdir();
return file;
2025-02-18 06:25:09 -05:00
} catch (Exception e) {
2025-01-23 16:10:01 -05:00
e.printStackTrace();
return null;
}
}
2025-02-18 22:22:40 -05:00
public static File getBackupDir() {
File base = getProfileDir();
File backup = new File(base, "backup");
2025-02-20 21:39:02 -05:00
if (!backup.exists()) {
2025-02-18 22:22:40 -05:00
backup.mkdir();
}
return backup;
}
2025-02-20 21:39:02 -05:00
public synchronized void login(EntityPlayer player) {
if (player == null)
2025-01-23 16:10:01 -05:00
return;
Profile profile;
2025-02-20 21:39:02 -05:00
if (activeProfiles.containsKey(player.getUniqueID())) {
2025-01-23 16:10:01 -05:00
profile = activeProfiles.get(player.getUniqueID());
2025-02-21 06:19:24 -05:00
profile.player = player;
2025-01-23 16:10:01 -05:00
} else {
2025-02-18 06:25:09 -05:00
NBTTagCompound compound = load(player);
profile = new Profile(player, compound);
2025-02-20 21:39:02 -05:00
if (profile.getSlots().isEmpty()) {
2025-02-18 22:22:40 -05:00
Slot defaultSlot = new Slot(0, "Default Slot");
2025-02-20 21:39:02 -05:00
defaultSlot.setLastLoaded(System.currentTimeMillis());
profile.getSlots().put(0, defaultSlot);
profile.currentSlotId = 0;
2025-02-18 22:22:40 -05:00
saveSlotData(player);
}
2025-02-21 06:19:24 -05:00
profile.player = player;
2025-01-23 16:10:01 -05:00
activeProfiles.put(player.getUniqueID(), profile);
2025-02-21 06:19:24 -05:00
verifySlotQuests(profile.player);
2025-02-21 07:05:56 -05:00
save(player, profile);
2025-01-23 16:10:01 -05:00
}
}
2025-02-20 21:44:15 -05:00
public synchronized NBTTagCompound load(EntityPlayer player) {
2025-01-23 16:10:01 -05:00
File saveDir = getProfileDir();
2025-02-18 06:25:09 -05:00
String filename = player.getUniqueID().toString() + ".dat";
try {
File file = new File(saveDir, filename);
2025-02-20 21:39:02 -05:00
if (file.exists()) {
2025-02-18 06:25:09 -05:00
return NBTJsonUtil.loadNBTData(file);
}
} catch (Exception e) {
LogWriter.error("Error loading profile file: " + filename, e);
}
return new NBTTagCompound();
}
2025-02-20 21:44:15 -05:00
public synchronized NBTTagCompound load(UUID uuid) {
2025-02-18 06:25:09 -05:00
File saveDir = getProfileDir();
String filename = uuid.toString() + ".dat";
2025-01-23 16:10:01 -05:00
try {
File file = new File(saveDir, filename);
2025-02-20 21:39:02 -05:00
if (file.exists()) {
2025-01-23 16:10:01 -05:00
return NBTJsonUtil.loadNBTData(file);
}
} catch (Exception e) {
LogWriter.error("Error loading profile file: " + filename, e);
}
return new NBTTagCompound();
}
2025-02-20 21:44:15 -05:00
public synchronized void saveOffline(Profile profile, UUID uuid) {
2025-02-20 21:39:02 -05:00
profile.setLocked(true);
CustomNPCsThreader.customNPCThread.execute(() -> {
final NBTTagCompound compound = profile.writeToNBT();
final String filename = uuid.toString() + ".dat";
try {
File saveDir = getProfileDir();
File fileNew = new File(saveDir, filename + "_new");
File fileOld = new File(saveDir, filename);
CompressedStreamTools.writeCompressed(compound, new FileOutputStream(fileNew));
2025-02-20 21:39:02 -05:00
if (fileOld.exists()) {
fileOld.delete();
}
fileNew.renameTo(fileOld);
backupProfile(uuid, compound);
} catch (Exception e) {
LogWriter.except(e);
2025-02-18 06:25:09 -05:00
}
});
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:44:15 -05:00
public synchronized void save(EntityPlayer player, Profile profile) {
2025-02-20 21:39:02 -05:00
profile.setLocked(true);
2025-01-23 16:10:01 -05:00
CustomNPCsThreader.customNPCThread.execute(() -> {
final NBTTagCompound compound = profile.writeToNBT();
final String filename = player.getUniqueID() + ".dat";
try {
File saveDir = getProfileDir();
2025-02-18 06:25:09 -05:00
File fileNew = new File(saveDir, filename + "_new");
File fileOld = new File(saveDir, filename);
CompressedStreamTools.writeCompressed(compound, new FileOutputStream(fileNew));
2025-02-20 21:39:02 -05:00
if (fileOld.exists()) {
2025-02-18 06:25:09 -05:00
fileOld.delete();
2025-01-23 16:10:01 -05:00
}
2025-02-18 06:25:09 -05:00
fileNew.renameTo(fileOld);
2025-02-20 21:39:02 -05:00
if (ConfigMain.AllowProfileBackups) {
2025-02-18 22:22:40 -05:00
backupProfile(player.getUniqueID(), compound);
}
2025-01-23 16:10:01 -05:00
} catch (Exception e) {
LogWriter.except(e);
2025-02-18 06:25:09 -05:00
} finally {
2025-02-20 21:39:02 -05:00
profile.setLocked(false);
2025-01-23 16:10:01 -05:00
}
});
}
2025-02-20 21:44:15 -05:00
private void backupProfile(UUID uuid, NBTTagCompound compound) {
2025-02-18 22:22:40 -05:00
try {
File backupDir = new File(getBackupDir(), uuid.toString());
2025-02-20 21:39:02 -05:00
if (!backupDir.exists()) {
2025-02-18 22:22:40 -05:00
backupDir.mkdirs();
}
String dateStr = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File backupFile = new File(backupDir, dateStr + ".dat");
CompressedStreamTools.writeCompressed(compound, new FileOutputStream(backupFile));
File[] backups = backupDir.listFiles((dir, name) -> name.endsWith(".dat"));
2025-02-20 21:39:02 -05:00
if (backups != null && backups.length > ConfigMain.ProfileBackupAmount) {
2025-02-18 22:22:40 -05:00
Arrays.sort(backups, Comparator.comparingLong(File::lastModified));
2025-02-20 21:39:02 -05:00
for (int i = 0; i < backups.length - ConfigMain.ProfileBackupAmount; i++) {
2025-02-18 22:22:40 -05:00
backups[i].delete();
}
}
2025-02-20 21:39:02 -05:00
} catch (Exception e) {
2025-02-18 22:22:40 -05:00
LogWriter.except(e);
}
}
2025-02-20 21:44:15 -05:00
public boolean rollbackProfile(String username, File backupFile) {
2025-02-18 22:22:40 -05:00
UUID uuid = getUUIDFromUsername(username);
2025-02-20 21:39:02 -05:00
if (uuid == null)
return false;
2025-02-18 22:22:40 -05:00
try (FileInputStream fis = new FileInputStream(backupFile)) {
NBTTagCompound compound = CompressedStreamTools.readCompressed(fis);
File saveDir = getProfileDir();
File mainFile = new File(saveDir, uuid.toString() + ".dat");
File fileNew = new File(saveDir, uuid.toString() + "_new");
CompressedStreamTools.writeCompressed(compound, new FileOutputStream(fileNew));
2025-02-20 21:39:02 -05:00
if (mainFile.exists()) {
2025-02-18 22:22:40 -05:00
mainFile.delete();
}
fileNew.renameTo(mainFile);
2025-02-21 07:05:56 -05:00
EntityPlayer player = NoppesUtilServer.getPlayerByName(username);
2025-02-18 22:22:40 -05:00
Profile newProfile;
2025-02-20 21:39:02 -05:00
if (player != null) {
2025-02-18 22:22:40 -05:00
newProfile = new Profile(player, compound);
activeProfiles.put(uuid, newProfile);
loadSlotData(player);
} else {
newProfile = new Profile(null, compound);
activeProfiles.put(uuid, newProfile);
}
return true;
2025-02-20 21:39:02 -05:00
} catch (Exception e) {
2025-02-18 22:22:40 -05:00
LogWriter.except(e);
return false;
}
}
2025-02-20 21:44:15 -05:00
public synchronized void logout(EntityPlayer player) {
2025-02-20 21:39:02 -05:00
if (player != null) {
2025-02-18 06:25:09 -05:00
activeProfiles.remove(player.getUniqueID());
}
}
2025-02-20 21:44:15 -05:00
public Profile getProfile(EntityPlayer player) {
2025-02-20 21:39:02 -05:00
if (player == null)
return null;
if (!activeProfiles.containsKey(player.getUniqueID()))
2025-02-18 06:25:09 -05:00
login(player);
return activeProfiles.get(player.getUniqueID());
}
2025-01-23 16:10:01 -05:00
2025-02-20 21:44:15 -05:00
public Profile getProfile(UUID uuid) {
2025-02-20 21:39:02 -05:00
if (activeProfiles.containsKey(uuid))
2025-02-18 06:25:09 -05:00
return activeProfiles.get(uuid);
NBTTagCompound compound = load(uuid);
return new Profile(null, compound);
}
2025-01-23 16:10:01 -05:00
2025-02-20 21:44:15 -05:00
public Profile getProfile(String username) {
2025-02-21 07:05:56 -05:00
EntityPlayer player = NoppesUtilServer.getPlayerByName(username);
2025-02-20 21:39:02 -05:00
if (player != null) {
2025-02-18 06:25:09 -05:00
return getProfile(player);
} else {
UUID uuid = getUUIDFromUsername(username);
2025-02-20 21:39:02 -05:00
if (uuid == null)
return null;
2025-02-18 06:25:09 -05:00
return getProfile(uuid);
}
}
2025-01-23 16:10:01 -05:00
2025-02-20 21:44:15 -05:00
public UUID getUUIDFromUsername(String username) {
2025-02-18 06:25:09 -05:00
try {
URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + username);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder temp = new StringBuilder();
String line;
2025-02-20 21:39:02 -05:00
while ((line = in.readLine()) != null) {
2025-02-18 06:25:09 -05:00
temp.append(line);
}
in.close();
con.disconnect();
String response = temp.toString();
2025-02-20 21:39:02 -05:00
if (response.contains("\"id\"")) {
2025-02-18 06:25:09 -05:00
int idIndex = response.indexOf("\"id\"");
int colonIndex = response.indexOf(":", idIndex);
int quoteStart = response.indexOf("\"", colonIndex);
int quoteEnd = response.indexOf("\"", quoteStart + 1);
String idString = response.substring(quoteStart + 1, quoteEnd);
idString = idString.replaceFirst(
"(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)",
"$1-$2-$3-$4-$5"
);
return UUID.fromString(idString);
}
} catch (IOException e) {
LogWriter.error("Error retrieving UUID for " + username, e);
}
return null;
2025-01-23 16:10:01 -05:00
}
2025-02-20 21:44:15 -05:00
private int getNextAvailableTempSlot(Profile profile) {
2025-02-18 06:25:09 -05:00
int id = -1;
2025-02-20 21:39:02 -05:00
while (profile.getSlots().containsKey(id)) {
2025-02-18 06:25:09 -05:00
id--;
}
return id;
}
2025-02-20 21:44:15 -05:00
private ProfileOperation cloneSlotInternal(Profile profile, int sourceSlotId, int destinationSlotId, boolean temporary) {
2025-02-20 21:39:02 -05:00
if (profile.isLocked()) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.locked(MSG_PROFILE_LOCKED_CLONE);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
if (profile.player != null) {
2025-02-18 20:05:55 -05:00
List<IProfileData> dataList = new ArrayList<>(profileTypes.values());
dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority));
2025-02-20 21:39:02 -05:00
for (IProfileData pd : dataList) {
2025-02-19 18:15:05 -05:00
if (pd.verifySwitch(profile.player).getResult() != EnumProfileOperation.SUCCESS) {
return pd.verifySwitch(profile.player);
2025-02-18 20:05:55 -05:00
}
}
}
2025-02-20 21:39:02 -05:00
if (!profile.getSlots().containsKey(sourceSlotId)) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_SOURCE_SLOT_NOT_EXIST);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
if (destinationSlotId == profile.getCurrentSlotId()) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_CANNOT_CLONE_CURRENT);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
if (temporary) {
2025-02-18 06:25:09 -05:00
destinationSlotId = getNextAvailableTempSlot(profile);
} else {
2025-02-20 21:39:02 -05:00
if (destinationSlotId <= 0) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_INVALID_DEST_SLOT);
2025-02-18 06:25:09 -05:00
}
}
2025-02-20 21:39:02 -05:00
ISlot sourceSlot = profile.getSlots().get(sourceSlotId);
Map<String, NBTTagCompound> newComponents = new HashMap<>();
for (String key : sourceSlot.getComponents().keySet()) {
2025-02-20 21:44:15 -05:00
newComponents.put(key, (NBTTagCompound) sourceSlot.getComponentData(key).copy());
2025-02-20 21:39:02 -05:00
}
Slot clonedSlot = new Slot(destinationSlotId, "Cloned Slot " + destinationSlotId, System.currentTimeMillis(), temporary, newComponents);
profile.getSlots().put(destinationSlotId, clonedSlot);
2025-02-19 18:15:05 -05:00
return ProfileOperation.success(MSG_CLONE_SUCCESS);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:44:15 -05:00
private ProfileOperation removeSlotInternal(Profile profile, int slotId) {
2025-02-20 21:39:02 -05:00
if (profile.isLocked()) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.locked(MSG_PROFILE_LOCKED_REMOVE);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
if (slotId == profile.getCurrentSlotId()) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_CANNOT_REMOVE_ACTIVE);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
if (!profile.getSlots().containsKey(slotId)) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_SLOT_NOT_EXIST);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
profile.getSlots().remove(slotId);
2025-02-19 18:15:05 -05:00
return ProfileOperation.success(MSG_REMOVE_SUCCESS);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:44:15 -05:00
public ProfileOperation createSlotInternal(Profile profile) {
2025-02-20 21:39:02 -05:00
if (profile.isLocked()) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.locked(MSG_PROFILE_LOCKED_CREATE);
}
int newSlotId = 0;
2025-02-20 21:39:02 -05:00
while (profile.getSlots().containsKey(newSlotId)) {
newSlotId++;
}
if (!allowSlotPermission(profile.player)) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_MAX_SLOTS_REACHED);
}
if (profile.player != null) {
List<IProfileData> dataList = new ArrayList<>(profileTypes.values());
dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority));
for (IProfileData pd : dataList) {
2025-02-19 18:15:05 -05:00
if (pd.verifySwitch(profile.player).getResult() != EnumProfileOperation.SUCCESS) {
return pd.verifySwitch(profile.player);
}
}
}
Slot newSlot = new Slot(newSlotId, "Slot " + newSlotId);
2025-02-20 21:39:02 -05:00
newSlot.setLastLoaded(System.currentTimeMillis());
profile.getSlots().put(newSlotId, newSlot);
2025-02-21 17:23:51 -05:00
if(profile.player != null){
verifySlotQuests(profile.player);
save(profile.player, profile);
}
2025-02-19 18:15:05 -05:00
return ProfileOperation.success(MSG_NEW_SLOT_CREATED);
}
2025-02-20 21:44:15 -05:00
private ProfileOperation changeSlotInternal(Profile profile, int newSlotId) {
2025-02-20 21:39:02 -05:00
if (profile.isLocked()) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.locked(MSG_PROFILE_LOCKED_CHANGE);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:39:02 -05:00
if (profile.getCurrentSlotId() == newSlotId) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_SLOT_ALREADY_ACTIVE);
2025-02-18 22:22:40 -05:00
}
2025-02-20 21:39:02 -05:00
if (!profile.getSlots().containsKey(newSlotId)) {
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_SLOT_NOT_EXIST);
}
2025-02-20 21:39:02 -05:00
if (profile.player != null) {
2025-02-20 13:36:07 -05:00
if (ConfigMain.RegionProfileSwitching) {
boolean allowed = hasPermission(profile.player, PROFILE_REGION_BYPASS);
2025-02-20 21:39:02 -05:00
if (!allowed) {
2025-02-20 13:36:07 -05:00
int playerDim = profile.player.dimension;
int playerX = (int) profile.player.posX;
int playerY = (int) profile.player.posY;
int playerZ = (int) profile.player.posZ;
for (List<Integer> region : ConfigMain.RestrictedProfileRegions) {
2025-02-20 21:39:02 -05:00
if (region.size() == 7) {
2025-02-20 13:36:07 -05:00
int dim = region.get(0);
int x1 = Math.min(region.get(1), region.get(4));
int y1 = Math.min(region.get(2), region.get(5));
int z1 = Math.min(region.get(3), region.get(6));
int x2 = Math.max(region.get(1), region.get(4));
int y2 = Math.max(region.get(2), region.get(5));
int z2 = Math.max(region.get(3), region.get(6));
2025-02-20 21:39:02 -05:00
if (playerDim == dim &&
2025-02-20 13:36:07 -05:00
playerX >= x1 && playerX <= x2 &&
playerY >= y1 && playerY <= y2 &&
playerZ >= z1 && playerZ <= z2) {
allowed = true;
break;
}
2025-02-19 18:15:05 -05:00
}
}
}
2025-02-20 13:36:07 -05:00
if (!allowed) {
return ProfileOperation.error(MSG_REGION_NOT_ALLOWED);
}
2025-02-19 18:15:05 -05:00
}
2025-02-18 20:08:26 -05:00
List<IProfileData> dataList = new ArrayList<>(profileTypes.values());
2025-02-18 22:22:40 -05:00
dataList.sort(Comparator.comparingInt(IProfileData::getSwitchPriority));
for (IProfileData pd : dataList) {
2025-02-19 18:15:05 -05:00
if (pd.verifySwitch(profile.player).getResult() != EnumProfileOperation.SUCCESS) {
return pd.verifySwitch(profile.player);
2025-02-18 20:08:26 -05:00
}
}
2025-02-18 06:25:09 -05:00
saveSlotData(profile.player);
2025-02-20 21:39:02 -05:00
profile.currentSlotId = newSlotId;
2025-02-18 06:25:09 -05:00
loadSlotData(profile.player);
PlayerData pdata = PlayerData.get(profile.player);
pdata.profileSlot = newSlotId;
pdata.save();
2025-02-20 13:36:07 -05:00
} else {
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
}
2025-02-19 18:15:05 -05:00
return ProfileOperation.success(MSG_CHANGE_SUCCESS);
2025-02-18 06:25:09 -05:00
}
2025-02-20 21:44:15 -05:00
public ProfileOperation cloneSlot(EntityPlayer player, int sourceSlotId, int destinationSlotId, boolean temporary) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(player);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = cloneSlotInternal(profile, sourceSlotId, destinationSlotId, temporary);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS && player != null) {
2025-02-18 06:25:09 -05:00
save(player, profile);
2025-02-19 18:15:05 -05:00
}
2025-02-18 06:25:09 -05:00
return result;
}
2025-02-20 21:44:15 -05:00
public ProfileOperation cloneSlot(UUID uuid, int sourceSlotId, int destinationSlotId, boolean temporary) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(uuid);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = cloneSlotInternal(profile, sourceSlotId, destinationSlotId, temporary);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS) {
if (profile.player != null)
2025-02-18 06:25:09 -05:00
save(profile.player, profile);
else
saveOffline(profile, uuid);
}
return result;
}
2025-02-20 21:44:15 -05:00
public ProfileOperation cloneSlot(String username, int sourceSlotId, int destinationSlotId, boolean temporary) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(username);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = cloneSlotInternal(profile, sourceSlotId, destinationSlotId, temporary);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS) {
if (profile.player != null)
2025-02-18 06:25:09 -05:00
save(profile.player, profile);
else {
UUID uuid = getUUIDFromUsername(username);
2025-02-20 21:39:02 -05:00
if (uuid != null)
2025-02-18 06:25:09 -05:00
saveOffline(profile, uuid);
}
}
return result;
}
2025-02-20 21:44:15 -05:00
public ProfileOperation removeSlot(EntityPlayer player, int slotId) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(player);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = removeSlotInternal(profile, slotId);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS && player != null) {
2025-02-18 06:25:09 -05:00
save(player, profile);
2025-02-19 18:15:05 -05:00
}
2025-02-18 06:25:09 -05:00
return result;
}
2025-02-20 21:44:15 -05:00
public ProfileOperation removeSlot(String username, int slotId) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(username);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = removeSlotInternal(profile, slotId);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS) {
if (profile.player != null)
2025-02-18 06:25:09 -05:00
save(profile.player, profile);
else {
UUID uuid = getUUIDFromUsername(username);
2025-02-20 21:39:02 -05:00
if (uuid != null)
2025-02-18 06:25:09 -05:00
saveOffline(profile, uuid);
}
}
return result;
}
2025-02-20 21:44:15 -05:00
public ProfileOperation changeSlot(EntityPlayer player, int newSlotId) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(player);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = changeSlotInternal(profile, newSlotId);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS && player != null)
2025-02-18 06:25:09 -05:00
save(player, profile);
return result;
}
2025-02-20 21:44:15 -05:00
public ProfileOperation changeSlot(String username, int newSlotId) {
2025-02-18 06:25:09 -05:00
Profile profile = getProfile(username);
2025-02-20 21:39:02 -05:00
if (profile == null)
2025-02-19 18:15:05 -05:00
return ProfileOperation.error(MSG_PLAYER_NOT_FOUND);
2025-02-18 06:25:09 -05:00
ProfileOperation result = changeSlotInternal(profile, newSlotId);
2025-02-20 21:39:02 -05:00
if (result.getResult() == EnumProfileOperation.SUCCESS) {
if (profile.player != null)
2025-02-18 06:25:09 -05:00
save(profile.player, profile);
else {
UUID uuid = getUUIDFromUsername(username);
2025-02-20 21:39:02 -05:00
if (uuid != null)
2025-02-18 06:25:09 -05:00
saveOffline(profile, uuid);
}
}
return result;
}
2025-02-20 21:39:02 -05:00
public void saveSlotData(EntityPlayer player) {
if (player == null || !activeProfiles.containsKey(player.getUniqueID()))
2025-01-23 16:10:01 -05:00
return;
2025-02-18 06:25:09 -05:00
Profile profile = activeProfiles.get(player.getUniqueID());
2025-02-20 21:39:02 -05:00
if (profile.isLocked()) {
2025-02-18 06:25:09 -05:00
return;
}
2025-02-20 21:39:02 -05:00
ISlot slot = profile.getSlots().get(profile.getCurrentSlotId());
if (slot == null) {
slot = new Slot(profile.getCurrentSlotId(), "Slot " + profile.getCurrentSlotId());
profile.getSlots().put(profile.getCurrentSlotId(), slot);
2025-01-23 16:10:01 -05:00
}
2025-02-20 21:39:02 -05:00
for (IProfileData profileData : profileTypes.values()) {
2025-02-20 21:44:15 -05:00
NBTTagCompound cloned = (NBTTagCompound) profileData.getCurrentNBT(player).copy();
2025-02-20 21:39:02 -05:00
slot.setComponentData(profileData.getTagName(), cloned);
2025-01-23 16:10:01 -05:00
}
2025-02-19 05:43:28 -05:00
slot.setLastLoaded(System.currentTimeMillis());
2025-01-23 16:10:01 -05:00
}
2025-02-20 21:44:15 -05:00
public void loadSlotData(EntityPlayer player) {
2025-02-20 21:39:02 -05:00
if (player == null || !activeProfiles.containsKey(player.getUniqueID()))
2025-01-23 16:10:01 -05:00
return;
Profile profile = activeProfiles.get(player.getUniqueID());
2025-02-20 21:39:02 -05:00
ISlot slot = profile.getSlots().get(profile.getCurrentSlotId());
if (slot == null)
2025-02-18 06:25:09 -05:00
return;
2025-02-20 21:39:02 -05:00
for (IProfileData profileData : profileTypes.values()) {
2025-02-18 06:25:09 -05:00
NBTTagCompound data;
2025-02-20 21:39:02 -05:00
if (slot.getComponents().containsKey(profileData.getTagName()))
data = slot.getComponentData(profileData.getTagName());
2025-02-18 06:25:09 -05:00
else
data = new NBTTagCompound();
profileData.setNBT(player, data);
2025-02-18 20:05:55 -05:00
}
2025-02-20 21:39:02 -05:00
for (IProfileData profileData : profileTypes.values()) {
2025-01-23 16:10:01 -05:00
profileData.save(player);
}
2025-02-18 06:25:09 -05:00
}
2025-01-23 16:10:01 -05:00
2025-02-20 21:44:15 -05:00
public List<InfoEntry> getProfileInfo(EntityPlayer player, int slotId) {
2025-02-19 05:43:28 -05:00
List<InfoEntry> infoList = new ArrayList<>();
2025-02-19 00:21:40 -05:00
Profile profile = getProfile(player);
if (profile == null)
return infoList;
2025-02-20 21:39:02 -05:00
if (slotId == profile.getCurrentSlotId()) {
for (IProfileData pd : profileTypes.values()) {
2025-02-19 00:21:40 -05:00
NBTTagCompound currentNBT = pd.getCurrentNBT(player);
2025-02-19 05:43:28 -05:00
List<InfoEntry> subInfo = pd.getInfo(player, currentNBT);
2025-02-19 00:21:40 -05:00
infoList.addAll(subInfo);
}
} else {
2025-02-20 21:39:02 -05:00
if (!profile.getSlots().containsKey(slotId))
2025-02-19 00:21:40 -05:00
return infoList;
2025-02-20 21:39:02 -05:00
ISlot slot = profile.getSlots().get(slotId);
for (IProfileData pd : profileTypes.values()) {
if (slot.getComponents().containsKey(pd.getTagName())) {
NBTTagCompound sub = slot.getComponentData(pd.getTagName());
2025-02-19 05:43:28 -05:00
List<InfoEntry> subInfo = pd.getInfo(player, sub);
2025-02-19 00:21:40 -05:00
infoList.addAll(subInfo);
}
}
}
return infoList;
}
2025-02-20 21:44:15 -05:00
public boolean allowSlotPermission(EntityPlayer player) {
2025-02-20 21:39:02 -05:00
Profile profile = getProfile(player);
int currentSlots = profile.getSlots().size();
if (CustomNpcsPermissions.hasCustomPermission(player, "customnpcs.profile.max.*")) {
return true;
}
int highestAllowed = 0;
for (int i = 1; i <= 50; i++) {
String perm = "customnpcs.profile.max." + i;
if (CustomNpcsPermissions.hasCustomPermission(player, perm)) {
highestAllowed = i;
}
}
if (highestAllowed == 0) {
highestAllowed = 1;
}
return currentSlots < highestAllowed;
}
2025-02-20 21:39:02 -05:00
@Override
public IProfile getProfile(IPlayer player) {
if(player == null || player.getMCEntity() == null)
return null;
2025-02-20 21:44:15 -05:00
return getProfile((EntityPlayer) player.getMCEntity());
2025-02-20 21:39:02 -05:00
}
@Override
public boolean changeSlot(IPlayer player, int slotID) {
if(player == null || player.getMCEntity() == null)
return false;
EntityPlayer entityPlayer = (EntityPlayer) player.getMCEntity();
ProfileOperation profileOperation = changeSlot(entityPlayer, slotID);
return profileOperation.getResult() == EnumProfileOperation.SUCCESS;
}
@Override
public boolean hasSlot(IPlayer player, int slotID) {
if(player == null || player.getMCEntity() == null)
return false;
EntityPlayer entityPlayer = (EntityPlayer) player.getMCEntity();
Profile profile = getProfile(entityPlayer);
if(profile == null)
return false;
return profile.getSlots().containsKey(slotID);
}
@Override
public boolean removeSlot(IPlayer player, int slotID) {
if(player == null || player.getMCEntity() == null)
return false;
EntityPlayer entityPlayer = (EntityPlayer) player.getMCEntity();
ProfileOperation profileOperation = removeSlot(entityPlayer, slotID);
return profileOperation.getResult() == EnumProfileOperation.SUCCESS;
}
@Override
public IPlayerData getSlotPlayerData(IPlayer player, int slotID) {
PlayerData playerData;
if(player == null || player.getMCEntity() == null)
return null;
EntityPlayer entityPlayer = (EntityPlayer) player.getMCEntity();
Profile profile = getProfile(entityPlayer);
2025-02-21 06:19:24 -05:00
if(profile == null)
return null;
return getSlotPlayerData(entityPlayer, slotID);
}
@Override
public void saveSlotData(IPlayer player) {
if(player == null || player.getMCEntity() == null)
return;
EntityPlayer entityPlayer = (EntityPlayer) player.getMCEntity();
saveSlotData(entityPlayer);
}
public IPlayerData getSlotPlayerData(EntityPlayer player, int slotID) {
PlayerData playerData;
Profile profile = getProfile(player);
2025-02-20 21:39:02 -05:00
if(profile == null)
return null;
if(profile.currentSlotId == slotID){
2025-02-21 06:19:24 -05:00
playerData = PlayerData.get(player);
2025-02-20 21:39:02 -05:00
} else {
Slot slot = (Slot) profile.getSlots().get(slotID);
2025-02-21 17:23:51 -05:00
playerData = getSlotPlayerData(player, slot);
2025-02-20 21:39:02 -05:00
}
return playerData;
}
2025-02-21 06:19:24 -05:00
public PlayerData getSlotPlayerData(EntityPlayer player, Slot slot) {
if(slot == null)
return null;
PlayerData playerData = new PlayerData();
playerData.player = player;
2025-02-21 17:23:51 -05:00
NBTTagCompound compound = slot.getComponentData(new CNPCData().getTagName());
if(compound == null)
compound = new NBTTagCompound();
playerData.setNBT(compound);
2025-02-21 06:19:24 -05:00
return playerData;
}
public void verifySlotQuests(EntityPlayer player) {
Profile profile = getProfile(player);
2025-02-21 16:40:44 -05:00
if (profile == null) {
2025-02-20 21:39:02 -05:00
return;
2025-02-21 16:40:44 -05:00
}
2025-02-20 21:39:02 -05:00
2025-02-21 16:40:44 -05:00
Map<Integer, Long> universalFinished = new HashMap<>();
for (Integer questId : QuestController.Instance.sharedQuests.keySet()) {
long maxTime = 0;
for (ISlot slot : profile.getSlots().values()) {
IPlayerData data = getSlotPlayerData(player, slot.getId());
if (data == null) {
continue;
}
PlayerQuestData questData = (PlayerQuestData) data.getQuestData();
Long t = questData.finishedQuests.get(questId);
if (t != null && t > maxTime) {
maxTime = t;
2025-02-21 06:19:24 -05:00
}
}
2025-02-21 16:40:44 -05:00
if (maxTime > 0) {
universalFinished.put(questId, maxTime);
}
2025-02-21 06:19:24 -05:00
}
2025-02-21 16:40:44 -05:00
// Push the universal shared completion times into every slot.
for (ISlot slot : profile.getSlots().values()) {
IPlayerData data = getSlotPlayerData(player, slot.getId());
if (data != null) {
2025-02-21 17:23:51 -05:00
PlayerData playerData = (PlayerData) data;
2025-02-21 16:40:44 -05:00
PlayerQuestData questData = (PlayerQuestData) data.getQuestData();
questData.finishedQuests.putAll(universalFinished);
2025-02-21 17:23:51 -05:00
slot.setComponentData(new CNPCData().getTagName(), playerData.getNBT());
2025-02-21 06:19:24 -05:00
}
}
}
public void shareQuestCompletion(EntityPlayer player, int questId, long completeTime) {
Profile profile = getProfile(player);
if (profile == null) {
return;
}
for (ISlot slot : profile.getSlots().values()) {
IPlayerData playerData = getSlotPlayerData(player, slot.getId());
if (playerData != null) {
PlayerQuestData questData = (PlayerQuestData) playerData.getQuestData();
Long existing = questData.finishedQuests.get(questId);
if (existing == null || completeTime > existing) {
questData.finishedQuests.put(questId, completeTime);
}
2025-02-21 07:05:56 -05:00
playerData.save();
2025-02-21 06:19:24 -05:00
}
}
save(player, profile);
2025-02-20 21:39:02 -05:00
}
2025-01-23 16:10:01 -05:00
}