Compare commits

..

2 Commits

Author SHA1 Message Date
65cf9c9b52 Makes a bunch of strings configurable
All checks were successful
KnarCraft/DynmapCitizens/pipeline/head This commit looks good
2024-05-05 02:27:51 +02:00
35589630a0 Adds POM relocations 2024-05-03 16:01:36 +02:00
10 changed files with 302 additions and 83 deletions

28
pom.xml
View File

@ -31,7 +31,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version> <version>3.3.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@ -40,6 +40,16 @@
</goals> </goals>
<configuration> <configuration>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>net.knarcraft.knarlib</pattern>
<shadedPattern>net.knarcraft.dynmapcitizens.lib.knarlib</shadedPattern>
</relocation>
<relocation>
<pattern>org.jetbrains.annotations</pattern>
<shadedPattern>net.knarcraft.dynmapcitizens.lib.annotations</shadedPattern>
</relocation>
</relocations>
<filters> <filters>
<filter> <filter>
<artifact>net.knarcraft:knarlib</artifact> <artifact>net.knarcraft:knarlib</artifact>
@ -48,10 +58,10 @@
</includes> </includes>
</filter> </filter>
<filter> <filter>
<excludes> <artifact>org.jetbrains:annotations</artifact>
<exclude>*.MF</exclude> <includes>
<exclude>*.yml</exclude> <include>org/jetbrains/annotations/**</include>
</excludes> </includes>
</filter> </filter>
</filters> </filters>
</configuration> </configuration>
@ -118,7 +128,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.20.2-R0.1-SNAPSHOT</version> <version>1.20.4-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -143,7 +153,7 @@
<dependency> <dependency>
<groupId>net.knarcraft</groupId> <groupId>net.knarcraft</groupId>
<artifactId>blacksmith</artifactId> <artifactId>blacksmith</artifactId>
<version>1.0.4-SNAPSHOT</version> <version>1.1.0-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -155,13 +165,13 @@
<dependency> <dependency>
<groupId>com.github.MilkBowl</groupId> <groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId> <artifactId>VaultAPI</artifactId>
<version>1.7</version> <version>1.7.1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.knarcraft</groupId> <groupId>net.knarcraft</groupId>
<artifactId>knarlib</artifactId> <artifactId>knarlib</artifactId>
<version>1.2.3</version> <version>1.2.7</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -45,7 +45,12 @@ public enum QuestsTranslatableMessage implements TranslatableMessage {
* *
* <p>Placeholders: {repeatDelay}</p> * <p>Placeholders: {repeatDelay}</p>
*/ */
QUEST_PLANNER_REPEAT, QUESTS_PLANNER_REPEAT,
/**
* The format for displaying a planner timestamp
*/
QUESTS_PLANNER_TIMESTAMP_FORMAT,
/** /**
* The format for a quest's requirements * The format for a quest's requirements
@ -160,6 +165,104 @@ public enum QuestsTranslatableMessage implements TranslatableMessage {
* <p>Placeholders: {areaName}, {questName}, {mobName}, {mobAmount}</p> * <p>Placeholders: {areaName}, {questName}, {mobName}, {mobAmount}</p>
*/ */
QUESTS_KILL_AREA_DESCRIPTION_FORMAT, QUESTS_KILL_AREA_DESCRIPTION_FORMAT,
/**
* The format for a quest's rewards
*
* <p>Placeholders: {money}, {experience}, {questPoints}, {permissions}, {items}, {commands}</p>
*/
QUESTS_REWARDS_FORMAT,
/**
* The format for a quest's money reward
*
* <p>Placeholders: {amount}, {currency}</p>
*/
QUESTS_REWARDS_MONEY,
/**
* The format for a quest's experience reward
*
* <p>Placeholders: {amount}</p>
*/
QUESTS_REWARDS_EXPERIENCE,
/**
* The format for a quest's quest point reward
*
* <p>Placeholders: {amount}</p>
*/
QUESTS_REWARDS_QUEST_POINTS,
/**
* The format for one of a quest's permission rewards
*
* <p>Placeholders: {permission}</p>
*/
QUESTS_REWARDS_PERMISSION,
/**
* The format for one of a quest's item rewards
*
* <p>Placeholders: {item}</p>
*/
QUESTS_REWARDS_ITEM,
/**
* The format for one of a quest's command rewards
*
* <p>Placeholders: {command}</p>
*/
QUESTS_REWARDS_COMMAND,
/**
* The format for displaying a quest marker name
*
* <p>Placeholders: {name}</p>
*/
QUESTS_MARKER_NAME_FORMAT,
/**
* The format for displaying offered quests on a quest NPC marker
*
* <p>Placeholders: {quests}</p>
*/
QUESTS_OFFERED_FORMAT,
/**
* The format for displaying one of the quests on a quest NPC marker
*
* <p>Placeholders: {name}, {description}, {stages}, {rewards}, {requirements}, {planner}</p>
*/
QUESTS_OFFERED_QUEST_FORMAT,
/**
* The format for displaying the different quests an NPC is involved in
*
* <p>Placeholders: {involvedQuests}</p>
*/
QUESTS_INVOLVED_IN_FORMAT,
/**
* The format for displaying that the NPC is a kill target in a quest
*
* <p>Placeholders: {questName}</p>
*/
QUESTS_INVOLVED_IN_KILL,
/**
* The format for displaying that the NPC is a delivery target in a quest
*
* <p>Placeholders: {questName}</p>
*/
QUESTS_INVOLVED_IN_DELIVERY_TARGET,
/**
* The format for displaying that the NPC is a interaction target in a quest
*
* <p>Placeholders: {questName}</p>
*/
QUESTS_INVOLVED_IN_INTERACT,
; ;
@Override @Override

View File

@ -4,8 +4,10 @@ import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.Trait;
import net.knarcraft.blacksmith.BlacksmithPlugin; import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.config.NPCSettings; import net.knarcraft.blacksmith.config.blacksmith.BlacksmithNPCSettings;
import net.knarcraft.blacksmith.config.scrapper.ScrapperNPCSettings;
import net.knarcraft.blacksmith.trait.BlacksmithTrait; import net.knarcraft.blacksmith.trait.BlacksmithTrait;
import net.knarcraft.blacksmith.trait.ScrapperTrait;
import net.knarcraft.dynmapcitizens.DynmapCitizens; import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.dynmapcitizens.property.Icon; import net.knarcraft.dynmapcitizens.property.Icon;
import net.knarcraft.dynmapcitizens.settings.BlacksmithSettings; import net.knarcraft.dynmapcitizens.settings.BlacksmithSettings;
@ -48,6 +50,7 @@ public class BlacksmithHandler extends AbstractTraitHandler {
super.markerSet.getMarkers().forEach(GenericMarker::deleteMarker); super.markerSet.getMarkers().forEach(GenericMarker::deleteMarker);
Class<? extends Trait> blacksmithTrait = CitizensAPI.getTraitFactory().getTraitClass("blacksmith"); Class<? extends Trait> blacksmithTrait = CitizensAPI.getTraitFactory().getTraitClass("blacksmith");
Class<? extends Trait> scrapperTrait = CitizensAPI.getTraitFactory().getTraitClass("scrapper");
for (NPC npc : CitizensAPI.getNPCRegistry()) { for (NPC npc : CitizensAPI.getNPCRegistry()) {
if (npc.hasTrait(blacksmithTrait)) { if (npc.hasTrait(blacksmithTrait)) {
BlacksmithTrait trait = npc.getTraitNullable(BlacksmithTrait.class); BlacksmithTrait trait = npc.getTraitNullable(BlacksmithTrait.class);
@ -60,10 +63,43 @@ public class BlacksmithHandler extends AbstractTraitHandler {
} }
addNPCMarker(npc.getUniqueId(), "Blacksmith NPC: ", description, addNPCMarker(npc.getUniqueId(), "Blacksmith NPC: ", description,
DynmapCitizens.getInstance().getGlobalSettings().getMarkerIcons().get(Icon.BLACKSMITH), super.markerSet); DynmapCitizens.getInstance().getGlobalSettings().getMarkerIcons().get(Icon.BLACKSMITH), super.markerSet);
} else if (npc.hasTrait(scrapperTrait)) {
ScrapperTrait trait = npc.getTraitNullable(ScrapperTrait.class);
String description = "";
if (trait == null) {
DynmapCitizens.getInstance().getLogger().log(Level.WARNING, "Unable to get scrapper trait");
} else {
description = getDetailedScrapperInfo(npc, trait.getSettings());
}
addNPCMarker(npc.getUniqueId(), "Scrapper NPC: ", description,
DynmapCitizens.getInstance().getGlobalSettings().getMarkerIcons().get(Icon.SCRAPPER), super.markerSet);
} }
} }
} }
/**
* Gets detailed information about a scrapper NPC
*
* @param npc <p>The NPC the settings belong to</p>
* @param npcSettings <p>The settings to search for information</p>
* @return <p>A string describing the scrapper</p>
*/
private @NotNull String getDetailedScrapperInfo(@NotNull NPC npc, @NotNull ScrapperNPCSettings npcSettings) {
String info = "<h2>" + npc.getName() + " the " +
npcSettings.getScrapperTitle() + "</h2>";
if (settings.displayBlacksmithSettings()) {
info += "<b>Fail chance:</b> " + npcSettings.getFailChance() +
"<br><b>Delay:</b> " +
npcSettings.getMinSalvageDelay() + " to " + npcSettings.getMaxSalvageDelay() +
" seconds<br><b>Cool-down:</b> " + npcSettings.getSalvageCoolDown() + " seconds<br><b>Drop item:</b> " +
npcSettings.getDropItem();
if (!npcSettings.getSalvageAbleItems().isEmpty()) {
info += "<br><b>Salvage-able items:</b> " + getReforgeAbleItemsString(npcSettings.getSalvageAbleItems());
}
}
return info;
}
/** /**
* Gets detailed information about a blacksmith NPC * Gets detailed information about a blacksmith NPC
* *
@ -71,7 +107,7 @@ public class BlacksmithHandler extends AbstractTraitHandler {
* @param npcSettings <p>The settings to search for information</p> * @param npcSettings <p>The settings to search for information</p>
* @return <p>A string describing the blacksmith</p> * @return <p>A string describing the blacksmith</p>
*/ */
private @NotNull String getDetailedBlacksmithInfo(@NotNull NPC npc, @NotNull NPCSettings npcSettings) { private @NotNull String getDetailedBlacksmithInfo(@NotNull NPC npc, @NotNull BlacksmithNPCSettings npcSettings) {
String info = "<h2>" + npc.getName() + " the " + String info = "<h2>" + npc.getName() + " the " +
npcSettings.getBlacksmithTitle() + "</h2>"; npcSettings.getBlacksmithTitle() + "</h2>";
if (settings.displayBlacksmithSettings()) { if (settings.displayBlacksmithSettings()) {

View File

@ -3,6 +3,8 @@ package net.knarcraft.dynmapcitizens.handler.trait.quests;
import me.pikamug.quests.quests.Quest; import me.pikamug.quests.quests.Quest;
import me.pikamug.quests.quests.components.Planner; import me.pikamug.quests.quests.components.Planner;
import net.knarcraft.dynmapcitizens.DynmapCitizens; import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.StringReplacer;
import net.knarcraft.knarlib.formatting.TimeFormatter; import net.knarcraft.knarlib.formatting.TimeFormatter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -10,12 +12,21 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_COOL_DOWN;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_DESCRIPTION;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_FROM;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_REPEAT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_TIMESTAMP_FORMAT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_UNREPEATABLE;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_PLANNER_UNTIL;
/** /**
* A class to generate a string containing all information about a quest's planner info * A class to generate a string containing all information about a quest's planner info
*/ */
public class QuestPlannerInfoGenerator { public class QuestPlannerInfoGenerator {
private final Quest quest; private final Quest quest;
private final StringFormatter formatter;
/** /**
* Instantiates a new quest planner info generator * Instantiates a new quest planner info generator
@ -24,6 +35,7 @@ public class QuestPlannerInfoGenerator {
*/ */
public QuestPlannerInfoGenerator(@NotNull Quest quest) { public QuestPlannerInfoGenerator(@NotNull Quest quest) {
this.quest = quest; this.quest = quest;
this.formatter = DynmapCitizens.getFormatter();
} }
/** /**
@ -33,40 +45,30 @@ public class QuestPlannerInfoGenerator {
*/ */
public @NotNull String getQuestPlannerInfo() { public @NotNull String getQuestPlannerInfo() {
Planner planner = quest.getPlanner(); Planner planner = quest.getPlanner();
StringBuilder plannerInfo = new StringBuilder(); StringReplacer replacer = new StringReplacer(formatter.getUnFormattedColoredMessage(QUESTS_PLANNER_DESCRIPTION));
plannerInfo.append("<b>Planner:</b><ul>");
//Quest can be repeated after a cool-down //Quest can be repeated after a cool-down
if (planner.hasCooldown()) { if (planner.hasCooldown()) {
plannerInfo.append("<li>Quest repeatable after: "); replacer.add("{questCoolDown}", formatter.replacePlaceholder(QUESTS_PLANNER_COOL_DOWN, "{coolDown}",
plannerInfo.append(TimeFormatter.getDurationString(DynmapCitizens.getTranslator(), TimeFormatter.getDurationString(DynmapCitizens.getTranslator(), planner.getCooldown() / 1000)));
planner.getCooldown() / 1000));
plannerInfo.append("</li>");
} else { } else {
plannerInfo.append("<li>Quest cannot be repeated!</li>"); replacer.add("{questCoolDown}", formatter.getUnFormattedColoredMessage(QUESTS_PLANNER_UNREPEATABLE));
} }
//Quest only becomes available after the start date //Quest only becomes available after the start date
if (planner.hasStart()) { replacer.add("{questFrom}", planner.hasStart() ? formatter.replacePlaceholder(QUESTS_PLANNER_FROM,
plannerInfo.append("<li>Quest available from "); "{startDate}", formatTimestamp(planner.getStartInMillis())) : "");
plannerInfo.append(formatTimestamp(planner.getStartInMillis())).append("</li>");
}
//Quest is only available until the end date //Quest is only available until the end date
if (planner.hasEnd()) { replacer.add("{questUntil}", planner.hasEnd() ? formatter.replacePlaceholder(QUESTS_PLANNER_UNTIL,
plannerInfo.append("<li>Quest available until "); "{endDate}", formatTimestamp(planner.getEndInMillis())) : "");
plannerInfo.append(formatTimestamp(planner.getEndInMillis())).append("</li>");
}
//Quest availability repeats //Quest availability repeats'
if (planner.hasRepeat()) { replacer.add("{questRepeat}", planner.hasRepeat() ? formatter.replacePlaceholder(QUESTS_PLANNER_REPEAT,
plannerInfo.append("<li>Quest will become available again after "); "{repeatDelay}", TimeFormatter.getDurationString(DynmapCitizens.getTranslator(),
plannerInfo.append(TimeFormatter.getDurationString(DynmapCitizens.getTranslator(), planner.getRepeat() / 1000)) : "");
planner.getRepeat() / 1000)).append("</li>");
}
plannerInfo.append("</ul>"); return replacer.replace();
return plannerInfo.toString();
} }
/** /**
@ -76,7 +78,7 @@ public class QuestPlannerInfoGenerator {
* @return <p>A datetime string</p> * @return <p>A datetime string</p>
*/ */
private @NotNull String formatTimestamp(long timestamp) { private @NotNull String formatTimestamp(long timestamp) {
DateFormat format = new SimpleDateFormat("dd MM yyyy HH:mm:ss"); DateFormat format = new SimpleDateFormat(formatter.getUnFormattedMessage(QUESTS_PLANNER_TIMESTAMP_FORMAT));
Date date = new Date(timestamp); Date date = new Date(timestamp);
return format.format(date); return format.format(date);
} }

View File

@ -2,16 +2,30 @@ package net.knarcraft.dynmapcitizens.handler.trait.quests;
import me.pikamug.quests.quests.Quest; import me.pikamug.quests.quests.Quest;
import me.pikamug.quests.quests.components.Rewards; import me.pikamug.quests.quests.components.Rewards;
import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.dynmapcitizens.util.QuestsHelper; import net.knarcraft.dynmapcitizens.util.QuestsHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.StringReplacer;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_COMMAND;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_EXPERIENCE;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_FORMAT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_ITEM;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_MONEY;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_PERMISSION;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_REWARDS_QUEST_POINTS;
/** /**
* A class to generate a string containing all information about a quest's rewards * A class to generate a string containing all information about a quest's rewards
*/ */
public class QuestRewardsInfoGenerator { public class QuestRewardsInfoGenerator {
private final Quest quest; private final Quest quest;
private final StringFormatter formatter;
/** /**
* Instantiates a new quest reward info generator * Instantiates a new quest reward info generator
@ -20,6 +34,7 @@ public class QuestRewardsInfoGenerator {
*/ */
public QuestRewardsInfoGenerator(@NotNull Quest quest) { public QuestRewardsInfoGenerator(@NotNull Quest quest) {
this.quest = quest; this.quest = quest;
this.formatter = DynmapCitizens.getFormatter();
} }
/** /**
@ -29,36 +44,39 @@ public class QuestRewardsInfoGenerator {
*/ */
public @NotNull String getQuestRewardsInfo() { public @NotNull String getQuestRewardsInfo() {
Rewards reward = quest.getRewards(); Rewards reward = quest.getRewards();
StringBuilder rewardInfo = new StringBuilder(); StringReplacer replacer = new StringReplacer(formatter.getUnFormattedColoredMessage(QUESTS_REWARDS_FORMAT));
rewardInfo.append("<b>Rewards:</b><ul>");
if (reward.getMoney() > 0) { replacer.add("{money}", reward.getMoney() > 0 ? formatter.replacePlaceholders(QUESTS_REWARDS_MONEY,
rewardInfo.append("<li>").append(reward.getMoney()).append(" ").append(QuestsHelper.getCurrency( List.of("{amount}", "{currency}"), List.of(String.valueOf(reward.getMoney()),
reward.getMoney())).append("</li>"); QuestsHelper.getCurrency(reward.getMoney()))) : "");
}
if (reward.getExp() > 0) { replacer.add("{experience}", reward.getExp() > 0 ? formatter.replacePlaceholder(
rewardInfo.append("<li>").append(reward.getExp()).append(" exp").append("</li>"); QUESTS_REWARDS_EXPERIENCE, "{amount}", String.valueOf(reward.getExp())) : "");
}
if (reward.getQuestPoints() > 0) { replacer.add("{questPoints}", reward.getQuestPoints() > 0 ? formatter.replacePlaceholder(
rewardInfo.append("<li>").append(reward.getQuestPoints()).append(" quest point(s)").append("</li>"); QUESTS_REWARDS_QUEST_POINTS, "{amount}", String.valueOf(reward.getQuestPoints())) : "");
}
StringBuilder permissionBuilder = new StringBuilder();
for (String permission : reward.getPermissions()) { for (String permission : reward.getPermissions()) {
rewardInfo.append("<li>").append("Permission: ").append(permission).append("</li>"); permissionBuilder.append(formatter.replacePlaceholder(QUESTS_REWARDS_PERMISSION, "{permission}",
permission));
} }
replacer.add("{permissions}", permissionBuilder.toString());
StringBuilder itemBuilder = new StringBuilder();
for (Object item : reward.getItems()) { for (Object item : reward.getItems()) {
rewardInfo.append("<li>").append(QuestsHelper.getUpperCasedItemStackString((ItemStack) item)).append("</li>"); itemBuilder.append(formatter.replacePlaceholder(QUESTS_REWARDS_ITEM, "{item}",
QuestsHelper.getUpperCasedItemStackString((ItemStack) item)));
} }
replacer.add("{items}", itemBuilder.toString());
StringBuilder commandBuilder = new StringBuilder();
for (String command : reward.getCommands()) { for (String command : reward.getCommands()) {
rewardInfo.append("<li>Command: ").append(command).append("</li>"); commandBuilder.append(formatter.replacePlaceholder(QUESTS_REWARDS_COMMAND, "{command}", command));
} }
replacer.add("{commands}", commandBuilder.toString());
rewardInfo.append("</ul>"); return replacer.replace();
return rewardInfo.toString();
} }
} }

View File

@ -6,11 +6,14 @@ import me.pikamug.quests.quests.components.Stage;
import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPCRegistry; import net.citizensnpcs.api.npc.NPCRegistry;
import net.knarcraft.dynmapcitizens.DynmapCitizens; import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage;
import net.knarcraft.dynmapcitizens.handler.trait.AbstractTraitHandler; import net.knarcraft.dynmapcitizens.handler.trait.AbstractTraitHandler;
import net.knarcraft.dynmapcitizens.property.Icon; import net.knarcraft.dynmapcitizens.property.Icon;
import net.knarcraft.dynmapcitizens.settings.QuestsSettings; import net.knarcraft.dynmapcitizens.settings.QuestsSettings;
import net.knarcraft.dynmapcitizens.settings.TraitSettings; import net.knarcraft.dynmapcitizens.settings.TraitSettings;
import net.knarcraft.dynmapcitizens.util.QuestsHelper; import net.knarcraft.dynmapcitizens.util.QuestsHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.StringReplacer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.dynmap.DynmapAPI; import org.dynmap.DynmapAPI;
import org.dynmap.markers.GenericMarker; import org.dynmap.markers.GenericMarker;
@ -25,6 +28,14 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_INVOLVED_IN_DELIVERY_TARGET;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_INVOLVED_IN_FORMAT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_INVOLVED_IN_INTERACT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_INVOLVED_IN_KILL;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_MARKER_NAME_FORMAT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_OFFERED_FORMAT;
import static net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage.QUESTS_OFFERED_QUEST_FORMAT;
/** /**
* A handler class for the quests trait * A handler class for the quests trait
*/ */
@ -125,7 +136,8 @@ public class QuestsHandler extends AbstractTraitHandler {
List<Quest> offeredQuests = info.getQuestStarts(); List<Quest> offeredQuests = info.getQuestStarts();
StringBuilder markerDescription = new StringBuilder(); StringBuilder markerDescription = new StringBuilder();
markerDescription.append("<h2>").append(registry.getByUniqueId(npcId).getName()).append("</h2>"); markerDescription.append(DynmapCitizens.getFormatter().replacePlaceholder(QUESTS_MARKER_NAME_FORMAT,
"{name}", registry.getByUniqueId(npcId).getName()));
//Print info about any offered quests //Print info about any offered quests
if (!offeredQuests.isEmpty()) { if (!offeredQuests.isEmpty()) {
@ -153,25 +165,27 @@ public class QuestsHandler extends AbstractTraitHandler {
* @param offeredQuests <p>The list of quests the NPC offers</p> * @param offeredQuests <p>The list of quests the NPC offers</p>
*/ */
private void appendOfferedQuestsInfo(@NotNull StringBuilder stringBuilder, @NotNull List<Quest> offeredQuests) { private void appendOfferedQuestsInfo(@NotNull StringBuilder stringBuilder, @NotNull List<Quest> offeredQuests) {
stringBuilder.append("<h3>Quests offered:</h3><ul>"); StringFormatter formatter = DynmapCitizens.getFormatter();
StringBuilder questsInfoBuilder = new StringBuilder();
for (Quest quest : offeredQuests) { for (Quest quest : offeredQuests) {
stringBuilder.append("<li><h4><b>").append(quest.getName()).append("</b></h4><h5><b>- "); StringReplacer replacer = new StringReplacer(formatter.getUnFormattedMessage(QUESTS_OFFERED_QUEST_FORMAT));
stringBuilder.append(quest.getDescription()).append("</b></h5>"); replacer.add("{name}", quest.getName());
if (settings.displayStageInfo()) { replacer.add("{description}", quest.getDescription());
stringBuilder.append(new QuestStagesInfoGenerator(quest).getQuestStagesInfo());
} replacer.add("{stages}", settings.displayStageInfo() ?
if (settings.displayRewardInfo()) { new QuestStagesInfoGenerator(quest).getQuestStagesInfo() : "");
stringBuilder.append(new QuestRewardsInfoGenerator(quest).getQuestRewardsInfo()); replacer.add("{rewards}", settings.displayRewardInfo() ?
} new QuestRewardsInfoGenerator(quest).getQuestRewardsInfo() : "");
if (settings.displayRequirementInfo()) { replacer.add("{requirements}", settings.displayRequirementInfo() ?
stringBuilder.append(new QuestRequirementsInfoGenerator(questsAPI, quest).getQuestRequirementsInfo()); new QuestRequirementsInfoGenerator(questsAPI, quest).getQuestRequirementsInfo() : "");
} replacer.add("{planner}", settings.displayPlannerInfo() ?
if (settings.displayPlannerInfo()) { new QuestPlannerInfoGenerator(quest).getQuestPlannerInfo() : "");
stringBuilder.append(new QuestPlannerInfoGenerator(quest).getQuestPlannerInfo()); questsInfoBuilder.append(replacer.replace());
}
stringBuilder.append("</li>");
} }
stringBuilder.append("</ul>");
stringBuilder.append(formatter.replacePlaceholder(QUESTS_OFFERED_FORMAT, "{quests}",
questsInfoBuilder.toString()));
} }
/** /**
@ -181,6 +195,7 @@ public class QuestsHandler extends AbstractTraitHandler {
* @return <p>Information about an NPC's involvement in different quests</p> * @return <p>Information about an NPC's involvement in different quests</p>
*/ */
private String getInvolvedInQuestsString(@NotNull NPCQuestInfo info) { private String getInvolvedInQuestsString(@NotNull NPCQuestInfo info) {
StringFormatter formatter = DynmapCitizens.getFormatter();
List<Quest> questKills = info.getQuestKills(); List<Quest> questKills = info.getQuestKills();
List<Quest> questInteractions = info.getQuestInteractions(); List<Quest> questInteractions = info.getQuestInteractions();
List<Quest> questDeliveries = info.getQuestDeliveries(); List<Quest> questDeliveries = info.getQuestDeliveries();
@ -189,25 +204,28 @@ public class QuestsHandler extends AbstractTraitHandler {
return ""; return "";
} }
StringBuilder markerDescription = new StringBuilder(); StringBuilder markerDescription = new StringBuilder();
markerDescription.append("<h3>Involved in quests:</h3><ul>");
addInvolvedInString("Killed in", questKills, markerDescription); addInvolvedInString(formatter, QUESTS_INVOLVED_IN_KILL, questKills, markerDescription);
addInvolvedInString("Delivery target in", questDeliveries, markerDescription); addInvolvedInString(formatter, QUESTS_INVOLVED_IN_DELIVERY_TARGET, questDeliveries, markerDescription);
addInvolvedInString("Interacted with in quest", questInteractions, markerDescription); addInvolvedInString(formatter, QUESTS_INVOLVED_IN_INTERACT, questInteractions, markerDescription);
markerDescription.append("</ul>");
return markerDescription.toString(); return formatter.replacePlaceholder(QUESTS_INVOLVED_IN_FORMAT, "{involvedQuests}",
markerDescription.toString());
} }
/** /**
* Adds string explaining how an NPC is involved with the given quests * Adds string explaining how an NPC is involved with the given quests
* *
* @param prefix <p>The string explaining how the NPC is involved</p> * @param formatter <p>The string formatter to use for formatting</p>
* @param quests <p>The quests the NPC is involved in</p> * @param translatableMessage <p>The translatable message to display</p>
* @param builder <p>The string builder to append to</p> * @param quests <p>The quests the NPC is involved in</p>
* @param builder <p>The string builder to append to</p>
*/ */
private void addInvolvedInString(@NotNull String prefix, @NotNull List<Quest> quests, private void addInvolvedInString(@NotNull StringFormatter formatter,
@NotNull QuestsTranslatableMessage translatableMessage, @NotNull List<Quest> quests,
@NotNull StringBuilder builder) { @NotNull StringBuilder builder) {
for (Quest quest : new HashSet<>(quests)) { for (Quest quest : new HashSet<>(quests)) {
builder.append("<li>").append(prefix).append(": ").append(quest.getName()).append("</li>"); builder.append(formatter.replacePlaceholder(translatableMessage, "{questName}", quest.getName()));
} }
} }

View File

@ -40,6 +40,11 @@ public enum Icon {
*/ */
BLACKSMITH, BLACKSMITH,
/**
* An icon representing a scrapper NPC
*/
SCRAPPER,
/** /**
* An icon representing a minstrel NPC * An icon representing a minstrel NPC
*/ */

View File

@ -84,6 +84,7 @@ public class GlobalSettings {
case SENTINEL -> "shield"; case SENTINEL -> "shield";
case MINSTREL -> "theater"; case MINSTREL -> "theater";
case TRADER -> "coins"; case TRADER -> "coins";
case SCRAPPER -> "fire";
}; };
} }

View File

@ -12,6 +12,8 @@ icon:
QUEST_CHAIN: "caution" QUEST_CHAIN: "caution"
# The marker used for blacksmiths # The marker used for blacksmiths
BLACKSMITH: "hammer" BLACKSMITH: "hammer"
# The marker used for scrappers
SCRAPPER: "fire"
# The marker used for sentinels # The marker used for sentinels
SENTINEL: "shield" SENTINEL: "shield"
# The marker used for minstrels # The marker used for minstrels

View File

@ -29,7 +29,8 @@ en:
QUESTS_PLANNER_UNREPEATABLE: "<li>Quest cannot be repeated!</li>" QUESTS_PLANNER_UNREPEATABLE: "<li>Quest cannot be repeated!</li>"
QUESTS_PLANNER_FROM: "<li>Quest available from {startDate}</li>" QUESTS_PLANNER_FROM: "<li>Quest available from {startDate}</li>"
QUESTS_PLANNER_UNTIL: "<li>Quest available until {endDate}</li>" QUESTS_PLANNER_UNTIL: "<li>Quest available until {endDate}</li>"
QUEST_PLANNER_REPEAT: "<li>Quest will become available again after {repeatDelay}</li>" QUESTS_PLANNER_REPEAT: "<li>Quest will become available again after {repeatDelay}</li>"
QUESTS_PLANNER_TIMESTAMP_FORMAT: "dd MM yyyy HH:mm:ss"
QUESTS_REQUIREMENTS_FORMAT: | QUESTS_REQUIREMENTS_FORMAT: |
<b>Requirements: </b><ul> <b>Requirements: </b><ul>
{requirementQuestPoints} {requirementQuestPoints}
@ -56,6 +57,29 @@ en:
QUESTS_REACH_AREA_DESCRIPTION_FORMAT: "{areaName}Target location for {questName}" QUESTS_REACH_AREA_DESCRIPTION_FORMAT: "{areaName}Target location for {questName}"
QUESTS_KILL_AREA_NAME_FORMAT: "<b>{name}</b><br>" QUESTS_KILL_AREA_NAME_FORMAT: "<b>{name}</b><br>"
QUESTS_KILL_AREA_DESCRIPTION_FORMAT: "{areaName}Kill location for {questName}<br>Kill {mobName} x {mobAmount}" QUESTS_KILL_AREA_DESCRIPTION_FORMAT: "{areaName}Kill location for {questName}<br>Kill {mobName} x {mobAmount}"
QUESTS_REWARDS_FORMAT: |
<b>Rewards:</b><ul>
{money}
{experience}
{questPoints}
{permissions}
{items}
{commands}
</ul>
QUESTS_REWARDS_MONEY: "<li>{amount} {currency}</li>"
QUESTS_REWARDS_EXPERIENCE: "<li>{amount} exp</li>"
QUESTS_REWARDS_QUEST_POINTS: "<li>{amount} quest point(s)</li>"
QUESTS_REWARDS_PERMISSION: "<li>Permission: {permission}</li>"
QUESTS_REWARDS_ITEM: "<li>{item}</li>"
QUESTS_REWARDS_COMMAND: "<li>Command: {command}</li>"
QUESTS_MARKER_NAME_FORMAT: "<h2>{name}</h2>"
QUESTS_OFFERED_FORMAT: "<h3>Quests offered:</h3><ul>{quests}</ul>"
QUESTS_OFFERED_QUEST_FORMAT: "<li><h4><b>{name}</b></h4><h5><b>- {description}</b></h5>{stages}{rewards}{requirements}{planner}</li>"
QUESTS_INVOLVED_IN_FORMAT: "<h3>Involved in quests:</h3><ul>{involvedQuests}</ul>"
QUESTS_INVOLVED_IN_KILL: "<li>Killed in: {questName}</li>"
QUESTS_INVOLVED_IN_DELIVERY_TARGET: "<li>Delivery target in: {questName}</li>"
QUESTS_INVOLVED_IN_INTERACT: "<li>Interacted with in quest: {questName}</li>"
# Strings related to displayed durations
DURATION_FORMAT: "in {time} {unit}" DURATION_FORMAT: "in {time} {unit}"
UNIT_NOW: "imminently" UNIT_NOW: "imminently"
UNIT_SECOND: "second" UNIT_SECOND: "second"