Add optional MySQL implementation, part 4. See #312

This commit is contained in:
PikaMug 2020-11-21 02:46:53 -05:00
parent 99b93d2d5b
commit d655d99ce9
8 changed files with 133 additions and 91 deletions

View File

@ -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<Quester> {
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<Integer, Quest> timers = new ConcurrentHashMap<Integer, Quest>();
@ -251,12 +250,12 @@ public class Quester implements Comparable<Quester> {
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<Quester> {
}
}
saveData();
loadData();
//loadData();
updateJournal();
}
@ -3196,26 +3195,9 @@ public class Quester implements Comparable<Quester> {
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<Quester> {
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<Quester> {
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("<br>")) {
getPlayer().sendMessage(msg);
}
if (!plugin.getSettings().canAskConfirmation()) {
takeQuest(plugin.getQuest(getQuestToTake()), false);
takeQuest(quest, false);
} else {
plugin.getConversationFactory().buildConversation(getPlayer()).begin();
}

View File

@ -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;
}
/**

View File

@ -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());
}
}

View File

@ -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"));

View File

@ -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());
}
}

View File

@ -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("<br>")) {
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<Quester> temp = (ConcurrentSkipListSet<Quester>) plugin.getOfflineQuesters();
/*final ConcurrentSkipListSet<Quester> temp = (ConcurrentSkipListSet<Quester>) 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<UUID> temp = plugin.getQuestFactory().getSelectingNpcs();
temp.remove(evt.getPlayer().getUniqueId());

View File

@ -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;
}
}

View File

@ -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<Quest, Integer> currentQuests = new ConcurrentHashMap<Quest, Integer>();
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<String> currentQuests = quester.getCurrentQuests().keySet().stream().map(Quest::getId).collect(Collectors.toSet());
final Set<String> 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<Quest, Integer> 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<Quest, Integer> getQuesterCurrentQuests(final UUID uniqueId) throws Exception {
final ConcurrentHashMap<Quest, Integer> currentQuests = new ConcurrentHashMap<Quest, Integer>();
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;
}
}