diff --git a/main/src/main/java/me/blackvein/quests/Quester.java b/main/src/main/java/me/blackvein/quests/Quester.java index ea96dbb8d..a2bd32ef1 100644 --- a/main/src/main/java/me/blackvein/quests/Quester.java +++ b/main/src/main/java/me/blackvein/quests/Quester.java @@ -12,7 +12,6 @@ package me.blackvein.quests; -import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -75,7 +74,7 @@ public class Quester implements Comparable { private final Quests plugin; public boolean hasJournal = false; private UUID id; - protected String questToTake; + protected String questIdToTake; protected int questPoints = 0; private String compassTargetQuestId; protected ConcurrentHashMap timers = new ConcurrentHashMap(); @@ -251,12 +250,12 @@ public class Quester implements Comparable { this.id = id; } - public String getQuestToTake() { - return questToTake; + public String getQuestIdToTake() { + return questIdToTake; } - public void setQuestToTake(final String questToTake) { - this.questToTake = questToTake; + public void setQuestToTake(final String questIdToTake) { + this.questIdToTake = questIdToTake; } public int getQuestPoints() { @@ -720,7 +719,7 @@ public class Quester implements Comparable { } } saveData(); - loadData(); + //loadData(); updateJournal(); } @@ -3196,26 +3195,9 @@ public class Quester implements Comparable { data.set("lastKnownName", representedPlayer.getName()); return data; } - - /** - * Get data file for this Quester - * - * @return file if exists, otherwise null - */ - public File getDataFile() { - File dataFile = new File(plugin.getDataFolder(), "data" + File.separator + id.toString() + ".yml"); - if (!dataFile.exists()) { - final OfflinePlayer p = getOfflinePlayer(); - dataFile = new File(plugin.getDataFolder(), "data" + File.separator + p.getName() + ".yml"); - if (!dataFile.exists()) { - return null; - } - } - return dataFile; - } /** - * Load data of the Quester from file + * Load data of the Quester from storage * * @return true if successful */ @@ -3271,15 +3253,28 @@ public class Quester implements Comparable { return getCurrentStage(quest).delay - (System.currentTimeMillis() - getQuestData(quest).getDelayStartTime()); } } - + + /** + * Check whether the Quester has base data, indicating they have participated in quests + * + * @return false if empty + * @deprecated Use {@link #hasBaseData()} + */ + @Deprecated public boolean hasData() { - if (currentQuests.isEmpty() == false || questData.isEmpty() == false) { + return hasBaseData(); + } + + /** + * Check whether the Quester has base data, indicating they have participated in quests + * + * @return false if empty + */ + public boolean hasBaseData() { + if (!currentQuests.isEmpty() || !questData.isEmpty() || !completedQuests.isEmpty()) { return true; } - if (questPoints > 1) { - return true; - } - return completedQuests.isEmpty() == false; + return false; } /** @@ -3705,14 +3700,13 @@ public class Quester implements Comparable { if (getPlayer() instanceof Conversable) { if (getPlayer().isConversing() == false) { setQuestToTake(quest.getName()); - final String s = ChatColor.GOLD + "- " + ChatColor.DARK_PURPLE + getQuestToTake() + ChatColor.GOLD - + " -\n" + "\n" + ChatColor.RESET + plugin.getQuest(getQuestToTake()).getDescription() - + "\n"; + final String s = ChatColor.GOLD + "- " + ChatColor.DARK_PURPLE + quest.getName() + ChatColor.GOLD + + " -\n" + "\n" + ChatColor.RESET + quest.getDescription() + "\n"; for (final String msg : s.split("
")) { getPlayer().sendMessage(msg); } if (!plugin.getSettings().canAskConfirmation()) { - takeQuest(plugin.getQuest(getQuestToTake()), false); + takeQuest(quest, false); } else { plugin.getConversationFactory().buildConversation(getPlayer()).begin(); } diff --git a/main/src/main/java/me/blackvein/quests/Quests.java b/main/src/main/java/me/blackvein/quests/Quests.java index 27cdd582d..890c0d3d8 100644 --- a/main/src/main/java/me/blackvein/quests/Quests.java +++ b/main/src/main/java/me/blackvein/quests/Quests.java @@ -467,15 +467,15 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener player.sendMessage(ChatColor.RED + Lang.get(player, "questSaveError")); } } - final String questToTake = quester.questToTake; + final String questIdToTake = quester.questIdToTake; try { - if (getQuest(questToTake) == null) { - getLogger().info(player.getName() + " attempted to take quest \"" + questToTake + if (getQuestById(questIdToTake) == null) { + getLogger().info(player.getName() + " attempted to take quest ID \"" + questIdToTake + "\" but something went wrong"); player.sendMessage(ChatColor.RED + "Something went wrong! Please report issue to an administrator."); } else { - getQuester(player.getUniqueId()).takeQuest(getQuest(questToTake), false); + getQuester(player.getUniqueId()).takeQuest(getQuestById(questIdToTake), false); } } catch (final Exception e) { e.printStackTrace(); @@ -1349,13 +1349,14 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener return quester; } } - if (!quester.loadData()) { + /*if (!quester.loadData()) { set.add(quester); } else { set.remove(quester); - } - setOfflineQuesters(set); - return quester; + }*/ + final Quester q = new Quester(this, id); + questers.add(q); + return q; } /** diff --git a/main/src/main/java/me/blackvein/quests/convo/npcs/NpcOfferQuestPrompt.java b/main/src/main/java/me/blackvein/quests/convo/npcs/NpcOfferQuestPrompt.java index c8d1f1117..659aaa373 100644 --- a/main/src/main/java/me/blackvein/quests/convo/npcs/NpcOfferQuestPrompt.java +++ b/main/src/main/java/me/blackvein/quests/convo/npcs/NpcOfferQuestPrompt.java @@ -171,8 +171,8 @@ public class NpcOfferQuestPrompt extends StringPrompt { } private String extracted(final Quests plugin, final Quester quester) { + final Quest quest = plugin.getQuestById(quester.getQuestIdToTake()); return MessageFormat.format("{0}- {1}{2}{3} -\n\n{4}{5}\n", ChatColor.GOLD, ChatColor.DARK_PURPLE, - quester.getQuestToTake(), ChatColor.GOLD, ChatColor.RESET, plugin.getQuest(quester.getQuestToTake()) - .getDescription()); + quest.getName(), ChatColor.GOLD, ChatColor.RESET, quest.getDescription()); } } diff --git a/main/src/main/java/me/blackvein/quests/listeners/CmdExecutor.java b/main/src/main/java/me/blackvein/quests/listeners/CmdExecutor.java index 95cea66c5..06040a9f5 100644 --- a/main/src/main/java/me/blackvein/quests/listeners/CmdExecutor.java +++ b/main/src/main/java/me/blackvein/quests/listeners/CmdExecutor.java @@ -783,6 +783,7 @@ public class CmdExecutor implements CommandExecutor { return; } } + //quester.setQuestToTake(questToFind); quester.offerQuest(questToFind, true); } else { player.sendMessage(ChatColor.YELLOW + Lang.get(player, "questNotFound")); diff --git a/main/src/main/java/me/blackvein/quests/listeners/NpcListener.java b/main/src/main/java/me/blackvein/quests/listeners/NpcListener.java index 352014628..aedcf8932 100644 --- a/main/src/main/java/me/blackvein/quests/listeners/NpcListener.java +++ b/main/src/main/java/me/blackvein/quests/listeners/NpcListener.java @@ -395,8 +395,8 @@ public class NpcListener implements Listener { } private String extracted(final Quester quester) { + final Quest quest = plugin.getQuestById(quester.getQuestIdToTake()); return MessageFormat.format("{0}- {1}{2}{3} -\n\n{4}{5}\n", ChatColor.GOLD, ChatColor.DARK_PURPLE, - quester.getQuestToTake(), ChatColor.GOLD, ChatColor.RESET, plugin.getQuest(quester.getQuestToTake()) - .getDescription()); + quest.getName(), ChatColor.GOLD, ChatColor.RESET, quest.getDescription()); } } diff --git a/main/src/main/java/me/blackvein/quests/listeners/PlayerListener.java b/main/src/main/java/me/blackvein/quests/listeners/PlayerListener.java index 675ad2afe..9aae9af81 100644 --- a/main/src/main/java/me/blackvein/quests/listeners/PlayerListener.java +++ b/main/src/main/java/me/blackvein/quests/listeners/PlayerListener.java @@ -13,7 +13,6 @@ package me.blackvein.quests.listeners; -import java.io.File; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -341,10 +340,10 @@ public class PlayerListener implements Listener { if (!plugin.getSettings().canAskConfirmation()) { quester.takeQuest(q, false); } else { + final Quest quest = plugin.getQuestById(quester.getQuestIdToTake()); final String s = ChatColor.GOLD + "- " + ChatColor.DARK_PURPLE - + quester.getQuestToTake() + ChatColor.GOLD + " -\n" + "\n" - + ChatColor.RESET + plugin.getQuest(quester.getQuestToTake()) - .getDescription() + "\n"; + + quest.getName() + ChatColor.GOLD + " -\n" + "\n" + + ChatColor.RESET + quest.getDescription() + "\n"; for (final String msg : s.split("
")) { player.sendMessage(msg); } @@ -790,16 +789,13 @@ public class PlayerListener implements Listener { @EventHandler public void onPlayerJoin(final PlayerJoinEvent evt) { if (plugin.canUseQuests(evt.getPlayer().getUniqueId())) { - final Quester quester = new Quester(plugin); - quester.setUUID(evt.getPlayer().getUniqueId()); - if (new File(plugin.getDataFolder(), "data" + File.separator + quester.getUUID() + ".yml").exists()) { - quester.loadData(); - } else if (plugin.getSettings().canGenFilesOnJoin()) { + final Quester quester = new Quester(plugin, evt.getPlayer().getUniqueId()); + if (!quester.loadData() && plugin.getSettings().canGenFilesOnJoin()) { quester.saveData(); } - final ConcurrentSkipListSet temp = (ConcurrentSkipListSet) plugin.getOfflineQuesters(); + /*final ConcurrentSkipListSet temp = (ConcurrentSkipListSet) plugin.getOfflineQuesters(); temp.add(quester); - plugin.setOfflineQuesters(temp); + plugin.setOfflineQuesters(temp);*/ for (final String s : quester.getCompletedQuests()) { final Quest q = plugin.getQuest(s); if (q != null) { @@ -858,10 +854,14 @@ public class PlayerListener implements Listener { quester.removeTimer(timerId); } } - - if (quester.hasData()) { + if (!plugin.getSettings().canGenFilesOnJoin()) { + if (quester.hasBaseData()) { + quester.saveData(); + } + } else { quester.saveData(); } + if (plugin.getQuestFactory().getSelectingNpcs().contains(evt.getPlayer().getUniqueId())) { final Set temp = plugin.getQuestFactory().getSelectingNpcs(); temp.remove(evt.getPlayer().getUniqueId()); diff --git a/main/src/main/java/me/blackvein/quests/storage/implementation/file/SeparatedYamlStorage.java b/main/src/main/java/me/blackvein/quests/storage/implementation/file/SeparatedYamlStorage.java index ac4d6fe59..55797ae38 100644 --- a/main/src/main/java/me/blackvein/quests/storage/implementation/file/SeparatedYamlStorage.java +++ b/main/src/main/java/me/blackvein/quests/storage/implementation/file/SeparatedYamlStorage.java @@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; @@ -65,7 +66,6 @@ public class SeparatedYamlStorage implements StorageImplementation { @Override public void close() { // TODO Auto-generated method stub - } @SuppressWarnings("deprecation") @@ -79,7 +79,7 @@ public class SeparatedYamlStorage implements StorageImplementation { quester = new Quester(plugin, uniqueId); } try { - final File dataFile = quester.getDataFile(); + final File dataFile = getDataFile(quester); if (dataFile != null) { data.load(dataFile); } else { @@ -495,4 +495,21 @@ public class SeparatedYamlStorage implements StorageImplementation { } return data.getString("lastKnownName"); } + + /** + * Get data file for this Quester + * + * @return file if exists, otherwise null + */ + public File getDataFile(final Quester quester) { + File dataFile = new File(plugin.getDataFolder(), "data" + File.separator + quester.getUUID().toString() + ".yml"); + if (!dataFile.exists()) { + final OfflinePlayer p = quester.getOfflinePlayer(); + dataFile = new File(plugin.getDataFolder(), "data" + File.separator + p.getName() + ".yml"); + if (!dataFile.exists()) { + return null; + } + } + return dataFile; + } } diff --git a/main/src/main/java/me/blackvein/quests/storage/implementation/sql/SqlStorage.java b/main/src/main/java/me/blackvein/quests/storage/implementation/sql/SqlStorage.java index 4f9b2bec7..547073f0f 100644 --- a/main/src/main/java/me/blackvein/quests/storage/implementation/sql/SqlStorage.java +++ b/main/src/main/java/me/blackvein/quests/storage/implementation/sql/SqlStorage.java @@ -17,9 +17,12 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Map.Entry; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; +import java.util.stream.Collectors; import me.blackvein.quests.Quest; import me.blackvein.quests.Quester; @@ -28,16 +31,17 @@ import me.blackvein.quests.storage.implementation.StorageImplementation; import me.blackvein.quests.storage.implementation.sql.connection.ConnectionFactory; public class SqlStorage implements StorageImplementation { - private static final String PLAYER_SELECT = "SELECT id, lastknownname, hasjournal, FROM '{prefix}players' WHERE uuid=?"; - private static final String PLAYER_SELECT_USERNAME_BY_UUID = "SELECT lastknownname FROM '{prefix}players' WHERE uuid=? LIMIT 1"; - private static final String PLAYER_UPDATE_USERNAME_FOR_UUID = "UPDATE '{prefix}players' SET lastknownname=? WHERE uuid=?"; + private static final String PLAYER_SELECT = "SELECT lastknownname, hasjournal, questpoints FROM '{prefix}players' WHERE uuid=?"; + private static final String PLAYER_SELECT_USERNAME = "SELECT lastknownname FROM '{prefix}players' WHERE uuid=? LIMIT 1"; + private static final String PLAYER_UPDATE_USERNAME = "UPDATE '{prefix}players' SET lastknownname=? WHERE uuid=?"; private static final String PLAYER_INSERT = "INSERT INTO '{prefix}players' (uuid, lastknownname, hasjournal, questpoints) " + "VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE uuid=uuid, lastknownname=lastknownname, hasjournal=hasjournal, questpoints=questpoints"; private static final String PLAYER_DELETE = "DELETE FROM '{prefix}players' WHERE uuid=?"; - private static final String PLAYER_CURRENT_QUESTS_SELECT_BY_UUID = "SELECT questid FROM '{prefix}player_currentquests' WHERE uuid=?"; - private static final String PLAYER_CURRENT_QUESTS_INSERT = "INSERT INTO '{prefix}player_currentquests' (uuid, questid) " - + "VALUES(?, ?) ON DUPLICATE KEY UPDATE uuid=uuid, questid=questid"; + private static final String PLAYER_CURRENT_QUESTS_SELECT_BY_UUID = "SELECT questid, stageNum FROM '{prefix}player_currentquests' WHERE uuid=?"; + private static final String PLAYER_CURRENT_QUESTS_DELETE_FOR_UUID_AND_QUEST = "DELETE FROM '{prefix}player_currentquests' WHERE uuid=? AND questId=?"; + private static final String PLAYER_CURRENT_QUESTS_INSERT = "INSERT INTO '{prefix}player_currentquests' (uuid, questid, stageNum) " + + "VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE uuid=uuid, questid=questid, stageNum=stageNum"; private static final String PLAYER_CURRENT_QUESTS_DELETE = "DELETE FROM '{prefix}player_currentquests' WHERE uuid=?"; private final Quests plugin; @@ -85,6 +89,7 @@ public class SqlStorage implements StorageImplementation { + "` (id INT AUTO_INCREMENT NOT NULL," + "`uuid` VARCHAR(36) NOT NULL, " + "`questid` VARCHAR(100) NOT NULL," + + "`stageNum` INT NOT NULL," + "PRIMARY KEY (`id`)," + "UNIQUE KEY (`uuid`, `questid`)" + ") DEFAULT CHARSET = utf8mb4"; @@ -116,10 +121,13 @@ public class SqlStorage implements StorageImplementation { @Override public Quester loadQuesterData(final UUID uniqueId) throws Exception { - final Quester quester = new Quester(plugin, uniqueId); + final Quester quester = plugin.getQuester(uniqueId); + if (quester == null) { + return null; + } try (Connection c = connectionFactory.getConnection()) { if (uniqueId != null) { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT))) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_SELECT))) { ps.setString(1, uniqueId.toString()); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { @@ -128,16 +136,7 @@ public class SqlStorage implements StorageImplementation { } } } - final ConcurrentHashMap currentQuests = new ConcurrentHashMap(); - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_CURRENT_QUESTS_SELECT_BY_UUID))) { - ps.setString(1, uniqueId.toString()); - try (ResultSet rs = ps.executeQuery()) { - while (rs.next()) { - currentQuests.put(plugin.getQuestById(rs.getString("questid")), 0); - } - } - } - quester.setCurrentQuests(currentQuests); + quester.setCurrentQuests(getQuesterCurrentQuests(uniqueId)); } } return quester; @@ -148,16 +147,19 @@ public class SqlStorage implements StorageImplementation { final UUID uniqueId = quester.getUUID(); final String lastknownname = quester.getOfflinePlayer().getName(); final String oldlastknownname = getQuesterLastKnownName(uniqueId); - + final Set currentQuests = quester.getCurrentQuests().keySet().stream().map(Quest::getId).collect(Collectors.toSet()); + final Set oldCurrentQuests = getQuesterCurrentQuests(uniqueId).keySet().stream().map(Quest::getId).collect(Collectors.toSet()); + oldCurrentQuests.removeAll(currentQuests); + try (final Connection c = connectionFactory.getConnection()) { if (oldlastknownname != null && !lastknownname.equals(oldlastknownname)) { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_UPDATE_USERNAME_FOR_UUID))) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_UPDATE_USERNAME))) { ps.setString(1, lastknownname); ps.setString(2, uniqueId.toString()); ps.execute(); } } else { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_INSERT))) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_INSERT))) { ps.setString(1, uniqueId.toString()); ps.setString(2, lastknownname); ps.setBoolean(3, quester.hasJournal); @@ -165,11 +167,23 @@ public class SqlStorage implements StorageImplementation { ps.execute(); } } - for (final Quest quest : quester.getCurrentQuests().keySet()) { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_CURRENT_QUESTS_INSERT))) { - ps.setString(1, uniqueId.toString()); - ps.setString(2, quest.getId()); - ps.execute(); + + if (!oldCurrentQuests.isEmpty()) { + for (final String questId : oldCurrentQuests) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_CURRENT_QUESTS_DELETE_FOR_UUID_AND_QUEST))) { + ps.setString(1, uniqueId.toString()); + ps.setString(2, questId); + ps.execute(); + } + } + } else { + for (final Entry entry : quester.getCurrentQuests().entrySet()) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_CURRENT_QUESTS_INSERT))) { + ps.setString(1, uniqueId.toString()); + ps.setString(2, entry.getKey().getId()); + ps.setInt(3, entry.getValue()); + ps.execute(); + } } } } @@ -178,11 +192,11 @@ public class SqlStorage implements StorageImplementation { @Override public void deleteQuesterData(final UUID uniqueId) throws Exception { try (Connection c = connectionFactory.getConnection()) { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_DELETE))) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_DELETE))) { ps.setString(1, uniqueId.toString()); ps.execute(); } - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_CURRENT_QUESTS_DELETE))) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_CURRENT_QUESTS_DELETE))) { ps.setString(1, uniqueId.toString()); ps.execute(); } @@ -192,7 +206,7 @@ public class SqlStorage implements StorageImplementation { @Override public String getQuesterLastKnownName(final UUID uniqueId) throws Exception { try (Connection c = connectionFactory.getConnection()) { - try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(PLAYER_SELECT_USERNAME_BY_UUID))) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_SELECT_USERNAME))) { ps.setString(1, uniqueId.toString()); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { @@ -203,4 +217,19 @@ public class SqlStorage implements StorageImplementation { } return null; } + + public ConcurrentHashMap getQuesterCurrentQuests(final UUID uniqueId) throws Exception { + final ConcurrentHashMap currentQuests = new ConcurrentHashMap(); + try (Connection c = connectionFactory.getConnection()) { + try (PreparedStatement ps = c.prepareStatement(statementProcessor.apply(PLAYER_CURRENT_QUESTS_SELECT_BY_UUID))) { + ps.setString(1, uniqueId.toString()); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + currentQuests.put(plugin.getQuestById(rs.getString("questid")), rs.getInt("stageNum")); + } + } + } + } + return currentQuests; + } }